1 /****************************************************************************/
2 // Ingenieria Almudi (www.almudi.com)
3 // Ported to LinCAN by Jose Pascual RamÃrez (josepascual@almudi.com)
6 // Copyright (C) 2001,2002,2003,2004 PEAK System-Technik GmbH
8 // linux@peak-system.com
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.
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.
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.
25 // Maintainer(s): Klaus Hitschler (klaus.hitschler@gmx.de)
27 // Contributions: Marcel Offermans (marcel.offermans@luminis.nl)
28 // Philipp Baer (philipp.baer@informatik.uni-ulm.de)
29 /****************************************************************************/
31 /****************************************************************************/
33 // all parts to handle the interface specific parts of pcan-dongle
35 // Revision 1.38 2004/07/28 22:03:29 jose pascual
38 // Revision 1.37 2004/04/11 22:03:29 klaus
41 // Revision 1.36 2004/04/10 12:25:39 klaus
42 // merge polished between HEAD and kernel-2.6 branch
44 // Revision 1.35 2004/04/10 08:57:26 klaus
45 // merge finished between HEAD and kernel-2.6 branch
47 // Revision 1.32.2.1 2004/03/21 12:09:09 klaus
48 // first commit for branch to kernel 2.6 code
50 // Revision 1.34 2004/03/27 16:57:06 klaus
51 // modified for use with kernels <= 2.2.14
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
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
59 // Revision 1.31 2003/06/22 15:34:50 klaus
60 // added parts to support devfs provided by Philipp Baer (partially untested)
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
65 // Revision 1.28 2003/03/02 10:58:07 klaus
66 // merged USB thread into main path
68 // Revision 1.27 2003/03/02 10:58:07 klaus
69 // merged USB thread into main path
71 // Revision 1.26.2.5 2003/01/29 20:34:20 klaus
72 // release_20030129_a and release_20030129_u released
74 // Revision 1.26.2.4 2003/01/29 20:34:19 klaus
75 // release_20030129_a and release_20030129_u released
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
80 // Revision 1.26.2.2 2003/01/14 20:31:53 klaus
81 // read/write/minor assigment is working
83 /****************************************************************************/
85 /****************************************************************************/
89 #include "../include/can.h"
90 #include "../include/can_sysdep.h"
91 #include "../include/main.h"
92 #include "../include/sja1000p.h"
94 #include <linux/parport.h>
96 #include "../include/pcan_dongle.h"
100 /****************************************************************************/
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
108 typedef void (*PARPORT_IRQ_HANLDER)(CAN_IRQ_HANDLER_ARGS(irq_number, dev_id));
110 /****************************************************************************/
112 CAN_DEFINE_SPINLOCK(pcan_lock);
114 /****************************************************************************/
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
122 static unsigned char nibble_decode[32] =
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
130 struct DONGLE_PORT dongle_port;
132 char dongle_type[] = "epp_dongle";
133 //char dongle_type[] = "sp_dongle";
135 /****************************************************************************/
138 //----------------------------------------------------------------------------
139 // enable and disable irqs
140 static void _parport_disable_irq(struct DONGLE_PORT *dng)
142 u16 _PC_ = (u16)dng->dwPort + 2;
143 can_outb(can_inb(_PC_) & ~0x10, _PC_);
146 static void _parport_enable_irq(struct DONGLE_PORT *dng)
148 u16 _PC_ = (u16)dng->dwPort + 2;
149 can_outb(can_inb(_PC_) | 0x10, _PC_);
153 // functions for SP port
154 static u8 pcan_dongle_sp_readreg(struct DONGLE_PORT *dng, u8 port) // read a register
156 u16 _PA_ = (u16)dng->dwPort;
160 u8 irqEnable = can_inb(_PC_) & 0x10; // don't influence irqEnable
161 can_spin_irqflags_t flags;
163 can_spin_lock_irqsave(&pcan_lock, flags);
165 can_outb((0x0B ^ 0x0D) | irqEnable, _PC_);
166 can_outb((port & 0x1F) | 0x80, _PA_);
167 can_outb((0x0B ^ 0x0C) | irqEnable, _PC_);
168 b1=nibble_decode[can_inb(_PB_)>>3];
169 can_outb(0x40, _PA_);
170 b0=nibble_decode[can_inb(_PB_)>>3];
171 can_outb((0x0B ^ 0x0D) | irqEnable, _PC_);
173 can_spin_unlock_irqrestore(&pcan_lock, flags);
175 return (b1 << 4) | b0 ;
178 static void pcan_dongle_writereg(struct DONGLE_PORT *dng, u8 port, u8 data) // write a register
180 u16 _PA_ = (u16)dng->dwPort;
182 u8 irqEnable = can_inb(_PC_) & 0x10; // don't influence irqEnable
183 can_spin_irqflags_t flags;
185 can_spin_lock_irqsave(&pcan_lock, flags);
187 can_outb((0x0B ^ 0x0D) | irqEnable, _PC_);
188 can_outb(port & 0x1F, _PA_);
189 can_outb((0x0B ^ 0x0C) | irqEnable, _PC_);
190 can_outb(data, _PA_);
191 can_outb((0x0B ^ 0x0D) | irqEnable, _PC_);
193 can_spin_unlock_irqrestore(&pcan_lock, flags);
196 // functions for EPP port
197 static u8 pcan_dongle_epp_readreg(struct DONGLE_PORT *dng, u8 port) // read a register
199 u16 _PA_ = (u16)dng->dwPort;
202 u8 irqEnable = can_inb(_PC_) & 0x10; // don't influence irqEnable
203 can_spin_irqflags_t flags;
205 can_spin_lock_irqsave(&pcan_lock, flags);
207 can_outb((0x0B ^ 0x0F) | irqEnable, _PC_);
208 can_outb((port & 0x1F) | 0x80, _PA_);
209 can_outb((0x0B ^ 0x2E) | irqEnable, _PC_);
210 wert = can_inb(_PA_);
211 can_outb((0x0B ^ 0x0F) | irqEnable, _PC_);
213 can_spin_unlock_irqrestore(&pcan_lock, flags);
218 static int pcan_dongle_req_irq(struct DONGLE_PORT *dng)
220 if (dng->wInitStep == 3)
228 static void pcan_dongle_free_irq(struct DONGLE_PORT *dng)
230 if (dng->wInitStep == 4)
236 // release and probe functions
237 static int pcan_dongle_cleanup(struct DONGLE_PORT *dng)
239 DEBUGMSG("%s: pcan_dongle_cleanup()\n", DEVICE_NAME);
241 switch(dng->wInitStep)
243 case 4: pcan_dongle_free_irq(dng);
244 case 3: if (dng->wType == HW_DONGLE_SJA)
248 dng_devices = sp_devices + epp_devices;
251 parport_unregister_device(dng->pardev);
252 case 0: dng->wInitStep = 0;
258 // to switch epp on or restore register
259 static void setECR(struct DONGLE_PORT *dng)
261 u16 wEcr = dng->wEcr;
263 dng->ucOldECRContent = can_inb(wEcr);
264 can_outb((dng->ucOldECRContent & 0x1F) | 0x20, wEcr);
266 if (dng->ucOldECRContent == 0xff)
267 DEBUGMSG("%s: realy ECP mode configured?\n", DEVICE_NAME);
270 static void restoreECR(struct DONGLE_PORT *dng)
272 u16 wEcr = dng->wEcr;
274 can_outb(dng->ucOldECRContent, wEcr);
276 DEBUGMSG("%s: restore ECR\n", DEVICE_NAME);
279 static int pcan_dongle_probe(struct DONGLE_PORT *dng) // probe for type
283 DEBUGMSG("%s: pcan_dongle_probe() - PARPORT_SUBSYSTEM\n", DEVICE_NAME);
285 // probe does not probe for the sja1000 device here - this is done at sja1000_open()
286 p = parport_find_base(dng->dwPort);
289 DEBUGMSG("found no parport\n");
294 dng->pardev = parport_register_device(p, "can", NULL, NULL,
295 (PARPORT_IRQ_HANLDER)dng->chip->chipspecops->irq_handler,
296 0, (void *)dng->chip);
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);
304 DEBUGMSG("found no parport device\n");
313 // interface depended open and close
314 static int pcan_dongle_open(struct DONGLE_PORT *dng)
319 DEBUGMSG("%s: pcan_dongle_open()\n", DEVICE_NAME);
321 result = parport_claim(dng->pardev);
325 if (dng->pardev->port->irq == PARPORT_IRQ_NONE)
327 DEBUGMSG(KERN_ERR "%s: no irq associated to parport.\n", DEVICE_NAME);
332 DEBUGMSG(KERN_ERR "%s: can't claim parport.\n", DEVICE_NAME);
337 wPort = (u16)dng->dwPort;
339 // save old port contents
340 dng->ucOldDataContent = can_inb(wPort);
341 dng->ucOldControlContent = can_inb(wPort + 2);
343 // switch to epp mode if possible
344 if (dng->wType == HW_DONGLE_SJA_EPP)
348 _parport_enable_irq(dng); // parport_enable_irq(dng->pardev->port); not working since 2.4.18
354 static int pcan_dongle_release(struct DONGLE_PORT *dng)
356 u16 wPort = (u16)dng->dwPort;
358 DEBUGMSG("%s: pcan_dongle_release()\n", DEVICE_NAME);
361 _parport_disable_irq(dng); // parport_disable_irq(dng->pardev->port); not working since 2.4.18
363 if (dng->wType == HW_DONGLE_SJA_EPP)
366 // restore port state
367 can_outb(dng->ucOldDataContent, wPort);
368 can_outb(dng->ucOldControlContent, wPort + 2);
370 parport_release(dng->pardev);
375 int pcan_dongle_init(struct DONGLE_PORT *dng, u32 dwPort, u16 wIrq, char *type)
379 DEBUGMSG("%s: pcan_dongle_init(), dng_devices = %d\n", DEVICE_NAME, dng_devices);
383 dng->wType = (!strncmp(dongle_type, "sp", 4)) ? HW_DONGLE_SJA : HW_DONGLE_SJA_EPP;
385 // set this before any instructions, fill struct pcandev, part 1
388 // fill struct pcandev, 1st check if a default is set
391 // there's no default available
392 if (dng_devices >= DNG_DEFAULT_COUNT)
395 dng->dwPort = dng_ports[dng_devices];
398 dng->dwPort = dwPort;
402 if (dng_devices >= DNG_DEFAULT_COUNT)
405 dng->wIrq = dng_irqs[dng_devices];
410 if (dng->wType == HW_DONGLE_SJA)
412 dng->nMinor = PCAN_DNG_SP_MINOR_BASE + sp_devices;
413 dng->wEcr = 0; // set to anything
417 dng->nMinor = PCAN_DNG_EPP_MINOR_BASE + epp_devices;
418 dng->wEcr = (u16)dng->dwPort + 0x402;
421 // is the device really available?
422 if ((err = pcan_dongle_probe(dng)) < 0)
425 if (dng->wType == HW_DONGLE_SJA)
430 dng_devices = sp_devices + epp_devices;
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);
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
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
457 int pcan_dongle_request_io(struct candevice_t *candev)
461 dongle_port.chip = candev->chip[0];
463 res_init = pcan_dongle_init(&dongle_port, 0, 0, dongle_type);
469 * template_elease_io - free reserved io memory range
470 * @candev: pointer to candevice/board which releases io
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
480 int pcan_dongle_release_io(struct candevice_t *candev)
482 /* release I/O port */
483 pcan_dongle_release(&dongle_port);
485 pcan_dongle_cleanup(&dongle_port);
491 * template_reset - hardware reset routine
492 * @candev: Pointer to candevice/board structure
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
500 int pcan_dongle_reset(struct candevice_t *candev)
503 struct canchip_t *chip;
507 DEBUGMSG("Resetting pcan_dongle hardware ...\n");
508 for(chipnr=0;chipnr<candev->nr_sja1000_chips;chipnr++) {
509 chip=candev->chip[chipnr];
511 pcan_dongle_write_register(sjaMOD_RM, chip->chip_base_addr+SJAMOD);
514 cdr=pcan_dongle_read_register(chip->chip_base_addr+SJACDR);
515 pcan_dongle_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
517 pcan_dongle_write_register(0, chip->chip_base_addr+SJAIER);
520 pcan_dongle_write_register(0, chip->chip_base_addr+SJAMOD);
521 while (pcan_dongle_read_register(chip->chip_base_addr+SJAMOD)&sjaMOD_RM) {
523 CANMSG("Reset status timeout!\n");
524 CANMSG("Please check your hardware.\n");
528 pcan_dongle_write_register(0, chip->chip_base_addr+SJAMOD);
531 cdr = pcan_dongle_read_register(chip->chip_base_addr+SJACDR);
532 pcan_dongle_write_register(cdr|sjaCDR_PELICAN, chip->chip_base_addr+SJACDR);
534 pcan_dongle_write_register(0, chip->chip_base_addr+SJAIER);
539 #define RESET_ADDR 0x0
544 * template_init_hw_data - Initialize hardware cards
545 * @candev: Pointer to candevice/board structure
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
557 int pcan_dongle_init_hw_data(struct candevice_t *candev)
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;
569 #define CHIP_TYPE "sja1000p"
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
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
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
599 int pcan_dongle_init_chip_data(struct candevice_t *candev, int chipnr)
603 /* initialize common routines for the SJA1000 chip */
604 sja1000p_fill_chipspecops(candev->chip[chipnr]);
607 candev->chip[chipnr]->chip_type=CHIP_TYPE;
608 candev->chip[chipnr]->chip_base_addr=can_ioport2ioptr(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;
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
624 * template_init_obj_data - Initialize message buffers
625 * @chip: Pointer to chip specific structure
626 * @objnr: Number of the message buffer
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
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
640 int pcan_dongle_init_obj_data(struct canchip_t *chip, int objnr)
642 chip->msgobj[objnr]->obj_base_addr=chip->chip_base_addr;
643 chip->msgobj[objnr]->obj_flags=0;
649 * template_program_irq - program interrupts
650 * @candev: Pointer to candevice/board structure
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
660 int pcan_dongle_program_irq(struct candevice_t *candev)
664 pcan_dongle_req_irq(&dongle_port);
665 ret_open = pcan_dongle_open(&dongle_port);
672 * template_write_register - Low level write register routine
673 * @data: data to be written
674 * @address: memory address to write to
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
682 void pcan_dongle_write_register(unsigned data, can_ioptr_t address)
684 address -= dongle_port.chip->chip_base_addr; // it's in mutiplexed mode
686 pcan_dongle_writereg(&dongle_port, (u8) address, (u8) data); // write a register
688 // DEBUGMSG("Write Reg at: 0x%lx data 0x%x \n", address, (unsigned) data);
692 * template_read_register - Low level read register routine
693 * @address: memory address to read from
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
701 unsigned pcan_dongle_read_register(can_ioptr_t address)
705 address -= dongle_port.chip->chip_base_addr; // it's in mutiplexed mode
707 if (dongle_port.wType == HW_DONGLE_SJA)
708 val = pcan_dongle_sp_readreg(&dongle_port, (u8) address); // functions for SP port
710 val = pcan_dongle_epp_readreg(&dongle_port, (u8) address); // functions for EPP port
712 // DEBUGMSG("Read Reg at: 0x%lx data 0x%x \n", address, val);
714 return ((unsigned)val);
717 /* !!! Don't change this function !!! */
718 int pcan_dongle_register(struct hwspecops_t *hwspecops)
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;