X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/f2fcdbb5f9333a58a08f56daaca8cad7e5a95699..04ac67cc3cac14cd601daacd0592121ec0b84012:/lincan/src/virtual.c diff --git a/lincan/src/virtual.c b/lincan/src/virtual.c index 5b39ecf..eb8043f 100644 --- a/lincan/src/virtual.c +++ b/lincan/src/virtual.c @@ -1,25 +1,60 @@ -/* virtual.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 -#include +/**************************************************************************/ +/* File: virtual.c - virtual chip/board support */ +/* */ +/* LinCAN - (Not only) Linux CAN bus driver */ +/* Copyright (C) 2002-2009 DCE FEE CTU Prague */ +/* Copyright (C) 2002-2009 Pavel Pisa */ +/* Funded by OCERA and FRESCOR IST projects */ +/* Based on CAN driver code by Arnaud Westenberg */ +/* */ +/* LinCAN is free software; you can redistribute it and/or modify it */ +/* under terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2, or (at your option) any */ +/* later version. LinCAN 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 LinCAN; see file */ +/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/* */ +/* To allow use of LinCAN in the compact embedded systems firmware */ +/* and RT-executives (RTEMS for example), main authors agree with next */ +/* special exception: */ +/* */ +/* Including LinCAN header files in a file, instantiating LinCAN generics */ +/* or templates, or linking other files with LinCAN objects to produce */ +/* an application image/executable, does not by itself cause the */ +/* resulting application image/executable to be covered by */ +/* the GNU General Public License. */ +/* This exception does not however invalidate any other reasons */ +/* why the executable file might be covered by the GNU Public License. */ +/* Publication of enhanced or derived LinCAN files is required although. */ +/**************************************************************************/ +#include "../include/can.h" +#include "../include/can_sysdep.h" #include "../include/main.h" + +long virtual_bus_latency(struct msgobj_t *obj) +{ + long latency; + latency=obj->hostchip->baudrate; + if(latency){ + latency=(long)HZ*1000/latency; + } + return latency; +} + + /* * * Virtual Chip Functionality * * */ -int virtual_enable_configuration(struct chip_t *chip) +int virtual_enable_configuration(struct canchip_t *chip) { return 0; } -int virtual_disable_configuration(struct chip_t *chip) +int virtual_disable_configuration(struct canchip_t *chip) { return 0; } @@ -31,7 +66,7 @@ int virtual_disable_configuration(struct chip_t *chip) * Return Value: negative value reports error. * File: src/virtual.c */ -int virtual_chip_config(struct chip_t *chip) +int virtual_chip_config(struct canchip_t *chip) { return 0; } @@ -45,7 +80,7 @@ int virtual_chip_config(struct chip_t *chip) * Return Value: negative value reports error. * File: src/virtual.c */ -int virtual_extended_mask(struct chip_t *chip, unsigned long code, unsigned long mask) +int virtual_extended_mask(struct canchip_t *chip, unsigned long code, unsigned long mask) { return 0; } @@ -62,7 +97,7 @@ int virtual_extended_mask(struct chip_t *chip, unsigned long code, unsigned lon * Return Value: negative value reports error. * File: src/virtual.c */ -int virtual_baud_rate(struct chip_t *chip, int rate, int clock, int sjw, +int virtual_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw, int sampl_pt, int flags) { return 0; @@ -75,7 +110,7 @@ int virtual_baud_rate(struct chip_t *chip, int rate, int clock, int sjw, * * File: src/virtual.c */ -void virtual_read(struct chip_t *chip, struct msgobj_t *obj) { +void virtual_read(struct canchip_t *chip, struct msgobj_t *obj) { } @@ -88,7 +123,7 @@ void virtual_read(struct chip_t *chip, struct msgobj_t *obj) { * Positive value indicates immediate reception of message. * File: src/virtual.c */ -int virtual_pre_read_config(struct chip_t *chip, struct msgobj_t *obj) +int virtual_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj) { return 0; } @@ -103,7 +138,7 @@ int virtual_pre_read_config(struct chip_t *chip, struct msgobj_t *obj) * Return Value: negative value reports error. * File: src/virtual.c */ -int virtual_pre_write_config(struct chip_t *chip, struct msgobj_t *obj, +int virtual_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj, struct canmsg_t *msg) { return 0; @@ -120,7 +155,7 @@ int virtual_pre_write_config(struct chip_t *chip, struct msgobj_t *obj, * Return Value: negative value reports error. * File: src/virtual.c */ -int virtual_send_msg(struct chip_t *chip, struct msgobj_t *obj, +int virtual_send_msg(struct canchip_t *chip, struct msgobj_t *obj, struct canmsg_t *msg) { return 0; @@ -135,7 +170,7 @@ int virtual_send_msg(struct chip_t *chip, struct msgobj_t *obj, * Zero value indicates finishing of all issued transmission requests. * File: src/virtual.c */ -int virtual_check_tx_stat(struct chip_t *chip) +int virtual_check_tx_stat(struct canchip_t *chip) { return 0; } @@ -149,7 +184,7 @@ int virtual_check_tx_stat(struct chip_t *chip) * Return Value: negative value reports error. * File: src/virtual.c */ -int virtual_set_btregs(struct chip_t *chip, unsigned short btr0, +int virtual_set_btregs(struct canchip_t *chip, unsigned short btr0, unsigned short btr1) { return 0; @@ -162,7 +197,7 @@ int virtual_set_btregs(struct chip_t *chip, unsigned short btr0, * Return Value: negative value reports error. * File: src/virtual.c */ -int virtual_start_chip(struct chip_t *chip) +int virtual_start_chip(struct canchip_t *chip) { return 0; } @@ -174,11 +209,35 @@ int virtual_start_chip(struct chip_t *chip) * Return Value: negative value reports error. * File: src/virtual.c */ -int virtual_stop_chip(struct chip_t *chip) +int virtual_stop_chip(struct canchip_t *chip) { return 0; } +/** + * virtual_attach_to_chip: - attaches to the chip, setups registers and state + * @chip: pointer to chip state structure + * + * Return Value: negative value reports error. + * File: src/virtual.c + */ +int virtual_attach_to_chip(struct canchip_t *chip) +{ + return 0; +} + +/** + * virtual_release_chip: - called before chip structure removal if %CHIP_ATTACHED is set + * @chip: pointer to chip state structure + * + * Return Value: negative value reports error. + * File: src/virtual.c + */ +int virtual_release_chip(struct canchip_t *chip) +{ + virtual_stop_chip(chip); + return 0; +} /** * virtual_remote_request: - configures message object and asks for RTR message @@ -188,7 +247,7 @@ int virtual_stop_chip(struct chip_t *chip) * Return Value: negative value reports error. * File: src/virtual.c */ -int virtual_remote_request(struct chip_t *chip, struct msgobj_t *obj) +int virtual_remote_request(struct canchip_t *chip, struct msgobj_t *obj) { CANMSG("virtual_remote_request not implemented\n"); return -ENOSYS; @@ -203,7 +262,7 @@ int virtual_remote_request(struct chip_t *chip, struct msgobj_t *obj) * Return Value: negative value reports error. * File: src/virtual.c */ -int virtual_standard_mask(struct chip_t *chip, unsigned short code, +int virtual_standard_mask(struct canchip_t *chip, unsigned short code, unsigned short mask) { CANMSG("virtual_standard_mask not implemented\n"); @@ -217,7 +276,7 @@ int virtual_standard_mask(struct chip_t *chip, unsigned short code, * Return Value: negative value reports error. * File: src/virtual.c */ -int virtual_clear_objects(struct chip_t *chip) +int virtual_clear_objects(struct canchip_t *chip) { CANMSG("virtual_clear_objects not implemented\n"); return -ENOSYS; @@ -231,7 +290,7 @@ int virtual_clear_objects(struct chip_t *chip) * Return Value: negative value reports error. * File: src/virtual.c */ -int virtual_config_irqs(struct chip_t *chip, short irqs) +int virtual_config_irqs(struct canchip_t *chip, short irqs) { CANMSG("virtual_config_irqs not implemented\n"); return -ENOSYS; @@ -248,7 +307,7 @@ int virtual_config_irqs(struct chip_t *chip, short irqs) * virtual_irq_write_handler() for transmit events. * File: src/virtual.c */ -void virtual_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) +void virtual_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj) { } @@ -260,9 +319,9 @@ void virtual_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) * @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 + * to chip state structure - @struct canchip_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 @@ -270,9 +329,59 @@ void virtual_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) * message queues. * File: src/virtual.c */ -irqreturn_t virtual_irq_handler(int irq, void *dev_id, struct pt_regs *regs) +int virtual_irq_handler(int irq, struct canchip_t *chip) +{ + return CANCHIP_IRQ_HANDLED; +} + + +void virtual_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+virtual_bus_latency(obj)); + DEBUGMSG("virtual: scheduled delivery\n"); + + } else + can_msgobj_clear_fl(obj,TX_LOCK); + + if(!can_msgobj_test_fl(obj,TX_REQUEST)) break; + DEBUGMSG("TX looping in virtual_schedule_next\n"); + } + + can_preempt_enable(); +} + + +void virtual_do_tx_timeout(unsigned long data) { - return IRQ_HANDLED; + struct msgobj_t *obj=(struct msgobj_t *)data; + + if(obj->tx_slot) { + /* fill CAN message timestamp */ + can_filltimestamp(&obj->tx_slot->msg.timestamp); + + /* 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("virtual: delayed delivery\n"); + } + can_msgobj_clear_fl(obj,TX_LOCK); + + virtual_schedule_next(obj); } /** @@ -280,25 +389,41 @@ irqreturn_t virtual_irq_handler(int irq, void *dev_id, struct pt_regs *regs) * @chip: pointer to chip state structure * @obj: pointer to message object structure * + * Function is responsible for initiating message transmition. + * It is responsible for clearing of object TX_REQUEST flag + * * Return Value: negative value reports error. * File: src/virtual.c */ -int virtual_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj) +int virtual_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj) { - /* set_bit(OBJ_TX_REQUEST,&obj->flags); */ - + /* can_msgobj_set_fl(obj,TX_REQUEST); */ + struct canque_edge_t *qedge; struct canque_slot_t *slot; int cmd; - - /* 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); + + can_msgobj_clear_fl(obj,TX_REQUEST); + + #ifndef CAN_WITH_RTL + if(!virtual_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) { + /* fill CAN message timestamp */ + can_filltimestamp(&slot->msg.timestamp); + + canque_filter_msg2edges(obj->qends, &slot->msg); + DEBUGMSG("virtual: direct delivery\n"); + } + canque_free_outslot(obj->qends, qedge, slot); } - canque_free_outslot(obj->qends, qedge, slot); + #ifndef CAN_WITH_RTL + } else { + virtual_schedule_next(obj); } + #endif /*CAN_WITH_RTL*/ return 0; } @@ -307,9 +432,9 @@ int virtual_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj) /* * * Virtual Board Functionality * * */ /** - * virtual_request_io: - reserve io memory - * @io_addr: The reserved memory starts at @io_addr, wich is the module - * parameter @io. + * virtual_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/virtual.c @@ -320,8 +445,8 @@ int virtual_request_io(struct candevice_t *candev) } /** - * virtual_release_io - free reserved io-memory - * @io_addr: Start of the memory range to be released. + * virtual_elease_io - free reserved io memory range + * @candev: pointer to candevice/board which releases io * * Return Value: The function always returns zero * File: src/virtual.c @@ -333,7 +458,7 @@ int virtual_release_io(struct candevice_t *candev) /** * virtual_reset - hardware reset routine - * @card: Number of the hardware card. + * @candev: Pointer to candevice/board structure * * Return Value: The function returns zero on success or %-ENODEV on failure * File: src/virtual.c @@ -344,19 +469,19 @@ int virtual_reset(struct candevice_t *candev) } /** - * virtual_init_hw_data - Initialze hardware cards - * @card: Number of the hardware card. + * virtual_init_hw_data - Initialize hardware cards + * @candev: Pointer to candevice/board structure * * Return Value: The function always returns zero * File: src/virtual.c */ -int virtual_init_hw_data(struct candevice_t *candev) +int virtual_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 |= PROGRAMMABLE_IRQ*0; + candev->flags |= CANDEV_PROGRAMMABLE_IRQ*0; return 0; } @@ -365,7 +490,7 @@ int virtual_init_hw_data(struct candevice_t *candev) /** * virtual_init_chip_data - Initialize chips - * @card: Number of the hardware card + * @candev: Pointer to candevice/board structure * @chipnr: Number of the CAN chip on the hardware card * * Return Value: The function always returns zero @@ -373,7 +498,7 @@ int virtual_init_hw_data(struct candevice_t *candev) */ int virtual_init_chip_data(struct candevice_t *candev, int chipnr) { - struct chip_t *chip = candev->chip[chipnr]; + struct canchip_t *chip = candev->chip[chipnr]; chip->chip_type = CHIP_TYPE; chip->chip_base_addr = 0; chip->clock = 10000000; @@ -397,32 +522,37 @@ int virtual_init_chip_data(struct candevice_t *candev, int chipnr) chip->chipspecops->remote_request=virtual_remote_request; chip->chipspecops->enable_configuration=virtual_enable_configuration; chip->chipspecops->disable_configuration=virtual_disable_configuration; + chip->chipspecops->attach_to_chip=virtual_attach_to_chip; + chip->chipspecops->release_chip=virtual_release_chip; chip->chipspecops->set_btregs=virtual_set_btregs; chip->chipspecops->start_chip=virtual_start_chip; chip->chipspecops->stop_chip=virtual_stop_chip; chip->chipspecops->irq_handler=NULL; + chip->chipspecops->irq_accept=NULL; return 0; } /** * virtual_init_obj_data - Initialize message buffers - * @chipnr: Number of the CAN chip + * @chip: Pointer to chip specific structure * @objnr: Number of the message buffer * * Return Value: The function always returns zero * File: src/virtual.c */ -int virtual_init_obj_data(struct chip_t *chip, int objnr) +int virtual_init_obj_data(struct canchip_t *chip, int objnr) { - chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr; - chip->msgobj[objnr]->flags=0; + struct msgobj_t *obj=chip->msgobj[objnr]; + obj->obj_base_addr=chip->chip_base_addr; + obj->tx_timeout.function=virtual_do_tx_timeout; + obj->tx_timeout.data=(unsigned long)obj; return 0; } /** * virtual_program_irq - program interrupts - * @card: Number of the hardware card. + * @candev: Pointer to candevice/board structure * * Return value: The function returns zero on success or %-ENODEV on failure * File: src/virtual.c