]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/pcan_dongle.c
The use of chip->chip_data is unnecessary, chip->hostdevice points to corresponding...
[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 CAN_DEFINE_SPINLOCK(pcan_lock);
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   can_spin_irqflags_t flags;
162
163   can_spin_lock_irqsave(&pcan_lock, flags);
164
165   outb((0x0B ^ 0x0D) | irqEnable, _PC_);
166   outb((port & 0x1F) | 0x80,      _PA_);
167   outb((0x0B ^ 0x0C) | irqEnable, _PC_);
168   b1=nibble_decode[inb(_PB_)>>3];
169   outb(0x40, _PA_);
170   b0=nibble_decode[inb(_PB_)>>3];
171   outb((0x0B ^ 0x0D) | irqEnable, _PC_);
172
173   can_spin_unlock_irqrestore(&pcan_lock, flags);
174
175   return  (b1 << 4) | b0 ;
176 }
177
178 static void pcan_dongle_writereg(struct DONGLE_PORT *dng, u8 port, u8 data) // write a register
179 {
180   u16 _PA_ = (u16)dng->dwPort;
181   u16 _PC_ = _PA_ + 2;
182   u8  irqEnable = inb(_PC_) & 0x10; // don't influence irqEnable
183   can_spin_irqflags_t flags;
184
185   can_spin_lock_irqsave(&pcan_lock, flags);
186
187   outb((0x0B ^ 0x0D) | irqEnable, _PC_);
188   outb(port & 0x1F,               _PA_);
189   outb((0x0B ^ 0x0C) | irqEnable, _PC_);
190   outb(data,                      _PA_);
191   outb((0x0B ^ 0x0D) | irqEnable, _PC_);
192
193   can_spin_unlock_irqrestore(&pcan_lock, flags);
194 }
195
196 // functions for EPP port
197 static u8 pcan_dongle_epp_readreg(struct DONGLE_PORT *dng, u8 port) // read a register
198 {
199   u16 _PA_ = (u16)dng->dwPort;
200   u16 _PC_ = _PA_ + 2;
201   u8  wert;
202   u8  irqEnable = inb(_PC_) & 0x10; // don't influence irqEnable
203   can_spin_irqflags_t flags;
204
205   can_spin_lock_irqsave(&pcan_lock, flags);
206
207   outb((0x0B ^ 0x0F) | irqEnable, _PC_);
208   outb((port & 0x1F) | 0x80,      _PA_);
209   outb((0x0B ^ 0x2E) | irqEnable, _PC_);
210   wert = inb(_PA_);
211   outb((0x0B ^ 0x0F) | irqEnable, _PC_);
212
213   can_spin_unlock_irqrestore(&pcan_lock, flags);
214
215   return wert;
216 }
217
218 static int pcan_dongle_req_irq(struct DONGLE_PORT *dng)
219 {
220   if (dng->wInitStep == 3)
221   {
222     dng->wInitStep++;
223   }
224
225   return 0;
226 }
227
228 static void pcan_dongle_free_irq(struct DONGLE_PORT *dng)
229 {
230   if (dng->wInitStep == 4)
231   {
232     dng->wInitStep--;
233   }
234 }
235
236 // release and probe functions
237 static int pcan_dongle_cleanup(struct DONGLE_PORT *dng)
238 {
239   DEBUGMSG("%s: pcan_dongle_cleanup()\n", DEVICE_NAME);
240
241   switch(dng->wInitStep)
242   {
243     case 4: pcan_dongle_free_irq(dng);
244     case 3: if (dng->wType == HW_DONGLE_SJA)
245               sp_devices--;
246             else
247               epp_devices--;
248             dng_devices = sp_devices + epp_devices;
249     case 2:
250     case 1:
251             parport_unregister_device(dng->pardev);
252     case 0: dng->wInitStep = 0;
253   }
254
255   return 0;
256 }
257
258 // to switch epp on or restore register
259 static void setECR(struct DONGLE_PORT *dng)
260 {
261         u16 wEcr = dng->wEcr;
262
263         dng->ucOldECRContent = inb(wEcr);
264         outb((dng->ucOldECRContent & 0x1F) | 0x20, wEcr);
265
266         if (dng->ucOldECRContent == 0xff)
267                 DEBUGMSG("%s: realy ECP mode configured?\n", DEVICE_NAME);
268 }
269
270 static void restoreECR(struct DONGLE_PORT *dng)
271 {
272   u16 wEcr = dng->wEcr;
273
274   outb(dng->ucOldECRContent, wEcr);
275
276   DEBUGMSG("%s: restore ECR\n", DEVICE_NAME);
277 }
278
279 static int pcan_dongle_probe(struct DONGLE_PORT *dng) // probe for type
280 {
281   struct parport *p;
282
283   DEBUGMSG("%s: pcan_dongle_probe() - PARPORT_SUBSYSTEM\n", DEVICE_NAME);
284   
285   // probe does not probe for the sja1000 device here - this is done at sja1000_open()
286   p = parport_find_base(dng->dwPort);
287   if (!p)
288   {
289     DEBUGMSG("found no parport\n");
290     return -ENXIO;
291   }
292   else
293   {
294        dng->pardev = parport_register_device(p, "can", NULL, NULL, 
295                           (PARPORT_IRQ_HANLDER)dng->chip->chipspecops->irq_handler,
296                           0, (void *)dng->chip);
297         
298 //    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",
299 //              dng->chip->chipspecops->irq_handler,
300 //              p,dng->chip,dng->pardev->port->irq, &sja1000p_irq_handler);
301                                       
302     if (!dng->pardev)
303     {
304       DEBUGMSG("found no parport device\n");
305       return -ENODEV;
306     }
307
308   }
309   
310   return 0;
311 }
312
313 // interface depended open and close
314 static int pcan_dongle_open(struct DONGLE_PORT *dng)
315 {
316   int result = 0;
317   u16 wPort;
318   
319   DEBUGMSG("%s: pcan_dongle_open()\n", DEVICE_NAME);
320   
321   result = parport_claim(dng->pardev);
322   
323   if (!result)
324   {
325     if (dng->pardev->port->irq == PARPORT_IRQ_NONE)
326     {
327       DEBUGMSG(KERN_ERR "%s: no irq associated to parport.\n", DEVICE_NAME);
328       result = -ENXIO;
329     }
330   }
331   else
332    DEBUGMSG(KERN_ERR "%s: can't claim parport.\n", DEVICE_NAME);        
333   
334   // save port state
335   if (!result)
336    {
337       wPort    = (u16)dng->dwPort;
338           
339      // save old port contents
340      dng->ucOldDataContent     = inb(wPort);
341      dng->ucOldControlContent  = inb(wPort + 2);
342           
343      // switch to epp mode if possible
344      if (dng->wType == HW_DONGLE_SJA_EPP)
345         setECR(dng); 
346   
347     // enable irqs
348     _parport_enable_irq(dng); // parport_enable_irq(dng->pardev->port); not working since 2.4.18
349   }     
350         
351   return result;
352 }
353
354 static int pcan_dongle_release(struct DONGLE_PORT *dng)
355 {
356   u16 wPort = (u16)dng->dwPort;
357
358   DEBUGMSG("%s: pcan_dongle_release()\n", DEVICE_NAME);
359   
360   // disable irqs
361   _parport_disable_irq(dng); // parport_disable_irq(dng->pardev->port); not working since 2.4.18
362
363   if (dng->wType == HW_DONGLE_SJA_EPP)
364     restoreECR(dng);
365     
366   // restore port state
367   outb(dng->ucOldDataContent, wPort);
368   outb(dng->ucOldControlContent, wPort + 2);
369       
370   parport_release(dng->pardev);
371   
372   return 0;
373 }
374
375 int  pcan_dongle_init(struct DONGLE_PORT *dng, u32 dwPort, u16 wIrq, char *type)
376 {
377   int err;
378   
379   DEBUGMSG("%s: pcan_dongle_init(), dng_devices = %d\n", DEVICE_NAME, dng_devices);
380   
381   dng->type = type;
382
383   dng->wType = (!strncmp(dongle_type, "sp", 4)) ? HW_DONGLE_SJA : HW_DONGLE_SJA_EPP;
384   
385   // set this before any instructions, fill struct pcandev, part 1 
386   dng->wInitStep   = 0;  
387         
388   // fill struct pcandev, 1st check if a default is set
389   if (!dwPort)
390   {
391     // there's no default available
392     if (dng_devices >= DNG_DEFAULT_COUNT)
393       return -ENODEV;
394     
395     dng->dwPort = dng_ports[dng_devices];
396   }
397   else
398     dng->dwPort = dwPort;
399   
400   if (!wIrq)
401   {
402     if (dng_devices >= DNG_DEFAULT_COUNT)
403       return -ENODEV;
404     
405     dng->wIrq   = dng_irqs[dng_devices];    
406   }
407   else
408     dng->wIrq   = wIrq;    
409   
410   if (dng->wType == HW_DONGLE_SJA)
411     {
412            dng->nMinor        = PCAN_DNG_SP_MINOR_BASE + sp_devices; 
413            dng->wEcr = 0; // set to anything
414     }
415   else
416     {
417             dng->nMinor        = PCAN_DNG_EPP_MINOR_BASE + epp_devices;  
418             dng->wEcr = (u16)dng->dwPort + 0x402;
419     }
420           
421         // is the device really available?              
422   if ((err = pcan_dongle_probe(dng)) < 0)
423     return err;
424   
425   if (dng->wType == HW_DONGLE_SJA)
426     sp_devices++;
427   else
428     epp_devices++;
429           
430   dng_devices = sp_devices + epp_devices;
431   
432   dng->wInitStep = 3;
433
434   DEBUGMSG(KERN_INFO "%s: %s device minor %d prepared (io=0x%04x,irq=%d)\n", DEVICE_NAME, 
435                                dng->type, dng->nMinor, dng->dwPort, dng->wIrq);
436         
437   return 0;
438 }
439
440
441
442
443 /**
444  * template_request_io: - reserve io or memory range for can board
445  * @candev: pointer to candevice/board which asks for io. Field @io_addr
446  *      of @candev is used in most cases to define start of the range
447  *
448  * The function template_request_io() is used to reserve the io-memory. If your
449  * hardware uses a dedicated memory range as hardware control registers you
450  * will have to add the code to reserve this memory as well. 
451  * %IO_RANGE is the io-memory range that gets reserved, please adjust according
452  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
453  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
454  * Return Value: The function returns zero on success or %-ENODEV on failure
455  * File: src/template.c
456  */
457 int pcan_dongle_request_io(struct candevice_t *candev)
458 {
459         int res_init;
460
461         dongle_port.chip = candev->chip[0];
462
463         res_init = pcan_dongle_init(&dongle_port, 0, 0, dongle_type);
464
465         return res_init;
466 }
467
468 /**
469  * template_elease_io - free reserved io memory range
470  * @candev: pointer to candevice/board which releases io
471  *
472  * The function template_release_io() is used to free reserved io-memory.
473  * In case you have reserved more io memory, don't forget to free it here.
474  * IO_RANGE is the io-memory range that gets released, please adjust according
475  * your hardware. Example: #define IO_RANGE 0x100 for i82527 chips or
476  * #define IO_RANGE 0x20 for sja1000 chips in basic CAN mode.
477  * Return Value: The function always returns zero
478  * File: src/template.c
479  */
480 int pcan_dongle_release_io(struct candevice_t *candev)
481 {
482         /* release I/O port */
483         pcan_dongle_release(&dongle_port);
484         
485         pcan_dongle_cleanup(&dongle_port);
486
487         return 0;
488 }
489
490 /**
491  * template_reset - hardware reset routine
492  * @candev: Pointer to candevice/board structure
493  *
494  * The function template_reset() is used to give a hardware reset. This is 
495  * rather hardware specific so I haven't included example code. Don't forget to 
496  * check the reset status of the chip before returning.
497  * Return Value: The function returns zero on success or %-ENODEV on failure
498  * File: src/template.c
499  */
500 int pcan_dongle_reset(struct candevice_t *candev)
501 {
502         int i=0;
503         struct canchip_t *chip;
504         int chipnr;
505         unsigned cdr;
506         
507         DEBUGMSG("Resetting pcan_dongle hardware ...\n");
508         for(chipnr=0;chipnr<candev->nr_sja1000_chips;chipnr++) {
509                 chip=candev->chip[chipnr];
510
511           pcan_dongle_write_register(sjaMOD_RM, chip->chip_base_addr+SJAMOD);
512           udelay(1000);
513         
514           cdr=pcan_dongle_read_register(chip->chip_base_addr+SJACDR);
515           pcan_dongle_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
516
517           pcan_dongle_write_register(0, chip->chip_base_addr+SJAIER);
518
519           i=20;
520           pcan_dongle_write_register(0, chip->chip_base_addr+SJAMOD);
521           while (pcan_dongle_read_register(chip->chip_base_addr+SJAMOD)&sjaMOD_RM) {
522                 if(!i--) {
523                         CANMSG("Reset status timeout!\n");
524                         CANMSG("Please check your hardware.\n");
525                         return -ENODEV;
526                 }
527                 udelay(1000);
528                 pcan_dongle_write_register(0, chip->chip_base_addr+SJAMOD);
529           }
530
531           cdr = pcan_dongle_read_register(chip->chip_base_addr+SJACDR);
532           pcan_dongle_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
533
534           pcan_dongle_write_register(0, chip->chip_base_addr+SJAIER);
535         }
536         return 0;
537 }
538
539 #define RESET_ADDR 0x0
540 #define NR_82527 0
541 #define NR_SJA1000 1
542
543 /**
544  * template_init_hw_data - Initialize hardware cards
545  * @candev: Pointer to candevice/board structure
546  *
547  * The function template_init_hw_data() is used to initialize the hardware
548  * structure containing information about the installed CAN-board.
549  * %RESET_ADDR represents the io-address of the hardware reset register.
550  * %NR_82527 represents the number of intel 82527 chips on the board.
551  * %NR_SJA1000 represents the number of philips sja1000 chips on the board.
552  * The flags entry can currently only be %CANDEV_PROGRAMMABLE_IRQ to indicate that
553  * the hardware uses programmable interrupts.
554  * Return Value: The function always returns zero
555  * File: src/template.c
556  */
557 int pcan_dongle_init_hw_data(struct candevice_t *candev) 
558 {
559         candev->res_addr=RESET_ADDR;
560         candev->nr_82527_chips=NR_82527;
561         candev->nr_sja1000_chips=NR_SJA1000;
562         candev->nr_all_chips=NR_82527+NR_SJA1000;
563 //      candev->flags &= ~CANDEV_PROGRAMMABLE_IRQ;
564         candev->flags |= CANDEV_PROGRAMMABLE_IRQ;
565
566         return 0;
567 }
568
569 #define CHIP_TYPE "sja1000p"
570 /**
571  * template_init_chip_data - Initialize chips
572  * @candev: Pointer to candevice/board structure
573  * @chipnr: Number of the CAN chip on the hardware card
574  *
575  * The function template_init_chip_data() is used to initialize the hardware
576  * structure containing information about the CAN chips.
577  * %CHIP_TYPE represents the type of CAN chip. %CHIP_TYPE can be "i82527" or
578  * "sja1000".
579  * The @chip_base_addr entry represents the start of the 'official' memory map
580  * of the installed chip. It's likely that this is the same as the @io_addr
581  * argument supplied at module loading time.
582  * The @clock entry holds the chip clock value in Hz.
583  * The entry @sja_cdr_reg holds hardware specific options for the Clock Divider
584  * register. Options defined in the %sja1000.h file:
585  * %CDR_CLKOUT_MASK, %CDR_CLK_OFF, %CDR_RXINPEN, %CDR_CBP, %CDR_PELICAN
586  * The entry @sja_ocr_reg holds hardware specific options for the Output Control
587  * register. Options defined in the %sja1000.h file:
588  * %OCR_MODE_BIPHASE, %OCR_MODE_TEST, %OCR_MODE_NORMAL, %OCR_MODE_CLOCK,
589  * %OCR_TX0_LH, %OCR_TX1_ZZ.
590  * The entry @int_clk_reg holds hardware specific options for the Clock Out
591  * register. Options defined in the %i82527.h file:
592  * %iCLK_CD0, %iCLK_CD1, %iCLK_CD2, %iCLK_CD3, %iCLK_SL0, %iCLK_SL1.
593  * The entry @int_bus_reg holds hardware specific options for the Bus 
594  * Configuration register. Options defined in the %i82527.h file:
595  * %iBUS_DR0, %iBUS_DR1, %iBUS_DT1, %iBUS_POL, %iBUS_CBY.
596  * Return Value: The function always returns zero
597  * File: src/template.c
598  */
599 int pcan_dongle_init_chip_data(struct candevice_t *candev, int chipnr)
600 {
601 //    if (chipnr == 0)
602      {
603         /* initialize common routines for the SJA1000 chip */
604         sja1000p_fill_chipspecops(candev->chip[chipnr]);
605
606
607         candev->chip[chipnr]->chip_type=CHIP_TYPE;
608         candev->chip[chipnr]->chip_base_addr=candev->io_addr;
609         candev->chip[chipnr]->clock = 16000000;
610         candev->chip[chipnr]->int_clk_reg = 0x0;
611         candev->chip[chipnr]->int_bus_reg = 0x0;
612         candev->chip[chipnr]->sja_cdr_reg = sjaCDR_CBP | sjaCDR_CLK_OFF;
613         candev->chip[chipnr]->sja_ocr_reg = sjaOCR_MODE_NORMAL | sjaOCR_TX0_LH;
614
615         candev->chip[chipnr]->flags |= CHIP_IRQ_CUSTOM;  // I don't want setup call request_irq 
616                                       // I'm going to do it through parport_register_device 
617
618      }
619
620     return 0;
621 }
622
623 /**
624  * template_init_obj_data - Initialize message buffers
625  * @chip: Pointer to chip specific structure
626  * @objnr: Number of the message buffer
627  *
628  * The function template_init_obj_data() is used to initialize the hardware
629  * structure containing information about the different message objects on the
630  * CAN chip. In case of the sja1000 there's only one message object but on the
631  * i82527 chip there are 15.
632  * The code below is for a i82527 chip and initializes the object base addresses
633  * The entry @obj_base_addr represents the first memory address of the message 
634  * object. In case of the sja1000 @obj_base_addr is taken the same as the chips
635  * base address.
636  * Unless the hardware uses a segmented memory map, flags can be set zero.
637  * Return Value: The function always returns zero
638  * File: src/template.c
639  */
640 int pcan_dongle_init_obj_data(struct canchip_t *chip, int objnr)
641 {
642         chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
643         chip->msgobj[objnr]->obj_flags=0;
644         
645         return 0;
646 }
647
648 /**
649  * template_program_irq - program interrupts
650  * @candev: Pointer to candevice/board structure
651  *
652  * The function template_program_irq() is used for hardware that uses 
653  * programmable interrupts. If your hardware doesn't use programmable interrupts
654  * you should not set the @candevices_t->flags entry to %CANDEV_PROGRAMMABLE_IRQ and 
655  * leave this function unedited. Again this function is hardware specific so 
656  * there's no example code.
657  * Return value: The function returns zero on success or %-ENODEV on failure
658  * File: src/template.c
659  */
660 int pcan_dongle_program_irq(struct candevice_t *candev)
661 {
662         int ret_open;
663
664         pcan_dongle_req_irq(&dongle_port);
665         ret_open = pcan_dongle_open(&dongle_port);
666
667         return ret_open;
668 }
669
670
671 /**
672  * template_write_register - Low level write register routine
673  * @data: data to be written
674  * @address: memory address to write to
675  *
676  * The function template_write_register() is used to write to hardware registers
677  * on the CAN chip. You should only have to edit this function if your hardware
678  * uses some specific write process.
679  * Return Value: The function does not return a value
680  * File: src/template.c
681  */
682 void pcan_dongle_write_register(unsigned data, unsigned long address)
683 {
684    address -= dongle_port.chip->chip_base_addr;  // it's in mutiplexed mode
685
686    pcan_dongle_writereg(&dongle_port, (u8) address, (u8) data); // write a register
687
688 //   DEBUGMSG("Write Reg at: 0x%lx data 0x%x \n", address, (unsigned) data);
689 }
690
691 /**
692  * template_read_register - Low level read register routine
693  * @address: memory address to read from
694  *
695  * The function template_read_register() is used to read from hardware registers
696  * on the CAN chip. You should only have to edit this function if your hardware
697  * uses some specific read process.
698  * Return Value: The function returns the value stored in @address
699  * File: src/template.c
700  */
701 unsigned pcan_dongle_read_register(unsigned long address)
702 {
703    u8 val;
704
705   address -= dongle_port.chip->chip_base_addr;  // it's in mutiplexed mode
706         
707   if (dongle_port.wType == HW_DONGLE_SJA)
708      val = pcan_dongle_sp_readreg(&dongle_port, (u8) address); // functions for SP port
709   else 
710      val = pcan_dongle_epp_readreg(&dongle_port, (u8) address); // functions for EPP port
711
712 //  DEBUGMSG("Read Reg at: 0x%lx data 0x%x \n", address, val);
713
714   return ((unsigned)val);
715 }
716
717 /* !!! Don't change this function !!! */
718 int pcan_dongle_register(struct hwspecops_t *hwspecops)
719 {
720         hwspecops->request_io = pcan_dongle_request_io;
721         hwspecops->release_io = pcan_dongle_release_io;
722         hwspecops->reset = pcan_dongle_reset;
723         hwspecops->init_hw_data = pcan_dongle_init_hw_data;
724         hwspecops->init_chip_data = pcan_dongle_init_chip_data;
725         hwspecops->init_obj_data = pcan_dongle_init_obj_data;
726         hwspecops->write_register = pcan_dongle_write_register;
727         hwspecops->read_register = pcan_dongle_read_register;
728         hwspecops->program_irq = pcan_dongle_program_irq;
729         return 0;
730 }
731
732