From 1fd6ebf194739bee96aa5696cdd24622ef658130 Mon Sep 17 00:00:00 2001 From: ppisa Date: Sun, 28 Mar 2004 14:36:53 +0000 Subject: [PATCH] One of many steps to support Unicontrols CAN cards. --- lincan/include/unican_cl2.h | 7 +- lincan/include/unican_types.h | 25 ++ lincan/src/Makefile.omk | 4 + lincan/src/boardlist.c | 6 +- lincan/src/unican.c | 517 ++++++++++++++++++++++++++++++++++ lincan/src/unican_cl2.c | 10 +- 6 files changed, 557 insertions(+), 12 deletions(-) create mode 100644 lincan/include/unican_types.h create mode 100644 lincan/src/unican.c diff --git a/lincan/include/unican_cl2.h b/lincan/include/unican_cl2.h index ffd6bec..8edf9f4 100644 --- a/lincan/include/unican_cl2.h +++ b/lincan/include/unican_cl2.h @@ -12,10 +12,7 @@ PORTING : Adapted for LinCAN driver by Pavel Pisa, OCERA team memb DULEZITE UPOZORNENI: ARCHIVACNI INFORMACE: -$Log$ -Revision 1.1 2004/03/13 23:13:31 ppisa -Interconnected OCERA configuration options with LinCAN boardlist.c compilation. - +Log: unican_cl2.h,v 27.1.1999 - corected value of CL2_ERROR_WARNING and CL2_ERROR_BUS_OFF constants @@ -41,7 +38,7 @@ UCEL A FUNKCE: /****** includes ******/ #ifndef __INC_ANCTYPES_H -#include "anctypes.h" +#include "unican_types.h" #endif /****** Definitions of constants ******/ diff --git a/lincan/include/unican_types.h b/lincan/include/unican_types.h new file mode 100644 index 0000000..3e330b8 --- /dev/null +++ b/lincan/include/unican_types.h @@ -0,0 +1,25 @@ +#ifndef _UNICAN_TYPES_H +#define _UNICAN_TYPES_H + +#include + +#ifndef U8 +#define U8 __u8 +#endif +#ifndef U16 +#define U16 __u16 +#endif +#ifndef U32 +#define U32 __u32 +#endif + +#define BOOLEAN1 __u8 + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +#endif /*_UNICAN_TYPES_H*/ diff --git a/lincan/src/Makefile.omk b/lincan/src/Makefile.omk index c7548b2..c130e33 100644 --- a/lincan/src/Makefile.omk +++ b/lincan/src/Makefile.omk @@ -22,6 +22,10 @@ kernel_INCLUDES += -DWITH_DEVFS_FS lincan_cards_SOURCES = $(lincan_cards_SELECTED:%=%.c) +ifeq ($(CONFIG_OC_LINCAN_CARD_unican),y) +lincan_cards_SOURCES += unican_cl2.c +endif + ifneq ($(CONFIG_OC_LINCANRTL),y) kernel_MODULES = lincan diff --git a/lincan/src/boardlist.c b/lincan/src/boardlist.c index 0f87484..f0b7dff 100644 --- a/lincan/src/boardlist.c +++ b/lincan/src/boardlist.c @@ -13,6 +13,7 @@ #include "lincan_config.h" extern int template_register(struct hwspecops_t *hwspecops); +extern int virtual_register(struct hwspecops_t *hwspecops); extern int pip5_register(struct hwspecops_t *hwspecops); extern int pip6_register(struct hwspecops_t *hwspecops); extern int m437_register(struct hwspecops_t *hwspecops); @@ -31,7 +32,7 @@ extern int ssv_register(struct hwspecops_t *hwspecops); extern int bfadcan_register(struct hwspecops_t *hwspecops); extern int pikronisa_register(struct hwspecops_t *hwspecops); extern int msmcan_register(struct hwspecops_t *hwspecops); -extern int virtual_register(struct hwspecops_t *hwspecops); +extern int unican_register(struct hwspecops_t *hwspecops); const struct boardtype_t can_boardtypes[]={ #ifdef CONFIG_OC_LINCAN_CARD_template @@ -90,6 +91,9 @@ const struct boardtype_t can_boardtypes[]={ #endif #ifdef CONFIG_OC_LINCAN_CARD_msmcan {"msmcan", msmcan_register, 1}, + #endif + #ifdef CONFIG_OC_LINCAN_CARD_unican + {"unican", unican_register, 1}, #endif {NULL} }; diff --git a/lincan/src/unican.c b/lincan/src/unican.c new file mode 100644 index 0000000..a64aeb3 --- /dev/null +++ b/lincan/src/unican.c @@ -0,0 +1,517 @@ +/* unican.c + * Linux CAN-bus device driver. + * Written for new CAN driver version by Pavel Pisa - OCERA team member + * email:pisa@cmp.felk.cvut.cz + * This software is released under the GPL-License. + * Version lincan-0.2 9 Jul 2003 + */ + +#include "../include/can.h" +#include "../include/can_sysdep.h" +#include "../include/main.h" +#include "../include/unican_cl2.h" + + +long unican_bus_latency(struct msgobj_t *obj) +{ + long latency; + latency=obj->hostchip->baudrate; + if(latency){ + latency=(long)HZ*1000/latency; + } + return latency; +} + + +/* * * unican Chip Functionality * * */ + +int unican_enable_configuration(struct chip_t *chip) +{ + return 0; +} + +int unican_disable_configuration(struct chip_t *chip) +{ + return 0; +} + +/** + * unican_chip_config: - can chip configuration + * @chip: pointer to chip state structure + * + * Return Value: negative value reports error. + * File: src/unican.c + */ +int unican_chip_config(struct chip_t *chip) +{ + return 0; +} + +/** + * unican_extended_mask: - setup of extended mask for message filtering + * @chip: pointer to chip state structure + * @code: can message acceptance code + * @mask: can message acceptance mask + * + * Return Value: negative value reports error. + * File: src/unican.c + */ +int unican_extended_mask(struct chip_t *chip, unsigned long code, unsigned long mask) +{ + return 0; +} + +/** + * unican_baud_rate: - set communication parameters. + * @chip: pointer to chip state structure + * @rate: baud rate in Hz + * @clock: frequency of sja1000 clock in Hz (ISA osc is 14318000) + * @sjw: synchronization jump width (0-3) prescaled clock cycles + * @sampl_pt: sample point in % (0-100) sets (TSEG1+1)/(TSEG1+TSEG2+2) ratio + * @flags: fields %BTR1_SAM, %OCMODE, %OCPOL, %OCTP, %OCTN, %CLK_OFF, %CBP + * + * Return Value: negative value reports error. + * File: src/unican.c + */ +int unican_baud_rate(struct chip_t *chip, int rate, int clock, int sjw, + int sampl_pt, int flags) +{ + return 0; +} + +/** + * unican_read: - reads and distributes one or more received messages + * @chip: pointer to chip state structure + * @obj: pinter to CAN message queue information + * + * File: src/unican.c + */ +void unican_read(struct chip_t *chip, struct msgobj_t *obj) { + +} + +/** + * unican_pre_read_config: - prepares message object for message reception + * @chip: pointer to chip state structure + * @obj: pointer to message object state structure + * + * Return Value: negative value reports error. + * Positive value indicates immediate reception of message. + * File: src/unican.c + */ +int unican_pre_read_config(struct chip_t *chip, struct msgobj_t *obj) +{ + return 0; +} + +#define MAX_TRANSMIT_WAIT_LOOPS 10 +/** + * unican_pre_write_config: - prepares message object for message transmission + * @chip: pointer to chip state structure + * @obj: pointer to message object state structure + * @msg: pointer to CAN message + * + * Return Value: negative value reports error. + * File: src/unican.c + */ +int unican_pre_write_config(struct chip_t *chip, struct msgobj_t *obj, + struct canmsg_t *msg) +{ + return 0; +} + +/** + * unican_send_msg: - initiate message transmission + * @chip: pointer to chip state structure + * @obj: pointer to message object state structure + * @msg: pointer to CAN message + * + * This function is called after unican_pre_write_config() function, + * which prepares data in chip buffer. + * Return Value: negative value reports error. + * File: src/unican.c + */ +int unican_send_msg(struct chip_t *chip, struct msgobj_t *obj, + struct canmsg_t *msg) +{ + return 0; +} + +/** + * unican_check_tx_stat: - checks state of transmission engine + * @chip: pointer to chip state structure + * + * Return Value: negative value reports error. + * Positive return value indicates transmission under way status. + * Zero value indicates finishing of all issued transmission requests. + * File: src/unican.c + */ +int unican_check_tx_stat(struct chip_t *chip) +{ + return 0; +} + +/** + * unican_set_btregs: - configures bitrate registers + * @chip: pointer to chip state structure + * @btr0: bitrate register 0 + * @btr1: bitrate register 1 + * + * Return Value: negative value reports error. + * File: src/unican.c + */ +int unican_set_btregs(struct chip_t *chip, unsigned short btr0, + unsigned short btr1) +{ + return 0; +} + +/** + * unican_stop_chip: - starts chip message processing + * @chip: pointer to chip state structure + * + * Return Value: negative value reports error. + * File: src/unican.c + */ +int unican_start_chip(struct chip_t *chip) +{ + return 0; +} + +/** + * unican_stop_chip: - stops chip message processing + * @chip: pointer to chip state structure + * + * Return Value: negative value reports error. + * File: src/unican.c + */ +int unican_stop_chip(struct chip_t *chip) +{ + return 0; +} + + +/** + * unican_remote_request: - configures message object and asks for RTR message + * @chip: pointer to chip state structure + * @obj: pointer to message object structure + * + * Return Value: negative value reports error. + * File: src/unican.c + */ +int unican_remote_request(struct chip_t *chip, struct msgobj_t *obj) +{ + CANMSG("unican_remote_request not implemented\n"); + return -ENOSYS; +} + +/** + * unican_standard_mask: - setup of mask for message filtering + * @chip: pointer to chip state structure + * @code: can message acceptance code + * @mask: can message acceptance mask + * + * Return Value: negative value reports error. + * File: src/unican.c + */ +int unican_standard_mask(struct chip_t *chip, unsigned short code, + unsigned short mask) +{ + CANMSG("unican_standard_mask not implemented\n"); + return -ENOSYS; +} + +/** + * unican_clear_objects: - clears state of all message object residing in chip + * @chip: pointer to chip state structure + * + * Return Value: negative value reports error. + * File: src/unican.c + */ +int unican_clear_objects(struct chip_t *chip) +{ + CANMSG("unican_clear_objects not implemented\n"); + return -ENOSYS; +} + +/** + * unican_config_irqs: - tunes chip hardware interrupt delivery + * @chip: pointer to chip state structure + * @irqs: requested chip IRQ configuration + * + * Return Value: negative value reports error. + * File: src/unican.c + */ +int unican_config_irqs(struct chip_t *chip, short irqs) +{ + CANMSG("unican_config_irqs not implemented\n"); + return -ENOSYS; +} + +/** + * unican_irq_write_handler: - part of ISR code responsible for transmit events + * @chip: pointer to chip state structure + * @obj: pointer to attached queue description + * + * The main purpose of this function is to read message from attached queues + * and transfer message contents into CAN controller chip. + * This subroutine is called by + * unican_irq_write_handler() for transmit events. + * File: src/unican.c + */ +void unican_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) +{ + +} + +#define MAX_RETR 10 + +/** + * unican_irq_handler: - interrupt service routine + * @irq: interrupt vector number, this value is system specific + * @dev_id: driver private pointer registered at time of request_irq() call. + * The CAN driver uses this pointer to store relationship of interrupt + * to chip state structure - @struct chip_t + * @regs: system dependent value pointing to registers stored in exception frame + * + * Interrupt handler is activated when state of CAN controller chip changes, + * there is message to be read or there is more space for new messages or + * error occurs. The receive events results in reading of the message from + * CAN controller chip and distribution of message through attached + * message queues. + * File: src/unican.c + */ +can_irqreturn_t unican_irq_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + return CAN_IRQ_HANDLED; +} + + +void unican_schedule_next(struct msgobj_t *obj) +{ + int cmd; + + can_preempt_disable(); + + can_msgobj_set_fl(obj,TX_REQUEST); + + while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){ + + can_msgobj_clear_fl(obj,TX_REQUEST); + + cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot); + if(cmd>=0) { + mod_timer(&obj->tx_timeout, + jiffies+unican_bus_latency(obj)); + DEBUGMSG("unican: scheduled delivery\n"); + + } else + can_msgobj_clear_fl(obj,TX_LOCK); + + if(!can_msgobj_test_fl(obj,TX_REQUEST)) break; + DEBUGMSG("TX looping in unican_schedule_next\n"); + } + + can_preempt_enable(); +} + + +void unican_do_tx_timeout(unsigned long data) +{ + struct msgobj_t *obj=(struct msgobj_t *)data; + + if(obj->tx_slot) { + /* Deliver message to edges */ + canque_filter_msg2edges(obj->qends, &obj->tx_slot->msg); + /* Free transmitted slot */ + canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot); + obj->tx_slot=NULL; + DEBUGMSG("unican: delayed delivery\n"); + } + can_msgobj_clear_fl(obj,TX_LOCK); + + unican_schedule_next(obj); +} + +/** + * unican_wakeup_tx: - wakeups TX processing + * @chip: pointer to chip state structure + * @obj: pointer to message object structure + * + * Return Value: negative value reports error. + * File: src/unican.c + */ +int unican_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj) +{ + /* can_msgobj_set_fl(obj,TX_REQUEST); */ + + struct canque_edge_t *qedge; + struct canque_slot_t *slot; + int cmd; + + can_msgobj_clear_fl(obj,TX_REQUEST); + + #ifndef CAN_WITH_RTL + if(!unican_bus_latency(obj)) { + #endif /*CAN_WITH_RTL*/ + /* Ensure delivery of all ready slots */ + while((cmd=canque_test_outslot(obj->qends, &qedge, &slot)) >= 0){ + if(cmd==0) { + canque_filter_msg2edges(obj->qends, &slot->msg); + DEBUGMSG("unican: direct delivery\n"); + } + canque_free_outslot(obj->qends, qedge, slot); + } + #ifndef CAN_WITH_RTL + } else { + unican_schedule_next(obj); + } + #endif /*CAN_WITH_RTL*/ + + return 0; +} + + +/* * * unican Board Functionality * * */ + +/** + * unican_request_io: - reserve io or memory range for can board + * @candev: pointer to candevice/board which asks for io. Field @io_addr + * of @candev is used in most cases to define start of the range + * + * Return Value: The function returns zero on success or %-ENODEV on failure + * File: src/unican.c + */ +int unican_request_io(struct candevice_t *candev) +{ + return 0; +} + +/** + * unican_elease_io - free reserved io memory range + * @candev: pointer to candevice/board which releases io + * + * Return Value: The function always returns zero + * File: src/unican.c + */ +int unican_release_io(struct candevice_t *candev) +{ + return 0; +} + +/** + * unican_reset - hardware reset routine + * @candev: Pointer to candevice/board structure + * + * Return Value: The function returns zero on success or %-ENODEV on failure + * File: src/unican.c + */ +int unican_reset(struct candevice_t *candev) +{ + return 0; +} + +/** + * unican_init_hw_data - Initialize hardware cards + * @candev: Pointer to candevice/board structure + * + * Return Value: The function always returns zero + * File: src/unican.c + */ +int unican_init_hw_data(struct candevice_t *candev) +{ + candev->res_addr=0; + candev->nr_82527_chips=0; + candev->nr_sja1000_chips=0; + candev->nr_all_chips=1; + candev->flags |= CANDEV_PROGRAMMABLE_IRQ*0; + + return 0; +} + +#define CHIP_TYPE "unican" + +/** + * unican_init_chip_data - Initialize chips + * @candev: Pointer to candevice/board structure + * @chipnr: Number of the CAN chip on the hardware card + * + * Return Value: The function always returns zero + * File: src/unican.c + */ +int unican_init_chip_data(struct candevice_t *candev, int chipnr) +{ + struct chip_t *chip = candev->chip[chipnr]; + chip->chip_type = CHIP_TYPE; + chip->chip_base_addr = 0; + chip->clock = 10000000; + chip->int_clk_reg = 0x0; + chip->int_bus_reg = 0x0; + chip->max_objects = 1; + + CANMSG("initializing unican chip operations\n"); + chip->chipspecops->chip_config=unican_chip_config; + chip->chipspecops->baud_rate=unican_baud_rate; + chip->chipspecops->standard_mask=unican_standard_mask; + chip->chipspecops->extended_mask=unican_extended_mask; + chip->chipspecops->message15_mask=unican_extended_mask; + chip->chipspecops->clear_objects=unican_clear_objects; + chip->chipspecops->config_irqs=unican_config_irqs; + chip->chipspecops->pre_read_config=unican_pre_read_config; + chip->chipspecops->pre_write_config=unican_pre_write_config; + chip->chipspecops->send_msg=unican_send_msg; + chip->chipspecops->check_tx_stat=unican_check_tx_stat; + chip->chipspecops->wakeup_tx=unican_wakeup_tx; + chip->chipspecops->remote_request=unican_remote_request; + chip->chipspecops->enable_configuration=unican_enable_configuration; + chip->chipspecops->disable_configuration=unican_disable_configuration; + chip->chipspecops->set_btregs=unican_set_btregs; + chip->chipspecops->start_chip=unican_start_chip; + chip->chipspecops->stop_chip=unican_stop_chip; + chip->chipspecops->irq_handler=NULL; + + return 0; +} + +/** + * unican_init_obj_data - Initialize message buffers + * @chip: Pointer to chip specific structure + * @objnr: Number of the message buffer + * + * Return Value: The function always returns zero + * File: src/unican.c + */ +int unican_init_obj_data(struct chip_t *chip, int objnr) +{ + struct msgobj_t *obj=chip->msgobj[objnr]; + obj->obj_base_addr=chip->chip_base_addr; + obj->tx_timeout.function=unican_do_tx_timeout; + obj->tx_timeout.data=(unsigned long)obj; + return 0; +} + +/** + * unican_program_irq - program interrupts + * @candev: Pointer to candevice/board structure + * + * Return value: The function returns zero on success or %-ENODEV on failure + * File: src/unican.c + */ +int unican_program_irq(struct candevice_t *candev) +{ + return 0; +} + +int unican_register(struct hwspecops_t *hwspecops) +{ + hwspecops->request_io = unican_request_io; + hwspecops->release_io = unican_release_io; + hwspecops->reset = unican_reset; + hwspecops->init_hw_data = unican_init_hw_data; + hwspecops->init_chip_data = unican_init_chip_data; + hwspecops->init_obj_data = unican_init_obj_data; + hwspecops->write_register = NULL; + hwspecops->read_register = NULL; + hwspecops->program_irq = unican_program_irq; + return 0; +} diff --git a/lincan/src/unican_cl2.c b/lincan/src/unican_cl2.c index 18a78e9..a3dd7f7 100644 --- a/lincan/src/unican_cl2.c +++ b/lincan/src/unican_cl2.c @@ -11,10 +11,7 @@ FIRMA : CVUT FEL, Dept. of Measurement DULEZITE UPOZORNENI: ARCHIVACNI INFORMACE: -$Log$ -Revision 1.1 2004/03/13 23:13:33 ppisa -Interconnected OCERA configuration options with LinCAN boardlist.c compilation. - +Log: unican_cl2.c,v 12.12.2000, J.B., cl2_receive_data - time stamp for even number of bytes corr. 26.8.1998 - cl2_buf_size - corrected, new function return code CL2_BAD_PARAM @@ -34,8 +31,9 @@ UCEL A FUNKCE: /* includes */ -#include "anctypes.h" -#include "cl2.h" +#include "../include/canmsg.h" +#include "../include/unican_types.h" +#include "../include/unican_cl2.h" /******************************************************************************* -- 2.39.2