📄 prep_pci.c
字号:
dev->irq = openpic_to_irq(bridge_intrs[intpin]); pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);}void __initprep_route_pci_interrupts(void){ unsigned char *ibc_pirq = (unsigned char *)0x80800860; unsigned char *ibc_pcicon = (unsigned char *)0x80800840; int i; if ( _prep_type == _PREP_Motorola) { unsigned short irq_mode; unsigned char cpu_type; unsigned char base_mod; int entry; cpu_type = inb(MOTOROLA_CPUTYPE_REG) & 0xF0; base_mod = inb(MOTOROLA_BASETYPE_REG); for (entry = 0; mot_info[entry].cpu_type != 0; entry++) { if (mot_info[entry].cpu_type & 0x200) { /* Check for Hawk chip */ if (!(MotMPIC & MOT_HAWK_PRESENT)) continue; } else { /* Check non hawk boards */ if ((mot_info[entry].cpu_type & 0xff) != cpu_type) continue; if (mot_info[entry].base_type == 0) { mot_entry = entry; break; } if (mot_info[entry].base_type != base_mod) continue; } if (!(mot_info[entry].max_cpu & 0x80)) { mot_entry = entry; break; } /* processor 1 not present and max processor zero indicated */ if ((*ProcInfo & MOT_PROC2_BIT) && !(mot_info[entry].max_cpu & 0x7f)) { mot_entry = entry; break; } /* processor 1 present and max processor zero indicated */ if (!(*ProcInfo & MOT_PROC2_BIT) && (mot_info[entry].max_cpu & 0x7f)) { mot_entry = entry; break; } } if (mot_entry == -1) /* No particular cpu type found - assume Blackhawk */ mot_entry = 3; Motherboard_map_name = (unsigned char *)mot_info[mot_entry].name; Motherboard_map = mot_info[mot_entry].map; Motherboard_routes = mot_info[mot_entry].routes; Motherboard_non0 = mot_info[mot_entry].map_non0_bus; if (!(mot_info[entry].cpu_type & 0x100)) { /* AJF adjust level/edge control according to routes */ irq_mode = 0; for (i = 1; i <= 4; i++) irq_mode |= ( 1 << Motherboard_routes[i] ); outb( irq_mode & 0xff, 0x4d0 ); outb( (irq_mode >> 8) & 0xff, 0x4d1 ); } } else if ( _prep_type == _PREP_IBM ) { unsigned char planar_id = inb(0x0852); unsigned char irq_edge_mask_lo, irq_edge_mask_hi; printk("IBM ID: %08x\n", planar_id); switch(planar_id) { case 0xff: Motherboard_map_name = "IBM Thinkpad 850/860"; Motherboard_map = Nobis_pci_IRQ_map; Motherboard_routes = Nobis_pci_IRQ_routes; irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */ irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */ break; case 0xfc: Motherboard_map_name = "IBM 6015/7020 (Sandalfoot/Sandalbow)"; Motherboard_map = ibm6015_pci_IRQ_map; Motherboard_routes = ibm6015_pci_IRQ_routes; irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */ irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */ break; case 0xd5: Motherboard_map_name = "IBM 43P-140 (Tiger1)"; Motherboard_map = ibm43p_pci_IRQ_map; Motherboard_routes = ibm43p_pci_IRQ_routes; Motherboard_non0 = ibm43p_pci_map_non0; irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */ irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */ break; default: printk(KERN_ERR "Unknown IBM motherboard! Defaulting to Carolina.\n"); case 0xf0: /* PowerSeries 830/850 */ case 0xf1: /* PowerSeries 830/850 */ case 0xf2: /* PowerSeries 830/850 */ case 0xf4: /* 7248-43P */ case 0xf5: /* 7248-43P */ case 0xf6: /* 7248-43P */ case 0xf7: /* 7248-43P (missing from Carolina Tech Spec) */ Motherboard_map_name = "IBM PS830/PS850/7248 (Carolina)"; Motherboard_map = ibm8xx_pci_IRQ_map; Motherboard_routes = ibm8xx_pci_IRQ_routes; irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */ irq_edge_mask_hi = 0xA4; /* irq's 10, 13, 15 level-triggered */ break; } outb(inb(0x04d0)|irq_edge_mask_lo, 0x04d0); /* primary 8259 */ outb(inb(0x04d1)|irq_edge_mask_hi, 0x04d1); /* cascaded 8259 */ } else { printk("No known machine pci routing!\n"); return; } /* Set up mapping from slots */ for (i = 1; i <= 4; i++) ibc_pirq[i-1] = Motherboard_routes[i]; /* Enable PCI interrupts */ *ibc_pcicon |= 0x20;}void __initprep_pib_init(void){ unsigned char reg; unsigned short short_reg; struct pci_dev *dev = NULL; if (( _prep_type == _PREP_Motorola) && (OpenPIC_Addr)) { /* * Perform specific configuration for the Via Tech or * or Winbond PCI-ISA-Bridge part. */ if ((dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, dev))) { /* * PPCBUG does not set the enable bits * for the IDE device. Force them on here. */ pci_read_config_byte(dev, 0x40, ®); reg |= 0x03; /* IDE: Chip Enable Bits */ pci_write_config_byte(dev, 0x40, reg); } if ((dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, dev)) && (dev->devfn = 0x5a)) { /* Force correct USB interrupt */ dev->irq = 11; pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); } if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, dev))) { /* Clear PCI Interrupt Routing Control Register. */ short_reg = 0x0000; pci_write_config_word(dev, 0x44, short_reg); if (OpenPIC_Addr){ /* Route IDE interrupts to IRQ 14 */ reg = 0xEE; pci_write_config_byte(dev, 0x43, reg); } } } if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, dev))){ if (OpenPIC_Addr){ /* * Disable LEGIRQ mode so PCI INTS are routed * directly to the 8259 and enable both channels */ pci_write_config_dword(dev, 0x40, 0x10ff0033); /* Force correct IDE interrupt */ dev->irq = 14; pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); } else { /* Enable LEGIRQ for PCI INT -> 8259 IRQ routing */ pci_write_config_dword(dev, 0x40, 0x10ff08a1); } }}static void __initPowerplus_Map_Non0(struct pci_dev *dev){ struct pci_bus *pbus; /* Parent bus structure pointer */ struct pci_dev *tdev = dev; /* Temporary device structure */ unsigned int devnum; /* Accumulated device number */ unsigned char intline; /* Linux interrupt value */ unsigned char intpin; /* PCI interrupt pin */ /* Check for valid PCI dev pointer */ if (dev == NULL) return; /* Initialize bridge IDSEL variable */ devnum = PCI_SLOT(tdev->devfn); /* Read the interrupt pin of the device and adjust for indexing */ pcibios_read_config_byte(dev->bus->number, dev->devfn, PCI_INTERRUPT_PIN, &intpin); /* If device doesn't request an interrupt, return */ if ( (intpin < 1) || (intpin > 4) ) return; intpin--; /* * Walk up to bus 0, adjusting the interrupt pin for the standard * PCI bus swizzle. */ do { intpin = (prep_pci_intpins[devnum % 4][intpin]) - 1; pbus = tdev->bus; /* up one level */ tdev = pbus->self; devnum = PCI_SLOT(tdev->devfn); } while(tdev->bus->number); /* Use the primary interrupt inputs by default */ intline = mot_info[mot_entry].pci_irq_list->primary[intpin]; /* * If the board has secondary interrupt inputs, walk the bus and * note the devfn of the bridge from bus 0. If it is the same as * the devfn of the bus bridge with secondary inputs, use those. * Otherwise, assume it's a PMC site and get the interrupt line * value from the interrupt routing table. */ if (mot_info[mot_entry].secondary_bridge_devfn) { pbus = dev->bus; while (pbus->primary != 0) pbus = pbus->parent; if ((pbus->self)->devfn != 0xA0) { if ((pbus->self)->devfn == mot_info[mot_entry].secondary_bridge_devfn) intline = mot_info[mot_entry].pci_irq_list->secondary[intpin]; else { if ((char *)(mot_info[mot_entry].map) == (char *)Mesquite_pci_IRQ_map) intline = mot_info[mot_entry].map[((pbus->self)->devfn)/8] + 16; else { int i; for (i=0;i<3;i++) intpin = (prep_pci_intpins[devnum % 4][intpin]) - 1; intline = mot_info[mot_entry].pci_irq_list->primary[intpin]; } } } } /* Write calculated interrupt value to header and device list */ dev->irq = intline; pci_write_config_byte(dev, PCI_INTERRUPT_LINE, (u8)dev->irq);}void __initprep_pcibios_fixup(void){ struct pci_dev *dev; extern unsigned char *Motherboard_map; extern unsigned char *Motherboard_routes; unsigned char i; prep_route_pci_interrupts(); printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name); if (OpenPIC_Addr) { /* PCI interrupts are controlled by the OpenPIC */ pci_for_each_dev(dev) { if (dev->bus->number == 0) { dev->irq = openpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]); pcibios_write_config_byte(dev->bus->number, dev->devfn, PCI_INTERRUPT_LINE, dev->irq); } else { if (Motherboard_non0 != NULL) Motherboard_non0(dev); } } /* Setup the Winbond or Via PIB */ prep_pib_init(); return; } pci_for_each_dev(dev) { /* * Use our old hard-coded kludge to figure out what * irq this device uses. This is necessary on things * without residual data. -- Cort */ unsigned char d = PCI_SLOT(dev->devfn); dev->irq = Motherboard_routes[Motherboard_map[d]]; for ( i = 0 ; i <= 5 ; i++ ) { /* * Relocate PCI I/O resources if necessary so the * standard 256MB BAT covers them. */ if ( (pci_resource_flags(dev, i) & IORESOURCE_IO) && (dev->resource[i].start > 0x10000000)) { printk("Relocating PCI address %lx -> %lx\n", dev->resource[i].start, (dev->resource[i].start & 0x00FFFFFF)| 0x01000000); dev->resource[i].start = (dev->resource[i].start & 0x00FFFFFF) | 0x01000000; pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + (i*0x4), dev->resource[i].start); dev->resource[i].end = (dev->resource[i].end & 0x00FFFFFF) | 0x01000000; } }#if 0 /* * If we have residual data and if it knows about this * device ask it what the irq is. * -- Cort */ ppcd = residual_find_device_id( ~0L, dev->device, -1,-1,-1, 0);#endif }}static void __initprep_pcibios_after_init(void){ struct pci_dev *dev; /* If there is a WD 90C, reset the IO BAR to 0x0 (it started that * way, but the PCI layer relocated it because it thought 0x0 was * invalid for a BAR). * If you don't do this, the card's VGA base will be <IO BAR>+0xc0000 * instead of 0xc0000. vgacon.c (for example) is completely unaware of * this little quirk. */ dev = pci_find_device(PCI_VENDOR_ID_WD, PCI_DEVICE_ID_WD_90C, NULL); if (dev) { dev->resource[1].end -= dev->resource[1].start; dev->resource[1].start = 0; /* tell the hardware */ pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0x0); }}static void __initprep_init_resource(struct resource *res, unsigned long start, unsigned long end, int flags){ res->flags = flags; res->start = start; res->end = end; res->name = "PCI host bridge"; res->parent = NULL; res->sibling = NULL; res->child = NULL;}void __initprep_find_bridges(void){ struct pci_controller* hose; hose = pcibios_alloc_controller(); if (!hose) return; hose->first_busno = 0; hose->last_busno = 0xff; hose->pci_mem_offset = PREP_ISA_MEM_BASE; hose->io_base_phys = PREP_ISA_IO_BASE; hose->io_base_virt = (void *)0x80000000; /* see prep_map_io() */ prep_init_resource(&hose->io_resource, 0, 0x0fffffff, IORESOURCE_IO); prep_init_resource(&hose->mem_resources[0], 0xc0000000, 0xfeffffff, IORESOURCE_MEM); printk("PReP architecture\n"); {#ifdef CONFIG_PREP_RESIDUAL PPC_DEVICE *hostbridge; hostbridge = residual_find_device(PROCESSORDEVICE, NULL, BridgeController, PCIBridge, -1, 0); if (hostbridge && hostbridge->DeviceId.Interface == PCIBridgeIndirect) { PnP_TAG_PACKET * pkt; pkt = PnP_find_large_vendor_packet( res->DevicePnPHeap+hostbridge->AllocatedOffset, 3, 0); if(pkt) {#define p pkt->L4_Pack.L4_Data.L4_PPCPack setup_indirect_pci(hose, ld_le32((unsigned *) (p.PPCData)), ld_le32((unsigned *) (p.PPCData+8))); } else setup_indirect_pci(hose, 0x80000cf8, 0x80000cfc); } else#endif /* CONFIG_PREP_RESIDUAL */ hose->ops = &prep_pci_ops; } ppc_md.pcibios_fixup = prep_pcibios_fixup; ppc_md.pcibios_after_init = prep_pcibios_after_init;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -