home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / lxapi32.zip / PCI / pci-i386.c < prev    next >
C/C++ Source or Header  |  2002-04-26  |  7KB  |  262 lines

  1. /* $Id: pci-i386.c,v 1.2 2002/04/26 23:09:34 smilcke Exp $ */
  2.  
  3. /*
  4.  * pci-i386.c
  5.  * Autor:               Stefan Milcke
  6.  * Erstellt am:         25.10.2001
  7.  * Letzte Aenderung am: 05.04.2002
  8.  *
  9. */
  10.  
  11. #include <linux/types.h>
  12. #include <linux/kernel.h>
  13. #include <linux/mm.h>
  14. #include <linux/pci.h>
  15. #include <linux/init.h>
  16. #include <linux/ioport.h>
  17. #include <linux/errno.h>
  18.  
  19. #include <ldefos2.h>
  20.  
  21. #include "pci-i386.h"
  22.  
  23. // From kernel/setup.c
  24. unsigned long pci_mem_start=0x10000000;
  25.  
  26. #ifdef TARGET_OS2
  27. extern int dopcienable;
  28. extern int dopcisetmaster;
  29. extern int dopciupdateresource;
  30. #endif
  31.  
  32. //-------------------------- pcibios_update_resource ---------------------------
  33. void pcibios_update_resource(struct pci_dev *dev,struct resource *root
  34.                              ,struct resource *res,int resource)
  35. {
  36.  u32 newr,check;
  37.  int reg;
  38.  newr=res->start | (res->flags & PCI_REGION_FLAG_MASK);
  39.  if(resource<6)
  40.   reg=PCI_BASE_ADDRESS_0+4*resource;
  41.  else if(resource==PCI_ROM_RESOURCE)
  42.  {
  43.   res->flags|=PCI_ROM_ADDRESS_ENABLE;
  44.   newr|=PCI_ROM_ADDRESS_ENABLE;
  45.   reg=dev->rom_base_reg;
  46.  }
  47.  else
  48.   // Somebody might have asked allocation of a non-standard resource
  49.   return;
  50.  #ifdef TARGET_OS2
  51.  if(0==dopciupdateresource)
  52.   return;
  53.  #endif
  54.  pci_write_config_dword(dev,reg,newr);
  55.  pci_read_config_dword(dev,reg,&check);
  56.  if((newr^check)&((newr&PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK))
  57.  {
  58.   CPK(printk(KERN_ERR "PCI: Error while updating region %s/%d (%08x != %08x)\n"
  59.          ,dev->slot_name, resource,newr, check));
  60.  }
  61. }
  62.  
  63. //--------------------------- pcibios_align_resource ---------------------------
  64. void pcibios_align_resource(void *data,struct resource *res,unsigned long size)
  65. {
  66.  if(res->flags&IORESOURCE_IO)
  67.  {
  68.   unsigned long start=res->start;
  69.   if(start & 0x300)
  70.   {
  71.    start=(start+0x3ff)&~0x3ff;
  72.    res->start=start;
  73.   }
  74.  }
  75. }
  76.  
  77. //----------------------- pcibios_allocate_bus_resources -----------------------
  78. static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
  79. {
  80.  struct list_head *ln;
  81.  struct pci_bus *bus;
  82.  struct pci_dev *dev;
  83.  int idx;
  84.  struct resource *r,*pr;
  85.  // Depth-First Search on bus tree
  86.  for(ln=bus_list->next;ln!=bus_list;ln=ln->next)
  87.  {
  88.   bus=pci_bus_b(ln);
  89.   if((dev=bus->self))
  90.   {
  91.    for(idx=PCI_BRIDGE_RESOURCES;idx<PCI_NUM_RESOURCES;idx++)
  92.    {
  93.     r=&dev->resource[idx];
  94.     if(!r->start)
  95.      continue;
  96.     pr=pci_find_parent_resource(dev,r);
  97.     if(!pr || request_resource(pr,r)<0)
  98.      CPK(printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n"
  99.                 ,idx,dev->slot_name));
  100.    }
  101.   }
  102.   pcibios_allocate_bus_resources(&bus->children);
  103.  }
  104. }
  105.  
  106. //------------------------- pcibios_allocate_resources -------------------------
  107. static void __init pcibios_allocate_resources(int pass)
  108. {
  109.  struct pci_dev *dev;
  110.  int idx,disabled;
  111.  u16 command;
  112.  struct resource *r,*pr;
  113.  pci_for_each_dev(dev)
  114.  {
  115.   pci_read_config_word(dev,PCI_COMMAND,&command);
  116.   for(idx=0;idx<6;idx++)
  117.   {
  118.    r=&dev->resource[idx];
  119.    if(r->parent)     // Already allocated
  120.     continue;
  121.    if(!r->start)     // Address not assigned at all
  122.     continue;
  123.    if(r->flags & IORESOURCE_IO)
  124.     disabled=!(command & PCI_COMMAND_IO);
  125.    else
  126.     disabled=!(command & PCI_COMMAND_MEMORY);
  127.    if(pass==disabled)
  128.    {
  129.     CPK(printk("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n"
  130.               ,r->start,r->end,r->flags,disabled,pass));
  131.     pr=pci_find_parent_resource(dev,r);
  132.     if(!pr||request_resource(pr,r)<0)
  133.     {
  134.      CPK(printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n"
  135.                 ,idx,dev->slot_name));
  136.      // We'll assign a new address later
  137.      r->end-=r->start;
  138.      r->start=0;
  139.     }
  140.    }
  141.   }
  142.   if(!pass)
  143.   {
  144.    r=&dev->resource[PCI_ROM_RESOURCE];
  145.    if(r->flags & PCI_ROM_ADDRESS_ENABLE)
  146.    { // Turn the ROM off, leave the resource region, but keep it unregistered
  147.     u32 reg;
  148.     CPK(printk("PCI: Switching off ROM of %s\n",dev->slot_name));
  149.     r->flags&=~PCI_ROM_ADDRESS_ENABLE;
  150.     pci_read_config_dword(dev,dev->rom_base_reg,®);
  151. #ifdef TARGET_OS2
  152.     if(0!=dopciupdateresource)
  153. #endif
  154.     pci_write_config_dword(dev,dev->rom_base_reg,reg & ~PCI_ROM_ADDRESS_ENABLE);
  155.    }
  156.   }
  157.  }
  158. }
  159.  
  160. //-------------------------- pcibios_assign_resources --------------------------
  161. static void __init pcibios_assign_resources(void)
  162. {
  163.  struct pci_dev *dev;
  164.  int idx;
  165.  struct resource *r;
  166.  pci_for_each_dev(dev)
  167.  {
  168.   int dclass=dev->pciclass>>8;
  169.   // Don't touch classless devices and host bridges
  170.   if(!dclass || dclass==PCI_CLASS_BRIDGE_HOST)
  171.    continue;
  172.   for(idx=0;idx<6;idx++)
  173.   {
  174.    r=&dev->resource[idx];
  175.    // Don't touch IDE controllers and I/O ports of video cards!
  176.    if((dclass==PCI_CLASS_STORAGE_IDE && idx<4) ||
  177.       (dclass==PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
  178.     continue;
  179.    // We shall assign a new address to this resource, either because
  180.    // the BIOS forgot to do so or because we have decided the old
  181.    // address was unusable for some reason
  182.    if(!r->start && r->end)
  183.     pci_assign_resource(dev,idx);
  184.   }
  185.   if(pci_probe & PCI_ASSIGN_ROMS)
  186.   {
  187.    r=&dev->resource[PCI_ROM_RESOURCE];
  188.    r->end-=r->start;
  189.    r->start=0;
  190.    if(r->end)
  191.     pci_assign_resource(dev,PCI_ROM_RESOURCE);
  192.   }
  193.  }
  194. }
  195.  
  196. //-------------------------- pcibios_resource_survey ---------------------------
  197. void __init pcibios_resource_survey(void)
  198. {
  199.  CPK(printk("PCI: Allocating resources\n"));
  200.  pcibios_allocate_bus_resources(&pci_root_buses);
  201.  pcibios_allocate_resources(0);
  202.  pcibios_allocate_resources(1);
  203.  pcibios_assign_resources();
  204. }
  205.  
  206. //-------------------------- pcibios_enable_resources --------------------------
  207. int pcibios_enable_resources(struct pci_dev *dev)
  208. {
  209.  u16 cmd,old_cmd;
  210.  int idx;
  211.  struct resource *r;
  212.  pci_read_config_word(dev,PCI_COMMAND,&cmd);
  213.  old_cmd=cmd;
  214.  for(idx=0;idx<6;idx++)
  215.  {
  216.   r=&dev->resource[idx];
  217.   if(!r->start && r->end)
  218.   {
  219.    CPK(printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n"
  220.               ,dev->slot_name));
  221.    return -EINVAL;
  222.   }
  223.   if(r->flags&IORESOURCE_IO)
  224.    cmd|=PCI_COMMAND_IO;
  225.   if(r->flags&IORESOURCE_MEM)
  226.    cmd|=PCI_COMMAND_MEMORY;
  227.  }
  228.  if(dev->resource[PCI_ROM_RESOURCE].start)
  229.   cmd|=PCI_COMMAND_MEMORY;
  230.  if(cmd!=old_cmd)
  231.  {
  232.   CPK(printk("PCI: Enabling device %s (%04x -> %04x)\n"
  233.              ,dev->slot_name, old_cmd, cmd));
  234. #ifdef TARGET_OS2
  235.   if(0!=dopcienable)
  236. #endif
  237.   pci_write_config_word(dev, PCI_COMMAND, cmd);
  238.  }
  239.  return 0;
  240. }
  241.  
  242. unsigned int pcibios_max_latency = 255;
  243.  
  244. //----------------------------- pcibios_set_master -----------------------------
  245. void pcibios_set_master(struct pci_dev *dev)
  246. {
  247.  u8 lat;
  248.  pci_read_config_byte(dev,PCI_LATENCY_TIMER,&lat);
  249.  if(lat<16)
  250.   lat=(64<=pcibios_max_latency) ? 64 : pcibios_max_latency;
  251.  else if(lat>pcibios_max_latency)
  252.   lat=pcibios_max_latency;
  253.  else
  254.   return;
  255.  CPK(printk("PCI: Setting latency timer of device %s to %d\n"
  256.             ,dev->slot_name,lat));
  257. #ifdef TARGET_OS2
  258.  if(0!=dopcisetmaster)
  259. #endif
  260.  pci_write_config_byte(dev,PCI_LATENCY_TIMER,lat);
  261. }
  262.