]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/virtual.c
Actual driver code for directly mapped SJA1000 into PCI mem region 0.
[lincan.git] / lincan / src / virtual.c
1 /**************************************************************************/
2 /* File: virtual.c - virtual chip/board support                           */
3 /*                                                                        */
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>      */
9 /*                                                                        */
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.                                              */
20 /*                                                                        */
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:                                                     */
24 /*                                                                        */
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"
37
38
39 long virtual_bus_latency(struct msgobj_t *obj)
40 {
41         long latency;
42         latency=obj->hostchip->baudrate;
43         if(latency){
44                 latency=(long)HZ*1000/latency;
45         }
46         return latency;
47 }
48
49
50 /* * * Virtual Chip Functionality * * */
51
52 int virtual_enable_configuration(struct canchip_t *chip)
53 {
54         return 0;
55 }
56
57 int virtual_disable_configuration(struct canchip_t *chip)
58 {
59         return 0;
60 }
61
62 /**
63  * virtual_chip_config: - can chip configuration
64  * @chip: pointer to chip state structure
65  *
66  * Return Value: negative value reports error.
67  * File: src/virtual.c
68  */
69 int virtual_chip_config(struct canchip_t *chip)
70 {
71         return 0;
72 }
73
74 /**
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
79  *
80  * Return Value: negative value reports error.
81  * File: src/virtual.c
82  */
83 int virtual_extended_mask(struct canchip_t *chip, unsigned long code, unsigned  long mask)
84 {
85         return 0;
86 }
87
88 /**
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
96  *
97  * Return Value: negative value reports error.
98  * File: src/virtual.c
99  */
100 int virtual_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw,
101                                                         int sampl_pt, int flags)
102 {
103         return 0;
104 }
105
106 /**
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
110  *
111  * File: src/virtual.c
112  */
113 void virtual_read(struct canchip_t *chip, struct msgobj_t *obj) {
114
115 }
116
117 /**
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
121  *
122  * Return Value: negative value reports error.
123  *      Positive value indicates immediate reception of message.
124  * File: src/virtual.c
125  */
126 int virtual_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj)
127 {
128         return 0;
129 }
130
131 #define MAX_TRANSMIT_WAIT_LOOPS 10
132 /**
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
137  *
138  * Return Value: negative value reports error.
139  * File: src/virtual.c
140  */
141 int virtual_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
142                                                         struct canmsg_t *msg)
143 {
144         return 0;
145 }
146
147 /**
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
152  *
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
157  */
158 int virtual_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
159                                                         struct canmsg_t *msg)
160 {
161         return 0;
162 }
163
164 /**
165  * virtual_check_tx_stat: - checks state of transmission engine
166  * @chip: pointer to chip state structure
167  *
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
172  */
173 int virtual_check_tx_stat(struct canchip_t *chip)
174 {
175         return 0;
176 }
177
178 /**
179  * virtual_set_btregs: -  configures bitrate registers
180  * @chip: pointer to chip state structure
181  * @btr0: bitrate register 0
182  * @btr1: bitrate register 1
183  *
184  * Return Value: negative value reports error.
185  * File: src/virtual.c
186  */
187 int virtual_set_btregs(struct canchip_t *chip, unsigned short btr0,
188                                                         unsigned short btr1)
189 {
190         return 0;
191 }
192
193 /**
194  * virtual_stop_chip: -  starts chip message processing
195  * @chip: pointer to chip state structure
196  *
197  * Return Value: negative value reports error.
198  * File: src/virtual.c
199  */
200 int virtual_start_chip(struct canchip_t *chip)
201 {
202         return 0;
203 }
204
205 /**
206  * virtual_stop_chip: -  stops chip message processing
207  * @chip: pointer to chip state structure
208  *
209  * Return Value: negative value reports error.
210  * File: src/virtual.c
211  */
212 int virtual_stop_chip(struct canchip_t *chip)
213 {
214         return 0;
215 }
216
217 /**
218  * virtual_attach_to_chip: - attaches to the chip, setups registers and state
219  * @chip: pointer to chip state structure
220  *
221  * Return Value: negative value reports error.
222  * File: src/virtual.c
223  */
224 int virtual_attach_to_chip(struct canchip_t *chip)
225 {
226         return 0;
227 }
228
229 /**
230  * virtual_release_chip: - called before chip structure removal if %CHIP_ATTACHED is set
231  * @chip: pointer to chip state structure
232  *
233  * Return Value: negative value reports error.
234  * File: src/virtual.c
235  */
236 int virtual_release_chip(struct canchip_t *chip)
237 {
238         virtual_stop_chip(chip);
239         return 0;
240 }
241
242 /**
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
246  *
247  * Return Value: negative value reports error.
248  * File: src/virtual.c
249  */
250 int virtual_remote_request(struct canchip_t *chip, struct msgobj_t *obj)
251 {
252         CANMSG("virtual_remote_request not implemented\n");
253         return -ENOSYS;
254 }
255
256 /**
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
261  *
262  * Return Value: negative value reports error.
263  * File: src/virtual.c
264  */
265 int virtual_standard_mask(struct canchip_t *chip, unsigned short code,
266                 unsigned short mask)
267 {
268         CANMSG("virtual_standard_mask not implemented\n");
269         return -ENOSYS;
270 }
271
272 /**
273  * virtual_clear_objects: - clears state of all message object residing in chip
274  * @chip: pointer to chip state structure
275  *
276  * Return Value: negative value reports error.
277  * File: src/virtual.c
278  */
279 int virtual_clear_objects(struct canchip_t *chip)
280 {
281         CANMSG("virtual_clear_objects not implemented\n");
282         return -ENOSYS;
283 }
284
285 /**
286  * virtual_config_irqs: - tunes chip hardware interrupt delivery
287  * @chip: pointer to chip state structure
288  * @irqs: requested chip IRQ configuration
289  *
290  * Return Value: negative value reports error.
291  * File: src/virtual.c
292  */
293 int virtual_config_irqs(struct canchip_t *chip, short irqs)
294 {
295         CANMSG("virtual_config_irqs not implemented\n");
296         return -ENOSYS;
297 }
298
299 /**
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
303  *
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
309  */
310 void virtual_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
311 {
312
313 }
314
315 #define MAX_RETR 10
316
317 /**
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
324  *
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
329  * message queues.
330  * File: src/virtual.c
331  */
332 int virtual_irq_handler(int irq, struct canchip_t *chip)
333 {
334         return CANCHIP_IRQ_HANDLED;
335 }
336
337
338 void virtual_schedule_next(struct msgobj_t *obj)
339 {
340         int cmd;
341
342         can_preempt_disable();
343
344         can_msgobj_set_fl(obj,TX_REQUEST);
345
346         while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)){
347
348                 can_msgobj_clear_fl(obj,TX_REQUEST);
349
350                 cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot);
351                 if(cmd>=0) {
352                         mod_timer(&obj->tx_timeout,
353                                 jiffies+virtual_bus_latency(obj));
354                         DEBUGMSG("virtual: scheduled delivery\n");
355
356                 } else
357                         can_msgobj_clear_fl(obj,TX_LOCK);
358
359                 if(!can_msgobj_test_fl(obj,TX_REQUEST)) break;
360                 DEBUGMSG("TX looping in virtual_schedule_next\n");
361         }
362
363         can_preempt_enable();
364 }
365
366
367 void virtual_do_tx_timeout(unsigned long data)
368 {
369         struct msgobj_t *obj=(struct msgobj_t *)data;
370
371         if(obj->tx_slot) {
372                 /* fill CAN message timestamp */
373                 can_filltimestamp(&obj->tx_slot->msg.timestamp);
374
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);
379                 obj->tx_slot=NULL;
380                 DEBUGMSG("virtual: delayed delivery\n");
381         }
382         can_msgobj_clear_fl(obj,TX_LOCK);
383
384         virtual_schedule_next(obj);
385 }
386
387 /**
388  * virtual_wakeup_tx: - wakeups TX processing
389  * @chip: pointer to chip state structure
390  * @obj: pointer to message object structure
391  *
392  * Function is responsible for initiating message transmition.
393  * It is responsible for clearing of object TX_REQUEST flag
394  *
395  * Return Value: negative value reports error.
396  * File: src/virtual.c
397  */
398 int virtual_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
399 {
400         /* can_msgobj_set_fl(obj,TX_REQUEST); */
401
402         struct canque_edge_t *qedge;
403         struct canque_slot_t *slot;
404         int cmd;
405
406         can_msgobj_clear_fl(obj,TX_REQUEST);
407
408     #ifndef CAN_WITH_RTL
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){
413                         if(cmd==0) {
414                                 /* fill CAN message timestamp */
415                                 can_filltimestamp(&slot->msg.timestamp);
416
417                                 canque_filter_msg2edges(obj->qends, &slot->msg);
418                                 DEBUGMSG("virtual: direct delivery\n");
419                         }
420                         canque_free_outslot(obj->qends, qedge, slot);
421                 }
422     #ifndef CAN_WITH_RTL
423         } else {
424                 virtual_schedule_next(obj);
425         }
426     #endif /*CAN_WITH_RTL*/
427
428         return 0;
429 }
430
431
432 /* * * Virtual Board Functionality * * */
433
434 /**
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
438  *
439  * Return Value: The function returns zero on success or %-ENODEV on failure
440  * File: src/virtual.c
441  */
442 int virtual_request_io(struct candevice_t *candev)
443 {
444         return 0;
445 }
446
447 /**
448  * virtual_elease_io - free reserved io memory range
449  * @candev: pointer to candevice/board which releases io
450  *
451  * Return Value: The function always returns zero
452  * File: src/virtual.c
453  */
454 int virtual_release_io(struct candevice_t *candev)
455 {
456         return 0;
457 }
458
459 /**
460  * virtual_reset - hardware reset routine
461  * @candev: Pointer to candevice/board structure
462  *
463  * Return Value: The function returns zero on success or %-ENODEV on failure
464  * File: src/virtual.c
465  */
466 int virtual_reset(struct candevice_t *candev)
467 {
468         return 0;
469 }
470
471 /**
472  * virtual_init_hw_data - Initialize hardware cards
473  * @candev: Pointer to candevice/board structure
474  *
475  * Return Value: The function always returns zero
476  * File: src/virtual.c
477  */
478 int virtual_init_hw_data(struct candevice_t *candev)
479 {
480         candev->res_addr=0;
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;
485
486         return 0;
487 }
488
489 #define CHIP_TYPE "virtual"
490
491 /**
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
495  *
496  * Return Value: The function always returns zero
497  * File: src/virtual.c
498  */
499 int virtual_init_chip_data(struct candevice_t *candev, int chipnr)
500 {
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;
508
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;
532
533         return 0;
534 }
535
536 /**
537  * virtual_init_obj_data - Initialize message buffers
538  * @chip: Pointer to chip specific structure
539  * @objnr: Number of the message buffer
540  *
541  * Return Value: The function always returns zero
542  * File: src/virtual.c
543  */
544 int virtual_init_obj_data(struct canchip_t *chip, int objnr)
545 {
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;
550         return 0;
551 }
552
553 /**
554  * virtual_program_irq - program interrupts
555  * @candev: Pointer to candevice/board structure
556  *
557  * Return value: The function returns zero on success or %-ENODEV on failure
558  * File: src/virtual.c
559  */
560 int virtual_program_irq(struct candevice_t *candev)
561 {
562         return 0;
563 }
564
565 int virtual_register(struct hwspecops_t *hwspecops)
566 {
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;
576         return 0;
577 }