]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/pcan_dongle.c
To prevent future name collisions "chip_t" changed to "canchip_t"
[lincan.git] / lincan / src / pcan_dongle.c
1 /****************************************************************************/
2 // Ingenieria Almudi (www.almudi.com)
3 // Ported to LinCAN by Jose Pascual Ramírez (josepascual@almudi.com)
4 // 
5 //
6 // Copyright (C) 2001,2002,2003,2004  PEAK System-Technik GmbH
7 //
8 // linux@peak-system.com
9 // www.peak-system.com
10 //
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 //
25 // Maintainer(s): Klaus Hitschler (klaus.hitschler@gmx.de)
26 //
27 // Contributions: Marcel Offermans (marcel.offermans@luminis.nl)
28 //                Philipp Baer (philipp.baer@informatik.uni-ulm.de)
29 /****************************************************************************/
30
31 /****************************************************************************/
32 //
33 // all parts to handle the interface specific parts of pcan-dongle
34 //
35 // Revision 1.38  2004/07/28 22:03:29  jose pascual
36 // ported to LinCAN
37 //
38 // Revision 1.37  2004/04/11 22:03:29  klaus
39 // cosmetic changes
40 //
41 // Revision 1.36  2004/04/10 12:25:39  klaus
42 // merge polished between HEAD and kernel-2.6 branch
43 //
44 // Revision 1.35  2004/04/10 08:57:26  klaus
45 // merge finished between HEAD and kernel-2.6 branch
46 //
47 // Revision 1.32.2.1  2004/03/21 12:09:09  klaus
48 // first commit for branch to kernel 2.6 code
49 //
50 // Revision 1.34  2004/03/27 16:57:06  klaus
51 // modified for use with kernels <= 2.2.14
52 //
53 // Revision 1.33  2004/03/27 15:10:54  klaus
54 // prepared for use with gcc 3.x, modified for use with kernels < 2.2.4
55 //
56 // Revision 1.32  2004/03/04 18:50:08  klaus
57 // renamed PA,PB,PC to _PA_, ... to support (partially) cross-compiling for MIPS
58 //
59 // Revision 1.31  2003/06/22 15:34:50  klaus
60 // added parts to support devfs provided by Philipp Baer (partially untested)
61 //
62 // Revision 1.30  2003/06/04 19:26:15  klaus
63 // adapted to kernel 2.5.69 using GCC 3.2.3 (marcel), released release_20030604_x
64 //
65 // Revision 1.28  2003/03/02 10:58:07  klaus
66 // merged USB thread into main path
67 //
68 // Revision 1.27  2003/03/02 10:58:07  klaus
69 // merged USB thread into main path
70 //
71 // Revision 1.26.2.5  2003/01/29 20:34:20  klaus
72 // release_20030129_a and release_20030129_u released
73 //
74 // Revision 1.26.2.4  2003/01/29 20:34:19  klaus
75 // release_20030129_a and release_20030129_u released
76 //
77 // Revision 1.26.2.3  2003/01/28 23:28:26  klaus
78 // reorderd pcan_usb.c and pcan_usb_kernel.c, tidied up
79 //
80 // Revision 1.26.2.2  2003/01/14 20:31:53  klaus
81 // read/write/minor assigment is working
82 //
83 /****************************************************************************/
84
85 /****************************************************************************/
86 // INCLUDES
87
88
89 #include "../include/can.h"
90 #include "../include/can_sysdep.h"
91 #include "../include/main.h"
92 #include "../include/sja1000p.h"
93
94 #include <linux/parport.h>
95
96 #include "../include/pcan_dongle.h"
97
98
99
100 /****************************************************************************/
101 // DEFINES
102 #define PCAN_DNG_SP_MINOR_BASE  16  // starting point of minors for SP devices
103 #define PCAN_DNG_EPP_MINOR_BASE 24  // starting point of minors for EPP devices
104 #define DNG_PORT_SIZE            4  // the address range of the dongle-port
105 #define ECR_PORT_SIZE            1  // size of the associated ECR register
106 #define DNG_DEFAULT_COUNT        4  // count of defaults for init
107
108 typedef void (*PARPORT_IRQ_HANLDER)(int, void *, struct pt_regs *);
109
110 /****************************************************************************/
111 // GLOBALS
112 spinlock_t pcan_lock = SPIN_LOCK_UNLOCKED;
113
114 /****************************************************************************/
115 // LOCALS
116 static u16 dng_ports[] = {0x378, 0x278, 0x3bc, 0x2bc};
117 static u8  dng_irqs[]  = {7, 5, 7, 5};
118 static u16 dng_devices = 0;        // the number of accepted dng_devices
119 static u16 epp_devices = 0;        // ... epp_devices
120 static u16 sp_devices  = 0;        // ... sp_devices
121
122 static unsigned char nibble_decode[32] =
123 {
124   0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
125   0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
126   0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
127   0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7
128 };
129
130 struct DONGLE_PORT dongle_port;
131
132 char dongle_type[] = "epp_dongle";
133 //char dongle_type[] = "sp_dongle";
134
135 /****************************************************************************/
136 // CODE
137
138 //----------------------------------------------------------------------------
139 // enable and disable irqs
140 static void _parport_disable_irq(struct DONGLE_PORT *dng)
141 {
142   u16 _PC_ = (u16)dng->dwPort + 2;
143   outb(inb(_PC_) & ~0x10, _PC_);
144 }
145
146 static void _parport_enable_irq(struct DONGLE_PORT *dng)
147 {
148   u16 _PC_ = (u16)dng->dwPort + 2;
149   outb(inb(_PC_) | 0x10, _PC_);
150 }
151
152
153 // functions for SP port
154 static u8 pcan_dongle_sp_readreg(struct DONGLE_PORT *dng, u8 port) // read a register
155 {
156   u16 _PA_ = (u16)dng->dwPort;
157   u16 _PB_ = _PA_ + 1;
158   u16 _PC_ = _PB_ + 1;
159   u8  b0, b1 ;
160   u8  irqEnable = inb(_PC_) & 0x10; // don't influence irqEnable
161   unsigned long flags;
162
163   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
164   save_flags(flags);
165   cli();
166   #else
167   spin_lock_irqsave(&pcan_lock, flags);
168   #endif
169
170   outb((0x0B ^ 0x0D) | irqEnable, _PC_);
171   outb((port & 0x1F) | 0x80,      _PA_);
172   outb((0x0B ^ 0x0C) | irqEnable, _PC_);
173   b1=nibble_decode[inb(_PB_)>>3];
174   outb(0x40, _PA_);
175   b0=nibble_decode[inb(_PB_)>>3];
176   outb((0x0B ^ 0x0D) | irqEnable, _PC_);
177
178   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
179   restore_flags(flags);
180   #else
181   spin_unlock_irqrestore(&pcan_lock, flags);
182   #endif
183
184   return  (b1 << 4) | b0 ;
185 }
186
187 static void pcan_dongle_writereg(struct DONGLE_PORT *dng, u8 port, u8 data) // write a register
188 {
189   u16 _PA_ = (u16)dng->dwPort;
190   u16 _PC_ = _PA_ + 2;
191   u8  irqEnable = inb(_PC_) & 0x10; // don't influence irqEnable
192   unsigned long flags;
193
194   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
195   save_flags(flags);
196   cli();
197   #else
198   spin_lock_irqsave(&pcan_lock, flags);
199   #endif
200
201   outb((0x0B ^ 0x0D) | irqEnable, _PC_);
202   outb(port & 0x1F,               _PA_);
203   outb((0x0B ^ 0x0C) | irqEnable, _PC_);
204   outb(data,                      _PA_);
205   outb((0x0B ^ 0x0D) | irqEnable, _PC_);
206
207   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
208   restore_flags(flags);
209   #else
210   spin_unlock_irqrestore(&pcan_lock, flags);
211   #endif
212 }
213
214 // functions for EPP port
215 static u8 pcan_dongle_epp_readreg(struct DONGLE_PORT *dng, u8 port) // read a register
216 {
217   u16 _PA_ = (u16)dng->dwPort;
218   u16 _PC_ = _PA_ + 2;
219   u8  wert;
220   u8  irqEnable = inb(_PC_) & 0x10; // don't influence irqEnable
221   unsigned long flags;
222
223   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
224   save_flags(flags);
225   cli();
226   #else
227   spin_lock_irqsave(&pcan_lock, flags);
228   #endif
229
230   outb((0x0B ^ 0x0F) | irqEnable, _PC_);
231   outb((port & 0x1F) | 0x80,      _PA_);
232   outb((0x0B ^ 0x2E) | irqEnable, _PC_);
233   wert = inb(_PA_);
234   outb((0x0B ^ 0x0F) | irqEnable, _PC_);
235
236   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
237   restore_flags(flags);
238   #else
239   spin_unlock_irqrestore(&pcan_lock, flags);
240   #endif
241
242   return wert;
243 }
244
245 static int pcan_dongle_req_irq(struct DONGLE_PORT *dng)
246 {
247   if (dng->wInitStep == 3)
248   {
249     dng->wInitStep++;
250   }
251
252   return 0;
253 }
254
255 static void pcan_dongle_free_irq(struct DONGLE_PORT *dng)
256 {
257   if (dng->wInitStep == 4)
258   {
259     dng->wInitStep--;
260   }
261 }
262
263 // release and probe functions
264 static int pcan_dongle_cleanup(struct DONGLE_PORT *dng)
265 {
266   DEBUGMSG("%s: pcan_dongle_cleanup()\n", DEVICE_NAME);
267
268   switch(dng->wInitStep)
269   {
270     case 4: pcan_dongle_free_irq(dng);
271     case 3: if (dng->wType == HW_DONGLE_SJA)
272               sp_devices--;
273             else
274               epp_devices--;
275             dng_devices = sp_devices + epp_devices;
276     case 2:
277     case 1:
278             parport_unregister_device(dng->pardev);
279     case 0: dng->wInitStep = 0;
280   }
281
282   return 0;
283 }
284
285 // to switch epp on or restore register
286 static void setECR(struct DONGLE_PORT *dng)
287 {
288         u16 wEcr = dng->wEcr;
289
290         dng->ucOldECRContent = inb(wEcr);
291         outb((dng->ucOldECRContent & 0x1F) | 0x20, wEcr);
292
293         if (dng->ucOldECRContent == 0xff)
294                 DEBUGMSG("%s: realy ECP mode configured?\n", DEVICE_NAME);
295 }
296
297 static void restoreECR(struct DONGLE_PORT *dng)
298 {
299   u16 wEcr = dng->wEcr;
300
301   outb(dng->ucOldECRContent, wEcr);
302
303   DEBUGMSG("%s: restore ECR\n", DEVICE_NAME);
304 }
305
306 static int pcan_dongle_probe(struct DONGLE_PORT *dng) // probe for type
307 {
308   struct parport *p;
309
310   DEBUGMSG("%s: pcan_dongle_probe() - PARPORT_SUBSYSTEM\n", DEVICE_NAME);
311   
312   // probe does not probe for the sja1000 device here - this is done at sja1000_open()
313   p = parport_find_base(dng->dwPort);
314   if (!p)
315   {
316     DEBUGMSG("found no parport\n");
317     return -ENXIO;
318   }
319   else
320   {
321        dng->pardev = parport_register_device(p, "can", NULL, NULL, 
322                           (PARPORT_IRQ_HANLDER)dng->chip->chipspecops->irq_handler,
323                           0, (void *)dng->chip);
324         
325 //    DEBUGMSG("datos IRQ: irq_handler=0x%x p=0x%x dng->chip=0x%x dng->pardev->port->irq=0x%x irq_handler2=0x%x\n",
326 //              dng->chip->chipspecops->irq_handler,
327 //              p,dng->chip,dng->pardev->port->irq, &sja1000p_irq_handler);
328                                       
329     if (!dng->pardev)
330     {
331       DEBUGMSG("found no parport device\n");
332       return -ENODEV;
333     }
334
335   }
336   
337   return 0;
338 }
339
340 // interface depended open and close
341 static int pcan_dongle_open(struct DONGLE_PORT *dng)
342 {
343   int result = 0;
344   u16 wPort;
345   
346   DEBUGMSG("%s: pcan_dongle_open()\n", DEVICE_NAME);
347   
348   result = parport_claim(dng->pardev);
349   
350   if (!result)
351   {
352     if (dng->pardev->port->irq == PARPORT_IRQ_NONE)
353     {
354       DEBUGMSG(KERN_ERR "%s: no irq associated to parport.\n", DEVICE_NAME);
355       result = -ENXIO;
356     }
357   }
358   else
359    DEBUGMSG(KERN_ERR "%s: can't claim parport.\n", DEVICE_NAME);        
360   
361   // save port state
362   if (!result)
363    {
364       wPort    = (u16)dng->dwPort;
365           
366      // save old port contents
367      dng->ucOldDataContent     = inb(wPort);
368      dng->ucOldControlContent  = inb(wPort + 2);
369           
370      // switch to epp mode if possible
371      if (dng->wType == HW_DONGLE_SJA_EPP)
372         setECR(dng); 
373   
374     // enable irqs
375     _parport_enable_irq(dng); // parport_enable_irq(dng->pardev->port); not working since 2.4.18
376   }     
377         
378   return result;
379 }
380
381 static int pcan_dongle_release(struct DONGLE_PORT *dng)
382 {
383   u16 wPort = (u16)dng->dwPort;
384
385   DEBUGMSG("%s: pcan_dongle_release()\n", DEVICE_NAME);
386   
387   // disable irqs
388   _parport_disable_irq(dng); // parport_disable_irq(dng->pardev->port); not working since 2.4.18
389
390   if (dng->wType == HW_DONGLE_SJA_EPP)
391     restoreECR(dng);
392     
393   // restore port state
394   outb(dng->ucOldDataContent, wPort);
395   outb(dng->ucOldControlContent, wPort + 2);
396       
397   parport_release(dng->pardev);
398   
399   return 0;
400 }
401
402 int  pcan_dongle_init(struct DONGLE_PORT *dng, u32 dwPort, u16 wIrq, char *type)
403 {
404   int err;
405   
406   DEBUGMSG("%s: pcan_dongle_init(), dng_devices = %d\n", DEVICE_NAME, dng_devices);
407   
408   dng->type = type;
409
410   dng->wType = (!strncmp(dongle_type, "sp", 4)) ? HW_DONGLE_SJA : HW_DONGLE_SJA_EPP;
411   
412   // set this before any instructions, fill struct pcandev, part 1 
413   dng->wInitStep   = 0;  
414         
415   // fill struct pcandev, 1st check if a default is set
416   if (!dwPort)
417   {
418     // there's no default available
419     if (dng_devices >= DNG_DEFAULT_COUNT)
420       return -ENODEV;
421     
422     dng->dwPort = dng_ports[dng_devices];
423   }
424   else
425     dng->dwPort = dwPort;
426   
427   if (!wIrq)
428   {
429     if (dng_devices >= DNG_DEFAULT_COUNT)
430       return -ENODEV;
431     
432     dng->wIrq   = dng_irqs[dng_devices];    
433   }
434   else
435     dng->wIrq   = wIrq;    
436   
437   if (dng->wType == HW_DONGLE_SJA)
438     {
439            dng->nMinor        = PCAN_DNG_SP_MINOR_BASE + sp_devices; 
440            dng->wEcr = 0; // set to anything
441     }
442   else
443     {
444             dng->nMinor        = PCAN_DNG_EPP_MINOR_BASE + epp_devices;  
445             dng->wEcr = (u16)dng->dwPort + 0x402;
446     }
447           
448         // is the device really available?              
449   if ((err = pcan_dongle_probe(dng)) < 0)
450     return err;
451   
452   if (dng->wType == HW_DONGLE_SJA)
453     sp_devices++;
454   else
455     epp_devices++;
456           
457   dng_devices = sp_devices + epp_devices;
458   
459   dng->wInitStep = 3;
460
461   DEBUGMSG(KERN_INFO "%s: %s device minor %d prepared (io=0x%04x,irq=%d)\n", DEVICE_NAME, 
462                                dng->type, dng->nMinor, dng->dwPort, dng->wIrq);
463         
464   return 0;
465 }
466
467
468
469
470 /**
471  * template_request_io: - reserve io or memory range for can board
472  * @candev: pointer to candevice/board which asks for io. Field @io_addr
473  *      of @candev is used in most cases to define start of the range
474  *
475  * The function template_request_io() is used to reserve the io-memory. If your
476  * hardware uses a dedicated memory range as hardware control registers you
477  * will have to add the code to reserve this memory as well. 
478  * %IO_RANGE is the io-memory range that gets reserved, please adjust according
479  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
480  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
481  * Return Value: The function returns zero on success or %-ENODEV on failure
482  * File: src/template.c
483  */
484 int pcan_dongle_request_io(struct candevice_t *candev)
485 {
486         int res_init;
487
488         dongle_port.chip = candev->chip[0];
489
490         res_init = pcan_dongle_init(&dongle_port, 0, 0, dongle_type);
491
492         return res_init;
493 }
494
495 /**
496  * template_elease_io - free reserved io memory range
497  * @candev: pointer to candevice/board which releases io
498  *
499  * The function template_release_io() is used to free reserved io-memory.
500  * In case you have reserved more io memory, don't forget to free it here.
501  * IO_RANGE is the io-memory range that gets released, please adjust according
502  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
503  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
504  * Return Value: The function always returns zero
505  * File: src/template.c
506  */
507 int pcan_dongle_release_io(struct candevice_t *candev)
508 {
509         /* release I/O port */
510         pcan_dongle_release(&dongle_port);
511         
512         pcan_dongle_cleanup(&dongle_port);
513
514         return 0;
515 }
516
517 /**
518  * template_reset - hardware reset routine
519  * @candev: Pointer to candevice/board structure
520  *
521  * The function template_reset() is used to give a hardware reset. This is 
522  * rather hardware specific so I haven't included example code. Don't forget to 
523  * check the reset status of the chip before returning.
524  * Return Value: The function returns zero on success or %-ENODEV on failure
525  * File: src/template.c
526  */
527 int pcan_dongle_reset(struct candevice_t *candev)
528 {
529         int i=0;
530         struct canchip_t *chip;
531         int chipnr;
532         unsigned cdr;
533         
534         DEBUGMSG("Resetting pcan_dongle hardware ...\n");
535         for(chipnr=0;chipnr<candev->nr_sja1000_chips;chipnr++) {
536                 chip=candev->chip[chipnr];
537
538           pcan_dongle_write_register(sjaMOD_RM, chip->chip_base_addr+SJAMOD);
539           udelay(1000);
540         
541           cdr=pcan_dongle_read_register(chip->chip_base_addr+SJACDR);
542           pcan_dongle_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
543
544           pcan_dongle_write_register(0, chip->chip_base_addr+SJAIER);
545
546           i=20;
547           pcan_dongle_write_register(0, chip->chip_base_addr+SJAMOD);
548           while (pcan_dongle_read_register(chip->chip_base_addr+SJAMOD)&sjaMOD_RM) {
549                 if(!i--) {
550                         CANMSG("Reset status timeout!\n");
551                         CANMSG("Please check your hardware.\n");
552                         return -ENODEV;
553                 }
554                 udelay(1000);
555                 pcan_dongle_write_register(0, chip->chip_base_addr+SJAMOD);
556           }
557
558           cdr = pcan_dongle_read_register(chip->chip_base_addr+SJACDR);
559           pcan_dongle_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
560
561           pcan_dongle_write_register(0, chip->chip_base_addr+SJAIER);
562         }
563         return 0;
564 }
565
566 #define RESET_ADDR 0x0
567 #define NR_82527 0
568 #define NR_SJA1000 1
569
570 /**
571  * template_init_hw_data - Initialize hardware cards
572  * @candev: Pointer to candevice/board structure
573  *
574  * The function template_init_hw_data() is used to initialize the hardware
575  * structure containing information about the installed CAN-board.
576  * %RESET_ADDR represents the io-address of the hardware reset register.
577  * %NR_82527 represents the number of intel 82527 chips on the board.
578  * %NR_SJA1000 represents the number of philips sja1000 chips on the board.
579  * The flags entry can currently only be %CANDEV_PROGRAMMABLE_IRQ to indicate that
580  * the hardware uses programmable interrupts.
581  * Return Value: The function always returns zero
582  * File: src/template.c
583  */
584 int pcan_dongle_init_hw_data(struct candevice_t *candev) 
585 {
586         candev->res_addr=RESET_ADDR;
587         candev->nr_82527_chips=NR_82527;
588         candev->nr_sja1000_chips=NR_SJA1000;
589         candev->nr_all_chips=NR_82527+NR_SJA1000;
590 //      candev->flags &= ~CANDEV_PROGRAMMABLE_IRQ;
591         candev->flags |= CANDEV_PROGRAMMABLE_IRQ;
592
593         return 0;
594 }
595
596 #define CHIP_TYPE "sja1000p"
597 /**
598  * template_init_chip_data - Initialize chips
599  * @candev: Pointer to candevice/board structure
600  * @chipnr: Number of the CAN chip on the hardware card
601  *
602  * The function template_init_chip_data() is used to initialize the hardware
603  * structure containing information about the CAN chips.
604  * %CHIP_TYPE represents the type of CAN chip. %CHIP_TYPE can be "i82527" or
605  * "sja1000".
606  * The @chip_base_addr entry represents the start of the 'official' memory map
607  * of the installed chip. It's likely that this is the same as the @io_addr
608  * argument supplied at module loading time.
609  * The @clock entry holds the chip clock value in Hz.
610  * The entry @sja_cdr_reg holds hardware specific options for the Clock Divider
611  * register. Options defined in the %sja1000.h file:
612  * %CDR_CLKOUT_MASK, %CDR_CLK_OFF, %CDR_RXINPEN, %CDR_CBP, %CDR_PELICAN
613  * The entry @sja_ocr_reg holds hardware specific options for the Output Control
614  * register. Options defined in the %sja1000.h file:
615  * %OCR_MODE_BIPHASE, %OCR_MODE_TEST, %OCR_MODE_NORMAL, %OCR_MODE_CLOCK,
616  * %OCR_TX0_LH, %OCR_TX1_ZZ.
617  * The entry @int_clk_reg holds hardware specific options for the Clock Out
618  * register. Options defined in the %i82527.h file:
619  * %iCLK_CD0, %iCLK_CD1, %iCLK_CD2, %iCLK_CD3, %iCLK_SL0, %iCLK_SL1.
620  * The entry @int_bus_reg holds hardware specific options for the Bus 
621  * Configuration register. Options defined in the %i82527.h file:
622  * %iBUS_DR0, %iBUS_DR1, %iBUS_DT1, %iBUS_POL, %iBUS_CBY.
623  * Return Value: The function always returns zero
624  * File: src/template.c
625  */
626 int pcan_dongle_init_chip_data(struct candevice_t *candev, int chipnr)
627 {
628 //    if (chipnr == 0)
629      {
630         /* initialize common routines for the SJA1000 chip */
631         sja1000p_fill_chipspecops(candev->chip[chipnr]);
632
633
634         candev->chip[chipnr]->chip_type=CHIP_TYPE;
635         candev->chip[chipnr]->chip_base_addr=candev->io_addr;
636         candev->chip[chipnr]->clock = 16000000;
637         candev->chip[chipnr]->int_clk_reg = 0x0;
638         candev->chip[chipnr]->int_bus_reg = 0x0;
639         candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF;
640         candev->chip[chipnr]->sja_ocr_reg = sjaOCR_MODE_NORMAL | sjaOCR_TX0_LH;
641
642         candev->chip[chipnr]->flags |= CHIP_IRQ_VME;  // I don't want setup call request_irq 
643                                       // I'm going to do it through parport_register_device 
644
645      }
646
647     return 0;
648 }
649
650 /**
651  * template_init_obj_data - Initialize message buffers
652  * @chip: Pointer to chip specific structure
653  * @objnr: Number of the message buffer
654  *
655  * The function template_init_obj_data() is used to initialize the hardware
656  * structure containing information about the different message objects on the
657  * CAN chip. In case of the sja1000 there's only one message object but on the
658  * i82527 chip there are 15.
659  * The code below is for a i82527 chip and initializes the object base addresses
660  * The entry @obj_base_addr represents the first memory address of the message 
661  * object. In case of the sja1000 @obj_base_addr is taken the same as the chips
662  * base address.
663  * Unless the hardware uses a segmented memory map, flags can be set zero.
664  * Return Value: The function always returns zero
665  * File: src/template.c
666  */
667 int pcan_dongle_init_obj_data(struct canchip_t *chip, int objnr)
668 {
669         chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
670         chip->msgobj[objnr]->obj_flags=0;
671         
672         return 0;
673 }
674
675 /**
676  * template_program_irq - program interrupts
677  * @candev: Pointer to candevice/board structure
678  *
679  * The function template_program_irq() is used for hardware that uses 
680  * programmable interrupts. If your hardware doesn't use programmable interrupts
681  * you should not set the @candevices_t->flags entry to %CANDEV_PROGRAMMABLE_IRQ and 
682  * leave this function unedited. Again this function is hardware specific so 
683  * there's no example code.
684  * Return value: The function returns zero on success or %-ENODEV on failure
685  * File: src/template.c
686  */
687 int pcan_dongle_program_irq(struct candevice_t *candev)
688 {
689         int ret_open;
690
691         pcan_dongle_req_irq(&dongle_port);
692         ret_open = pcan_dongle_open(&dongle_port);
693
694         return ret_open;
695 }
696
697
698 /**
699  * template_write_register - Low level write register routine
700  * @data: data to be written
701  * @address: memory address to write to
702  *
703  * The function template_write_register() is used to write to hardware registers
704  * on the CAN chip. You should only have to edit this function if your hardware
705  * uses some specific write process.
706  * Return Value: The function does not return a value
707  * File: src/template.c
708  */
709 void pcan_dongle_write_register(unsigned data, unsigned long address)
710 {
711    address -= dongle_port.chip->chip_base_addr;  // it's in mutiplexed mode
712
713    pcan_dongle_writereg(&dongle_port, (u8) address, (u8) data); // write a register
714
715 //   DEBUGMSG("Write Reg at: 0x%lx data 0x%x \n", address, (unsigned) data);
716 }
717
718 /**
719  * template_read_register - Low level read register routine
720  * @address: memory address to read from
721  *
722  * The function template_read_register() is used to read from hardware registers
723  * on the CAN chip. You should only have to edit this function if your hardware
724  * uses some specific read process.
725  * Return Value: The function returns the value stored in @address
726  * File: src/template.c
727  */
728 unsigned pcan_dongle_read_register(unsigned long address)
729 {
730    u8 val;
731
732   address -= dongle_port.chip->chip_base_addr;  // it's in mutiplexed mode
733         
734   if (dongle_port.wType == HW_DONGLE_SJA)
735      val = pcan_dongle_sp_readreg(&dongle_port, (u8) address); // functions for SP port
736   else 
737      val = pcan_dongle_epp_readreg(&dongle_port, (u8) address); // functions for EPP port
738
739 //  DEBUGMSG("Read Reg at: 0x%lx data 0x%x \n", address, val);
740
741   return ((unsigned)val);
742 }
743
744 /* !!! Don't change this function !!! */
745 int pcan_dongle_register(struct hwspecops_t *hwspecops)
746 {
747         hwspecops->request_io = pcan_dongle_request_io;
748         hwspecops->release_io = pcan_dongle_release_io;
749         hwspecops->reset = pcan_dongle_reset;
750         hwspecops->init_hw_data = pcan_dongle_init_hw_data;
751         hwspecops->init_chip_data = pcan_dongle_init_chip_data;
752         hwspecops->init_obj_data = pcan_dongle_init_obj_data;
753         hwspecops->write_register = pcan_dongle_write_register;
754         hwspecops->read_register = pcan_dongle_read_register;
755         hwspecops->program_irq = pcan_dongle_program_irq;
756         return 0;
757 }
758
759