#endif
#endif
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+ #define can_pci_dev_get(_M_pdev) (_M_pdev)
+ #define can_pci_dev_put(_M_pdev) do {} while(0)
+ #define can_pci_get_device pci_find_device
+ #define can_pci_get_subsys pci_find_subsys
+#else /* > 2.6.0 */
+ #define can_pci_dev_get pci_dev_get
+ #define can_pci_dev_put pci_dev_put
+ #define can_pci_get_device pci_get_device
+ #define can_pci_get_subsys pci_get_subsys
+#endif
+
#ifndef CAN_WITH_RTL
/* Standard LINUX kernel */
int (*release_io)(struct candevice_t *candev);
int (*reset)(struct candevice_t *candev);
int (*init_hw_data)(struct candevice_t *candev);
+ void (*done_hw_data)(struct candevice_t *candev);
int (*init_chip_data)(struct candevice_t *candev, int chipnr);
int (*init_obj_data)(struct canchip_t *chip, int objnr);
int (*program_irq)(struct candevice_t *candev);
int can_request_mem_region(unsigned long start, unsigned long n, const char *name);
void can_release_mem_region(unsigned long start, unsigned long n);
+#ifdef CAN_ENABLE_PCI_SUPPORT
+struct pci_dev *can_pci_get_next_untaken_device(unsigned int vendor, unsigned int device);
+struct pci_dev *can_pci_get_next_untaken_subsyst(unsigned int vendor, unsigned int device,
+ unsigned int ss_vendor, unsigned int ss_device);
+#endif /*CAN_ENABLE_PCI_SUPPORT*/
+
struct boardtype_t {
const char *boardtype;
int (*board_register)(struct hwspecops_t *hwspecops);
int adlink7841_init_hw_data(struct candevice_t *candev)
{
- struct pci_dev *pcidev = NULL;
+ struct pci_dev *pcidev;
int i;
- do {
- pcidev = pci_find_device(ADLINK7841_PCI_VENDOR_ID, ADLINK7841_PCI_PRODUCT_ID, pcidev);
- if(pcidev == NULL) return -ENODEV;
- } while(can_check_dev_taken(pcidev));
+ pcidev = can_pci_get_next_untaken_device(ADLINK7841_PCI_VENDOR_ID, ADLINK7841_PCI_PRODUCT_ID);
+ if(pcidev == NULL)
+ return -ENODEV;
if (pci_enable_device (pcidev)){
printk(KERN_CRIT "Setup of ADLINK7841 failed\n");
+ can_pci_dev_put(pcidev);
return -EIO;
}
candev->sysdevptr.pcidev=pcidev;
for(i=1;i<3;i++){
if(!(pci_resource_flags(pcidev,i)&IORESOURCE_IO)){
printk(KERN_CRIT "ADLINK7841 region %d is not IO\n",i);
+ can_pci_dev_put(pcidev);
return -EIO;
}
}
return 0;
}
+void adlink7841_done_hw_data(struct candevice_t *candev)
+{
+ struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+ can_pci_dev_put(pcidev);
+}
+
int adlink7841_init_chip_data(struct candevice_t *candev, int chipnr)
{
hwspecops->release_io = adlink7841_release_io;
hwspecops->reset = adlink7841_reset;
hwspecops->init_hw_data = adlink7841_init_hw_data;
+ hwspecops->done_hw_data = adlink7841_done_hw_data;
hwspecops->init_chip_data = adlink7841_init_chip_data;
hwspecops->init_obj_data = adlink7841_init_obj_data;
hwspecops->write_register = adlink7841_write_register;
int ems_cpcpci_init_hw_data(struct candevice_t *candev)
{
- struct pci_dev *pcidev = NULL;
+ struct pci_dev *pcidev;
int i;
unsigned long l;
- pcidev = pci_find_device(EMS_CPCPCI_PCICAN_VENDOR, EMS_CPCPCI_PCICAN_ID, pcidev);
- if(pcidev == NULL) return -ENODEV;
+ pcidev = can_pci_get_next_untaken_device(EMS_CPCPCI_PCICAN_VENDOR, EMS_CPCPCI_PCICAN_ID);
+ if(pcidev == NULL)
+ return -ENODEV;
if (pci_enable_device (pcidev)){
printk(KERN_CRIT "Setup of EMS_CPCPCI failed\n");
+ can_pci_dev_put(pcidev);
return -EIO;
}
candev->sysdevptr.pcidev=pcidev;
for(i=0;i<2;i++){
if(!(pci_resource_flags(pcidev,0)&IORESOURCE_MEM)){
printk(KERN_CRIT "EMS_CPCPCI region %d is not memory\n",i);
+ can_pci_dev_put(pcidev);
return -EIO;
}
}
/*request IO access temporarily to check card presence*/
- if(ems_cpcpci_request_io(candev)<0)
+ if(ems_cpcpci_request_io(candev)<0) {
+ can_pci_dev_put(pcidev);
return -ENODEV;
+ }
/*** candev->aux_base_addr=pci_resource_start(pcidev,0); ***/
/* some control registers */
candev->nr_all_chips=2;
ems_cpcpci_release_io(candev);
-
+
return 0;
}
+void ems_cpcpci_done_hw_data(struct candevice_t *candev)
+{
+ struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+ can_pci_dev_put(pcidev);
+}
+
int ems_cpcpci_init_chip_data(struct candevice_t *candev, int chipnr)
{
if(candev->sysdevptr.pcidev==NULL)
hwspecops->release_io = ems_cpcpci_release_io;
hwspecops->reset = ems_cpcpci_reset;
hwspecops->init_hw_data = ems_cpcpci_init_hw_data;
+ hwspecops->done_hw_data = ems_cpcpci_done_hw_data;
hwspecops->init_chip_data = ems_cpcpci_init_chip_data;
hwspecops->init_obj_data = ems_cpcpci_init_obj_data;
hwspecops->write_register = ems_cpcpci_write_register;
int esdpci200_init_hw_data(struct candevice_t *candev)
{
- struct pci_dev *pcidev = NULL;
+ struct pci_dev *pcidev;
+
+ pcidev = can_pci_get_next_untaken_device(ESDPCI200_PCI_VENDOR_ID, ESDPCI200_PCI_PRODUCT_ID);
+ if(pcidev == NULL)
+ return -ENODEV;
- do {
- pcidev = pci_find_device(ESDPCI200_PCI_VENDOR_ID, ESDPCI200_PCI_PRODUCT_ID, pcidev);
- if(pcidev == NULL) return -ENODEV;
- } while(can_check_dev_taken(pcidev));
-
if (pci_enable_device (pcidev)){
printk(KERN_CRIT "Setup of ESDPCI200 failed\n");
+ can_pci_dev_put(pcidev);
return -EIO;
}
candev->sysdevptr.pcidev=pcidev;
if(!(pci_resource_flags(pcidev, 0)&IORESOURCE_MEM))
{
printk(KERN_CRIT "PCI200 region %d is not MEM\n",0);
+ can_pci_dev_put(pcidev);
return -EIO;
}
if(!(pci_resource_flags(pcidev, 1)&IORESOURCE_IO))
{
printk(KERN_CRIT "PCI200 region %d is not IO\n",1);
+ can_pci_dev_put(pcidev);
return -EIO;
}
if(!(pci_resource_flags(pcidev,2)&IORESOURCE_MEM))
{
printk(KERN_CRIT "PCI200 region %d is not MEM\n",2);
+ can_pci_dev_put(pcidev);
return -EIO;
}
return 0;
}
+void esdpci200_done_hw_data(struct candevice_t *candev)
+{
+ struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+ can_pci_dev_put(pcidev);
+}
+
int esdpci200_init_chip_data(struct candevice_t *candev, int chipnr)
{
hwspecops->release_io = esdpci200_release_io;
hwspecops->reset = esdpci200_reset;
hwspecops->init_hw_data = esdpci200_init_hw_data;
+ hwspecops->done_hw_data = esdpci200_done_hw_data;
hwspecops->init_chip_data = esdpci200_init_chip_data;
hwspecops->init_obj_data = esdpci200_init_obj_data;
hwspecops->write_register = esdpci200_write_register;
int esdpci266_init_hw_data(struct candevice_t *candev)
{
- struct pci_dev *pcidev = NULL;
+ struct pci_dev *pcidev;
printk("lincan: search for ESD PCI/PMC 266 board ...\n");
- do {
- pcidev =
- pci_find_device(PLX_9056_VENDOR_ID, PLX_9056_DEVICE_ID,
- pcidev);
- if (pcidev == NULL)
- return -ENODEV;
- if (pcidev->subsystem_vendor != ESDPCI266_PCI_VENDOR_ID
- || pcidev->subsystem_device != ESDPCI266_PCI_PRODUCT_ID) {
- printk
- ("PLX9056 found, subvendor/subdevice mismatch (%04d:%04d)\n",
- pcidev->subsystem_vendor,
- pcidev->subsystem_device);
- continue;
- }
- } while (can_check_dev_taken(pcidev));
+ pcidev = can_pci_get_next_untaken_subsyst(PLX_9056_VENDOR_ID, PLX_9056_DEVICE_ID,
+ ESDPCI266_PCI_VENDOR_ID, ESDPCI266_PCI_PRODUCT_ID);
+ if(pcidev == NULL)
+ return -ENODEV;
if (pci_enable_device(pcidev)) {
printk("lincan: pci_enable_device() failed\n");
+ can_pci_dev_put(pcidev);
return -EIO;
}
return 0;
}
+void esdpci266_done_hw_data(struct candevice_t *candev)
+{
+ struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+ can_pci_dev_put(pcidev);
+}
+
int esdpci266_init_chip_data(struct candevice_t *candev, int chipnr)
{
if (candev->sysdevptr.pcidev == NULL)
hwspecops->release_io = esdpci266_release_io;
hwspecops->reset = esdpci266_reset;
hwspecops->init_hw_data = esdpci266_init_hw_data;
+ hwspecops->done_hw_data = esdpci266_done_hw_data;
hwspecops->init_chip_data = esdpci266_init_chip_data;
hwspecops->init_obj_data = esdpci266_init_obj_data;
hwspecops->write_register = esdpci266_write_register;
candev->hwspecops->release_io(candev);
candev->flags &= ~CANDEV_IO_RESERVED;
}
+ if(candev->hwspecops->done_hw_data != NULL)
+ candev->hwspecops->done_hw_data(candev);
+
can_checked_free(candev->hwspecops);
candev->hwspecops=NULL;
}
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));
if (pci_enable_device (pcidev))
{
CANMSG ("Cannot enable PCI device\n");
+ can_pci_dev_put(pcidev);
return -EIO;
}
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"
/**
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;
int kv_pcican_init_hw_data(struct candevice_t *candev)
{
- struct pci_dev *pcidev = NULL;
+ struct pci_dev *pcidev;
int i;
- do {
- pcidev = pci_find_device(KV_PCICAN_PCICAN_VENDOR, KV_PCICAN_PCICAN_ID, pcidev);
- if(pcidev == NULL) return -ENODEV;
- } while(can_check_dev_taken(pcidev));
+ pcidev = can_pci_get_next_untaken_device(KV_PCICAN_PCICAN_VENDOR, KV_PCICAN_PCICAN_ID);
+ if(pcidev == NULL)
+ return -ENODEV;
if (pci_enable_device (pcidev)){
printk(KERN_CRIT "Setup of PCICAN failed\n");
+ can_pci_dev_put(pcidev);
return -EIO;
}
candev->sysdevptr.pcidev=pcidev;
for(i=0;i<3;i++){
if(!(pci_resource_flags(pcidev,i)&IORESOURCE_IO)){
printk(KERN_CRIT "PCICAN region %d is not IO\n",i);
+ can_pci_dev_put(pcidev);
return -EIO;
}
}
return 0;
}
+void kv_pcican_done_hw_data(struct candevice_t *candev)
+{
+ struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+ can_pci_dev_put(pcidev);
+}
+
int kv_pcican_init_chip_data(struct candevice_t *candev, int chipnr)
{
hwspecops->release_io = kv_pcican_release_io;
hwspecops->reset = kv_pcican_reset;
hwspecops->init_hw_data = kv_pcican_init_hw_data;
+ hwspecops->done_hw_data = kv_pcican_done_hw_data;
hwspecops->init_chip_data = kv_pcican_init_chip_data;
hwspecops->init_obj_data = kv_pcican_init_obj_data;
hwspecops->write_register = kv_pcican_write_register;
*/
int nsi_canpci_init_hw_data(struct candevice_t *candev)
- {
- struct pci_dev *pcidev = NULL;
+{
+ struct pci_dev *pcidev;
- /* looking for NSI CANPCI ident on the pci bus*/
- do
- {
- pcidev = pci_find_device(NSI_VENDOR_ID, NSI_CANPCI_DEVICE_ID, pcidev);
- }
- while(can_check_dev_taken(pcidev));
-
- if(pcidev == NULL)
- {
- do
- {
- pcidev = pci_find_device(NSI_VENDOR_ID, NSI_CANPCI_DEVICE_ID+1, pcidev);
- }
- while(can_check_dev_taken(pcidev));
- if(pcidev == NULL)
- {
+ /* looking for NSI CANPCI ident on the pci bus*/
+ pcidev = can_pci_get_next_untaken_device(NSI_VENDOR_ID, NSI_CANPCI_DEVICE_ID);
+ if(pcidev == NULL)
+ pcidev = can_pci_get_next_untaken_device(NSI_VENDOR_ID, NSI_CANPCI_DEVICE_ID+1);
+ if(pcidev == NULL) {
CANMSG ("Error : NSI CAN PCI device not found\n");
return -ENODEV;
}
- else
- {
- CANMSG ("NSI CANPCI OPTO device found\n");
- }
- }
- else
- {
+
CANMSG ("NSI CANPCI device found\n");
- }
-
+
/* enable it */
if (pci_enable_device (pcidev))
{
CANMSG ("Cannot enable PCI device\n");
- return -EIO;
+ goto error_io;
}
CANMSG ("NSI CANPCI device started\n");
candev->sysdevptr.pcidev = pcidev;
pci_release_region(pcidev,0);
pci_release_region(pcidev,1);
pci_release_region(pcidev,2);
- return -EIO;
+ goto error_io;
}
}
else
{
pci_release_region(pcidev,0);
pci_release_region(pcidev,1);
- return -EIO;
+ goto error_io;
}
}
else
{
pci_release_region(pcidev,0);
- return -EIO;
+ goto error_io;
}
}
else
{
- return -EIO;
+ goto error_io;
}
candev->dev_base_addr=(unsigned long)(kmalloc(sizeof(t_CardArray),GFP_ATOMIC));
if((unsigned long)candev->dev_base_addr==0)
- return -EIO;
+ goto error_io;
//PLX register
((t_CardArray*)(candev->dev_base_addr))->addr_BAR_remap[0]=ioremap(pci_resource_start(pcidev,0),pci_resource_len(pcidev,0) );
//PLX IO
//Short acces to plx register
candev->io_addr=(unsigned long)(((t_CardArray*)(candev->dev_base_addr))->addr_BAR_remap[0]);
return 0;
+
+error_io:
+ can_pci_dev_put(pcidev);
+ return -EIO;
}
+
+void nsi_canpci_done_hw_data(struct candevice_t *candev)
+{
+ struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+ can_pci_dev_put(pcidev);
+}
+
+
/* The function template_init_chip_data is used to initialize the hardware
* structure containing information about the CAN chips.
* CHIP_TYPE represents the type of CAN chip. CHIP_TYPE can be "i82527" or
hwspecops->release_io = nsi_canpci_release_io;
hwspecops->reset = nsi_canpci_reset;
hwspecops->init_hw_data = nsi_canpci_init_hw_data;
+ hwspecops->done_hw_data = nsi_canpci_done_hw_data;
hwspecops->init_chip_data = nsi_canpci_init_chip_data;
hwspecops->init_obj_data = nsi_canpci_init_obj_data;
hwspecops->write_register = nsi_canpci_write_register;
int nr_chips;
u16 subsysid;
- i = 0;
- do {
- pcidev = pci_find_device(PCAN_PCI_VENDOR_ID, PCAN_PCI_PRODUCT_ID, pcidev);
- if(pcidev == NULL) {
- printk(KERN_ERR "No unused PCAN_PCI #%d card found\n", i);
- return -ENODEV;
- }
- i++;
- } while(can_check_dev_taken(pcidev));
+ pcidev = can_pci_get_next_untaken_device(PCAN_PCI_VENDOR_ID, PCAN_PCI_PRODUCT_ID);
+ if(pcidev == NULL) {
+ printk(KERN_ERR "No unused PCAN_PCI card found\n");
+ return -ENODEV;
+ }
if (pci_enable_device (pcidev)){
printk(KERN_ERR "Enable PCAN_PCI failed\n");
+ can_pci_dev_put(pcidev);
return -EIO;
}
candev->sysdevptr.pcidev=pcidev;
printk(KERN_CRIT "Setup of PCAN_PCI failed\n");
pci_disable_device (pcidev);
+ can_pci_dev_put(pcidev);
return -EIO;
}
+void pcan_pci_done_hw_data(struct candevice_t *candev)
+{
+ struct pci_dev *pcidev = candev->sysdevptr.pcidev;
+ can_pci_dev_put(pcidev);
+}
+
int pcan_pci_init_chip_data(struct candevice_t *candev, int chipnr)
{
hwspecops->release_io = pcan_pci_release_io;
hwspecops->reset = pcan_pci_reset;
hwspecops->init_hw_data = pcan_pci_init_hw_data;
+ hwspecops->done_hw_data = pcan_pci_done_hw_data;
hwspecops->init_chip_data = pcan_pci_init_chip_data;
hwspecops->init_obj_data = pcan_pci_init_obj_data;
hwspecops->write_register = pcan_pci_write_register;
#endif
}
+#ifdef CAN_ENABLE_PCI_SUPPORT
+
+struct pci_dev *can_pci_get_next_untaken_device(unsigned int vendor, unsigned int device)
+{
+ struct pci_dev *pcidev = NULL;
+
+ do {
+ pcidev = can_pci_get_device(vendor, device, pcidev);
+ if(pcidev == NULL)
+ return NULL;
+ } while(can_check_dev_taken(pcidev));
+
+ return pcidev;
+}
+
+struct pci_dev *can_pci_get_next_untaken_subsyst(unsigned int vendor, unsigned int device,
+ unsigned int ss_vendor, unsigned int ss_device)
+{
+ struct pci_dev *pcidev = NULL;
+
+ do {
+ pcidev = can_pci_get_subsys(vendor, device, ss_vendor, ss_device, pcidev);
+ if(pcidev == NULL)
+ return NULL;
+ } while(can_check_dev_taken(pcidev));
+
+ return pcidev;
+}
+
+#endif /*CAN_ENABLE_PCI_SUPPORT*/
+
#ifndef CAN_WITH_RTL
/**
{
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->io_addr=pci_resource_start(pcidev,0);
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)
{
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;