⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pci.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 3 页
字号:
         if ((buses & 0xFFFFFF) != 0)         {            unsigned int cmax;            child->primary = buses & 0xFF;            child->secondary = (buses >> 8) & 0xFF;            child->subordinate = (buses >> 16) & 0xFF;            child->number = child->secondary;            cmax = pci_scan_bus(child);            if (cmax > max) max = cmax;         }         else         {            /*             * Configure the bus numbers for this bridge:             */            buses &= 0xff000000;            buses |=               (((unsigned int)(child->primary)     <<  0) |                ((unsigned int)(child->secondary)   <<  8) |                ((unsigned int)(child->subordinate) << 16));            pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses);            /*             * Now we can scan all subordinate buses:             */            max = pci_scan_bus(child);            /*             * Set the subordinate bus number to its real             * value:             */            child->subordinate = max;            buses = (buses & 0xff00ffff)               | ((unsigned int)(child->subordinate) << 16);            pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses);         }         pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, cr );      }   /*    * We've scanned the bus and so we know all about what's on    * the other side of any bridges that may be on this bus plus    * any devices.    *    * Return how far we've got finding sub-buses.    */   return max;}#if 0voidpci_fixup(void) {   struct pci_dev *p;   struct pci_bus *bus;   for (bus = &pci_root; bus; bus=bus->next)    {      for (p=bus->devices; p; p=p->sibling)       {      }   }}static void print_pci_info(){   pci_resource *r;   struct pci_bus *pb = &pci_root;   printk("\n");   printk("PCI busses:\n");   for(pb= &pci_root; pb; pb=pb->children )   {      printk("   number %d, primary %d, secondary %d, subordinate %d\n",             pb->number,              pb->primary,             pb->secondary,             pb->subordinate );      printk("   bridge; vendor %04x, device %04x\n",             pb->self->vendor,             pb->self->device );      {         struct pci_dev *pd;         for(pd= pb->devices; pd; pd=pd->sibling )         {            printk("       vendor %04x, device %04x, irq %d\n",                   pd->vendor,                   pd->device,                   pd->irq );                    }         printk("\n");      }   }   printk("\n");   printk("PCI resources:\n");   for (r=pci->resources; r; r= r->next)   {      printk("   bus %d, vendor %04x, device %04x, base %08x, size %08x, type %d\n",             r->dev->bus->number,              r->dev->vendor,             r->dev->device,             r->base,             r->size,             r->type );   }   printk("\n");   return;}#endifstatic struct _addr_start{      unsigned32 start_pcimem;      unsigned32 start_pciio;      unsigned32 start_prefetch;} astart;static pci_resource *enum_device_resources( struct pci_dev *pdev, int i ){   pci_resource *r;   for(r= pci->resources; r; r= r->next )   {      if( r->dev == pdev )      {         if( i-- == 0 ) break;      }   }   return r;}static void recursive_bus_reconfigure( struct pci_bus *pbus ){   struct pci_dev       *pdev;   struct pci_bus       *childbus;   int  isroot = 0;   if( !pbus )   {      /* start with the root bus */      astart.start_pcimem   = BUSREST_MEM_START;      astart.start_pciio    = BUSREST_IO_START;      astart.start_prefetch = ((BUSREST_MEM_END >> 16) << 16);      pbus = &pci_root;      isroot = -1;   }#define WRITE_BRIDGE_IO#define WRITE_BRIDGE_MEM#define WRITE_BRIDGE_PF#define WRITE_BRIDGE_ENABLE/*** Run thru the p2p bridges on this bus and recurse into subordinate busses*/   for( childbus= pbus->children; childbus; childbus= childbus->next )   {      pdev= childbus->self;      pcibios_write_config_byte(pdev->bus->number, pdev->devfn, PCI_LATENCY_TIMER,     0x80 );      pcibios_write_config_byte(pdev->bus->number, pdev->devfn, PCI_SEC_LATENCY_TIMER, 0x80 );      {         struct _addr_start   addrhold;         unsigned8            base8, limit8;         unsigned16           base16, limit16, ubase16, ulimit16;         /* save the base address values */         memcpy( &addrhold, &astart, sizeof(struct _addr_start));         recursive_bus_reconfigure( childbus );#ifdef PCI_DEBUG         printk("pci: configuring bus %d bridge (%04x:%04x), bus %d : (%d-%d)\n",                pdev->bus->number,                pdev->vendor,                pdev->device,                childbus->primary,                childbus->secondary,                childbus->subordinate );#endif            /*          ** use the current values & the saved ones to figure out         ** the address spaces for the bridge         */         if( addrhold.start_pciio == astart.start_pciio )         {            base8 = limit8 = 0xff;            ubase16 = ulimit16 = 0xffff;         }         else         {            base8    = (unsigned8) ((addrhold.start_pciio >> 8) & 0xf0);            ubase16  = (unsigned16)(addrhold.start_pciio >> 16);            limit8   = (unsigned8) ((astart.start_pciio >> 8 ) & 0xf0);            ulimit16 = (unsigned16)(astart.start_pciio >> 16);            astart.start_pciio += 0x1000;         }#ifdef PCI_DEBUG         printk("pci:     io base %08x limit %08x\n", (base8<<8)+(ubase16<<16), (limit8<<8)+(ulimit16<<16));#endif#ifdef WRITE_BRIDGE_IO         pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_IO_BASE_UPPER16, ubase16 );         pcibios_write_config_byte(pdev->bus->number, pdev->devfn, PCI_IO_BASE, base8 );         pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_IO_LIMIT_UPPER16, ulimit16 );         pcibios_write_config_byte(pdev->bus->number, pdev->devfn, PCI_IO_LIMIT, limit8 );#endif         if( addrhold.start_pcimem == astart.start_pcimem )         {            limit16 = 0;            base16 = 0xffff;         }         else         {            limit16= (unsigned16)((astart.start_pcimem >> 16) & 0xfff0);            base16 = (unsigned16)((addrhold.start_pcimem >> 16) & 0xfff0);            astart.start_pcimem += 0x100000;         }#ifdef PCI_DEBUG         printk("pci:      memory %04x, limit %04x\n", base16, limit16);#endif#ifdef WRITE_BRIDGE_MEM         pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_MEMORY_BASE, base16 );         pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_MEMORY_LIMIT, limit16 );#endif         if( astart.start_prefetch == addrhold.start_prefetch )         {            limit16 = 0;            base16 = 0xffff;         }         else         {            limit16= (unsigned16)((addrhold.start_prefetch >> 16) & 0xfff0);            base16 = (unsigned16)((astart.start_prefetch >> 16) & 0xfff0);            astart.start_prefetch -= 0x100000;         }#ifdef PCI_DEBUG         printk("pci:   pf memory %04x, limit %04x\n", base16, limit16);#endif#ifdef WRITE_BRIDGE_PF         pcibios_write_config_dword(pdev->bus->number, pdev->devfn, PCI_PREF_BASE_UPPER32, 0);           pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_PREF_MEMORY_BASE, base16 );         pcibios_write_config_dword(pdev->bus->number, pdev->devfn, PCI_PREF_LIMIT_UPPER32, 0);         pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_PREF_MEMORY_LIMIT, limit16 );#endif#ifdef WRITE_BRIDGE_ENABLE         pcibios_write_config_word(pdev->bus->number,                                    pdev->devfn,                                    PCI_BRIDGE_CONTROL,                                    (unsigned16)( 0 ));         pcibios_write_config_word(pdev->bus->number,                                    pdev->devfn,                                    PCI_COMMAND,                                    (unsigned16)( PCI_COMMAND_IO |                                                                                               PCI_COMMAND_MEMORY |                                                 PCI_COMMAND_MASTER ));#endif      }   }   if( !isroot )   {#ifdef PCI_DEBUG      printk("pci: Configuring devices on bus %d\n", pbus->number);#endif      /*      ** Run thru this bus and set up addresses for all the non-bridge devices      */      for( pdev = pbus->devices; pdev; pdev= pdev->sibling )      {         if( (pdev->class >> 8) != PCI_CLASS_BRIDGE_PCI )         {            pci_resource *r;            int i = 0;            unsigned alloc;            /* enumerate all the resources defined by this device & reserve space            ** for each of their defined regions.            */#ifdef PCI_DEBUG            printk("pci: configuring; vendor %04x, device %04x\n", pdev->vendor, pdev->device );#endif            while( (r= enum_device_resources( pdev, i++ )) )            {               /*               ** Force all memory spaces to be non-prefetchable because               ** on the pci bus, byte-wise reads against prefetchable               ** memory are applied as 32 bit reads, which is a pain               ** when you're trying to talk to hardware.  This is a               ** little sub-optimal because the algorithm doesn't sort               ** the address regions to pack them in, OTOH, perhaps its               ** not so bad because the inefficient packing will help               ** avoid buffer overflow/underflow problems.               */#if 0               if( (r->type & PCI_BASE_ADDRESS_MEM_PREFETCH) )               {                  /* prefetchable space */                  /* shift base pointer down to an integer multiple of the size of the desired region */                  astart.start_prefetch -= (alloc= ((r->size / PAGE_SIZE) + 1) * PAGE_SIZE);                  /* shift base pointer down to an integer multiple of the size of the desired region */                  astart.start_prefetch = (astart.start_prefetch / r->size) * r->size;                  r->base = astart.start_prefetch;#ifdef PCI_DEBUG                  printk("pci:       pf %08X, size %08X, alloc %08X\n", r->base, r->size, alloc );#endif               }#endif               if( r->type & PCI_BASE_ADDRESS_SPACE_IO )               {                  /* io space */                  /* shift base pointer up to an integer multiple of the size of the desired region */                  if( astart.start_pciio % r->size )                     astart.start_pciio = (((astart.start_pciio / r->size) + 1) * r->size);                  r->base = astart.start_pciio;                  astart.start_pciio += (alloc= ((r->size / PAGE_SIZE) + 1) * PAGE_SIZE);#ifdef PCI_DEBUG                  printk("pci:      io  %08X, size %08X, alloc %08X\n", r->base, r->size, alloc );#endif               }               else               {                  /* memory space */                                    /* shift base pointer up to an integer multiple of the size of the desired region */                  if( astart.start_pcimem % r->size )                     astart.start_pcimem = (((astart.start_pcimem / r->size) + 1) * r->size);                  r->base = astart.start_pcimem;                  astart.start_pcimem += (alloc= ((r->size / PAGE_SIZE) + 1) * PAGE_SIZE);#ifdef PCI_DEBUG                  printk("pci:      mem %08X, size %08X, alloc %08X\n", r->base, r->size, alloc );#endif               }            }         }      }   }}void pci_init(void) {   PPC_DEVICE *hostbridge;   if (pci->last_dev_p) {      printk("Two or more calls to pci_init!\n");      return;   }   pci->last_dev_p = &(bd->pci_devices);   hostbridge=residual_find_device(PROCESSORDEVICE, NULL,                                    BridgeController,                                   PCIBridge, -1, 0);   if (hostbridge) {      if (hostbridge->DeviceId.Interface==PCIBridgeIndirect) {         bd->pci_functions=&indirect_functions;         /* Should be extracted from residual data,           * indeed MPC106 in CHRP mode is different,          * but we should not use residual data in          * this case anyway.           */         pci->config_addr = ((volatile u_int *)                              (ptr_mem_map->io_base+0xcf8));         pci->config_data = ptr_mem_map->io_base+0xcfc;      } else if(hostbridge->DeviceId.Interface==PCIBridgeDirect) {         bd->pci_functions=&direct_functions;         pci->config_data=(u_char *) 0x80800000;      } else {      }   } else {      /* Let us try by experimentation at our own risk! */      u_int id0;      bd->pci_functions = &direct_functions;      /* On all direct bridges I know the host bridge itself       * appears as device 0 function 0.        */      pcibios_read_config_dword(0, 0, PCI_VENDOR_ID, &id0);      if (id0==~0U) {         bd->pci_functions = &indirect_functions;         pci->config_addr = ((volatile u_int *)                             (ptr_mem_map->io_base+0xcf8));         pci->config_data = ptr_mem_map->io_base+0xcfc;      }      /* Here we should check that the host bridge is actually       * present, but if it not, we are in such a desperate       * situation, that we probably can't even tell it.       */   }   /* Now build a small database of all found PCI devices */   printk("\nPCI: Probing PCI hardware\n");   pci_root.subordinate=pci_scan_bus(&pci_root);   print_pci_resources("Installed PCI resources:\n");   recursive_bus_reconfigure(NULL);   reconfigure_pci();   print_pci_resources("Allocated PCI resources:\n");#if 0   print_pci_info();#endif}/* eof */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -