/*
       *	drivers/pci/setup-res.c
       *
       * Extruded from code written by
       *      Dave Rusling (david.rusling@reo.mts.dec.com)
       *      David Mosberger (davidm@cs.arizona.edu)
       *	David Miller (davem@redhat.com)
       *
       * Support routines for initializing a PCI subsystem.
       */
      
      /* fixed for multiple pci buses, 1999 Andrea Arcangeli <andrea@suse.de> */
      
      /*
       * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
       *	     Resource sorting
       */
      
      #include <linux/init.h>
      #include <linux/kernel.h>
      #include <linux/pci.h>
      #include <linux/errno.h>
      #include <linux/ioport.h>
      #include <linux/cache.h>
      #include <linux/slab.h>
      
      
      #define DEBUG_CONFIG 1
      #if DEBUG_CONFIG
      # define DBGC(args)     printk args
      #else
      # define DBGC(args)
      #endif
      
      
      int __init
  37  pci_claim_resource(struct pci_dev *dev, int resource)
      {
              struct resource *res = &dev->resource[resource];
      	struct resource *root = pci_find_parent_resource(dev, res);
      	int err;
      
      	err = -EINVAL;
  44  	if (root != NULL) {
      		err = request_resource(root, res);
  46  		if (err) {
      			printk(KERN_ERR "PCI: Address space collision on "
      			       "region %d of device %s [%lx:%lx]\n",
      			       resource, dev->name, res->start, res->end);
      		}
  51  	} else {
      		printk(KERN_ERR "PCI: No parent found for region %d "
      		       "of device %s\n", resource, dev->name);
      	}
      
  56  	return err;
      }
      
      /*
       * Given the PCI bus a device resides on, try to
       * find an acceptable resource allocation for a
       * specific device resource..
       */
  64  static int pci_assign_bus_resource(const struct pci_bus *bus,
      	struct pci_dev *dev,
      	struct resource *res,
      	unsigned long size,
      	unsigned long min,
      	unsigned int type_mask,
      	int resno)
      {
      	int i;
      
      	type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
  75  	for (i = 0 ; i < 4; i++) {
      		struct resource *r = bus->resource[i];
  77  		if (!r)
  78  			continue;
      
      		/* type_mask must match */
  81  		if ((res->flags ^ r->flags) & type_mask)
  82  			continue;
      
      		/* We cannot allocate a non-prefetching resource from a pre-fetching area */
  85  		if ((r->flags & IORESOURCE_PREFETCH) && !(res->flags & IORESOURCE_PREFETCH))
  86  			continue;
      
      		/* Ok, try it out.. */
  89  		if (allocate_resource(r, res, size, min, -1, size, pcibios_align_resource, dev) < 0)
  90  			continue;
      
      		/* Update PCI config space.  */
      		pcibios_update_resource(dev, r, res, resno);
  94  		return 0;
      	}
  96  	return -EBUSY;
      }
      
      int 
 100  pci_assign_resource(struct pci_dev *dev, int i)
      {
      	const struct pci_bus *bus = dev->bus;
      	struct resource *res = dev->resource + i;
      	unsigned long size, min;
      
      	size = res->end - res->start + 1;
      	min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
      
      	/* First, try exact prefetching match.. */
 110  	if (pci_assign_bus_resource(bus, dev, res, size, min, IORESOURCE_PREFETCH, i) < 0) {
      		/*
      		 * That failed.
      		 *
      		 * But a prefetching area can handle a non-prefetching
      		 * window (it will just not perform as well).
      		 */
 117  		if (!(res->flags & IORESOURCE_PREFETCH) || pci_assign_bus_resource(bus, dev, res, size, min, 0, i) < 0) {
      			printk(KERN_ERR "PCI: Failed to allocate resource %d for %s\n", i, dev->name);
 119  			return -EBUSY;
      		}
      	}
      
      	DBGC(("  got res[%lx:%lx] for resource %d of %s\n", res->start,
      						res->end, i, dev->name));
      
 126  	return 0;
      }
      
      /* Sort resources of a given type by alignment */
      void __init
 131  pdev_sort_resources(struct pci_dev *dev,
      		    struct resource_list *head, u32 type_mask)
      {
      	int i;
      
 136  	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
      		struct resource *r;
      		struct resource_list *list, *tmp;
      		unsigned long r_size;
      
      		/* PCI-PCI bridges may have I/O ports or
      		   memory on the primary bus */
      		if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI &&
 144  						i >= PCI_BRIDGE_RESOURCES)
 145  			continue;
      
      		r = &dev->resource[i];
      		r_size = r->end - r->start;
      		
 150  		if (!(r->flags & type_mask) || r->parent)
 151  			continue;
 152  		if (!r_size) {
      			printk(KERN_WARNING "PCI: Ignore bogus resource %d "
      					 "[%lx:%lx] of %s\n",
      					  i, r->start, r->end, dev->name);
 156  			continue;
      		}
 158  		for (list = head; ; list = list->next) {
      			unsigned long size = 0;
      			struct resource_list *ln = list->next;
      
 162  			if (ln)
      				size = ln->res->end - ln->res->start;
 164  			if (r_size > size) {
      				tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
      				tmp->next = ln;
      				tmp->res = r;
      				tmp->dev = dev;
      				list->next = tmp;
 170  				break;
      			}
      		}
      	}
      }
      
      void __init
 177  pdev_enable_device(struct pci_dev *dev)
      {
      	u32 reg;
      	u16 cmd;
      	int i;
      
      	DBGC(("PCI enable device: (%s)\n", dev->name));
      
      	pci_read_config_word(dev, PCI_COMMAND, &cmd);
      
 187  	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
      		struct resource *res = &dev->resource[i];
      
 190  		if (res->flags & IORESOURCE_IO)
      			cmd |= PCI_COMMAND_IO;
 192  		else if (res->flags & IORESOURCE_MEM)
      			cmd |= PCI_COMMAND_MEMORY;
      	}
      
      	/* Special case, disable the ROM.  Several devices act funny
      	   (ie. do not respond to memory space writes) when it is left
      	   enabled.  A good example are QlogicISP adapters.  */
      
 200  	if (dev->rom_base_reg) {
      		pci_read_config_dword(dev, dev->rom_base_reg, ®);
      		reg &= ~PCI_ROM_ADDRESS_ENABLE;
      		pci_write_config_dword(dev, dev->rom_base_reg, reg);
      		dev->resource[PCI_ROM_RESOURCE].flags &= ~PCI_ROM_ADDRESS_ENABLE;
      	}
      
      	/* All of these (may) have I/O scattered all around and may not
      	   use I/O base address registers at all.  So we just have to
      	   always enable IO to these devices.  */
      	if ((dev->class >> 8) == PCI_CLASS_NOT_DEFINED
      	    || (dev->class >> 8) == PCI_CLASS_NOT_DEFINED_VGA
      	    || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE
 213  	    || (dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
      		cmd |= PCI_COMMAND_IO;
      	}
      
      	/* ??? Always turn on bus mastering.  If the device doesn't support
      	   it, the bit will go into the bucket. */
      	cmd |= PCI_COMMAND_MASTER;
      
      	/* Set the cache line and default latency (32).  */
      	pci_write_config_word(dev, PCI_CACHE_LINE_SIZE,
      			(32 << 8) | (L1_CACHE_BYTES / sizeof(u32)));
      
      	/* Enable the appropriate bits in the PCI command register.  */
      	pci_write_config_word(dev, PCI_COMMAND, cmd);
      
      	DBGC(("  cmd reg 0x%x\n", cmd));
      }