X-Git-Url: http://rtime.felk.cvut.cz/gitweb/lincan.git/blobdiff_plain/92b76dca553a98a228f368f8ff6eedc25e33b870..c759ac4ffabb78a8863d9bced695980077eeb319:/lincan/src/unican.c diff --git a/lincan/src/unican.c b/lincan/src/unican.c index efc5ac2..f2c7ec6 100644 --- a/lincan/src/unican.c +++ b/lincan/src/unican.c @@ -3,7 +3,7 @@ * 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 + * Version lincan-0.3 17 Jun 2004 */ #include "../include/can.h" @@ -12,10 +12,8 @@ #include "../include/unican_cl2.h" #include "../include/setup.h" -#ifdef CAN_WITH_RTL - -#endif /*CAN_WITH_RTL*/ - +#define UNICAN_PCI_VENDOR 0xFA3C +#define UNICAN_PCI_ID 0x0101 static void unican_delay(long msdelay) { @@ -195,14 +193,14 @@ void unican_read(struct chip_t *chip, struct msgobj_t *obj) { do { ptr16 = (__u16*)chipext->rxBufPtr; - u = readw(ptr16++); + u = unican_readw(ptr16++); if ( !(u & CL2_MESSAGE_VALID) ) break; /* No more messages in the queue */ obj->rx_msg.id = ((__u32)(u & 0xFF00 )) << 16; - u = readw(ptr16++); + u = unican_readw(ptr16++); obj->rx_msg.id |= ((__u32)( u & 0x00FF )) << 16; obj->rx_msg.id |= (__u32)( u & 0xFF00 ); - u = readw(ptr16++); + u = unican_readw(ptr16++); obj->rx_msg.id |= (__u32)( u & 0x00FF ); @@ -223,17 +221,17 @@ void unican_read(struct chip_t *chip, struct msgobj_t *obj) { if(obj->rx_msg.length > CAN_MSG_LENGTH) obj->rx_msg.length = CAN_MSG_LENGTH; for ( i = 0; i < obj->rx_msg.length; ) { - u = readw(ptr16++); + u = unican_readw(ptr16++); obj->rx_msg.data[i++] = (__u8)( u ); obj->rx_msg.data[i++] = (__u8)( u >> 8 ); } if ( obj->rx_msg.length & 0x01 ) { /* odd */ - timestamp = ( (readw(ptr16++) & 0x00FF) | (u & 0xFF00) ); + timestamp = ( (unican_readw(ptr16++) & 0x00FF) | (u & 0xFF00) ); } else { /* even */ - u = readw(ptr16++); + u = unican_readw(ptr16++); timestamp = (u << 8) | (u >> 8); } - writew(0x000,(__u16*)chipext->rxBufPtr); + unican_writew(0x000,(__u16*)chipext->rxBufPtr); #ifdef CAN_MSG_VERSION_2 obj->rx_msg.timestamp.tv_sec = 0; @@ -462,7 +460,7 @@ void unican_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) do { ptr16 = (__u16*)chipext->asyncTxBufPtr; - if(readw(ptr16) & CL2_MESSAGE_VALID) + if(unican_readw(ptr16) & CL2_MESSAGE_VALID) return; /* No free space in asynchronous Tx queue */ cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot); @@ -479,7 +477,7 @@ void unican_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) } ptr16++; u = ((cobid>>16) & 0x00FF ) + (cobid & 0xFF00); - writew(u,ptr16++); + unican_writew(u,ptr16++); len = obj->tx_slot->msg.length; if(len > CAN_MSG_LENGTH) @@ -491,24 +489,24 @@ void unican_irq_write_handler(struct chip_t *chip, struct msgobj_t *obj) if ( obj->tx_slot->msg.flags & MSG_EXT ) u |= CL2_EXT_FRAME<<8; - writew(u,ptr16++); + unican_writew(u,ptr16++); for ( i = 0; i < len-1; ) { u = obj->tx_slot->msg.data[i++]; u |= ((__u16)obj->tx_slot->msg.data[i]<<8); i++; - writew(u,ptr16++); + unican_writew(u,ptr16++); } if(i == len) { - writew(timestamp,ptr16); + unican_writew(timestamp,ptr16); } else { u = obj->tx_slot->msg.data[i++]; u |= ((timestamp & 0x00FF)<<8); - writew(u,ptr16++); - writew(timestamp & 0x00FF, ptr16); + unican_writew(u,ptr16++); + unican_writew(timestamp & 0x00FF, ptr16); } u = ((cobid>>16) & 0xFF00) | CL2_MESSAGE_VALID; - writew(u,(__u16*)chipext->asyncTxBufPtr); + unican_writew(u,(__u16*)chipext->asyncTxBufPtr); if ( (chipext->asyncTxBufBase + chipext->asyncTxBufSize*16) <= (chipext->asyncTxBufPtr += 16) ) { @@ -761,8 +759,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 @@ -774,7 +770,7 @@ 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; + chip->chip_type = "unican"; chip->chip_base_addr = 0; chip->clock = 10000000; chip->int_clk_reg = 0x0; @@ -848,3 +844,123 @@ int unican_register(struct hwspecops_t *hwspecops) hwspecops->program_irq = unican_program_irq; return 0; } + + +/* Unicontrols PCI board specific functions */ + +#ifdef CAN_ENABLE_PCI_SUPPORT + +int unican_pci_request_io(struct candevice_t *candev) +{ + unsigned long 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"); + return -ENODEV; + } + #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/ + if(pci_request_regions(candev->sysdevptr.pcidev, "kv_pcican") != 0){ + CANMSG("Request of Unican PCI range failed\n"); + return -ENODEV; + } + #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/ + + candev->dev_base_addr=pci_resource_start(candev->sysdevptr.pcidev,0); + candev->io_addr=candev->dev_base_addr; + candev->res_addr=candev->dev_base_addr; + + if ( !( remap_addr = (long) 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", + candev->dev_base_addr, candev->chip[0]->chip_base_addr); + + return 0; +} + + +int unican_pci_release_io(struct candevice_t *candev) +{ + iounmap((void*)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))*/ + pci_release_regions(candev->sysdevptr.pcidev); + #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/ + return 0; +} + + +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)); + + if (pci_enable_device (pcidev)){ + printk(KERN_CRIT "Setup of Unican PCI failed\n"); + 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"); + return -EIO; + } + candev->dev_base_addr=pci_resource_start(pcidev,0); + candev->io_addr=candev->dev_base_addr; + candev->res_addr=candev->dev_base_addr; + + /*candev->flags |= CANDEV_PROGRAMMABLE_IRQ;*/ + + candev->nr_82527_chips=0; + candev->nr_sja1000_chips=0; + candev->nr_all_chips=1; + + return 0; +} + + +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_init_chip_data(candev, chipnr); + candev->chip[chipnr]->flags |= CHIP_IRQ_PCI; + return ret; +} + +int unican_pci_register(struct hwspecops_t *hwspecops) +{ + hwspecops->request_io = unican_pci_request_io; + hwspecops->release_io = unican_pci_release_io; + hwspecops->reset = unican_reset; + hwspecops->init_hw_data = unican_pci_init_hw_data; + hwspecops->init_chip_data = unican_pci_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; +} + +#endif /*CAN_ENABLE_PCI_SUPPORT*/ + +#ifdef CAN_ENABLE_VME_SUPPORT + +#include "unican_vme.c" + +#endif /*CAN_ENABLE_VME_SUPPORT*/