📄 pci.c
字号:
if (0) { /* don't assign ROMs */ r = &dev->resource[PCI_ROM_RESOURCE]; r->end -= r->start; r->start = 0; if (r->end) pci_assign_resource(dev, PCI_ROM_RESOURCE); } }}intpcibios_enable_resources(struct pci_dev *dev, int mask){ u16 cmd, old_cmd; int idx; struct resource *r; pci_read_config_word(dev, PCI_COMMAND, &cmd); old_cmd = cmd; for(idx=0; idx<6; idx++) { if(!(mask & (1<<idx))) continue; r = &dev->resource[idx]; if (!r->start && r->end) { printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name); return -EINVAL; } if (r->flags & IORESOURCE_IO) cmd |= PCI_COMMAND_IO; if (r->flags & IORESOURCE_MEM) cmd |= PCI_COMMAND_MEMORY; } if (dev->resource[PCI_ROM_RESOURCE].start) cmd |= PCI_COMMAND_MEMORY; if (cmd != old_cmd) { printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd); pci_write_config_word(dev, PCI_COMMAND, cmd); } return 0;}/* * Allocate pci_controller(phb) initialized common variables. */struct pci_controller * __initpci_alloc_pci_controller(char *model, enum phb_types controller_type){ struct pci_controller *hose; PPCDBG(PPCDBG_PHBINIT, "PCI: Allocate pci_controller for %s\n",model); hose = (struct pci_controller *)alloc_bootmem(sizeof(struct pci_controller)); if(hose == NULL) { printk(KERN_ERR "PCI: Allocate pci_controller failed.\n"); return NULL; } memset(hose, 0, sizeof(struct pci_controller)); if(strlen(model) < 8) strcpy(hose->what,model); else memcpy(hose->what,model,7); hose->type = controller_type; hose->global_number = global_phb_number; phbtab[global_phb_number++] = hose; *hose_tail = hose; hose_tail = &hose->next; return hose;}/* * This fixup is arch independent and probably should go somewhere else. */void __initpcibios_generic_fixup(void){ struct pci_dev *dev; /* Fix miss-identified vendor AMD pcnet32 adapters. */ dev = NULL; while ((dev = pci_find_device(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE, dev)) != NULL && dev->class == (PCI_CLASS_NETWORK_ETHERNET << 8)) dev->vendor = PCI_VENDOR_ID_AMD;}/*********************************************************************** * * * ***********************************************************************/void __initpcibios_init(void){ struct pci_controller *hose; struct pci_bus *bus; int next_busno;#ifndef CONFIG_PPC_ISERIES pSeries_pcibios_init();#else iSeries_pcibios_init(); #endif ppc64_boot_msg(0x40, "PCI Probe"); printk("PCI: Probing PCI hardware\n"); PPCDBG(PPCDBG_BUSWALK,"PCI: Probing PCI hardware\n"); /* Scan all of the recorded PCI controllers. */ for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { hose->last_busno = 0xff; bus = pci_scan_bus(hose->first_busno, hose->ops, hose->arch_data); hose->bus = bus; hose->last_busno = bus->subordinate; if (pci_assign_all_busses || next_busno <= hose->last_busno) next_busno = hose->last_busno+1; } pci_bus_count = next_busno; /* Call machine dependant fixup */ if (ppc_md.pcibios_fixup) { ppc_md.pcibios_fixup(); } /* Generic fixups */ pcibios_generic_fixup(); /* Allocate and assign resources */ pcibios_allocate_bus_resources(&pci_root_buses); pcibios_allocate_resources(0); pcibios_allocate_resources(1); pcibios_assign_resources();#ifndef CONFIG_PPC_ISERIES pci_fix_bus_sysdata(); create_tce_tables(); PPCDBG(PPCDBG_BUSWALK,"pSeries create_tce_tables()\n");#endif /* Cache the location of the ISA bridge (if we have one) */ ppc64_isabridge_dev = pci_find_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); if (ppc64_isabridge_dev != NULL ) printk("ISA bridge at %s\n", ppc64_isabridge_dev->slot_name); printk("PCI: Probing PCI hardware done\n"); PPCDBG(PPCDBG_BUSWALK,"PCI: Probing PCI hardware done.\n"); ppc64_boot_msg(0x41, "PCI Done");}int __initpcibios_assign_all_busses(void){ return pci_assign_all_busses;}unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, unsigned long start, unsigned long size){ return start;}void __init pcibios_fixup_bus(struct pci_bus *bus){#ifndef CONFIG_PPC_ISERIES struct pci_controller *phb = PCI_GET_PHB_PTR(bus); struct resource *res; int i; if (bus->parent == NULL) { /* This is a host bridge - fill in its resources */ phb->bus = bus; bus->resource[0] = res = &phb->io_resource; if (!res->flags) BUG(); /* No I/O resource for this PHB? */ for (i = 0; i < 3; ++i) { res = &phb->mem_resources[i]; if (!res->flags) { if (i == 0) BUG(); /* No memory resource for this PHB? */ } bus->resource[i+1] = res; } } else { /* This is a subordinate bridge */ pci_read_bridge_bases(bus); for (i = 0; i < 4; ++i) { if ((res = bus->resource[i]) == NULL) continue; if (!res->flags) continue; if (res == pci_find_parent_resource(bus->self, res)) { /* Transparent resource -- don't try to "fix" it. */ continue; } if (is_eeh_implemented()) { if (res->flags & (IORESOURCE_IO|IORESOURCE_MEM)) { res->start = eeh_token(phb->global_number, bus->number, 0, 0); res->end = eeh_token(phb->global_number, bus->number, 0xff, 0xffffffff); } } else { if (res->flags & IORESOURCE_IO) { res->start += (unsigned long)phb->io_base_virt; res->end += (unsigned long)phb->io_base_virt; } else if (phb->pci_mem_offset && (res->flags & IORESOURCE_MEM)) { if (res->start < phb->pci_mem_offset) { res->start += phb->pci_mem_offset; res->end += phb->pci_mem_offset; } } } } }#endif if ( ppc_md.pcibios_fixup_bus ) ppc_md.pcibios_fixup_bus(bus);}char __init *pcibios_setup(char *str){ return str;}int pcibios_enable_device(struct pci_dev *dev, int mask){ u16 cmd, old_cmd; int idx; struct resource *r; PPCDBG(PPCDBG_BUSWALK,"PCI: %s for device %s \n",__FUNCTION__,dev->slot_name); if (ppc_md.pcibios_enable_device_hook) if (ppc_md.pcibios_enable_device_hook(dev, 0)) return -EINVAL; pci_read_config_word(dev, PCI_COMMAND, &cmd); old_cmd = cmd; for (idx=0; idx<6; idx++) { r = &dev->resource[idx]; if (!r->start && r->end) { printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name); return -EINVAL; } if (r->flags & IORESOURCE_IO) cmd |= PCI_COMMAND_IO; if (r->flags & IORESOURCE_MEM) cmd |= PCI_COMMAND_MEMORY; } if (cmd != old_cmd) { printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd); PPCDBG(PPCDBG_BUSWALK,"PCI: Enabling device %s \n",dev->slot_name); pci_write_config_word(dev, PCI_COMMAND, cmd); } return 0;}struct pci_controller*pci_bus_to_hose(int bus){ struct pci_controller* hose = hose_head; for (; hose; hose = hose->next) if (bus >= hose->first_busno && bus <= hose->last_busno) return hose; return NULL;}void*pci_bus_io_base(unsigned int bus){ struct pci_controller *hose; hose = pci_bus_to_hose(bus); if (!hose) return NULL; return hose->io_base_virt;}unsigned longpci_bus_io_base_phys(unsigned int bus){ struct pci_controller *hose; hose = pci_bus_to_hose(bus); if (!hose) return 0; return hose->io_base_phys;}unsigned longpci_bus_mem_base_phys(unsigned int bus){ struct pci_controller *hose; hose = pci_bus_to_hose(bus); if (!hose) return 0; return hose->pci_mem_offset;}/* * Return the index of the PCI controller for device pdev. */int pci_controller_num(struct pci_dev *dev){ struct pci_controller *hose = PCI_GET_PHB_PTR(dev); return hose->global_number;}/* * Platform support for /proc/bus/pci/X/Y mmap()s, * modelled on the sparc64 implementation by Dave Miller. * -- paulus. *//* * Adjust vm_pgoff of VMA such that it is the physical page offset * corresponding to the 32-bit pci bus offset for DEV requested by the user. * * Basically, the user finds the base address for his device which he wishes * to mmap. They read the 32-bit value from the config space base register, * add whatever PAGE_SIZE multiple offset they wish, and feed this into the * offset parameter of mmap on /proc/bus/pci/XXX for that device. * * Returns negative error code on failure, zero on success. */static __inline__ int__pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state){ struct pci_controller *hose = PCI_GET_PHB_PTR(dev); unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; unsigned long io_offset = 0; int i, res_bit; if (hose == 0) return -EINVAL; /* should never happen */ /* If memory, add on the PCI bridge address offset */ if (mmap_state == pci_mmap_mem) { offset += hose->pci_mem_offset; res_bit = IORESOURCE_MEM; } else { io_offset = (unsigned long)hose->io_base_virt; offset += io_offset; res_bit = IORESOURCE_IO; } /* * Check that the offset requested corresponds to one of the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -