From ca640a474326cafe00ff1d34137aeb983c92ac11 Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Sun, 11 Jun 2006 21:34:21 +0000 Subject: [PATCH] Patch from abbotti@mev.co.uk (Ian Abbott). Note, I am planning to revert/alter parts of this patch shortly, I am commiting the original patch so it is clear what I changed. I've been through the PCI code of all the drivers (apart from the ones in the addi_data directory) to apply the following rules: 1. Call pci_enable_device before looking at resources. (I didn't do this for the card list display code in amcc_s5933.c as it's only for debugging; it might display bogus values on some platforms.) 2. Call pci_request_regions to request all PCI I/O and memory areas. (Some drivers were calling request_region on a subset of the valid regions, but pci_request_regions is preferred. Some drivers didn't bother requesting regions and just used them anyway.) 3. If 1 and 2 succeeded, then when done with the device (on comedi detach), call pci_release_regions and pci_disable_device. Note that pci_disable_device is not called if rule 2 failed, because that indicates that the device is being used by something else (most likely another comedi device). I've fixed some brokenness along the way, but the amcc_s5933 driver will still break if more than one client driver uses it (but at least it now works if more than one device is using that client driver). To fix it properly will require separate device lists for each vendor ID and maybe a reference count for each of those lists - a job for another day! More brokenness in the adv_pci_dio driver has been fixed. It tried to be clever by keeping a list of PCI devices in use, but its list handling code was completely broken. I changed the s626 driver to use pci_get_device and pci_put_device instead of the old pci_find_device. I've checked over the changes twice, but am not able to test all the drivers of course, so I might have introduced an odd bug or two, but I hope not! --- comedi/drivers/adl_pci6208.c | 15 ++++++- comedi/drivers/adl_pci7432.c | 23 +++++++++- comedi/drivers/adl_pci8164.c | 22 +++++++++- comedi/drivers/adl_pci9111.c | 10 +++++ comedi/drivers/adl_pci9118.c | 34 +++++---------- comedi/drivers/adv_pci1710.c | 32 ++++++-------- comedi/drivers/adv_pci_dio.c | 64 ++++++++++++++-------------- comedi/drivers/amcc_s5933.c | 33 +++++++++++++-- comedi/drivers/amplc_dio200.c | 57 +++++++++++++++---------- comedi/drivers/amplc_pc236.c | 54 ++++++++++++------------ comedi/drivers/amplc_pc263.c | 46 ++++++++++++-------- comedi/drivers/amplc_pci224.c | 2 + comedi/drivers/amplc_pci230.c | 19 +++++---- comedi/drivers/cb_pcidas.c | 74 ++++++++++++--------------------- comedi/drivers/cb_pcidas64.c | 19 ++++----- comedi/drivers/cb_pcidda.c | 19 +++++---- comedi/drivers/cb_pcimdas.c | 27 +++++++----- comedi/drivers/cb_pcimdda.c | 28 ++++++------- comedi/drivers/contec_pci_dio.c | 20 +++++++-- comedi/drivers/daqboard2000.c | 28 +++++++------ comedi/drivers/das08.c | 34 ++++++++------- comedi/drivers/dt3000.c | 23 ++++++++-- comedi/drivers/gsc_hpdi.c | 19 ++++----- comedi/drivers/icp_multi.c | 27 +++++------- comedi/drivers/icp_multi.h | 33 +++++++++++++-- comedi/drivers/ke_counter.c | 23 +++++++--- comedi/drivers/me4000.c | 48 +++++++++++---------- comedi/drivers/me_daq.c | 23 +++++++++- comedi/drivers/mite.c | 4 +- comedi/drivers/rtd520.c | 47 +++++++++++++++------ comedi/drivers/s626.c | 72 ++++++++++++++++++++------------ 31 files changed, 596 insertions(+), 383 deletions(-) diff --git a/comedi/drivers/adl_pci6208.c b/comedi/drivers/adl_pci6208.c index ea50c970..b44700a7 100644 --- a/comedi/drivers/adl_pci6208.c +++ b/comedi/drivers/adl_pci6208.c @@ -100,6 +100,7 @@ MODULE_DEVICE_TABLE(pci, pci6208_pci_table); typedef struct{ int data; struct pci_dev *pci_dev; /* for a PCI device */ + int pci_setup; /* non-zero in PCI set up okay */ lsampl_t ao_readback[2]; /* Used for AO readback */ }pci6208_private; @@ -155,6 +156,9 @@ static int pci6208_attach(comedi_device *dev,comedi_devconfig *it) retval = pci6208_pci_setup(devpriv->pci_dev, &io_base, dev->minor); if (retval < 0) return retval; + + // Allow resources to be freed and PCI device to be disabled. + devpriv->pci_setup = 1; dev->iobase=io_base; dev->board_name = thisboard->name; @@ -205,7 +209,10 @@ static int pci6208_detach(comedi_device *dev) printk("comedi%d: pci6208: remove\n",dev->minor); if(devpriv && devpriv->pci_dev){ - pci_release_regions(devpriv->pci_dev); + if (devpriv->pci_setup) { + pci_release_regions(devpriv->pci_dev); + pci_disable_device(devpriv->pci_dev); + } pci_dev_put(devpriv->pci_dev); } @@ -358,6 +365,12 @@ static int pci6208_pci_setup(struct pci_dev *pci_dev, int *io_base_ptr, int dev_minor) { int io_base, io_range, lcr_io_base, lcr_io_range; + + // Enable PCI device + if (pci_enable_device(pci_dev) < 0) { + printk("comedi%d: Failed to enable PCI device\n", dev_minor); + return -EIO; + } // Read local configuration register base address [PCI_BASE_ADDRESS #1]. lcr_io_base = pci_resource_start(pci_dev, 1); diff --git a/comedi/drivers/adl_pci7432.c b/comedi/drivers/adl_pci7432.c index dd8ee444..aa3ff86a 100644 --- a/comedi/drivers/adl_pci7432.c +++ b/comedi/drivers/adl_pci7432.c @@ -60,9 +60,10 @@ MODULE_DEVICE_TABLE(pci, adl_pci7432_pci_table); typedef struct{ int data; struct pci_dev *pci_dev; + int pci_setup; } adl_pci7432_private; -#define devpriv ((pci7432_private *)dev->private) +#define devpriv ((adl_pci7432_private *)dev->private) static int adl_pci7432_attach(comedi_device *dev,comedi_devconfig *it); static int adl_pci7432_detach(comedi_device *dev); @@ -108,6 +109,16 @@ static int adl_pci7432_attach(comedi_device *dev,comedi_devconfig *it) if ( pcidev->vendor == PCI_VENDOR_ID_ADLINK && pcidev->device == PCI_DEVICE_ID_PCI7432 ) { + devpriv->pci_dev = pcidev; + if (pci_enable_device(pcidev) < 0) { + printk("comedi%d: Failed to enable PCI device\n", dev->minor); + return -EIO; + } + if (pci_request_regions(pcidev, "adl_pci7432") < 0) { + printk("comedi%d: I/O port conflict\n", dev->minor); + return -EIO; + } + devpriv->pci_setup = 1; /* Allow resources to be freed on detach */ dev->iobase = pci_resource_start ( pcidev, 2 ); printk ( "comedi: base addr %4lx\n", dev->iobase ); @@ -132,6 +143,8 @@ static int adl_pci7432_attach(comedi_device *dev,comedi_devconfig *it) s->io_bits = 0xffffffff; s->range_table = &range_digital; s->insn_bits = adl_pci7432_do_insn_bits; + + break; } } @@ -145,6 +158,14 @@ static int adl_pci7432_detach(comedi_device *dev) { printk("comedi%d: pci7432: remove\n",dev->minor); + if (devpriv && devpriv->pci_dev) { + if (devpriv->pci_setup) { + pci_release_regions(devpriv->pci_dev); + pci_disable_device(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } + return 0; } diff --git a/comedi/drivers/adl_pci8164.c b/comedi/drivers/adl_pci8164.c index ae4b1662..a614e26d 100644 --- a/comedi/drivers/adl_pci8164.c +++ b/comedi/drivers/adl_pci8164.c @@ -72,9 +72,10 @@ MODULE_DEVICE_TABLE(pci, adl_pci8164_pci_table); typedef struct{ int data; struct pci_dev *pci_dev; + int pci_setup; } adl_pci8164_private; -#define devpriv ((pci8164_private *)dev->private) +#define devpriv ((adl_pci8164_private *)dev->private) static int adl_pci8164_attach(comedi_device *dev,comedi_devconfig *it); static int adl_pci8164_detach(comedi_device *dev); @@ -126,6 +127,16 @@ static int adl_pci8164_attach(comedi_device *dev,comedi_devconfig *it) if ( pcidev->vendor == PCI_VENDOR_ID_ADLINK && pcidev->device == PCI_DEVICE_ID_PCI8164 ) { + devpriv->pci_dev = pcidev; + if (pci_enable_device(pcidev) < 0) { + printk("comedi%d: Failed to enable PCI device\n", dev->minor); + return -EIO; + } + if (pci_request_regions(pcidev, "adl_pci8164") < 0) { + printk("comedi%d: I/O port conflict\n", dev->minor); + return -EIO; + } + devpriv->pci_setup = 1; /* Allow resources to be freed on detach */ dev->iobase = pci_resource_start ( pcidev, 2 ); printk ( "comedi: base addr %4lx\n", dev->iobase ); @@ -171,6 +182,7 @@ static int adl_pci8164_attach(comedi_device *dev,comedi_devconfig *it) s->insn_read = adl_pci8164_insn_read_buf1; s->insn_write = adl_pci8164_insn_write_buf1; + break; } } @@ -184,6 +196,14 @@ static int adl_pci8164_detach(comedi_device *dev) { printk("comedi%d: pci8164: remove\n",dev->minor); + if (devpriv && devpriv->pci_dev) { + if (devpriv->pci_setup) { + pci_release_regions(devpriv->pci_dev); + pci_disable_device(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } + return 0; } diff --git a/comedi/drivers/adl_pci9111.c b/comedi/drivers/adl_pci9111.c index 52a3b7de..7731575a 100644 --- a/comedi/drivers/adl_pci9111.c +++ b/comedi/drivers/adl_pci9111.c @@ -1326,6 +1326,14 @@ found: lcr_io_base, lcr_io_range); + // Enable PCI device + if(pci_enable_device (pci_device) < 0) + { + printk("comedi%d: Failed to enable PCI device\n", dev->minor); + pci_dev_put(pci_device); + return -EIO; + } + // Read PCI6308 register base address [PCI_BASE_ADDRESS #2]. io_base = pci_resource_start (pci_device, 2); @@ -1350,6 +1358,7 @@ found: if(alloc_private(dev,sizeof(pci9111_private_data_struct))<0) { pci_release_regions(pci_device); + pci_disable_device(pci_device); pci_dev_put(pci_device); return -ENOMEM; } @@ -1465,6 +1474,7 @@ static int pci9111_detach(comedi_device *dev) if (dev_private!=0 && dev_private->pci_device!=0) { pci_release_regions(dev_private->pci_device); + pci_disable_device(dev_private->pci_device); pci_dev_put(dev_private->pci_device); } diff --git a/comedi/drivers/adl_pci9118.c b/comedi/drivers/adl_pci9118.c index 0babd0a3..c80e0010 100644 --- a/comedi/drivers/adl_pci9118.c +++ b/comedi/drivers/adl_pci9118.c @@ -180,7 +180,7 @@ static comedi_lrange range_pci9118hg={ 8, { static int pci9118_attach(comedi_device *dev,comedi_devconfig *it); static int pci9118_detach(comedi_device *dev); -static unsigned short pci_list_builded=0; /*=1 list of cards is know */ +static unsigned short pci_list_builded=0; /*>0 list of cards is known */ typedef struct { char *name; // driver name @@ -245,7 +245,6 @@ typedef struct{ int iobase_a; // base+size for AMCC chip struct pcilst_struct *amcc; // ptr too AMCC data unsigned int master; // master capable - unsigned char allocated; // we have blocked card struct pci_dev *pcidev; // ptr to actual pcidev unsigned int usemux; // we want to use external multiplexor! #ifdef PCI9118_PARANOIDCHECK @@ -1677,9 +1676,8 @@ static int pci9118_attach(comedi_device *dev,comedi_devconfig *it) unsigned char pci_bus,pci_slot,pci_func; u16 u16w; - if (!pci_list_builded) { + if (pci_list_builded++ == 0) { pci_card_list_init(PCI_VENDOR_ID_AMCC,0); - pci_list_builded=1; } rt_printk("comedi%d: adl_pci9118: board=%s",dev->minor,this_board->name); @@ -1690,7 +1688,8 @@ static int pci9118_attach(comedi_device *dev,comedi_devconfig *it) master=1; } - /* this call pci_enable_device() and pci_set_master() */ + /* this call pci_enable_device(), pci_request_regions(), + * and pci_set_master() */ if ((card=select_and_alloc_pci_card(PCI_VENDOR_ID_AMCC, this_board->device_id, it->options[0], it->options[1], master))==NULL) return -EIO; @@ -1706,24 +1705,18 @@ static int pci9118_attach(comedi_device *dev,comedi_devconfig *it) rt_printk(", b:s:f=%d:%d:%d, io=0x%4x, 0x%4x",pci_bus,pci_slot,pci_func,iobase_9,iobase_a); - if (!request_region(iobase_9, this_board->iorange_9118, "ADLink PCI-9118")) { - rt_printk("I/O port conflict\n"); - return -EIO; - } - dev->iobase=iobase_9; dev->board_name = this_board->name; - if((ret=alloc_private(dev,sizeof(pci9118_private)))<0) + if((ret=alloc_private(dev,sizeof(pci9118_private)))<0) { + pci_card_free(card); + rt_printk(" - Allocation failed!\n"); return -ENOMEM; + } devpriv->amcc=card; devpriv->pcidev=card->pcidev; - if (!request_region(iobase_a, this_board->iorange_amcc, "ADLink PCI-9118")) { - rt_printk("I/O port conflict\n"); - return -EIO; - } devpriv->iobase_a=iobase_a; if (it->options[3]&2) irq=0; // user don't want use IRQ @@ -1868,19 +1861,14 @@ static int pci9118_detach(comedi_device *dev) { if (dev->private) { if (devpriv->valid) pci9118_reset(dev); - if (devpriv->iobase_a) release_region(devpriv->iobase_a,this_board->iorange_amcc); - if (devpriv->allocated) pci_card_free(devpriv->amcc); + if(dev->irq) comedi_free_irq(dev->irq,dev); + if (devpriv->amcc) pci_card_free(devpriv->amcc); if (devpriv->dmabuf_virt[0]) free_pages((unsigned long)devpriv->dmabuf_virt[0],devpriv->dmabuf_pages[0]); if (devpriv->dmabuf_virt[1]) free_pages((unsigned long)devpriv->dmabuf_virt[1],devpriv->dmabuf_pages[1]); } - if(dev->irq) comedi_free_irq(dev->irq,dev); - - if(dev->iobase) release_region(dev->iobase,this_board->iorange_9118); - - if (pci_list_builded) { + if (--pci_list_builded == 0) { pci_card_list_cleanup(PCI_VENDOR_ID_AMCC); - pci_list_builded=0; } return 0; diff --git a/comedi/drivers/adv_pci1710.c b/comedi/drivers/adv_pci1710.c index f0239c77..ca3d77e1 100644 --- a/comedi/drivers/adv_pci1710.c +++ b/comedi/drivers/adv_pci1710.c @@ -182,7 +182,7 @@ static comedi_lrange range_pci171x_da={ 2, { static int pci1710_attach(comedi_device *dev,comedi_devconfig *it); static int pci1710_detach(comedi_device *dev); -static unsigned short pci_list_builded=0; /*=1 list of card is know */ +static unsigned short pci_list_builded=0; /*>0 list of card is known */ typedef struct { char *name; // driver name @@ -262,6 +262,7 @@ static comedi_driver driver_pci1710={ }; typedef struct{ + struct pcilst_struct *amcc; // ptr to AMCC data char valid; // card is usable char neverending_ai; // we do unlimited AI unsigned int CntrlReg; // Control register @@ -1227,7 +1228,7 @@ static int pci1710_attach(comedi_device *dev,comedi_devconfig *it) unsigned int iobase; unsigned char pci_bus,pci_slot,pci_func; - if (!pci_list_builded) { + if (pci_list_builded++ == 0) { pci_card_list_init(PCI_VENDOR_ID_ADVANTECH, #ifdef PCI171X_EXTDEBUG 1 @@ -1235,12 +1236,11 @@ static int pci1710_attach(comedi_device *dev,comedi_devconfig *it) 0 #endif ); - pci_list_builded=1; } rt_printk("comedi%d: adv_pci1710: board=%s",dev->minor,this_board->name); - /* this call pci_enable_device() */ + /* this call pci_enable_device() and pci_request_regions() */ if ((card=select_and_alloc_pci_card(PCI_VENDOR_ID_ADVANTECH, this_board->device_id, it->options[0], it->options[1], 0))==NULL) return -EIO; @@ -1255,22 +1255,18 @@ static int pci1710_attach(comedi_device *dev,comedi_devconfig *it) rt_printk(", b:s:f=%d:%d:%d, io=0x%4x",pci_bus,pci_slot,pci_func,iobase); - if (!request_region(iobase, this_board->iorange, "Advantech PCI-1710")) { - pci_card_free(card); - rt_printk("I/O port conflict\n"); - return -EIO; - } - dev->iobase=iobase; dev->board_name = this_board->name; if((ret=alloc_private(dev,sizeof(pci1710_private)))<0) { - release_region(dev->iobase, this_board->iorange); pci_card_free(card); + rt_printk(" - Allocation failed!\n"); return -ENOMEM; } + devpriv->amcc = card; + n_subdevices = 0; if (this_board->n_aichan) n_subdevices++; if (this_board->n_aochan) n_subdevices++; @@ -1279,8 +1275,7 @@ static int pci1710_attach(comedi_device *dev,comedi_devconfig *it) if (this_board->n_counter) n_subdevices++; if((ret=alloc_subdevices(dev, n_subdevices))<0) { - release_region(dev->iobase, this_board->iorange); - pci_card_free(card); + rt_printk(" - Allocation failed!\n"); return ret; } @@ -1399,15 +1394,14 @@ static int pci1710_attach(comedi_device *dev,comedi_devconfig *it) static int pci1710_detach(comedi_device *dev) { - if (dev->private) + if (dev->private) { if (devpriv->valid) pci1710_reset(dev); - - if (dev->irq) comedi_free_irq(dev->irq,dev); - if (dev->iobase) release_region(dev->iobase,this_board->iorange); + if (dev->irq) comedi_free_irq(dev->irq,dev); + if (devpriv->amcc) pci_card_free(devpriv->amcc); + } - if (pci_list_builded) { + if (--pci_list_builded == 0) { pci_card_list_cleanup(PCI_VENDOR_ID_ADVANTECH); - pci_list_builded=0; } diff --git a/comedi/drivers/adv_pci_dio.c b/comedi/drivers/adv_pci_dio.c index c7387790..7f72948a 100644 --- a/comedi/drivers/adv_pci_dio.c +++ b/comedi/drivers/adv_pci_dio.c @@ -843,12 +843,7 @@ static int CheckAndAllocCard(comedi_device *dev, comedi_devconfig *it, { pci_dio_private *pr, *prev; - if (!pci_priv) { // well, first card in system - pci_priv=devpriv; - return 1; - } - - for (pr=pci_priv, prev=NULL; pr!=NULL; prev=pr, pr=pr->next) + for (pr=pci_priv, prev=NULL; pr!=NULL; prev=pr, pr=pr->next) { if (pr->pcidev==pcidev) { if (it->options[0]||it->options[1]) { if ((pr->pcidev->bus->number==it->options[0])&& @@ -859,9 +854,16 @@ static int CheckAndAllocCard(comedi_device *dev, comedi_devconfig *it, } return 0; // this card is used, look for another } + } + + if (prev) { + devpriv->prev=prev; + prev->next = devpriv; + } else { + pci_priv = devpriv; + } - if (prev) { devpriv->prev=prev; } - { pci_priv=devpriv; } + devpriv->pcidev = pcidev; return 1; } @@ -897,38 +899,30 @@ static int pci_dio_attach(comedi_device *dev, comedi_devconfig *it) ret=CheckAndAllocCard(dev, it, pcidev); if (ret==1) { found=1; break; } if (ret>1) { - pci_dio_detach(dev); - pci_dev_put(pcidev); return -EIO; } } if (!found) { rt_printk(", Error: Requested type of the card was not found!\n"); - pci_dio_detach(dev); return -EIO; } - iobase=pci_resource_start(pcidev, this_board->main_pci_region); - rt_printk(", b:s:f=%d:%d:%d, io=0x%4x", - pcidev->bus->number, PCI_SLOT(pcidev->devfn), PCI_FUNC(pcidev->devfn), - iobase); - - if (pci_request_regions(pcidev, driver_pci_dio.driver_name)) { - pci_dio_detach(dev); - pci_dev_put(pcidev); - rt_printk(", Error: Cann't allocate PCI device!\n"); + if (pci_enable_device(pcidev)) { + rt_printk(", Error: Can't enable PCI device!\n"); return -EIO; } - devpriv->pcidev=pcidev; - - if (pci_enable_device(pcidev)) { - pci_dio_detach(dev); - rt_printk(", Error: Cann't enable PCI device!\n"); + if (pci_request_regions(pcidev, driver_pci_dio.driver_name)) { + rt_printk(", Error: Can't allocate PCI device!\n"); return -EIO; } devpriv->enabled=1; + iobase=pci_resource_start(pcidev, this_board->main_pci_region); + rt_printk(", b:s:f=%d:%d:%d, io=0x%4x", + pcidev->bus->number, PCI_SLOT(pcidev->devfn), PCI_FUNC(pcidev->devfn), + iobase); + dev->iobase=iobase; dev->board_name=this_board->name; @@ -947,7 +941,6 @@ static int pci_dio_attach(comedi_device *dev, comedi_devconfig *it) if((ret=alloc_subdevices(dev, n_subdevices))<0) { rt_printk(", Error: Cann't allocate subdevice memory!\n"); - pci_dio_detach(dev); return ret; } @@ -1034,18 +1027,23 @@ static int pci_dio_detach(comedi_device *dev) s->private=NULL; } - if (devpriv->enabled) + if (devpriv->enabled) { + pci_release_regions(devpriv->pcidev); pci_disable_device(devpriv->pcidev); + } + + if (devpriv->prev) { + devpriv->prev->next=devpriv->next; + } else { + pci_priv=devpriv->next; + } + if (devpriv->next) { + devpriv->next->prev=devpriv->prev; + } if (devpriv->pcidev) { - pci_release_regions(devpriv->pcidev); pci_dev_put(devpriv->pcidev); } - - if (devpriv->prev) { devpriv->prev->next=devpriv->next; } - { pci_priv=devpriv->next; } - if (devpriv->next) { devpriv->next->prev=devpriv->prev; } - } return 0; diff --git a/comedi/drivers/amcc_s5933.c b/comedi/drivers/amcc_s5933.c index d0624835..9a62aa80 100644 --- a/comedi/drivers/amcc_s5933.c +++ b/comedi/drivers/amcc_s5933.c @@ -52,6 +52,9 @@ void pci_card_list_init(unsigned short pci_vendor, char display) amcc->pci_bus=pcidev->bus->number; amcc->pci_slot=PCI_SLOT(pcidev->devfn); amcc->pci_func=PCI_FUNC(pcidev->devfn); + /* Note: resources may be invalid if PCI device + * not enabled, but they are corrected in + * pci_card_alloc. */ for (i=0;i<5;i++) amcc->io_addr[i]=pci_resource_start(pcidev, i); amcc->irq=pcidev->irq; @@ -123,10 +126,27 @@ int find_free_pci_card_by_position(unsigned short vendor_id, unsigned short devi /* mark card as used */ int pci_card_alloc(struct pcilst_struct *amcc, char master) { - if (!amcc) return -1; + int i; + + if (!amcc) { + rt_printk(" - BUG!! amcc is NULL!\n"); + return -1; + } if (amcc->used) return 1; - if (pci_enable_device(amcc->pcidev)) return -1; + if (pci_enable_device(amcc->pcidev)) { + rt_printk(" - Can't enable PCI device!\n"); + return -1; + } + /* Resources will be accurate now. */ + for (i=0;i<5;i++) + amcc->io_addr[i]=pci_resource_start(amcc->pcidev, i); + amcc->irq=amcc->pcidev->irq; + /* Request regions on behalf of client. */ + if (pci_request_regions(amcc->pcidev, "amcc_s5933")) { + rt_printk(" - I/O port conflict!\n"); + return -1; + } if (master) pci_set_master(amcc->pcidev); amcc->used=1; @@ -141,6 +161,8 @@ int pci_card_free(struct pcilst_struct *amcc) if (!amcc->used) return 1; amcc->used=0; + pci_release_regions(amcc->pcidev); + pci_disable_device(amcc->pcidev); return 0; } @@ -186,6 +208,7 @@ int pci_card_data(struct pcilst_struct *amcc, struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id, unsigned short device_id, unsigned short pci_bus, unsigned short pci_slot, char master) { struct pcilst_struct *card; + int err; if ((pci_bus<1)&&(pci_slot<1)) { // use autodetection if ((card=find_free_pci_card_by_device(vendor_id,device_id))==NULL) { @@ -204,8 +227,10 @@ struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id, unsign } - if (pci_card_alloc(card, master)!=0) { - rt_printk(" - Can't allocate card!\n"); + if ((err=pci_card_alloc(card, master))!=0) { + if (err > 0) + rt_printk(" - Can't allocate card!\n"); + /* else: error already printed. */ return NULL; } diff --git a/comedi/drivers/amplc_dio200.c b/comedi/drivers/amplc_dio200.c index 98bb0b6e..4005fc06 100644 --- a/comedi/drivers/amplc_dio200.c +++ b/comedi/drivers/amplc_dio200.c @@ -396,7 +396,6 @@ MODULE_DEVICE_TABLE(pci, dio200_pci_table); feel free to suggest moving the variable to the comedi_device struct. */ typedef struct { struct pci_dev *pci_dev; /* PCI device */ - int share_irq; int intr_sd; } dio200_private; @@ -514,7 +513,7 @@ dio200_find_pci(comedi_device *dev, int bus, int slot, static int dio200_request_region(unsigned minor, unsigned long from, unsigned long extent) { - if (!request_region(from, extent, DIO200_DRIVER_NAME)) { + if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) { printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n", minor, from, extent); return -EIO; @@ -1199,7 +1198,7 @@ dio200_attach(comedi_device *dev,comedi_devconfig *it) printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, DIO200_DRIVER_NAME); - /* Get card bus position and base address. */ + /* Process options. */ switch (thisboard->bustype) { case isa_bustype: iobase = it->options[0]; @@ -1213,15 +1212,6 @@ dio200_attach(comedi_device *dev,comedi_devconfig *it) if ((ret=dio200_find_pci(dev, bus, slot, &pci_dev)) < 0) return ret; - - if ((ret=pci_enable_device(pci_dev)) < 0) { - printk(KERN_ERR "comedi%d: error! cannot enable PCI device!\n", - dev->minor); - pci_dev_put(pci_dev); - return ret; - } - iobase = pci_resource_start(pci_dev, 2); - irq = pci_dev->irq; break; default: printk(KERN_ERR "comedi%d: %s: BUG! cannot determine board type!\n", @@ -1238,14 +1228,32 @@ dio200_attach(comedi_device *dev,comedi_devconfig *it) return ret; } - devpriv->pci_dev = pci_dev; - devpriv->share_irq = share_irq; devpriv->intr_sd = -1; - /* Reserve I/O spaces. */ - ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE); - if (ret < 0) { - return ret; + /* Enable device and reserve I/O spaces. */ + if (pci_dev) { + ret = pci_enable_device(pci_dev); + if (ret < 0) { + printk(KERN_ERR "comedi%d: error! cannot enable PCI device!\n", + dev->minor); + pci_dev_put(pci_dev); + return ret; + } + iobase = pci_resource_start(pci_dev, 2); + irq = pci_dev->irq; + ret = pci_request_regions(pci_dev, DIO200_DRIVER_NAME); + if (ret < 0) { + printk(KERN_ERR "comedi%d: I/O port conflict (PCI)!\n", + dev->minor); + pci_dev_put(pci_dev); + return ret; + } + devpriv->pci_dev = pci_dev; + } else { + ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE); + if (ret < 0) { + return ret; + } } dev->iobase = iobase; @@ -1373,11 +1381,14 @@ dio200_detach(comedi_device *dev) } } } - if (dev->iobase) { - release_region(dev->iobase, DIO200_IO_SIZE); - } - if (devpriv && devpriv->pci_dev) { - pci_dev_put(devpriv->pci_dev); + if (devpriv) { + if (devpriv->pci_dev) { + pci_release_regions(devpriv->pci_dev); + pci_disable_device(devpriv->pci_dev); + pci_dev_put(devpriv->pci_dev); + } else if (dev->iobase) { + release_region(dev->iobase, DIO200_IO_SIZE); + } } if (dev->board_name) { printk(KERN_INFO "comedi%d: %s removed\n", diff --git a/comedi/drivers/amplc_pc236.c b/comedi/drivers/amplc_pc236.c index bccd7ca8..15678535 100644 --- a/comedi/drivers/amplc_pc236.c +++ b/comedi/drivers/amplc_pc236.c @@ -119,7 +119,6 @@ typedef struct{ struct pci_dev *pci_dev; int lcr_iobase; /* PLX PCI9052 config registers in PCIBAR1 */ int enable_irq; - int share_irq; }pc236_private; #define devpriv ((pc236_private *)dev->private) @@ -167,7 +166,6 @@ static int pc236_attach(comedi_device *dev,comedi_devconfig *it) comedi_subdevice *s; struct pci_dev *pci_dev = NULL; int iobase = 0, irq = 0; - int lcr_iobase = 0; int bus = 0, slot = 0; struct pci_device_id *pci_id; int share_irq = 0; @@ -175,7 +173,7 @@ static int pc236_attach(comedi_device *dev,comedi_devconfig *it) printk("comedi%d: %s: ",dev->minor, PC236_DRIVER_NAME); - /* Get card bus position and base address. */ + /* Process options. */ switch (thisboard->bustype) { case isa_bustype: iobase = it->options[0]; @@ -227,14 +225,6 @@ static int pc236_attach(comedi_device *dev,comedi_devconfig *it) printk("no %s found!\n", thisboard->fancy_name); return -EIO; } - if ((ret=pci_enable_device(pci_dev)) < 0) { - printk("error enabling PCI device!\n"); - pci_dev_put(pci_dev); - return ret; - } - lcr_iobase = pci_resource_start(pci_dev, 1); - iobase = pci_resource_start(pci_dev, 2); - irq = pci_dev->irq; break; default: printk("bug! cannot determine board type!\n"); @@ -259,18 +249,26 @@ static int pc236_attach(comedi_device *dev,comedi_devconfig *it) return ret; } - devpriv->pci_dev = pci_dev; - devpriv->share_irq = share_irq; - - /* Reserve I/O spaces. */ - if (lcr_iobase) { - if ((ret=pc236_request_region(lcr_iobase, PC236_LCR_IO_SIZE)) < 0) { + /* Enable device and reserve I/O spaces. */ + if (pci_dev) { + if ((ret=pci_enable_device(pci_dev)) < 0) { + printk("error enabling PCI device!\n"); + pci_dev_put(pci_dev); + return ret; + } + if ((ret=pci_request_regions(pci_dev, PC236_DRIVER_NAME)) < 0) { + printk("I/O port conflict (PCI)!\n"); + pci_dev_put(pci_dev); + return ret; + } + devpriv->pci_dev = pci_dev; + devpriv->lcr_iobase = pci_resource_start(pci_dev, 1); + iobase = pci_resource_start(pci_dev, 2); + irq = pci_dev->irq; + } else { + if ((ret=pc236_request_region(iobase, PC236_IO_SIZE)) < 0) { return ret; } - devpriv->lcr_iobase = lcr_iobase; - } - if ((ret=pc236_request_region(iobase, PC236_IO_SIZE)) < 0) { - return ret; } dev->iobase = iobase; @@ -347,14 +345,14 @@ static int pc236_detach(comedi_device *dev) if (dev->subdevices) { subdev_8255_cleanup(dev, dev->subdevices+0); } - if (dev->iobase) { - release_region(dev->iobase, PC236_IO_SIZE); - } if (devpriv) { - if (devpriv->lcr_iobase) - release_region(devpriv->lcr_iobase, PC236_LCR_IO_SIZE); - if (devpriv->pci_dev) + if (devpriv->pci_dev) { + pci_release_regions(devpriv->pci_dev); + pci_disable_device(devpriv->pci_dev); pci_dev_put(devpriv->pci_dev); + } else if (dev->iobase) { + release_region(dev->iobase, PC236_IO_SIZE); + } } return 0; @@ -366,7 +364,7 @@ static int pc236_detach(comedi_device *dev) */ static int pc236_request_region(unsigned long from, unsigned long extent) { - if (!request_region(from, extent, PC236_DRIVER_NAME)) { + if (!from || !request_region(from, extent, PC236_DRIVER_NAME)) { printk("I/O port conflict (%#lx,%lu)!\n", from, extent); return -EIO; } diff --git a/comedi/drivers/amplc_pc263.c b/comedi/drivers/amplc_pc263.c index bfd5e1e6..1aa4bc5a 100644 --- a/comedi/drivers/amplc_pc263.c +++ b/comedi/drivers/amplc_pc263.c @@ -149,7 +149,7 @@ static int pc263_attach(comedi_device *dev,comedi_devconfig *it) printk("comedi%d: %s: ",dev->minor, PC263_DRIVER_NAME); - /* Get card bus position and base address. */ + /* Process options. */ switch (thisboard->bustype) { case isa_bustype: iobase = it->options[0]; @@ -198,12 +198,6 @@ static int pc263_attach(comedi_device *dev,comedi_devconfig *it) printk("no %s found!\n", thisboard->fancy_name); return -EIO; } - if ((ret=pci_enable_device(pci_dev)) < 0) { - printk("error enabling PCI device!\n"); - pci_dev_put(pci_dev); - return ret; - } - iobase = pci_resource_start(pci_dev, 2); break; default: printk("bug! cannot determine board type!\n"); @@ -228,11 +222,24 @@ static int pc263_attach(comedi_device *dev,comedi_devconfig *it) return ret; } - devpriv->pci_dev = pci_dev; - - /* Reserve I/O space. */ - if ((ret=pc263_request_region(iobase, PC263_IO_SIZE)) < 0) { - return ret; + /* Enable device and reserve I/O spaces. */ + if (pci_dev) { + if ((ret=pci_enable_device(pci_dev)) < 0) { + printk("error enabling PCI device!\n"); + pci_dev_put(pci_dev); + return ret; + } + if ((ret=pci_request_regions(pci_dev, PC263_DRIVER_NAME)) < 0) { + printk("I/O port conflict (PCI)!\n"); + pci_dev_put(pci_dev); + return ret; + } + devpriv->pci_dev = pci_dev; + iobase = pci_resource_start(pci_dev, 2); + } else { + if ((ret=pc263_request_region(iobase, PC263_IO_SIZE)) < 0) { + return ret; + } } dev->iobase = iobase; @@ -286,11 +293,16 @@ static int pc263_detach(comedi_device *dev) { printk("comedi%d: %s: remove\n", dev->minor, PC263_DRIVER_NAME); - if (dev->iobase) - release_region(dev->iobase, PC263_IO_SIZE); - if (devpriv && devpriv->pci_dev) - pci_dev_put(devpriv->pci_dev); - + if (devpriv) { + if (devpriv->pci_dev) { + pci_release_regions(devpriv->pci_dev); + pci_disable_device(devpriv->pci_dev); + pci_dev_put(devpriv->pci_dev); + } else if (dev->iobase) { + release_region(dev->iobase, PC263_IO_SIZE); + } + } + return 0; } diff --git a/comedi/drivers/amplc_pci224.c b/comedi/drivers/amplc_pci224.c index 8b15c339..c6377a35 100644 --- a/comedi/drivers/amplc_pci224.c +++ b/comedi/drivers/amplc_pci224.c @@ -1355,6 +1355,7 @@ pci224_attach(comedi_device *dev,comedi_devconfig *it) printk(KERN_ERR "comedi%d: error! out of memory!\n", dev->minor); pci_release_regions(pci_dev); + pci_disable_device(pci_dev); pci_dev_put(pci_dev); return ret; } @@ -1545,6 +1546,7 @@ pci224_detach(comedi_device *dev) } if (devpriv->pci_dev) { pci_release_regions(devpriv->pci_dev); + pci_disable_device(devpriv->pci_dev); pci_dev_put(devpriv->pci_dev); } } diff --git a/comedi/drivers/amplc_pci230.c b/comedi/drivers/amplc_pci230.c index def3bd4d..6c59ea25 100644 --- a/comedi/drivers/amplc_pci230.c +++ b/comedi/drivers/amplc_pci230.c @@ -364,21 +364,24 @@ static int pci230_attach(comedi_device *dev,comedi_devconfig *it) pci_iobase = pci_resource_start(pci_dev, 2); iobase = pci_resource_start(pci_dev, 3); + /* Reserve I/O spaces. */ + if(pci_request_regions(pci_dev,"PCI230")<0){ + printk("comedi%d: amplc_pci230: I/O space conflict\n",dev->minor); + pci_dev_put(pci_dev); + return -EIO; + } + printk("comedi%d: amplc_pci230: I/O region 1 0x%04x I/O region 2 0x%04x\n",dev->minor, pci_iobase, iobase); /* Allocate the private structure area using alloc_private(). * Macro defined in comedidev.h - memsets struct fields to 0. */ if((alloc_private(dev,sizeof(struct pci230_private)))<0){ + pci_release_regions(pci_dev); + pci_disable_device(pci_dev); pci_dev_put(pci_dev); return -ENOMEM; } devpriv->pci_dev = pci_dev; - - /* Reserve I/O spaces. */ - if(pci_request_regions(pci_dev,"PCI230")<0){ - printk("comedi%d: amplc_pci230: I/O space conflict\n",dev->minor); - return -EIO; - } devpriv->pci_iobase = pci_iobase; dev->iobase = iobase; @@ -487,8 +490,8 @@ static int pci230_detach(comedi_device *dev) if(devpriv){ if(devpriv->pci_dev){ - if(devpriv->pci_iobase) - pci_release_regions(devpriv->pci_dev); + pci_release_regions(devpriv->pci_dev); + pci_disable_device(devpriv->pci_dev); pci_dev_put(devpriv->pci_dev); } } diff --git a/comedi/drivers/cb_pcidas.c b/comedi/drivers/cb_pcidas.c index 2420ff80..d89ae308 100644 --- a/comedi/drivers/cb_pcidas.c +++ b/comedi/drivers/cb_pcidas.c @@ -507,9 +507,6 @@ static int cb_pcidas_attach(comedi_device *dev, comedi_devconfig *it) comedi_subdevice *s; struct pci_dev* pcidev; int index; - unsigned long s5933_config, control_status, adc_fifo, - pacer_counter_dio, ao_registers; - int err; int i; printk("comedi%d: cb_pcidas: ",dev->minor); @@ -546,7 +543,6 @@ static int cb_pcidas_attach(comedi_device *dev, comedi_devconfig *it) continue; } } - devpriv->pci_dev = pcidev; dev->board_ptr = cb_pcidas_boards + index; goto found; } @@ -559,50 +555,37 @@ static int cb_pcidas_attach(comedi_device *dev, comedi_devconfig *it) found: printk("Found %s on bus %i, slot %i\n", cb_pcidas_boards[index].name, - devpriv->pci_dev->bus->number, PCI_SLOT(devpriv->pci_dev->devfn)); + pcidev->bus->number, PCI_SLOT(pcidev->devfn)); /* - * Initialize devpriv->control_status and devpriv->adc_fifo to point to - * their base address. + * Enable PCI device and reserve I/O ports. */ - if(pci_enable_device(devpriv->pci_dev)) - return -EIO; - s5933_config = pci_resource_start(devpriv->pci_dev, S5933_BADRINDEX); - control_status = pci_resource_start(devpriv->pci_dev, CONT_STAT_BADRINDEX); - adc_fifo = pci_resource_start(devpriv->pci_dev, ADC_FIFO_BADRINDEX); - pacer_counter_dio = pci_resource_start(devpriv->pci_dev, PACER_BADRINDEX); - ao_registers = pci_resource_start(devpriv->pci_dev, AO_BADRINDEX); - - // reserve io ports - err = 0; - if(request_region(s5933_config, AMCC_OP_REG_SIZE, "cb_pcidas")) - devpriv->s5933_config = s5933_config; - else - err++; - if(request_region(control_status, CONT_STAT_SIZE, "cb_pcidas")) - devpriv->control_status = control_status; - else - err++; - if(request_region(adc_fifo, ADC_FIFO_SIZE, "cb_pcidas")) - devpriv->adc_fifo = adc_fifo; - else - err++; - if(request_region(pacer_counter_dio, PACER_SIZE, "cb_pcidas")) - devpriv->pacer_counter_dio = pacer_counter_dio; - else - err++; - if(thisboard->ao_nchan) + if(pci_enable_device(pcidev)) { - if(request_region(ao_registers, AO_SIZE, "cb_pcidas")) - devpriv->ao_registers = ao_registers; - else - err++; + printk(" Failed to enable PCI device\n"); + pci_dev_put(pcidev); + return -EIO; } - if(err) + if(pci_request_regions(pcidev, "cb_pcidas")) { printk(" I/O port conflict\n"); + pci_dev_put(pcidev); return -EIO; } + devpriv->pci_dev = pcidev; + + /* + * Initialize devpriv->control_status and devpriv->adc_fifo to point to + * their base address. + */ + devpriv->s5933_config = pci_resource_start(devpriv->pci_dev, S5933_BADRINDEX); + devpriv->control_status = pci_resource_start(devpriv->pci_dev, CONT_STAT_BADRINDEX); + devpriv->adc_fifo = pci_resource_start(devpriv->pci_dev, ADC_FIFO_BADRINDEX); + devpriv->pacer_counter_dio = pci_resource_start(devpriv->pci_dev, PACER_BADRINDEX); + if(thisboard->ao_nchan) + { + devpriv->ao_registers = pci_resource_start(devpriv->pci_dev, AO_BADRINDEX); + } // get irq if(comedi_request_irq(devpriv->pci_dev->irq, cb_pcidas_interrupt, SA_SHIRQ, "cb_pcidas", dev )) @@ -752,23 +735,18 @@ static int cb_pcidas_detach(comedi_device *dev) #ifdef CB_PCIDAS_DEBUG rt_printk("detaching, incsr is 0x%x\n", inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR)); #endif - release_region(devpriv->s5933_config, AMCC_OP_REG_SIZE); } - if(devpriv->control_status) - release_region(devpriv->control_status, CONT_STAT_SIZE); - if(devpriv->adc_fifo) - release_region(devpriv->adc_fifo, ADC_FIFO_SIZE); - if(devpriv->pacer_counter_dio) - release_region(devpriv->pacer_counter_dio, PACER_SIZE); - if(devpriv->ao_registers) - release_region(devpriv->ao_registers, AO_SIZE); } if(dev->irq) comedi_free_irq(dev->irq, dev); if(dev->subdevices) subdev_8255_cleanup(dev,dev->subdevices + 2); if(devpriv && devpriv->pci_dev) + { + pci_release_regions(devpriv->pci_dev); + pci_disable_device(devpriv->pci_dev); pci_dev_put(devpriv->pci_dev); + } return 0; } diff --git a/comedi/drivers/cb_pcidas64.c b/comedi/drivers/cb_pcidas64.c index f6bcf24a..5c28fc9c 100644 --- a/comedi/drivers/cb_pcidas64.c +++ b/comedi/drivers/cb_pcidas64.c @@ -1696,22 +1696,23 @@ static int attach(comedi_device *dev, comedi_devconfig *it) if( pci_enable_device( pcidev ) ) { + printk(KERN_WARNING " failed to enable PCI device\n"); pci_dev_put( pcidev ); return -EIO; } - pci_set_master( pcidev ); - - priv(dev)->hw_dev = pcidev; - - //Initialize dev->board_name - dev->board_name = board(dev)->name; - if( pci_request_regions( pcidev, driver_cb_pcidas.driver_name ) ) { /* Couldn't allocate io space */ printk(KERN_WARNING " failed to allocate io memory\n"); + pci_dev_put( pcidev ); return -EIO; } + pci_set_master( pcidev ); + + priv(dev)->hw_dev = pcidev; + + //Initialize dev->board_name + dev->board_name = board(dev)->name; priv(dev)->plx9080_phys_iobase = pci_resource_start(pcidev, PLX9080_BADDRINDEX); priv(dev)->main_phys_iobase = pci_resource_start(pcidev, MAIN_BADDRINDEX); @@ -1794,9 +1795,6 @@ static int detach(comedi_device *dev) iounmap((void*)priv(dev)->main_iobase); if(priv(dev)->dio_counter_iobase) iounmap((void*)priv(dev)->dio_counter_iobase); - if(priv(dev)->plx9080_phys_iobase || - priv(dev)->main_phys_iobase || priv(dev)->dio_counter_phys_iobase) - pci_release_regions( priv(dev)->hw_dev ); // free pci dma buffers for(i = 0; i < ai_dma_ring_count(board(dev)); i++) { @@ -1817,6 +1815,7 @@ static int detach(comedi_device *dev) if(priv(dev)->ao_dma_desc) pci_free_consistent(priv(dev)->hw_dev, sizeof(struct plx_dma_desc) * AO_DMA_RING_COUNT, priv(dev)->ao_dma_desc, priv(dev)->ao_dma_desc_bus_addr ); + pci_release_regions(priv(dev)->hw_dev); pci_disable_device(priv(dev)->hw_dev); pci_dev_put(priv(dev)->hw_dev); } diff --git a/comedi/drivers/cb_pcidda.c b/comedi/drivers/cb_pcidda.c index 9ea4ff38..d2c1f3d5 100644 --- a/comedi/drivers/cb_pcidda.c +++ b/comedi/drivers/cb_pcidda.c @@ -314,7 +314,6 @@ static int cb_pcidda_attach(comedi_device *dev, comedi_devconfig *it) return -EIO; found: - devpriv->pci_dev = pcidev; dev->board_ptr = cb_pcidda_boards+index; // "thisboard" macro can be used from here. printk("Found %s at requested position\n",thisboard->name); @@ -323,17 +322,23 @@ found: * Initialize devpriv->control_status and devpriv->adc_fifo to point to * their base address. */ - if(pci_enable_device(devpriv->pci_dev)) + if(pci_enable_device(pcidev)) + { + printk("cb_pcidda: failed to enable PCI device\n"); + pci_dev_put(pcidev); return -EIO; + } /* * Allocate the I/O ports. */ - if (pci_request_regions(devpriv->pci_dev, thisboard->name)) + if (pci_request_regions(pcidev, thisboard->name)) { printk("cb_pcidda: I/O port conflict\n"); + pci_dev_put(pcidev); return -EIO; } + devpriv->pci_dev = pcidev; devpriv->digitalio = pci_resource_start(devpriv->pci_dev, DIGITALIO_BADRINDEX); devpriv->dac = pci_resource_start(devpriv->pci_dev, DAC_BADRINDEX); @@ -405,12 +410,12 @@ static int cb_pcidda_detach(comedi_device *dev) */ if(devpriv) { - if(devpriv->digitalio) - release_region(devpriv->digitalio, DIGITALIO_SIZE); - if(devpriv->dac) - release_region(devpriv->dac, 8 + thisboard->ao_chans*2); if(devpriv->pci_dev) + { + pci_release_regions(devpriv->pci_dev); + pci_disable_device(devpriv->pci_dev); pci_dev_put(devpriv->pci_dev); + } } // cleanup 8255 if(dev->subdevices) diff --git a/comedi/drivers/cb_pcimdas.c b/comedi/drivers/cb_pcimdas.c index 79be50d7..66c32347 100644 --- a/comedi/drivers/cb_pcimdas.c +++ b/comedi/drivers/cb_pcimdas.c @@ -235,7 +235,6 @@ static int cb_pcimdas_attach(comedi_device *dev,comedi_devconfig *it) continue; } } - devpriv->pci_dev = pcidev; dev->board_ptr = cb_pcimdas_boards + index; goto found; } @@ -248,7 +247,7 @@ static int cb_pcimdas_attach(comedi_device *dev,comedi_devconfig *it) found: printk("Found %s on bus %i, slot %i\n", cb_pcimdas_boards[index].name, - devpriv->pci_dev->bus->number, PCI_SLOT(devpriv->pci_dev->devfn)); + pcidev->bus->number, PCI_SLOT(pcidev->devfn)); // Warn about non-tested features switch(thisboard->device_id) @@ -260,19 +259,26 @@ found: "PLEASE REPORT USAGE TO \n"); }; - if(pci_request_regions(devpriv->pci_dev, "cb_pcimdas")) + if(pci_enable_device(pcidev)) + { + printk(" Failed to enable PCI device\n"); + pci_dev_put(pcidev); + return -EIO; + } + if(pci_request_regions(pcidev, "cb_pcimdas")) { printk(" I/O port conflict\n"); + pci_dev_put(pcidev); return -EIO; } + devpriv->pci_dev = pcidev; + devpriv->BADR0 = pci_resource_start(devpriv->pci_dev, 0); devpriv->BADR1 = pci_resource_start(devpriv->pci_dev, 1); devpriv->BADR2 = pci_resource_start(devpriv->pci_dev, 2); devpriv->BADR3 = pci_resource_start(devpriv->pci_dev, 3); devpriv->BADR4 = pci_resource_start(devpriv->pci_dev, 4); - if(pci_enable_device(devpriv->pci_dev)) - return -EIO; #ifdef CBPCIMDAS_DEBUG printk("devpriv->BADR0 = %d\n",devpriv->BADR0); printk("devpriv->BADR1 = %d\n",devpriv->BADR1); @@ -360,18 +366,17 @@ static int cb_pcimdas_detach(comedi_device *dev) } #endif printk("comedi%d: cb_pcimdas: remove\n",dev->minor); + if(dev->irq) + comedi_free_irq(dev->irq, dev); if(devpriv) { - if(devpriv->BADR0) + if(devpriv->pci_dev) { pci_release_regions(devpriv->pci_dev); - } - if(devpriv->pci_dev) + pci_disable_device(devpriv->pci_dev); pci_dev_put(devpriv->pci_dev); + } } - - if(dev->irq) - comedi_free_irq(dev->irq, dev); return 0; } diff --git a/comedi/drivers/cb_pcimdda.c b/comedi/drivers/cb_pcimdda.c index fd8e787a..e6e2ac40 100644 --- a/comedi/drivers/cb_pcimdda.c +++ b/comedi/drivers/cb_pcimdda.c @@ -337,7 +337,6 @@ static int detach(comedi_device *dev) if (devpriv) { if (devpriv->registers && thisboard) { - release_region(devpriv->registers, REG_SZ); devpriv->registers = 0; } @@ -348,6 +347,8 @@ static int detach(comedi_device *dev) } if (devpriv->pci_dev) { + pci_release_regions(devpriv->pci_dev); + pci_disable_device(devpriv->pci_dev); pci_dev_put(devpriv->pci_dev); } @@ -465,22 +466,21 @@ static int probe(comedi_device *dev, const comedi_devconfig *it) } /* found ! */ - /* todo: if we support more than 1 board, revise - this to be more generic */ - devpriv->pci_dev = pcidev; - pci_enable_device(devpriv->pci_dev); /* make sure board is on */ dev->board_ptr = boards + index; - registers = pci_resource_start(devpriv->pci_dev, REGS_BADRINDEX); - request_region(registers, REG_SZ,thisboard->name); -#if 0 + if (pci_enable_device(pcidev)) + { + printk("cb_pcimdda: Failed to enable PCI device\n"); + pci_dev_put(pcidev); + return -EIO; + } + if (pci_request_regions(pcidev, thisboard->name)) { - printk("cb_pcimdda: " - "I/O port conflict failed to allocate ports " - "0x%x to 0x%x\n", registers, - registers + REG_SZ - 1); - return -EBUSY; + printk("cb_pcimdda: I/O port conflict\n"); + pci_dev_put(pcidev); + return -EIO; } -#endif + devpriv->pci_dev = pcidev; + registers = pci_resource_start(devpriv->pci_dev, REGS_BADRINDEX); devpriv->registers = registers; devpriv->dio_registers = devpriv->registers + thisboard->dio_offset; diff --git a/comedi/drivers/contec_pci_dio.c b/comedi/drivers/contec_pci_dio.c index 5414799a..7c29abaa 100644 --- a/comedi/drivers/contec_pci_dio.c +++ b/comedi/drivers/contec_pci_dio.c @@ -112,6 +112,14 @@ static int contec_attach(comedi_device *dev,comedi_devconfig *it) if ( pcidev->vendor == PCI_VENDOR_ID_CONTEC && pcidev->device == PCI_DEVICE_ID_PIO1616L ) { + if (pci_enable_device(pcidev)) { + printk("error enabling PCI device!\n"); + return -EIO; + } + if (pci_request_regions(pcidev, "contec_pci_dio")) { + printk("I/O port conflict!\n"); + return -EIO; + } devpriv->pci_dev = pcidev; dev->iobase = pci_resource_start ( pcidev, 0 ); printk ( " base addr %lx ", dev->iobase ); @@ -135,12 +143,15 @@ static int contec_attach(comedi_device *dev,comedi_devconfig *it) s->range_table = &range_digital; s->insn_bits = contec_do_insn_bits; + printk("attached\n"); + + return 1; } } - printk("attached\n"); + printk("card not present!\n"); - return 1; + return -EIO; } @@ -148,8 +159,11 @@ static int contec_detach(comedi_device *dev) { printk("comedi%d: contec: remove\n",dev->minor); - if (devpriv && devpriv->pci_dev) + if (devpriv && devpriv->pci_dev) { + pci_release_regions(devpriv->pci_dev); + pci_disable_device(devpriv->pci_dev); pci_dev_put(devpriv->pci_dev); + } return 0; } diff --git a/comedi/drivers/daqboard2000.c b/comedi/drivers/daqboard2000.c index 3026b43d..d6d57d78 100644 --- a/comedi/drivers/daqboard2000.c +++ b/comedi/drivers/daqboard2000.c @@ -698,17 +698,10 @@ static int daqboard2000_attach(comedi_device *dev, comedi_devconfig *it) printk(" no daqboard2000 found\n"); result = -EIO; goto out; - } - - if((result = pci_enable_device(card))<0){ - pci_dev_put(card); - goto out; - } - - if (card->hdr_type == PCI_HEADER_TYPE_NORMAL) { + }else{ u32 id; int i; - pci_read_config_dword(card, PCI_SUBSYSTEM_VENDOR_ID, &id); + id = ((u32)card->subsystem_device << 16) | card->subsystem_vendor; for(i=0;iboard_ptr=boardtypes; } - }else{ - printk(" abnormal pci header type !?!?\n"); - result=-EIO; + } + + if((result = pci_enable_device(card))<0){ pci_dev_put(card); goto out; } - + + if((result = pci_request_regions(card, "daqboard2000")) < 0) { + pci_dev_put(card); + goto out; + } + result = alloc_private(dev,sizeof(daqboard2000_private)); if(result<0){ + pci_release_regions(card); + pci_disable_device(card); pci_dev_put(card); goto out; } @@ -815,6 +815,8 @@ static int daqboard2000_detach(comedi_device * dev) free_irq(dev->irq, dev); } if (devpriv && devpriv->pci_dev) { + pci_release_regions(devpriv->pci_dev); + pci_disable_device(devpriv->pci_dev); pci_dev_put(devpriv->pci_dev); } return 0; diff --git a/comedi/drivers/das08.c b/comedi/drivers/das08.c index 69e40a57..154f2353 100644 --- a/comedi/drivers/das08.c +++ b/comedi/drivers/das08.c @@ -810,8 +810,8 @@ int das08_common_attach(comedi_device *dev, unsigned long iobase ) comedi_subdevice *s; int ret; - // allocate ioports for non-pcmcia boards - if(thisboard->bustype != pcmcia) + // allocate ioports for non-pcmcia, non-pci boards + if((thisboard->bustype != pcmcia) && (thisboard->bustype != pci)) { printk(" iobase 0x%lx\n", iobase); if(!request_region(iobase, thisboard->iosize,"das08")){ @@ -955,18 +955,23 @@ static int das08_attach(comedi_device *dev,comedi_devconfig *it) printk("No pci das08 cards found\n"); return -EIO; } - devpriv->pdev = pdev; - // read base addresses - if(pci_enable_device(pdev)) + // enable PCI device + if(pci_enable_device(pdev)){ + printk(" Error enabling PCI device\n"); + pci_dev_put(pdev); return -EIO; - pci_iobase = pci_resource_start(pdev, 1); - iobase = pci_resource_start(pdev, 2); - printk("pcibase 0x%lx ", pci_iobase); - // reserve io ports for 9052 pci chip - if(!request_region(pci_iobase,PCIDAS08_SIZE,"das08")){ + } + // reserve I/O spaces + if(pci_request_regions(pdev, "das08")){ printk(" I/O port conflict\n"); + pci_dev_put(pdev); return -EIO; } + devpriv->pdev = pdev; + // read base addresses + pci_iobase = pci_resource_start(pdev, 1); + iobase = pci_resource_start(pdev, 2); + printk("pcibase 0x%lx iobase 0x%lx\n", pci_iobase, iobase); devpriv->pci_iobase = pci_iobase; #if 0 /* We could enable to pci-das08's interrupt here to make it possible @@ -994,18 +999,17 @@ int das08_common_detach(comedi_device *dev) if(dev->subdevices) subdev_8255_cleanup(dev,dev->subdevices+4); - // deallocate ioports for non-pcmcia boards - if(thisboard->bustype != pcmcia) + // deallocate ioports for non-pcmcia, non-pci boards + if((thisboard->bustype != pcmcia) && (thisboard->bustype != pci)) { if(dev->iobase) release_region(dev->iobase, thisboard->iosize); } if(devpriv){ - if(devpriv->pci_iobase){ - release_region(devpriv->pci_iobase, PCIDAS08_SIZE); - } if(devpriv->pdev){ + pci_release_regions(devpriv->pdev); + pci_disable_device(devpriv->pdev); pci_dev_put(devpriv->pdev); } } diff --git a/comedi/drivers/dt3000.c b/comedi/drivers/dt3000.c index d95d2201..183ea70e 100644 --- a/comedi/drivers/dt3000.c +++ b/comedi/drivers/dt3000.c @@ -253,6 +253,7 @@ MODULE_DEVICE_TABLE(pci, dt3k_pci_table); typedef struct{ struct pci_dev *pci_dev; + int pci_enabled; unsigned long phys_addr; void *io_addr; unsigned int lock; @@ -855,7 +856,15 @@ static int dt3000_detach(comedi_device *dev) if(devpriv) { - if(devpriv->pci_dev) pci_dev_put(devpriv->pci_dev); + if(devpriv->pci_dev) + { + if (devpriv->pci_enabled) + { + pci_release_regions(devpriv->pci_dev); + pci_disable_device(devpriv->pci_dev); + } + pci_dev_put(devpriv->pci_dev); + } if(devpriv->io_addr) iounmap(devpriv->io_addr); } /* XXX */ @@ -870,14 +879,17 @@ static int setup_pci(comedi_device *dev); static int dt_pci_probe(comedi_device *dev) { int board; + int ret; devpriv->pci_dev=dt_pci_find_device(NULL,&board); - dev->board_ptr=dt3k_boardtypes+board; + if(board >= 0) + dev->board_ptr=dt3k_boardtypes+board; if(!devpriv->pci_dev) return 0; - setup_pci(dev); + if ((ret=setup_pci(dev)) < 0) + return ret; return 1; } @@ -891,6 +903,11 @@ static int setup_pci(comedi_device *dev) ret = pci_enable_device(devpriv->pci_dev); if(ret<0)return ret; + ret = pci_request_regions(devpriv->pci_dev, "dt3000"); + if(ret<0)return ret; + + devpriv->pci_enabled = 1; + addr=pci_resource_start(devpriv->pci_dev,0); devpriv->phys_addr=addr; offset = devpriv->phys_addr & ~PAGE_MASK; diff --git a/comedi/drivers/gsc_hpdi.c b/comedi/drivers/gsc_hpdi.c index e6743bfd..1e3b27a2 100644 --- a/comedi/drivers/gsc_hpdi.c +++ b/comedi/drivers/gsc_hpdi.c @@ -577,22 +577,23 @@ static int hpdi_attach(comedi_device *dev, comedi_devconfig *it) if( pci_enable_device( pcidev ) ) { + printk(KERN_WARNING " failed enable PCI device\n"); pci_dev_put( pcidev ); return -EIO; } - pci_set_master( pcidev ); - - priv(dev)->hw_dev = pcidev; - - //Initialize dev->board_name - dev->board_name = board(dev)->name; - if( pci_request_regions( pcidev, driver_hpdi.driver_name ) ) { /* Couldn't allocate io space */ printk(KERN_WARNING " failed to allocate io memory\n"); + pci_dev_put( pcidev ); return -EIO; } + pci_set_master( pcidev ); + + priv(dev)->hw_dev = pcidev; + + //Initialize dev->board_name + dev->board_name = board(dev)->name; priv(dev)->plx9080_phys_iobase = pci_resource_start(pcidev, PLX9080_BADDRINDEX); priv(dev)->hpdi_phys_iobase = pci_resource_start(pcidev, HPDI_BADDRINDEX); @@ -667,9 +668,6 @@ static int hpdi_detach(comedi_device *dev) } if( priv(dev)->hpdi_iobase ) iounmap((void*)priv(dev)->hpdi_iobase); - if( priv(dev)->plx9080_phys_iobase || - priv(dev)->hpdi_phys_iobase ) - pci_release_regions( priv(dev)->hw_dev ); // free pci dma buffers for( i = 0; i < NUM_DMA_BUFFERS; i++ ) { @@ -681,6 +679,7 @@ static int hpdi_detach(comedi_device *dev) if( priv(dev)->dma_desc ) pci_free_consistent( priv(dev)->hw_dev, sizeof( struct plx_dma_desc ) * NUM_DMA_DESCRIPTORS, priv(dev)->dma_desc, priv(dev)->dma_desc_phys_addr ); + pci_release_regions( priv(dev)->hw_dev ); pci_disable_device( priv(dev)->hw_dev ); pci_dev_put(priv(dev)->hw_dev); } diff --git a/comedi/drivers/icp_multi.c b/comedi/drivers/icp_multi.c index 4653a1de..20376420 100644 --- a/comedi/drivers/icp_multi.c +++ b/comedi/drivers/icp_multi.c @@ -136,7 +136,7 @@ static int icp_multi_detach(comedi_device *dev); Data & Structure declarations ============================================================================== */ -static unsigned short pci_list_builded=0; /*=1 list of card is know */ +static unsigned short pci_list_builded=0; /*>0 list of card is known */ typedef struct { char *name; // driver name @@ -191,6 +191,7 @@ static comedi_driver driver_icp_multi={ COMEDI_INITCLEANUP(driver_icp_multi); typedef struct{ + struct pcilst_struct *card; // pointer to card char valid; // card is usable void *io_addr; // Pointer to mapped io address unsigned long phys_iobase; // Physical io address @@ -873,7 +874,7 @@ static int icp_multi_attach(comedi_device *dev,comedi_devconfig *it) return ret; // Initialise list of PCI cards in system, if not already done so - if (!pci_list_builded) { + if (pci_list_builded++ == 0) { pci_card_list_init(PCI_VENDOR_ID_ICP, #ifdef ICP_MULTI_EXTDEBUG 1 @@ -881,7 +882,6 @@ static int icp_multi_attach(comedi_device *dev,comedi_devconfig *it) 0 #endif ); - pci_list_builded=1; } printk("Anne's comedi%d: icp_multi: board=%s", dev->minor, this_board->name); @@ -889,20 +889,14 @@ static int icp_multi_attach(comedi_device *dev,comedi_devconfig *it) if ((card=select_and_alloc_pci_card(PCI_VENDOR_ID_ICP, this_board->device_id, it->options[0], it->options[1]))==NULL) return -EIO; + devpriv->card = card; + if ((pci_card_data(card, &pci_bus, &pci_slot, &pci_func, &io_addr[0], &irq, &master))<0) { - pci_card_free(card); printk(" - Can't get configuration data!\n"); return -EIO; } iobase=io_addr[2]; - - if(!request_mem_region(iobase, ICP_MULTI_SIZE, "icp_multi")) - { - /* Couldn't allocate io space */ - printk(KERN_WARNING "couldn't allocate IO space\n"); - return -EIO; - } devpriv->phys_iobase = iobase; printk(", b:s:f=%d:%d:%d, io=0x%8lx \n", pci_bus, pci_slot, pci_func, iobase); @@ -928,7 +922,6 @@ static int icp_multi_attach(comedi_device *dev,comedi_devconfig *it) if (this_board->n_ctrs) n_subdevices++; if((ret=alloc_subdevices(dev, n_subdevices))<0) { - pci_card_free(card); return ret; } @@ -1058,14 +1051,14 @@ static int icp_multi_detach(comedi_device *dev) if (dev->irq) comedi_free_irq(dev->irq,dev); - if (dev->private && devpriv->io_addr) { + if (dev->private && devpriv->io_addr) iounmap(devpriv->io_addr); - release_mem_region(devpriv->phys_iobase, ICP_MULTI_SIZE); - } - if (pci_list_builded) { + if (dev->private && devpriv->card) + pci_card_free(devpriv->card); + + if (--pci_list_builded == 0) { pci_card_list_cleanup(PCI_VENDOR_ID_ICP); - pci_list_builded=0; } diff --git a/comedi/drivers/icp_multi.h b/comedi/drivers/icp_multi.h index 27cc3c4f..6086da96 100644 --- a/comedi/drivers/icp_multi.h +++ b/comedi/drivers/icp_multi.h @@ -81,6 +81,9 @@ inova->master = 1; //XXX inova->pci_bus=pcidev->bus->number; inova->pci_slot=PCI_SLOT(pcidev->devfn); inova->pci_func=PCI_FUNC(pcidev->devfn); + /* Note: resources may be invalid if PCI device + * not enabled, but they are corrected in + * pci_card_alloc. */ for (i=0;i<5;i++) inova->io_addr[i]=pci_resource_start(pcidev, i); inova->irq=pcidev->irq; @@ -145,10 +148,27 @@ static int find_free_pci_card_by_position(unsigned short vendor_id, unsigned sho /* mark card as used */ static int pci_card_alloc(struct pcilst_struct *inova) { - if (!inova) return -1; + int i; + + if (!inova) { + rt_printk(" - BUG!! inova is NULL!\n"); + return -1; + } if (inova->used) return 1; - if(pci_enable_device(inova->pcidev)) return -1; + if(pci_enable_device(inova->pcidev)) { + rt_printk(" - Can't enable PCI device!\n"); + return -1; + } + /* Resources will be accurate now. */ + for (i=0;i<5;i++) + inova->io_addr[i]=pci_resource_start(inova->pcidev, i); + inova->irq=inova->pcidev->irq; + /* Request regions on behalf of client. */ + if (pci_request_regions(inova->pcidev, "icp_multi")) { + rt_printk(" - I/O port conflict!\n"); + return -1; + } inova->used=1; return 0; } @@ -161,6 +181,8 @@ static int pci_card_free(struct pcilst_struct *inova) if (!inova->used) return 1; inova->used=0; + pci_release_regions(inova->pcidev); + pci_disable_device(inova->pcidev); return 0; } @@ -206,6 +228,7 @@ static int pci_card_data(struct pcilst_struct *inova, static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id, unsigned short device_id, unsigned short pci_bus, unsigned short pci_slot) { struct pcilst_struct *card; + int err; if ((pci_bus<1)&(pci_slot<1)) { // use autodetection if ((card=find_free_pci_card_by_device(vendor_id,device_id))==NULL) { @@ -224,8 +247,10 @@ static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id, } - if (pci_card_alloc(card)!=0) { - rt_printk(" - Can't allocate card!\n"); + if ((err=pci_card_alloc(card))!=0) { + if (err > 0) + rt_printk(" - Can't allocate card!\n"); + /* else: error already printed. */ return NULL; } diff --git a/comedi/drivers/ke_counter.c b/comedi/drivers/ke_counter.c index 658084a2..54308062 100644 --- a/comedi/drivers/ke_counter.c +++ b/comedi/drivers/ke_counter.c @@ -185,9 +185,22 @@ found: board->name, pci_device->bus->number, PCI_SLOT(pci_device->devfn)); dev->board_name = board->name; + /* enable PCI device */ + if((error = pci_enable_device(pci_device)) < 0) + { + pci_dev_put(pci_device); + return error; + } + + /* request PCI regions */ + if((error = pci_request_regions(pci_device, CNT_DRIVER_NAME)) < 0) + { + pci_dev_put(pci_device); + return error; + } + /* read register base address [PCI_BASE_ADDRESS #0] */ io_base = pci_resource_start(pci_device, 0); - request_region(io_base & PCI_BASE_ADDRESS_IO_MASK, 0x08, CNT_DRIVER_NAME); dev->iobase = io_base & PCI_BASE_ADDRESS_IO_MASK; /* allocate device private structure */ @@ -231,12 +244,10 @@ found: static int cnt_detach(comedi_device *dev) { - if (dev->iobase) - { - release_region(dev->iobase, 0x08); - } - if (devpriv->pcidev) + if (devpriv && devpriv->pcidev) { + pci_release_regions(devpriv->pcidev); + pci_disable_device(devpriv->pcidev); pci_dev_put(devpriv->pcidev); } diff --git a/comedi/drivers/me4000.c b/comedi/drivers/me4000.c index 5214deef..d694ea14 100644 --- a/comedi/drivers/me4000.c +++ b/comedi/drivers/me4000.c @@ -444,79 +444,82 @@ found: /* Set data in device structure */ dev->board_name = board->name; - info->pci_dev_p = pci_device; - /* Get the PCI base registers */ - result = get_registers(dev, pci_device); + /* Enable PCI device */ + result = pci_enable_device(pci_device); if(result){ - printk(KERN_ERR"comedi%d: me4000: me4000_probe(): Cannot get registers\n", dev->minor); - goto PROBE_ERROR_1; + printk(KERN_ERR"comedi%d: me4000: me4000_probe(): Cannot enable PCI device\n", dev->minor); + pci_dev_put(pci_device); + return result; } /* Request the PCI register regions */ result = pci_request_regions(pci_device, dev->board_name); if (result < 0){ printk(KERN_ERR"comedi%d: me4000: me4000_probe(): Cannot request I/O regions\n", dev->minor); - goto PROBE_ERROR_1; + pci_dev_put(pci_device); + return result; } - /* Initialize board info */ + /* Get the PCI base registers */ + result = get_registers(dev, pci_device); + if(result){ + printk(KERN_ERR"comedi%d: me4000: me4000_probe(): Cannot get registers\n", dev->minor); + pci_release_regions(pci_device); + pci_disable_device(pci_device); + pci_dev_put(pci_device); + return result; + } + /* Initialize board info (sets info->pci_dev_p) */ result = init_board_info(dev, pci_device); if (result){ printk(KERN_ERR"comedi%d: me4000: me4000_probe(): Cannot init baord info\n", dev->minor); - goto PROBE_ERROR_2; + return result; } /* Init analog output context */ result = init_ao_context(dev); if (result){ printk(KERN_ERR"comedi%d: me4000: me4000_probe(): Cannot init ao context\n", dev->minor); - goto PROBE_ERROR_2; + return result; } /* Init analog input context */ result = init_ai_context(dev); if (result){ printk(KERN_ERR"comedi%d: me4000: me4000_probe(): Cannot init ai context\n", dev->minor); - goto PROBE_ERROR_2; + return result; } /* Init digital I/O context */ result = init_dio_context(dev); if (result){ printk(KERN_ERR"comedi%d: me4000: me4000_probe(): Cannot init dio context\n", dev->minor); - goto PROBE_ERROR_2; + return result; } /* Init counter context */ result = init_cnt_context(dev); if (result){ printk(KERN_ERR"comedi%d: me4000: me4000_probe(): Cannot init cnt context\n", dev->minor); - goto PROBE_ERROR_2; + return result; } /* Download the xilinx firmware */ result = xilinx_download(dev); if(result){ printk(KERN_ERR"comedi%d: me4000: me4000_probe(): Can't download firmware\n", dev->minor); - goto PROBE_ERROR_2; + return result; } /* Make a hardware reset */ result = reset_board(dev); if(result){ printk(KERN_ERR"comedi%d: me4000: me4000_probe(): Can't reset board\n", dev->minor); - goto PROBE_ERROR_2; + return result; } return 0; - -PROBE_ERROR_2: - pci_release_regions(pci_device); - -PROBE_ERROR_1: - - return result; } @@ -856,9 +859,8 @@ static int me4000_detach(comedi_device *dev){ CALL_PDEBUG("In me4000_detach()\n"); if(info){ - reset_board(dev); - if(info->pci_dev_p) { + reset_board(dev); pci_release_regions(info->pci_dev_p); pci_dev_put(info->pci_dev_p); } diff --git a/comedi/drivers/me_daq.c b/comedi/drivers/me_daq.c index fda6451f..60f49180 100644 --- a/comedi/drivers/me_daq.c +++ b/comedi/drivers/me_daq.c @@ -737,6 +737,22 @@ found: return -ENOMEM; } + // Enable PCI device + if(pci_enable_device(pci_device) < 0) + { + printk("comedi%d: Failed to enable PCI device\n", dev->minor); + pci_dev_put(pci_device); + return -EIO; + } + + // Request PCI regions + if(pci_request_regions(pci_device, ME_DRIVER_NAME) < 0) + { + printk("comedi%d: I/O memory conflict\n", dev->minor); + pci_dev_put(pci_device); + return -EIO; + } + // Set data in device structure dev->board_name = board->name; @@ -881,10 +897,15 @@ static int me_detach(comedi_device *dev) { if(dev_private) { - me_reset(dev); + if (dev_private->me_regbase) + { + me_reset(dev); + } if(dev_private->pci_device) { + pci_release_regions(dev_private->pci_device); + pci_disable_device(dev_private->pci_device); pci_dev_put(dev_private->pci_device); } } diff --git a/comedi/drivers/mite.c b/comedi/drivers/mite.c index d4330994..2e195226 100644 --- a/comedi/drivers/mite.c +++ b/comedi/drivers/mite.c @@ -195,8 +195,10 @@ void mite_unsetup(struct mite_struct *mite) iounmap(mite->daq_io_addr); mite->daq_io_addr=NULL; } - if( mite->used ) + if( mite->used ){ pci_release_regions( mite->pcidev ); + pci_disable_device( mite->pcidev ); + } mite->used = 0; } diff --git a/comedi/drivers/rtd520.c b/comedi/drivers/rtd520.c index cc22ddd2..0abcbebe 100644 --- a/comedi/drivers/rtd520.c +++ b/comedi/drivers/rtd520.c @@ -800,18 +800,25 @@ static int rtd_attach ( return -EIO; } - devpriv->pci_dev = pcidev; if (pcidev->device != thisboard->device_id) { printk ("Found an RTD card, but not the supported type (%x).\n", pcidev->device); + pci_dev_put(pcidev); return -EIO; } dev->board_name = thisboard->name; if((ret=pci_enable_device(pcidev))<0){ + pci_dev_put(pcidev); + return ret; + } + if((ret=pci_request_regions(pcidev, "rtd520"))<0){ + pci_dev_put(pcidev); return ret; } + devpriv->pci_dev = pcidev; + /* * Initialize base addresses */ @@ -825,6 +832,10 @@ static int rtd_attach ( devpriv->las1 = ioremap_nocache(physLas1, LAS1_PCISIZE); devpriv->lcfg = ioremap_nocache(physLcfg, LCFG_PCISIZE); + if(!devpriv->las0 || !devpriv->las1 || !devpriv->lcfg){ + return -ENOMEM; + } + DPRINTK ("%s: LAS0=%lx, LAS1=%lx, CFG=%lx.\n", dev->board_name, physLas0, physLas1, physLcfg); { /* The RTD driver does this */ @@ -923,6 +934,7 @@ static int rtd_attach ( if((ret=comedi_request_irq (dev->irq, rtd_interrupt, SA_SHIRQ, "rtd520", dev)) < 0) { printk("Could not get interrupt! (%d)\n", dev->irq); + dev->irq = 0; return ret; } printk("( irq=%d )", dev->irq); @@ -1086,23 +1098,30 @@ static int rtd_detach ( int index; #endif - DPRINTK("comedi%d: rtd520: removing (%ld ints)\n(int status 0x%x, overrun status 0x%x, fifo status 0x%x)...\n", - dev->minor, devpriv->intCount, - 0xffff & RtdInterruptStatus (dev), - 0xffff & RtdInterruptOverrunStatus (dev), - (0xffff & RtdFifoStatus (dev)) ^ 0x6666); + DPRINTK("comedi%d: rtd520: removing (%ld ints)\n", + dev->minor, (devpriv ? devpriv->intCount : 0L)); + if (devpriv && devpriv->lcfg) { + DPRINTK("(int status 0x%x, overrun status 0x%x, fifo status 0x%x)...\n", + 0xffff & RtdInterruptStatus (dev), + 0xffff & RtdInterruptOverrunStatus (dev), + (0xffff & RtdFifoStatus (dev)) ^ 0x6666); + } if (devpriv) { /* Shut down any board ops by resetting it */ #ifdef USE_DMA - RtdDma0Control (dev, 0); /* disable DMA */ - RtdDma1Control (dev, 0); /* disable DMA */ - RtdPlxInterruptWrite (dev, ICS_PIE | ICS_PLIE); + if (devpriv->lcfg) { + RtdDma0Control (dev, 0); /* disable DMA */ + RtdDma1Control (dev, 0); /* disable DMA */ + RtdPlxInterruptWrite (dev, ICS_PIE | ICS_PLIE); + } #endif /* USE_DMA */ - RtdResetBoard (dev); - RtdInterruptMask (dev, 0); - RtdInterruptClearMask (dev,~0); - RtdInterruptClear(dev); /* clears bits set by mask */ + if (devpriv->las0) { + RtdResetBoard (dev); + RtdInterruptMask (dev, 0); + RtdInterruptClearMask (dev,~0); + RtdInterruptClear(dev); /* clears bits set by mask */ + } #ifdef USE_DMA /* release DMA */ @@ -1145,6 +1164,8 @@ static int rtd_detach ( iounmap (devpriv->lcfg); } if (devpriv->pci_dev) { + pci_release_regions(devpriv->pci_dev); + pci_disable_device(devpriv->pci_dev); pci_dev_put(devpriv->pci_dev); } } diff --git a/comedi/drivers/s626.c b/comedi/drivers/s626.c index 90bbe091..ea6ac1a5 100644 --- a/comedi/drivers/s626.c +++ b/comedi/drivers/s626.c @@ -481,24 +481,32 @@ static int s626_attach(comedi_device *dev,comedi_devconfig *it) uint64_t resourceStart; dma_addr_t appdma; comedi_subdevice *s; + struct pci_dev *pdev; if(alloc_private(dev,sizeof(s626_private))<0) return -ENOMEM; - devpriv->pdev=NULL; - - devpriv->pdev=pci_find_device(PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, NULL); + pdev=pci_get_device(PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, NULL); - if(devpriv->pdev==NULL) { + if(pdev==NULL) { printk("s626_attach: Board not present!!!"); return -ENODEV; } - if((result = pci_enable_device(devpriv->pdev))<0){ + if((result = pci_enable_device(pdev))<0){ printk("s626_attach: pci_enable_device fails\n"); + pci_dev_put(pdev); + return -ENODEV; + } + + if((result = pci_request_regions(pdev, "s626"))<0){ + printk("s626_attach: pci_request_regions fails\n"); + pci_dev_put(pdev); return -ENODEV; } + devpriv->pdev = pdev; + resourceStart=(uint64_t)pci_resource_start(devpriv->pdev,0); devpriv->base_addr=ioremap(resourceStart, SIZEOF_ADDRESS_SPACE); @@ -1194,29 +1202,41 @@ static irqreturn_t s626_irq_handler(int irq,void *d,struct pt_regs * regs) static int s626_detach(comedi_device *dev) { - //stop ai_command - devpriv->ai_cmd_running=0; - - //interrupt mask - WR7146( P_IER, 0 ); // Disable master interrupt. - WR7146( P_ISR, IRQ_GPIO3 | IRQ_RPS1 ); // Clear board's IRQ status - // flag. - - // Disable the watchdog timer and battery charger. - WriteMISC2(dev,0); - - // Close all interfaces on 7146 device. - WR7146( P_MC1, MC1_SHUTDOWN ); - WR7146( P_ACON1, ACON1_BASE ); - - CloseDMAB(dev,&devpriv->RPSBuf,DMABUF_SIZE); - CloseDMAB(dev,&devpriv->ANABuf,DMABUF_SIZE); + if(devpriv){ + //stop ai_command + devpriv->ai_cmd_running=0; + + if(devpriv->base_addr){ + //interrupt mask + WR7146( P_IER, 0 ); // Disable master interrupt. + WR7146( P_ISR, IRQ_GPIO3 | IRQ_RPS1 ); // Clear board's IRQ status + // flag. + + // Disable the watchdog timer and battery charger. + WriteMISC2(dev,0); + + // Close all interfaces on 7146 device. + WR7146( P_MC1, MC1_SHUTDOWN ); + WR7146( P_ACON1, ACON1_BASE ); + + CloseDMAB(dev,&devpriv->RPSBuf,DMABUF_SIZE); + CloseDMAB(dev,&devpriv->ANABuf,DMABUF_SIZE); + } - if(dev->irq){ - comedi_free_irq(dev->irq,dev); - } + if(dev->irq){ + comedi_free_irq(dev->irq,dev); + } + + if(devpriv->base_addr){ + iounmap(devpriv->base_addr); + } - iounmap(devpriv->base_addr); + if(devpriv->pdev){ + pci_release_regions(devpriv->pdev); + pci_disable_device(devpriv->pdev); + pci_dev_put(devpriv->pdev); + } + } DEBUG("s626_detach: S626 detached!\n"); -- 2.26.2