X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/4a1f32c3421f6e8f1ea90192e4ef4074f09db891..04ac67cc3cac14cd601daacd0592121ec0b84012:/lincan/src/unican.c diff --git a/lincan/src/unican.c b/lincan/src/unican.c index 2347a67..ae2934a 100644 --- a/lincan/src/unican.c +++ b/lincan/src/unican.c @@ -1,10 +1,36 @@ -/* unican.c - * Linux CAN-bus device driver. - * Written for new CAN driver version by Pavel Pisa - OCERA team member - * email:pisa@cmp.felk.cvut.cz - * This software is released under the GPL-License. - * Version lincan-0.2 9 Jul 2003 - */ +/**************************************************************************/ +/* File: unican.c - Unicontrols PCAN,PCAN-PCI, VCAN boards support */ +/* */ +/* LinCAN - (Not only) Linux CAN bus driver */ +/* Copyright (C) 2002-2009 DCE FEE CTU Prague */ +/* Copyright (C) 2002-2009 Pavel Pisa */ +/* Funded by OCERA and FRESCOR IST projects */ +/* Based on CAN driver code by Arnaud Westenberg */ +/* */ +/* LinCAN is free software; you can redistribute it and/or modify it */ +/* under terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2, or (at your option) any */ +/* later version. LinCAN is distributed in the hope that it will be */ +/* useful, but WITHOUT ANY WARRANTY; without even the implied warranty */ +/* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ +/* General Public License for more details. You should have received a */ +/* copy of the GNU General Public License along with LinCAN; see file */ +/* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, */ +/* Cambridge, MA 02139, USA. */ +/* */ +/* To allow use of LinCAN in the compact embedded systems firmware */ +/* and RT-executives (RTEMS for example), main authors agree with next */ +/* special exception: */ +/* */ +/* Including LinCAN header files in a file, instantiating LinCAN generics */ +/* or templates, or linking other files with LinCAN objects to produce */ +/* an application image/executable, does not by itself cause the */ +/* resulting application image/executable to be covered by */ +/* the GNU General Public License. */ +/* This exception does not however invalidate any other reasons */ +/* why the executable file might be covered by the GNU Public License. */ +/* Publication of enhanced or derived LinCAN files is required although. */ +/**************************************************************************/ #include "../include/can.h" #include "../include/can_sysdep.h" @@ -29,26 +55,14 @@ static void unican_delay(long msdelay) } - -long unican_bus_latency(struct msgobj_t *obj) -{ - long latency; - latency=obj->hostchip->baudrate; - if(latency){ - latency=(long)HZ*1000/latency; - } - return latency; -} - - /* * * unican Chip Functionality * * */ -int unican_enable_configuration(struct chip_t *chip) +int unican_enable_configuration(struct canchip_t *chip) { return 0; } -int unican_disable_configuration(struct chip_t *chip) +int unican_disable_configuration(struct canchip_t *chip) { return 0; } @@ -60,13 +74,13 @@ int unican_disable_configuration(struct chip_t *chip) * Return Value: negative value reports error. * File: src/unican.c */ -int unican_chip_config(struct chip_t *chip) +int unican_chip_config(struct canchip_t *chip) { int ret; sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data; unican_delay(10); - + /* disable all card interrupts */ ret = cl2_int_mode(chipext, INT_MODE_ALL*0); if(ret != CL2_OK) { @@ -77,13 +91,13 @@ int unican_chip_config(struct chip_t *chip) if (chip->baudrate == 0) chip->baudrate=1000000; - + ret = chip->chipspecops->baud_rate(chip,chip->baudrate,chip->clock,0,75,0); if(ret < 0){ CANMSG("can not set baudrate\n"); return ret; } - + unican_delay(2); /* set interrupt inhibit time to 1 ms */ ret = cl2_set_iit(chipext, 10); @@ -100,7 +114,7 @@ int unican_chip_config(struct chip_t *chip) return -ENODEV; } unican_delay(1); - + /* enable all card interrupts */ ret = cl2_int_mode(chipext, INT_MODE_ALL); if(ret != CL2_OK) { @@ -125,7 +139,7 @@ int unican_chip_config(struct chip_t *chip) * Return Value: negative value reports error. * File: src/unican.c */ -int unican_extended_mask(struct chip_t *chip, unsigned long code, unsigned long mask) +int unican_extended_mask(struct canchip_t *chip, unsigned long code, unsigned long mask) { return 0; } @@ -142,7 +156,7 @@ int unican_extended_mask(struct chip_t *chip, unsigned long code, unsigned long * Return Value: negative value reports error. * File: src/unican.c */ -int unican_baud_rate(struct chip_t *chip, int rate, int clock, int sjw, +int unican_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw, int sampl_pt, int flags) { int ret; @@ -163,12 +177,12 @@ int unican_baud_rate(struct chip_t *chip, int rate, int clock, int sjw, case 1000000:bt_val = CL2_BITRATE_1M; break; default: return -EINVAL; } - + ret=cl2_set_bitrate(chipext,bt_val); if(ret == CL2_COMMAND_BUSY) return -EBUSY; if(ret != CL2_OK) return -EINVAL; unican_delay(2); - + return 0; } @@ -184,7 +198,7 @@ int unican_baud_rate(struct chip_t *chip, int rate, int clock, int sjw, * * File: src/unican.c */ -void unican_read(struct chip_t *chip, struct msgobj_t *obj) { +void unican_read(struct canchip_t *chip, struct msgobj_t *obj) { sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data; __u16 *ptr16; __u16 u; @@ -214,7 +228,7 @@ void unican_read(struct chip_t *chip, struct msgobj_t *obj) { obj->rx_msg.flags = 0; } - /*if ( !(u & (CL2_REMOTE_FRAME<<8)) ) + /*if ( !(u & (CL2_REMOTE_FRAME<<8)) ) obj->rx_msg.flags |= MSG_RTR;*/ obj->rx_msg.length = ( (u >> 4) & 0x000F ); @@ -239,7 +253,7 @@ void unican_read(struct chip_t *chip, struct msgobj_t *obj) { #else /* CAN_MSG_VERSION_2 */ obj->rx_msg.timestamp = timestamp; #endif /* CAN_MSG_VERSION_2 */ - + /* increment rx-buffer pointer */ if ( (chipext->rxBufBase + chipext->rxBufSize*16 ) <= (chipext->rxBufPtr += 16) ) { chipext->rxBufPtr = chipext->rxBufBase; @@ -259,7 +273,7 @@ void unican_read(struct chip_t *chip, struct msgobj_t *obj) { * Positive value indicates immediate reception of message. * File: src/unican.c */ -int unican_pre_read_config(struct chip_t *chip, struct msgobj_t *obj) +int unican_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj) { return 0; } @@ -274,7 +288,7 @@ int unican_pre_read_config(struct chip_t *chip, struct msgobj_t *obj) * Return Value: negative value reports error. * File: src/unican.c */ -int unican_pre_write_config(struct chip_t *chip, struct msgobj_t *obj, +int unican_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj, struct canmsg_t *msg) { return 0; @@ -291,7 +305,7 @@ int unican_pre_write_config(struct chip_t *chip, struct msgobj_t *obj, * Return Value: negative value reports error. * File: src/unican.c */ -int unican_send_msg(struct chip_t *chip, struct msgobj_t *obj, +int unican_send_msg(struct canchip_t *chip, struct msgobj_t *obj, struct canmsg_t *msg) { return 0; @@ -306,7 +320,7 @@ int unican_send_msg(struct chip_t *chip, struct msgobj_t *obj, * Zero value indicates finishing of all issued transmission requests. * File: src/unican.c */ -int unican_check_tx_stat(struct chip_t *chip) +int unican_check_tx_stat(struct canchip_t *chip) { return 0; } @@ -320,7 +334,7 @@ int unican_check_tx_stat(struct chip_t *chip) * Return Value: negative value reports error. * File: src/unican.c */ -int unican_set_btregs(struct chip_t *chip, unsigned short btr0, +int unican_set_btregs(struct canchip_t *chip, unsigned short btr0, unsigned short btr1) { int ret; @@ -342,7 +356,7 @@ int unican_set_btregs(struct chip_t *chip, unsigned short btr0, * Return Value: negative value reports error. * File: src/unican.c */ -int unican_start_chip(struct chip_t *chip) +int unican_start_chip(struct canchip_t *chip) { return 0; } @@ -354,11 +368,39 @@ int unican_start_chip(struct chip_t *chip) * Return Value: negative value reports error. * File: src/unican.c */ -int unican_stop_chip(struct chip_t *chip) +int unican_stop_chip(struct canchip_t *chip) +{ + return 0; +} + +/** + * unican_attach_to_chip: - attaches to the chip, setups registers and state + * @chip: pointer to chip state structure + * + * Return Value: negative value reports error. + * File: src/sja1000p.c + */ +int unican_attach_to_chip(struct canchip_t *chip) { return 0; } +/** + * unican_release_chip: - called before chip structure removal if %CHIP_ATTACHED is set + * @chip: pointer to chip state structure + * + * Return Value: negative value reports error. + * File: src/sja1000p.c + */ +int unican_release_chip(struct canchip_t *chip) +{ + sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data; + + unican_stop_chip(chip); + cl2_clear_interrupt(chipext); + + return 0; +} /** * unican_remote_request: - configures message object and asks for RTR message @@ -368,7 +410,7 @@ int unican_stop_chip(struct chip_t *chip) * Return Value: negative value reports error. * File: src/unican.c */ -int unican_remote_request(struct chip_t *chip, struct msgobj_t *obj) +int unican_remote_request(struct canchip_t *chip, struct msgobj_t *obj) { CANMSG("unican_remote_request not implemented\n"); return -ENOSYS; @@ -383,7 +425,7 @@ int unican_remote_request(struct chip_t *chip, struct msgobj_t *obj) * Return Value: negative value reports error. * File: src/unican.c */ -int unican_standard_mask(struct chip_t *chip, unsigned short code, +int unican_standard_mask(struct canchip_t *chip, unsigned short code, unsigned short mask) { CANMSG("unican_standard_mask not implemented\n"); @@ -397,7 +439,7 @@ int unican_standard_mask(struct chip_t *chip, unsigned short code, * Return Value: negative value reports error. * File: src/unican.c */ -int unican_clear_objects(struct chip_t *chip) +int unican_clear_objects(struct canchip_t *chip) { CANMSG("unican_clear_objects not implemented\n"); return -ENOSYS; @@ -411,7 +453,7 @@ int unican_clear_objects(struct chip_t *chip) * Return Value: negative value reports error. * File: src/unican.c */ -int unican_config_irqs(struct chip_t *chip, short irqs) +int unican_config_irqs(struct canchip_t *chip, short irqs) { CANMSG("unican_config_irqs not implemented\n"); @@ -429,7 +471,7 @@ int unican_config_irqs(struct chip_t *chip, short irqs) * unican_irq_write_handler() for transmit events. * File: src/unican.c */ -void unican_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) +void unican_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj) { int cmd; sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data; @@ -466,10 +508,10 @@ void unican_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot); if(cmd<0) return; /* No more messages to send */ - + cobid = obj->tx_slot->msg.id; - + if ( (obj->tx_slot->msg.flags & MSG_EXT) ) { /* 2.0B frame */ cobid <<= 3; } else { /* 2.0A frame */ @@ -483,10 +525,10 @@ void unican_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH; u = (len << 12) | (cobid & 0x00FF); - - if ( !(obj->tx_slot->msg.flags & MSG_RTR) ) + + if ( !(obj->tx_slot->msg.flags & MSG_RTR) ) u |= CL2_REMOTE_FRAME<<8; - if ( obj->tx_slot->msg.flags & MSG_EXT ) + if ( obj->tx_slot->msg.flags & MSG_EXT ) u |= CL2_EXT_FRAME<<8; unican_writew(u,ptr16++); @@ -508,7 +550,7 @@ void unican_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) u = ((cobid>>16) & 0xFF00) | CL2_MESSAGE_VALID; unican_writew(u,(__u16*)chipext->asyncTxBufPtr); - if ( (chipext->asyncTxBufBase + chipext->asyncTxBufSize*16) <= + if ( (chipext->asyncTxBufBase + chipext->asyncTxBufSize*16) <= (chipext->asyncTxBufPtr += 16) ) { chipext->asyncTxBufPtr = chipext->asyncTxBufBase; } @@ -524,14 +566,14 @@ void unican_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) /* Free transmitted slot */ canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot); obj->tx_slot=NULL; - + }while(1); - + return; } -void unican_irq_sync_activities(struct chip_t *chip, struct msgobj_t *obj) +void unican_irq_sync_activities(struct canchip_t *chip, struct msgobj_t *obj) { while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)) { @@ -558,11 +600,8 @@ void unican_irq_sync_activities(struct chip_t *chip, struct msgobj_t *obj) /** * unican_irq_handler: - interrupt service routine * @irq: interrupt vector number, this value is system specific - * @dev_id: driver private pointer registered at time of request_irq() call. - * The CAN driver uses this pointer to store relationship of interrupt - * to chip state structure - @struct chip_t - * @regs: system dependent value pointing to registers stored in exception frame - * + * @chip: pointer to chip state structure + * * Interrupt handler is activated when state of CAN controller chip changes, * there is message to be read or there is more space for new messages or * error occurs. The receive events results in reading of the message from @@ -570,9 +609,8 @@ void unican_irq_sync_activities(struct chip_t *chip, struct msgobj_t *obj) * message queues. * File: src/unican.c */ -can_irqreturn_t unican_irq_handler(int irq, void *dev_id, struct pt_regs *regs) +int unican_irq_handler(int irq, struct canchip_t *chip) { - struct chip_t *chip=(struct chip_t *)dev_id; sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data; struct msgobj_t *obj=chip->msgobj[0]; __u16 status; @@ -580,11 +618,16 @@ can_irqreturn_t unican_irq_handler(int irq, void *dev_id, struct pt_regs *regs) if(!(chip->flags&CHIP_CONFIGURED)) { CANMSG("unican_irq_handler: called for non-configured device\n"); - return CAN_IRQ_NONE; + return CANCHIP_IRQ_NONE; } - if (cl2_get_status(chipext, &status) == CL2_NO_REQUEST) - return CAN_IRQ_NONE; + if (cl2_get_status(chipext, &status) == CL2_NO_REQUEST) { + /* Reenable interrupts generation, this has to be even there, + * because irq_accept disables interrupts + */ + cl2_gen_interrupt(chipext); + return CANCHIP_IRQ_NONE; + } cl2_clear_interrupt(chipext); @@ -607,16 +650,35 @@ can_irqreturn_t unican_irq_handler(int irq, void *dev_id, struct pt_regs *regs) unican_read(chip, obj); } + /* Reenable interrupts generation */ cl2_gen_interrupt(chipext); - return CAN_IRQ_HANDLED; + return CANCHIP_IRQ_HANDLED; } +/** + * unican_irq_accept: - fast irq accept routine, blocks further interrupts + * @irq: interrupt vector number, this value is system specific + * @chip: pointer to chip state structure + * + * This routine only accepts interrupt reception and stops further + * incoming interrupts, but does not handle situation causing interrupt. + * File: src/unican.c + */ +int unican_irq_accept(int irq, struct canchip_t *chip) +{ + sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data; + + cl2_clear_interrupt(chipext); + + return CANCHIP_IRQ_ACCEPTED; +} + /*void unican_do_tx_timeout(unsigned long data) { struct msgobj_t *obj=(struct msgobj_t *)data; - + }*/ /** @@ -627,7 +689,7 @@ can_irqreturn_t unican_irq_handler(int irq, void *dev_id, struct pt_regs *regs) * Return Value: negative value reports error. * File: src/unican.c */ -int unican_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj) +int unican_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj) { can_preempt_disable(); @@ -657,16 +719,16 @@ int unican_wakeup_tx(struct chip_t *chip, struct msgobj_t *obj) */ int unican_request_io(struct candevice_t *candev) { - unsigned long remap_addr; + can_ioptr_t remap_addr; if (!can_request_mem_region(candev->io_addr,IO_RANGE,DEVICE_NAME " - unican")) { CANMSG("Unable to request IO-memory: 0x%lx\n",candev->io_addr); return -ENODEV; } - if ( !( remap_addr = (long) ioremap( candev->io_addr, IO_RANGE ) ) ) { + if ( !( remap_addr = ioremap( candev->io_addr, IO_RANGE ) ) ) { CANMSG("Unable to access I/O memory at: 0x%lx\n", candev->io_addr); can_release_mem_region(candev->io_addr,IO_RANGE); return -ENODEV; - + } can_base_addr_fixup(candev, remap_addr); DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1); @@ -682,7 +744,7 @@ int unican_request_io(struct candevice_t *candev) */ int unican_release_io(struct candevice_t *candev) { - iounmap((void*)candev->dev_base_addr); + iounmap(candev->dev_base_addr); can_release_mem_region(candev->io_addr,IO_RANGE); return 0; } @@ -698,9 +760,9 @@ int unican_reset(struct candevice_t *candev) { int ret; int i; - struct chip_t *chip = candev->chip[0]; + struct canchip_t *chip = candev->chip[0]; sCAN_CARD *chipext; - + if(chip->chip_data == NULL) { chip->chip_data = can_checked_malloc(sizeof(sCAN_CARD)); @@ -712,9 +774,9 @@ int unican_reset(struct candevice_t *candev) return -ENODEV; } } - + chipext = (sCAN_CARD *)chip->chip_data; - + i = 0; /* reset and test whether the card is present */ do { @@ -728,14 +790,14 @@ int unican_reset(struct candevice_t *candev) CANMSG("card check failed %d\n",ret); return -ENODEV; } - + /* start card firmware */ ret = cl2_start_firmware(chipext); if(ret != CL2_OK){ CANMSG("cl2_start_firmware returned %d\n",ret); return -ENODEV; } - + unican_delay(100); return 0; @@ -748,7 +810,7 @@ int unican_reset(struct candevice_t *candev) * Return Value: The function always returns zero * File: src/unican.c */ -int unican_init_hw_data(struct candevice_t *candev) +int unican_init_hw_data(struct candevice_t *candev) { candev->res_addr=0; candev->nr_82527_chips=0; @@ -759,8 +821,6 @@ int unican_init_hw_data(struct candevice_t *candev) return 0; } -#define CHIP_TYPE "unican" - /** * unican_init_chip_data - Initialize chips * @candev: Pointer to candevice/board structure @@ -771,15 +831,15 @@ int unican_init_hw_data(struct candevice_t *candev) */ int unican_init_chip_data(struct candevice_t *candev, int chipnr) { - struct chip_t *chip = candev->chip[chipnr]; - chip->chip_type = CHIP_TYPE; + struct canchip_t *chip = candev->chip[chipnr]; + chip->chip_type = "unican"; chip->chip_base_addr = 0; chip->clock = 10000000; chip->int_clk_reg = 0x0; chip->int_bus_reg = 0x0; chip->max_objects = 1; - chip->chip_base_addr=candev->io_addr; - + chip->chip_base_addr=candev->dev_base_addr; + CANMSG("initializing unican chip operations\n"); chip->chipspecops->chip_config=unican_chip_config; chip->chipspecops->baud_rate=unican_baud_rate; @@ -797,9 +857,12 @@ int unican_init_chip_data(struct candevice_t *candev, int chipnr) chip->chipspecops->enable_configuration=unican_enable_configuration; chip->chipspecops->disable_configuration=unican_disable_configuration; chip->chipspecops->set_btregs=unican_set_btregs; + chip->chipspecops->attach_to_chip=unican_attach_to_chip; + chip->chipspecops->release_chip=unican_release_chip; chip->chipspecops->start_chip=unican_start_chip; chip->chipspecops->stop_chip=unican_stop_chip; chip->chipspecops->irq_handler=unican_irq_handler; + chip->chipspecops->irq_accept=unican_irq_accept; return 0; } @@ -812,7 +875,7 @@ int unican_init_chip_data(struct candevice_t *candev, int chipnr) * Return Value: The function always returns zero * File: src/unican.c */ -int unican_init_obj_data(struct chip_t *chip, int objnr) +int unican_init_obj_data(struct canchip_t *chip, int objnr) { struct msgobj_t *obj=chip->msgobj[objnr]; obj->obj_base_addr=chip->chip_base_addr; @@ -854,6 +917,8 @@ int unican_register(struct hwspecops_t *hwspecops) int unican_pci_request_io(struct candevice_t *candev) { + can_ioptr_t remap_addr; + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21)) if(pci_request_region(candev->sysdevptr.pcidev, 0, "unican_pci") != 0){ CANMSG("Request of Unican PCI range failed\n"); @@ -866,12 +931,32 @@ int unican_pci_request_io(struct candevice_t *candev) } #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/ + candev->io_addr=pci_resource_start(candev->sysdevptr.pcidev,0); + candev->res_addr=candev->io_addr; + + if ( !( remap_addr = ioremap( candev->io_addr, IO_RANGE ) ) ) { + CANMSG("Unable to access I/O memory at: 0x%lx\n", candev->io_addr); + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21)) + pci_release_region(candev->sysdevptr.pcidev, 0); + #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/ + pci_release_regions(candev->sysdevptr.pcidev); + #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/ + return -ENODEV; + + } + can_base_addr_fixup(candev, remap_addr); + DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1); + DEBUGMSG("VMA: dev_base_addr: 0x%lx chip_base_addr: 0x%lx\n", + can_ioptr2ulong(candev->dev_base_addr), + can_ioptr2ulong(candev->chip[0]->chip_base_addr)); + return 0; } int unican_pci_release_io(struct candevice_t *candev) { + iounmap(candev->dev_base_addr); #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21)) pci_release_region(candev->sysdevptr.pcidev, 0); #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/ @@ -885,25 +970,26 @@ int unican_pci_init_hw_data(struct candevice_t *candev) { struct pci_dev *pcidev = NULL; - do { - pcidev = pci_find_device(UNICAN_PCI_VENDOR, UNICAN_PCI_ID, pcidev); - if(pcidev == NULL) return -ENODEV; - } while(can_check_dev_taken(pcidev)); - + pcidev = can_pci_get_next_untaken_device(UNICAN_PCI_VENDOR, UNICAN_PCI_ID); + if(pcidev == NULL) + return -ENODEV; + if (pci_enable_device (pcidev)){ printk(KERN_CRIT "Setup of Unican PCI failed\n"); + can_pci_dev_put(pcidev); return -EIO; } candev->sysdevptr.pcidev=pcidev; - + if(!(pci_resource_flags(pcidev,0)&IORESOURCE_MEM)){ printk(KERN_CRIT "Unican PCI region 0 is not MEM\n"); + can_pci_dev_put(pcidev); return -EIO; } - candev->dev_base_addr=pci_resource_start(pcidev,0); /*S5920*/ - candev->io_addr=candev->dev_base_addr; - candev->res_addr=candev->dev_base_addr; - + candev->io_addr=pci_resource_start(pcidev,0); + candev->res_addr=candev->io_addr; + candev->dev_base_addr=NULL; + /*candev->flags |= CANDEV_PROGRAMMABLE_IRQ;*/ candev->nr_82527_chips=0; @@ -913,12 +999,17 @@ int unican_pci_init_hw_data(struct candevice_t *candev) return 0; } +void unican_pci_done_hw_data(struct candevice_t *candev) +{ + struct pci_dev *pcidev = candev->sysdevptr.pcidev; + can_pci_dev_put(pcidev); +} int unican_pci_init_chip_data(struct candevice_t *candev, int chipnr) { int ret; candev->chip[chipnr]->chip_irq=candev->sysdevptr.pcidev->irq; - ret = unican_pci_init_chip_data(candev, chipnr); + ret = unican_init_chip_data(candev, chipnr); candev->chip[chipnr]->flags |= CHIP_IRQ_PCI; return ret; } @@ -929,6 +1020,7 @@ int unican_pci_register(struct hwspecops_t *hwspecops) hwspecops->release_io = unican_pci_release_io; hwspecops->reset = unican_reset; hwspecops->init_hw_data = unican_pci_init_hw_data; + hwspecops->done_hw_data = unican_pci_done_hw_data; hwspecops->init_chip_data = unican_pci_init_chip_data; hwspecops->init_obj_data = unican_init_obj_data; hwspecops->write_register = NULL; @@ -941,26 +1033,6 @@ int unican_pci_register(struct hwspecops_t *hwspecops) #ifdef CAN_ENABLE_VME_SUPPORT -int unican_vme_reset(struct candevice_t *candev) -{ - struct chip_t *chip = candev->chip[0]; - unican_writew(chip->chip_irq,chip->chip_base_addr+CL2_VME_INT_VECTOR); - return unican_reset(candev); -} - - -int unican_vme_register(struct hwspecops_t *hwspecops) -{ - hwspecops->request_io = unican_request_io; - hwspecops->release_io = unican_release_io; - hwspecops->reset = unican_vme_reset; - hwspecops->init_hw_data = unican_init_hw_data; - hwspecops->init_chip_data = unican_init_chip_data; - hwspecops->init_obj_data = unican_init_obj_data; - hwspecops->write_register = NULL; - hwspecops->read_register = NULL; - hwspecops->program_irq = unican_program_irq; - return 0; -} +#include "unican_vme.c" #endif /*CAN_ENABLE_VME_SUPPORT*/