Patch from abbotti@mev.co.uk (Ian Abbott). Note, I am planning
authorFrank Mori Hess <fmhess@speakeasy.net>
Sun, 11 Jun 2006 21:34:21 +0000 (21:34 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Sun, 11 Jun 2006 21:34:21 +0000 (21:34 +0000)
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!

31 files changed:
comedi/drivers/adl_pci6208.c
comedi/drivers/adl_pci7432.c
comedi/drivers/adl_pci8164.c
comedi/drivers/adl_pci9111.c
comedi/drivers/adl_pci9118.c
comedi/drivers/adv_pci1710.c
comedi/drivers/adv_pci_dio.c
comedi/drivers/amcc_s5933.c
comedi/drivers/amplc_dio200.c
comedi/drivers/amplc_pc236.c
comedi/drivers/amplc_pc263.c
comedi/drivers/amplc_pci224.c
comedi/drivers/amplc_pci230.c
comedi/drivers/cb_pcidas.c
comedi/drivers/cb_pcidas64.c
comedi/drivers/cb_pcidda.c
comedi/drivers/cb_pcimdas.c
comedi/drivers/cb_pcimdda.c
comedi/drivers/contec_pci_dio.c
comedi/drivers/daqboard2000.c
comedi/drivers/das08.c
comedi/drivers/dt3000.c
comedi/drivers/gsc_hpdi.c
comedi/drivers/icp_multi.c
comedi/drivers/icp_multi.h
comedi/drivers/ke_counter.c
comedi/drivers/me4000.c
comedi/drivers/me_daq.c
comedi/drivers/mite.c
comedi/drivers/rtd520.c
comedi/drivers/s626.c

index ea50c9707d082d0934bf8192017fbe27184d1b1f..b44700a759766f1c41ea55d264ed5a55a1f21a11 100644 (file)
@@ -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);
index dd8ee44494aa8e1246460c05db4ed110fed8f19f..aa3ff86adc5db687d306ec0207ad6f903080d3bc 100644 (file)
@@ -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;
 }
 
index ae4b1662e2e15153bbe1d92a150245640ab530ba..a614e26d4c01e39649caf667d9b0bfc9244a112b 100644 (file)
@@ -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;
 }
 
index 52a3b7de4d0c7855cf0d02cebbfbb3f31d11e484..7731575a921de26ecc9f98af49ae0a54976fcd5f 100644 (file)
@@ -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);
   }
 
index 0babd0a35b2196a159f74a6130b7d8fb1b745160..c80e0010c708691f2e48fc46eb5ff43895085a54 100644 (file)
@@ -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;
index f0239c77592602bf2908e703070f045b0601637d..ca3d77e1024569678a707a5645d50e52d521115a 100644 (file)
@@ -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;
        }
 
 
index c7387790279fbfb1edf4e0a125f4364ceb5d168d..7f72948a72a30ebc9541db2c8428fccaa224e991 100644 (file)
@@ -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;
index d062483587b3c2d09afd8353ea1f89d08c74aa3c..9a62aa80dcdd920e0f2ed40fa7f48b70b70d11f2 100644 (file)
@@ -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;
        }
 
index 98bb0b6e98db757370dbdbd10981987d2cf98c74..4005fc06adff9b5d4ad3e570a9891f22acaba7d4 100644 (file)
@@ -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",
index bccd7ca886cf956b3eaf8ce7b6c2eaddcba11d2c..1567853543370949eb7cba73b4e60566e98a2bae 100644 (file)
@@ -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;
        }
index bfd5e1e65acd2323ac13b271d3169364da92d26a..1aa4bc5ae2a9f02adb704597abbb57a2c7e97886 100644 (file)
@@ -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;
 }
 
index 8b15c339d8a58eff6de868322d428a9719e88fa0..c6377a359b8feb6355015aa1bf8188a0c42b0534 100644 (file)
@@ -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);
                }
        }
