X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/90b3359a796fd552c6b1063986e820b020d0d0ec..HEAD:/lincan/src/ipci165.c diff --git a/lincan/src/ipci165.c b/lincan/src/ipci165.c index 2a1f7c4..bff48dd 100644 --- a/lincan/src/ipci165.c +++ b/lincan/src/ipci165.c @@ -1,10 +1,37 @@ -/* ipci165.c - * Linux CAN-bus device driver for IXXAT iPC-I 165 (PCI) compatible HW. - * Written for new CAN driver version by Radim Kalas - * email:kalas@unicontrols.cz - * This software is released under the GPL-License. - * Version lincan-0.3 17 Jun 2004 - */ +/**************************************************************************/ +/* File: ipci165.c - support for IXXAT iPC-I 165 (PCI) compatible HW */ +/* */ +/* LinCAN - (Not only) Linux CAN bus driver */ +/* Copyright (C) 2002-2009 DCE FEE CTU Prague */ +/* Copyright (C) 2002-2009 Pavel Pisa */ +/* Copyright (C) 2004-2005 Radim Kalas */ +/* 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" @@ -465,12 +492,12 @@ int ipci165_set_btregs(struct canchip_t *chip, unsigned short btr0, DEBUGMSG ("ipci165_set_btregs[%i]: btr0=%02x, btr1=%02x\n",chip->chip_idx, (unsigned)btr0,(unsigned)btr1); - + /* configure the chip */ data[0] = chip->chip_idx; data[1] = btr0; data[2] = btr1; - + size = 1; if (bci_command(chip->hostdevice, CMD_INIT_CAN, 3, data) || bci_response(chip->hostdevice, CMD_INIT_CAN, &size, data) || @@ -495,10 +522,10 @@ int ipci165_start_chip(struct canchip_t *chip) int size; DEBUGMSG ("ipci165_start_chip[%i]\n",chip->chip_idx); - + /* start CAN */ data[0] = chip->chip_idx; - + size = 1; if (bci_command(chip->hostdevice, CMD_START_CAN, 1, data) || bci_response(chip->hostdevice, CMD_START_CAN, &size, data) || @@ -523,10 +550,10 @@ int ipci165_stop_chip(struct canchip_t *chip) int size; DEBUGMSG ("ipci165_stop_chip[%i]\n",chip->chip_idx); - + /* configure the chip */ data[0] = chip->chip_idx; - + size = 1; if (bci_command(chip->hostdevice, CMD_STOP_CAN, 1, data) || bci_response(chip->hostdevice, CMD_STOP_CAN, &size, data) || @@ -642,7 +669,7 @@ void ipci165_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj) obj->rx_msg.flags = (frame_info & BCI_MSG_FRAME_RTR ? MSG_RTR : 0); obj->rx_msg.cob = 0; obj->rx_msg.timestamp.tv_sec = 0; - obj->rx_msg.timestamp.tv_usec = + obj->rx_msg.timestamp.tv_usec = BCI_TIMESTAMP_RES * can_readl(msg_addr + BCI_MSG_TIMESTAMP); /* BCI_TIMESTAMP_RES * le32_to_cpu(can_readl(msg_addr + BCI_MSG_TIMESTAMP)); */ @@ -678,7 +705,7 @@ void ipci165_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj) DEBUGMSG ("ipci165_irq_read_handler[%i]: CAN status=%04x\n",chip->chip_idx, status); /* wake up the reset thread if the CAN is in bus off */ - if (status & BCI_CAN_STATUS_BUS_OFF) + if (status & BCI_CAN_STATUS_BUS_OFF) { CANMSG ("BUS-OFF detected! Restarting\n"); set_bit(CHIP_FLAG_BUS_OFF,&chip_data->flags); @@ -818,9 +845,9 @@ void ipci165_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj) */ void ipci165_irq_sync_activities(struct canchip_t *chip, struct msgobj_t *obj) { - while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)) + while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)) { - if(can_msgobj_test_and_clear_fl(obj,TX_REQUEST)) + if(can_msgobj_test_and_clear_fl(obj,TX_REQUEST)) { ipci165_irq_write_handler(chip, obj); } @@ -839,14 +866,14 @@ void ipci165_irq_sync_activities(struct canchip_t *chip, struct msgobj_t *obj) * @chip: pointer to chip state structure * * The main purpose of this function is to perform all necessary channel - * operations as a reaction on signalled interrupt. + * operations as a reaction on signalled interrupt. * File: src/ipci165.c */ void ipci165_irq_chip_handler(struct canchip_t *chip) { struct msgobj_t *obj = chip->msgobj[0]; struct ipci165_chip_t *chip_data = chip->chip_data; - struct bci_queue_t *queue; + struct bci_queue_t *queue; DEBUGMSG ("ipci165_irq_chip_handler[%i]\n",chip->chip_idx); @@ -877,7 +904,7 @@ void ipci165_irq_chip_handler(struct canchip_t *chip) * The CAN driver uses this pointer to store relationship of interrupt * to chip state structure - @struct canchip_t * @regs: system dependent value pointing to registers stored in exception frame - * + * * The interrupt handler is activated when the ipci165 controller generates * an interrupt as a reaction an internal state change. The interrupt is * acknowledged and ipci165_irq_chip_handler is called for every channel. @@ -1062,12 +1089,12 @@ int ipci165_request_io(struct candevice_t *candev) { #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/ - if ((candev->dev_base_addr = ioremap(dpram_addr, + if ((candev->dev_base_addr = ioremap(dpram_addr, pci_resource_len(candev->sysdevptr.pcidev,2)))) { DEBUGMSG ("ipci165_request_io: dpram remapped to 0x%lx\n", candev->dev_base_addr); - if ((candev->aux_base_addr = ioremap(crm_addr, + if ((candev->aux_base_addr = ioremap(crm_addr, pci_resource_len(candev->sysdevptr.pcidev,0)))) { DEBUGMSG ("ipci165_request_io: crm remapped to 0x%lx\n", can_ioptr2ulong(candev->aux_base_addr)); @@ -1116,7 +1143,7 @@ int ipci165_release_io(struct candevice_t *candev) { struct ipci165_chip_t *chip_data; int i; - + /* disable irq on HW */ ipci165_disconnect_irq(candev); @@ -1161,7 +1188,7 @@ int ipci165_download_fw(struct candevice_t *candev) DEBUGMSG ("ipci165_download_fw\n"); - /* read name and version */ + /* read name and version */ memcpy_fromio (board_name, dpram_addr + BOARD_NAME_OFS, BOARD_NAME_LEN); board_name[BOARD_NAME_LEN] = 0; @@ -1331,7 +1358,7 @@ int ipci165_reset(struct candevice_t *candev) candev->nr_all_chips = chips; canchip_done(candev->chip[1]); - } else CANMSG ("Chip 2 Type: %s\n",buffer+OF_BOARD_INFO_CHIP2_TYPE); + } else CANMSG ("Chip 2 Type: %s\n",buffer+OF_BOARD_INFO_CHIP2_TYPE); /* start kernel threads */ for (i = 0 ; i < chips ; i++) @@ -1356,21 +1383,20 @@ int ipci165_reset(struct candevice_t *candev) int ipci165_init_hw_data(struct candevice_t *candev) { struct pci_dev *pcidev = NULL; - unsigned short SubsystemID; DEBUGMSG ("ipci165_init_hw_data\n"); /* find iPC-I 165 on PCI bus */ do { - pcidev = pci_find_device(IPCI165_VENDOR_ID, IPCI165_DEVICE_ID, pcidev); - if(pcidev == NULL) return -ENODEV; + pcidev = can_pci_get_device(IPCI165_VENDOR_ID, IPCI165_DEVICE_ID, pcidev); + if(pcidev == NULL) + return -ENODEV; /* check subvendor ID */ - pci_read_config_word (pcidev, PCI_SUBSYSTEM_ID, &SubsystemID); - if ((SubsystemID != IPCI165_SUBSYSTEM_ID) && - (SubsystemID != CP350_SUBSYSTEM_ID)) - break; + if ((pcidev->subsystem_vendor != IPCI165_SUBSYSTEM_ID) && + (pcidev->subsystem_vendor != CP350_SUBSYSTEM_ID)) + continue; } while(can_check_dev_taken(pcidev)); @@ -1378,6 +1404,7 @@ int ipci165_init_hw_data(struct candevice_t *candev) if (pci_enable_device (pcidev)) { CANMSG ("Cannot enable PCI device\n"); + can_pci_dev_put(pcidev); return -EIO; } @@ -1388,7 +1415,7 @@ int ipci165_init_hw_data(struct candevice_t *candev) /* we do not know yet, whether our HW has one or two chan chips. Let's prepare configuration for maximal configuration = 2. This will be corrected later on */ - candev->nr_all_chips=2; + candev->nr_all_chips=2; candev->flags |= CANDEV_PROGRAMMABLE_IRQ*0; /* initialize device spinlock */ can_spin_lock_init(&candev->device_lock); @@ -1396,6 +1423,12 @@ int ipci165_init_hw_data(struct candevice_t *candev) return 0; } +void ipci165_done_hw_data(struct candevice_t *candev) +{ + struct pci_dev *pcidev = candev->sysdevptr.pcidev; + can_pci_dev_put(pcidev); +} + #define CHIP_TYPE "ipci165" /** @@ -1486,9 +1519,9 @@ int ipci165_init_chip_data(struct candevice_t *candev, int chipnr) int ipci165_init_obj_data(struct canchip_t *chip, int objnr) { struct msgobj_t *obj=chip->msgobj[objnr]; - + DEBUGMSG ("ipci165_init_obj_data\n"); - + obj->obj_base_addr = 0; /* not known yet */ obj->tx_timeout.function = ipci165_do_tx_timeout; obj->tx_timeout.data = (unsigned long)obj; @@ -1520,6 +1553,7 @@ int ipci165_register(struct hwspecops_t *hwspecops) hwspecops->release_io = ipci165_release_io; hwspecops->reset = ipci165_reset; hwspecops->init_hw_data = ipci165_init_hw_data; + hwspecops->done_hw_data = ipci165_done_hw_data; hwspecops->init_chip_data = ipci165_init_chip_data; hwspecops->init_obj_data = ipci165_init_obj_data; hwspecops->write_register = NULL; @@ -1542,7 +1576,7 @@ void dump_mem(char *ptr, int size) strp = str; for (j = 0; j < to ; j++) strp += sprintf(strp, "%02x ",buf[j]); - for (; j < 16 ; j++) + for (; j < 16 ; j++) strp += sprintf(strp, " "); for (j = 0; j < to ; j++) *strp++= isprint(buf[j]) ? buf[j] : '.';