1 /**************************************************************************/
2 /* File: virtual.c - virtual chip/board support */
4 /* LinCAN - (Not only) Linux CAN bus driver */
5 /* Copyright (C) 2002-2009 DCE FEE CTU Prague <http://dce.felk.cvut.cz> */
6 /* Copyright (C) 2002-2009 Pavel Pisa <pisa@cmp.felk.cvut.cz> */
7 /* Funded by OCERA and FRESCOR IST projects */
8 /* Based on CAN driver code by Arnaud Westenberg <arnaud@wanadoo.nl> */
10 /* LinCAN is free software; you can redistribute it and/or modify it */
11 /* under terms of the GNU General Public License as published by the */
12 /* Free Software Foundation; either version 2, or (at your option) any */
13 /* later version. LinCAN is distributed in the hope that it will be */
14 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */
15 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
16 /* General Public License for more details. You should have received a */
17 /* copy of the GNU General Public License along with LinCAN; see file */
18 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, */
19 /* Cambridge, MA 02139, USA. */
21 /* To allow use of LinCAN in the compact embedded systems firmware */
22 /* and RT-executives (RTEMS for example), main authors agree with next */
23 /* special exception: */
25 /* Including LinCAN header files in a file, instantiating LinCAN generics */
26 /* or templates, or linking other files with LinCAN objects to produce */
27 /* an application image/executable, does not by itself cause the */
28 /* resulting application image/executable to be covered by */
29 /* the GNU General Public License. */
30 /* This exception does not however invalidate any other reasons */
31 /* why the executable file might be covered by the GNU Public License. */
32 /* Publication of enhanced or derived LinCAN files is required although. */
33 /**************************************************************************/
34 #include "../include/can.h"
35 #include "../include/can_sysdep.h"
36 #include "../include/main.h"
39 long virtual_bus_latency(struct msgobj_t *obj)
42 latency=obj->hostchip->baudrate;
44 latency=(long)HZ*1000/latency;
50 /* * * Virtual Chip Functionality * * */
52 int virtual_enable_configuration(struct canchip_t *chip)
57 int virtual_disable_configuration(struct canchip_t *chip)
63 * virtual_chip_config: - can chip configuration
64 * @chip: pointer to chip state structure
66 * Return Value: negative value reports error.
69 int virtual_chip_config(struct canchip_t *chip)
75 * virtual_extended_mask: - setup of extended mask for message filtering
76 * @chip: pointer to chip state structure
77 * @code: can message acceptance code
78 * @mask: can message acceptance mask
80 * Return Value: negative value reports error.
83 int virtual_extended_mask(struct canchip_t *chip, unsigned long code, unsigned long mask)
89 * virtual_baud_rate: - set communication parameters.
90 * @chip: pointer to chip state structure
91 * @rate: baud rate in Hz
92 * @clock: frequency of sja1000 clock in Hz (ISA osc is 14318000)
93 * @sjw: synchronization jump width (0-3) prescaled clock cycles
94 * @sampl_pt: sample point in % (0-100) sets (TSEG1+1)/(TSEG1+TSEG2+2) ratio
95 * @flags: fields %BTR1_SAM, %OCMODE, %OCPOL, %OCTP, %OCTN, %CLK_OFF, %CBP
97 * Return Value: negative value reports error.
100 int virtual_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw,
101 int sampl_pt, int flags)
107 * virtual_read: - reads and distributes one or more received messages
108 * @chip: pointer to chip state structure
109 * @obj: pinter to CAN message queue information
111 * File: src/virtual.c
113 void virtual_read(struct canchip_t *chip, struct msgobj_t *obj) {
118 * virtual_pre_read_config: - prepares message object for message reception
119 * @chip: pointer to chip state structure
120 * @obj: pointer to message object state structure
122 * Return Value: negative value reports error.
123 * Positive value indicates immediate reception of message.
124 * File: src/virtual.c
126 int virtual_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj)
131 #define MAX_TRANSMIT_WAIT_LOOPS 10
133 * virtual_pre_write_config: - prepares message object for message transmission
134 * @chip: pointer to chip state structure
135 * @obj: pointer to message object state structure
136 * @msg: pointer to CAN message
138 * Return Value: negative value reports error.
139 * File: src/virtual.c
141 int virtual_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
142 struct canmsg_t *msg)
148 * virtual_send_msg: - initiate message transmission
149 * @chip: pointer to chip state structure
150 * @obj: pointer to message object state structure
151 * @msg: pointer to CAN message
153 * This function is called after virtual_pre_write_config() function,
154 * which prepares data in chip buffer.
155 * Return Value: negative value reports error.
156 * File: src/virtual.c
158 int virtual_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
159 struct canmsg_t *msg)
165 * virtual_check_tx_stat: - checks state of transmission engine
166 * @chip: pointer to chip state structure
168 * Return Value: negative value reports error.
169 * Positive return value indicates transmission under way status.
170 * Zero value indicates finishing of all issued transmission requests.
171 * File: src/virtual.c
173 int virtual_check_tx_stat(struct canchip_t *chip)
179 * virtual_set_btregs: - configures bitrate registers
180 * @chip: pointer to chip state structure
181 * @btr0: bitrate register 0
182 * @btr1: bitrate register 1
184 * Return Value: negative value reports error.
185 * File: src/virtual.c
187 int virtual_set_btregs(struct canchip_t *chip, unsigned short btr0,
194 * virtual_stop_chip: - starts chip message processing
195 * @chip: pointer to chip state structure
197 * Return Value: negative value reports error.
198 * File: src/virtual.c
200 int virtual_start_chip(struct canchip_t *chip)
206 * virtual_stop_chip: - stops chip message processing
207 * @chip: pointer to chip state structure
209 * Return Value: negative value reports error.
210 * File: src/virtual.c
212 int virtual_stop_chip(struct canchip_t *chip)
218 * virtual_attach_to_chip: - attaches to the chip, setups registers and state
219 * @chip: pointer to chip state structure
221 * Return Value: negative value reports error.
222 * File: src/virtual.c
224 int virtual_attach_to_chip(struct canchip_t *chip)
230 * virtual_release_chip: - called before chip structure removal if %CHIP_ATTACHED is set
231 * @chip: pointer to chip state structure
233 * Return Value: negative value reports error.
234 * File: src/virtual.c
236 int virtual_release_chip(struct canchip_t *chip)
238 virtual_stop_chip(chip);
243 * virtual_remote_request: - configures message object and asks for RTR message
244 * @chip: pointer to chip state structure
245 * @obj: pointer to message object structure
247 * Return Value: negative value reports error.
248 * File: src/virtual.c
250 int virtual_remote_request(struct canchip_t *chip, struct msgobj_t *obj)
252 CANMSG("virtual_remote_request not implemented\n");
257 * virtual_standard_mask: - setup of mask for message filtering
258 * @chip: pointer to chip state structure
259 * @code: can message acceptance code
260 * @mask: can message acceptance mask
262 * Return Value: negative value reports error.
263 * File: src/virtual.c
265 int virtual_standard_mask(struct canchip_t *chip, unsigned short code,
268 CANMSG("virtual_standard_mask not implemented\n");
273 * virtual_clear_objects: - clears state of all message object residing in chip
274 * @chip: pointer to chip state structure
276 * Return Value: negative value reports error.
277 * File: src/virtual.c
279 int virtual_clear_objects(struct canchip_t *chip)
281 CANMSG("virtual_clear_objects not implemented\n");
286 * virtual_config_irqs: - tunes chip hardware interrupt delivery
287 * @chip: pointer to chip state structure
288 * @irqs: requested chip IRQ configuration
290 * Return Value: negative value reports error.
291 * File: src/virtual.c
293 int virtual_config_irqs(struct canchip_t *chip, short irqs)
295 CANMSG("virtual_config_irqs not implemented\n");
300 * virtual_irq_write_handler: - part of ISR code responsible for transmit events
301 * @chip: pointer to chip state structure
302 * @obj: pointer to attached queue description
304 * The main purpose of this function is to read message from attached queues
305 * and transfer message contents into CAN controller chip.
306 * This subroutine is called by
307 * virtual_irq_write_handler() for transmit events.
308 * File: src/virtual.c
310 void virtual_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
318 * virtual_irq_handler: - interrupt service routine
319 * @irq: interrupt vector number, this value is system specific
320 * @dev_id: driver private pointer registered at time of request_irq() call.
321 * The CAN driver uses this pointer to store relationship of interrupt
322 * to chip state structure - @struct canchip_t
323 * @regs: system dependent value pointing to registers stored in exception frame
325 * Interrupt handler is activated when state of CAN controller chip changes,
326 * there is message to be read or there is more space for new messages or
327 * error occurs. The receive events results in reading of the message from
328 * CAN controller chip and distribution of message through attached
330 * File: src/virtual.c
332 int virtual_irq_handler(int irq, struct canchip_t *chip)
334 return CANCHIP_IRQ_HANDLED;
338 void virtual_schedule_next(struct msgobj_t *obj)
342 can_preempt_disable();
344 can_msgobj_set_fl(obj,TX_REQUEST);
346 while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
348 can_msgobj_clear_fl(obj,TX_REQUEST);
350 cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot);
352 mod_timer(&obj->tx_timeout,
353 jiffies+virtual_bus_latency(obj));
354 DEBUGMSG("virtual: scheduled delivery\n");
357 can_msgobj_clear_fl(obj,TX_LOCK);
359 if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
360 DEBUGMSG("TX looping in virtual_schedule_next\n");
363 can_preempt_enable();
367 void virtual_do_tx_timeout(unsigned long data)
369 struct msgobj_t *obj=(struct msgobj_t *)data;
372 /* fill CAN message timestamp */
373 can_filltimestamp(&obj->tx_slot->msg.timestamp);
375 /* Deliver message to edges */
376 canque_filter_msg2edges(obj->qends, &obj->tx_slot->msg);
377 /* Free transmitted slot */
378 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
380 DEBUGMSG("virtual: delayed delivery\n");
382 can_msgobj_clear_fl(obj,TX_LOCK);
384 virtual_schedule_next(obj);
388 * virtual_wakeup_tx: - wakeups TX processing
389 * @chip: pointer to chip state structure
390 * @obj: pointer to message object structure
392 * Function is responsible for initiating message transmition.
393 * It is responsible for clearing of object TX_REQUEST flag
395 * Return Value: negative value reports error.
396 * File: src/virtual.c
398 int virtual_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
400 /* can_msgobj_set_fl(obj,TX_REQUEST); */
402 struct canque_edge_t *qedge;
403 struct canque_slot_t *slot;
406 can_msgobj_clear_fl(obj,TX_REQUEST);
409 if(!virtual_bus_latency(obj)) {
410 #endif /*CAN_WITH_RTL*/
411 /* Ensure delivery of all ready slots */
412 while((cmd=canque_test_outslot(obj->qends, &qedge, &slot)) >= 0){
414 /* fill CAN message timestamp */
415 can_filltimestamp(&slot->msg.timestamp);
417 canque_filter_msg2edges(obj->qends, &slot->msg);
418 DEBUGMSG("virtual: direct delivery\n");
420 canque_free_outslot(obj->qends, qedge, slot);
424 virtual_schedule_next(obj);
426 #endif /*CAN_WITH_RTL*/
432 /* * * Virtual Board Functionality * * */
435 * virtual_request_io: - reserve io or memory range for can board
436 * @candev: pointer to candevice/board which asks for io. Field @io_addr
437 * of @candev is used in most cases to define start of the range
439 * Return Value: The function returns zero on success or %-ENODEV on failure
440 * File: src/virtual.c
442 int virtual_request_io(struct candevice_t *candev)
448 * virtual_elease_io - free reserved io memory range
449 * @candev: pointer to candevice/board which releases io
451 * Return Value: The function always returns zero
452 * File: src/virtual.c
454 int virtual_release_io(struct candevice_t *candev)
460 * virtual_reset - hardware reset routine
461 * @candev: Pointer to candevice/board structure
463 * Return Value: The function returns zero on success or %-ENODEV on failure
464 * File: src/virtual.c
466 int virtual_reset(struct candevice_t *candev)
472 * virtual_init_hw_data - Initialize hardware cards
473 * @candev: Pointer to candevice/board structure
475 * Return Value: The function always returns zero
476 * File: src/virtual.c
478 int virtual_init_hw_data(struct candevice_t *candev)
481 candev->nr_82527_chips=0;
482 candev->nr_sja1000_chips=0;
483 candev->nr_all_chips=1;
484 candev->flags |= CANDEV_PROGRAMMABLE_IRQ*0;
489 #define CHIP_TYPE "virtual"
492 * virtual_init_chip_data - Initialize chips
493 * @candev: Pointer to candevice/board structure
494 * @chipnr: Number of the CAN chip on the hardware card
496 * Return Value: The function always returns zero
497 * File: src/virtual.c
499 int virtual_init_chip_data(struct candevice_t *candev, int chipnr)
501 struct canchip_t *chip = candev->chip[chipnr];
502 chip->chip_type = CHIP_TYPE;
503 chip->chip_base_addr = 0;
504 chip->clock = 10000000;
505 chip->int_clk_reg = 0x0;
506 chip->int_bus_reg = 0x0;
507 chip->max_objects = 1;
509 CANMSG("initializing virtual chip operations\n");
510 chip->chipspecops->chip_config=virtual_chip_config;
511 chip->chipspecops->baud_rate=virtual_baud_rate;
512 chip->chipspecops->standard_mask=virtual_standard_mask;
513 chip->chipspecops->extended_mask=virtual_extended_mask;
514 chip->chipspecops->message15_mask=virtual_extended_mask;
515 chip->chipspecops->clear_objects=virtual_clear_objects;
516 chip->chipspecops->config_irqs=virtual_config_irqs;
517 chip->chipspecops->pre_read_config=virtual_pre_read_config;
518 chip->chipspecops->pre_write_config=virtual_pre_write_config;
519 chip->chipspecops->send_msg=virtual_send_msg;
520 chip->chipspecops->check_tx_stat=virtual_check_tx_stat;
521 chip->chipspecops->wakeup_tx=virtual_wakeup_tx;
522 chip->chipspecops->remote_request=virtual_remote_request;
523 chip->chipspecops->enable_configuration=virtual_enable_configuration;
524 chip->chipspecops->disable_configuration=virtual_disable_configuration;
525 chip->chipspecops->attach_to_chip=virtual_attach_to_chip;
526 chip->chipspecops->release_chip=virtual_release_chip;
527 chip->chipspecops->set_btregs=virtual_set_btregs;
528 chip->chipspecops->start_chip=virtual_start_chip;
529 chip->chipspecops->stop_chip=virtual_stop_chip;
530 chip->chipspecops->irq_handler=NULL;
531 chip->chipspecops->irq_accept=NULL;
537 * virtual_init_obj_data - Initialize message buffers
538 * @chip: Pointer to chip specific structure
539 * @objnr: Number of the message buffer
541 * Return Value: The function always returns zero
542 * File: src/virtual.c
544 int virtual_init_obj_data(struct canchip_t *chip, int objnr)
546 struct msgobj_t *obj=chip->msgobj[objnr];
547 obj->obj_base_addr=chip->chip_base_addr;
548 obj->tx_timeout.function=virtual_do_tx_timeout;
549 obj->tx_timeout.data=(unsigned long)obj;
554 * virtual_program_irq - program interrupts
555 * @candev: Pointer to candevice/board structure
557 * Return value: The function returns zero on success or %-ENODEV on failure
558 * File: src/virtual.c
560 int virtual_program_irq(struct candevice_t *candev)
565 int virtual_register(struct hwspecops_t *hwspecops)
567 hwspecops->request_io = virtual_request_io;
568 hwspecops->release_io = virtual_release_io;
569 hwspecops->reset = virtual_reset;
570 hwspecops->init_hw_data = virtual_init_hw_data;
571 hwspecops->init_chip_data = virtual_init_chip_data;
572 hwspecops->init_obj_data = virtual_init_obj_data;
573 hwspecops->write_register = NULL;
574 hwspecops->read_register = NULL;
575 hwspecops->program_irq = virtual_program_irq;