index def3bd4d0f57373c1935804a3f5f804fc8e32ecd..6c59ea251c815f7f7444d159259191ce3fb647ac 100644 (file)
@@ -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);
                }
        }
index 2420ff80b3745191a5090a17589f281e1ee4f07d..d89ae308d28a8db2c077ecdc11d7edffe140cde1 100644 (file)
@@ -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;
 }
index f6bcf24aa6b36610e88e9c74bc13f25b8b614bd1..5c28fc9c7c151f936516f1c541c38e186036b23e 100644 (file)
@@ -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);
                }
index 9ea4ff3833dfa295f9bed8ab387eec5605c616f1..d2c1f3d5a02a80b3d67b77118c795bcaafa6a880 100644 (file)
@@ -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)
index 79be50d7129f79e81171358380c5e5f4c006918d..66c32347892e470b5410865724703a9c21c00859 100644 (file)
@@ -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 <mocelet@sucs.org>\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;
 }
index fd8e787ab03b33ba5c6ab066b2d1b6a358345f48..e6e2ac40caf5d687c2096f259d2165ebfe60e541 100644 (file)
@@ -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;
index 5414799a8e5f7740980141f5d14393dfcda6fbce..7c29abaa7002006382f0a419626a7a7baa27489a 100644 (file)
@@ -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;
 }
index 3026b43dcccf8aac5fb01eb733d5bb842b0df300..d6d57d78124bd9f85836b91d03047fd0bc7fcdc4 100644 (file)
@@ -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;i<n_boardtypes;i++){
       if(boardtypes[i].id==id){
        printk(" %s",boardtypes[i].name);
@@ -719,15 +712,22 @@ static int daqboard2000_attach(comedi_device *dev, comedi_devconfig *it)
       printk(" unknown subsystem id %08x (pretend it is an ids2)",id);
       dev->board_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;
index 69e40a576fc90f87263294b65b277bac0a0b14d5..154f235320fbc6deae902a5dd67db46b606a5b94 100644 (file)
@@ -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);
                }
        }
index d95d22018c2ffbb48ec1b9a7f1330909f96bf84c..183ea70e25adfb52faa4a5ee488541a9bd7a4f1f 100644 (file)
@@ -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;
index e6743bfdaef2fcca846a3c10605222732181fff5..1e3b27a2f5e1695163d38a66577298833ea6468b 100644 (file)
@@ -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);
                }
index 4653a1de6f11df70e31744b3a9b4018a6137d658..2037642069244d9558cdb30529ee9d4a982d761a 100644 (file)
@@ -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;
        }
 
 
index 27cc3c4f6ac4b709ae18c46f843e7dec9991445b..6086da96cc1350c8fff0e9940246f3a666955135 100644 (file)
@@ -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;
        }
 
index 658084a2bac48366fb4fd0413b5d9eda8f2b2f11..5430806280b6be3fc0b8e331b74bc699509b5241 100644 (file)
@@ -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);
   }
 
index 5214deeff91eb4fd61fd4e94e6cbad8ef1a980e5..d694ea140e80afe5f65f40662a392121a78dc4a7 100644 (file)
@@ -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);
        }
index fda6451ffdcd30e4c45d0ebb184a845df58369e6..60f491806edae1cdb09fba282d4c58a5e2fdc569 100644 (file)
@@ -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);
     }
   }
index d4330994deaa9c297bb160732b69e74c35f794c1..2e19522649d8f0a406d1147edb151f6010faf29a 100644 (file)
@@ -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;
 }
index cc22ddd212ef423968c04ae14ed2cf298c1cd2ba..0abcbebe6118535862b608b2f8554a910684a920 100644 (file)
@@ -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);
        }
     }
index 90bbe091f8c08acd96865a203ebe3e7b5e6e3dc1..ea6ac1a546a8c2ae9ea57d668879ae5125d0d2ea 100644 (file)
@@ -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");