📄 sb_pci_machdep.c
字号:
{ /* Check for a host bridge seen internally, in which case we don't want to allocate any address space for its BARs. */ return (tag == SB_PCI_BRIDGE ? 1 : 0);}/* Called for each non-bridge (Type 0) function after assigning the BAR and InterruptLine resources. */voidpci_device_setup (pcitag_t tag){}/* Called for each bridge (Type 1) function after configuring the secondary bus, to allow device-specific initialization. */voidpci_bridge_setup (pcitag_t tag, pci_flags_t flags){}/* Machine dependent access primitives and utility functions */voidpci_flush (void){}pcitag_tpci_make_tag (int port, int bus, int device, int function){ return PCI_MAKE_TAG(bus, device, function);}voidpci_break_tag (pcitag_t tag, int *portp, int *busp, int *devicep, int *functionp){ if (portp) *portp = 0; if (busp) *busp = (tag >> 16) & PCI_BUSMAX; if (devicep) *devicep = (tag >> 11) & PCI_DEVMAX; if (functionp) *functionp = (tag >> 8) & PCI_FUNCMAX;}/* Read/write access to PCI configuration registers. Type0 addresses are used for bus 0, with a unary encoding of IDSEL in which device n is mapped to bit 16+n (16 possible devices, 0..15). */intpci_canscan (pcitag_t tag){ int bus, device, function; pci_break_tag(tag, NULL, &bus, &device, &function); if (bus > PCI_BUSMAX || device > PCI_DEVMAX || function > PCI_FUNCMAX) return 0; return (bus != 0 || (device >= 0 && device < 16));}intpci_probe_tag(pcitag_t tag){ pcireg_t data; jmpbuf_t *jb; if (!pci_canscan(tag)) return 0; jb = exc_initialize_block(); if (jb == NULL) return 0; if (exc_try(jb) == 0) data = pci_conf_read(tag, PCI_ID_REG); /* bus error if no response */ else data = 0xffffffff; exc_cleanup_block(jb); /* if it returned all vendor id bits set, it's not a device */ return (PCI_VENDOR(data) != 0xffff);}/* Note that READCFG/WRITECFG uses below can generate bus errors that are not caught; guard calls with these functions with pci_probe_tag. */pcireg_tpci_conf_read(pcitag_t tag, int reg){ int bus, device, function; pcireg_t data; uint32_t addr; pci_break_tag(tag, NULL, &bus, &device, &function); addr = (function << 8) | (reg & 0xFC); /* common part */ if (bus == 0) { if (device < 16) { /* Generate a Type0 configuration cycle. */ addr |= (1 << (16 + device)); WRITECSR(R_SB_TO_PCI_TRANSLATION1, (addr & M_SBXLAT_UA) | V_SBXLAT_AT(K_AT_CFG0_RW)); (void)READCSR(R_SB_TO_PCI_TRANSLATION1); /* push */ addr &= ~M_SBXLAT_UA; data = READCFG(addr); } else data = 0xFFFFFFFF; } else { /* Generate a Type1 configuration cycle. */ addr |= (bus << 16) | (device << 11); WRITECSR(R_SB_TO_PCI_TRANSLATION1, (addr & M_SBXLAT_UA) | V_SBXLAT_AT(K_AT_CFG1_RW)); (void)READCSR(R_SB_TO_PCI_TRANSLATION1); /* push */ addr &= ~M_SBXLAT_UA; data = READCFG(addr); } return data;}voidpci_conf_write(pcitag_t tag, int reg, pcireg_t data){ int bus, device, function; uint32_t addr; pci_break_tag(tag, NULL, &bus, &device, &function); addr = (function << 8) | (reg & 0xFC); /* common part */ if (bus == 0) { if (device < 16) { /* Generate a Type0 configuration cycle. */ addr |= (1 << (16 + device)); WRITECSR(R_SB_TO_PCI_TRANSLATION1, (addr & M_SBXLAT_UA) | V_SBXLAT_AT(K_AT_CFG0_RW)); (void)READCSR(R_SB_TO_PCI_TRANSLATION1); /* push */ addr &= ~M_SBXLAT_UA; WRITECFG(addr & ~SB_PCI_CFG_BASE, data); } } else { /* Generate a Type1 configuration cycle. */ addr |= (bus << 16) | (device << 11); WRITECSR(R_SB_TO_PCI_TRANSLATION1, (addr & M_SBXLAT_UA) | V_SBXLAT_AT(K_AT_CFG1_RW)); addr &= ~M_SBXLAT_UA; (void)READCSR(R_SB_TO_PCI_TRANSLATION1); /* push */ WRITECFG(addr, data); }}intpci_conf_write_acked(pcitag_t tag, int reg, pcireg_t data){ pci_conf_write(tag, reg, data); (void) pci_conf_read(tag, reg); return 1;}intpci_map_io(pcitag_t tag, int reg, pci_endian_t endian, phys_addr_t *pap){ pci_tagprintf(tag, "pci_map_io: i/o regions not supported\n"); return -1;}intpci_map_mem(pcitag_t tag, int reg, pci_endian_t endian, phys_addr_t *pap){ pcireg_t address; phys_addr_t pa; if (reg == PCI_MAPREG_ROM) { /* expansion ROM */ address = pci_conf_read(tag, reg); if ((address & PCI_MAPREG_ROM_ENABLE) == 0) { pci_tagprintf(tag, "pci_map_mem: attempt to map missing rom\n"); return -1; } pa = address & PCI_MAPREG_ROM_ADDR_MASK; } else { if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) { if (_pciverbose != 0) pci_tagprintf(tag, "pci_map_mem: bad request\n"); return -1; } address = pci_conf_read(tag, reg); if ((address & PCI_MAPREG_TYPE_IO) != 0) { if (_pciverbose != 0) pci_tagprintf(tag, "pci_map_mem: attempt to memory map an I/O region\n"); return -1; } pa = address & PCI_MAPREG_MEM_ADDR_MASK; switch (address & PCI_MAPREG_MEM_TYPE_MASK) { case PCI_MAPREG_MEM_TYPE_32BIT: case PCI_MAPREG_MEM_TYPE_32BIT_1M: break; case PCI_MAPREG_MEM_TYPE_64BIT: if (reg + 4 < PCI_MAPREG_END) pa |= ((phys_addr_t)pci_conf_read(tag, reg+4) << 32); else { if (_pciverbose != 0) pci_tagprintf(tag, "pci_map_mem: bad 64-bit reguest\n"); return -1; } break; default: if (_pciverbose != 0) pci_tagprintf(tag, "pci_map_mem: reserved mapping type\n"); return -1; } } /* XXX Do something about endian. Byte-swapping in cross-endian systems cannot really be handled here. In the BCM47xx cores, swapping of DRAM accesses (only) is controlled by a bit in the DRAM address, not in the PCI address as in the BCM1250. */ *pap = pa; return 0;}/* ISA-style i/o access (not supported) */uint8_tinb (unsigned int port){ xprintf("inb: i/o regions not supported\n"); return 0xFF;}uint16_tinw (unsigned int port){ xprintf("inw: i/o regions not supported\n"); return 0xFFFF;}uint32_tinl (unsigned int port){ xprintf("inl: i/o regions not supported\n"); return 0xFFFFFFFF;}voidoutb (unsigned int port, uint8_t val){ xprintf("outb: i/o regions not supported\n");}voidoutw (unsigned int port, uint16_t val){ xprintf("outw: i/o regions not supported\n");}voidoutl (unsigned int port, uint32_t val){ xprintf("outl: i/o regions not supported\n");}/* Interrupt slot wiring. Eval boards apparently connect only INTA and INTB but use INTA<->INTA for all devices and slots. This should be board specific except that, for all boards, all PCI interrupts are reduced to a single backplane flag before being routed to the CPU. *//* Map PCI interrupts A, B, C, D into a value for the IntLine register. Return the source number used by the interrupt mapper, or 0xff if none. */uint8_tpci_int_line(uint8_t pci_int){ uint32_t flag; flag = READCSR(R_SBTPSFLAG); return (pci_int == 0) ? 0xFF : G_SBTSF_FN(flag);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -