static uint32 config_cmd(si_t *sih, uint bus, uint dev, uint func, uint off) { uint coreidx; sbpciregs_t *pci; uint32 addr = 0, *sbtopci1; osl_t *osh; uint8 port; /* CardBusMode supports only one device */ if (cardbus && dev > 1) return 0; /* Convert logical bus to physical port/bus for following processing */ port = PCIE_GET_PORT_BY_BUS(bus); if (port == 1) { /* 1-based bus number */ bus = bus - PCIE_PORT1_BUS_START + 1; } osh = si_osh(sih); coreidx = si_coreidx(sih); pci = (sbpciregs_t *)si_setcore(sih, PCI_CORE_ID, port); if (pci) { sbtopci1 = &pci->sbtopci1; } else { sbpcieregs_t *pcie; pcie = (sbpcieregs_t *)si_setcore(sih, PCIE_CORE_ID, port); /* Issue config commands only when the data link is up (atleast * one external pcie device is present). */ if (pcie && (dev < 2) && (pcie_readreg(osh, pcie, PCIE_PCIEREGS, PCIE_DLLP_LSREG) & PCIE_DLLP_LSREG_LINKUP)) { sbtopci1 = &pcie->sbtopcie1; } else { si_setcoreidx(sih, coreidx); return 0; } } /* Type 0 transaction */ if (bus == 1) { /* Skip unwired slots */ if (dev < PCI_SLOT_MAX) { /* Slide the PCI window to the appropriate slot */ if (pci) { uint32 win; win = (SBTOPCI_CFG0 | ((1 << (dev + PCI_SLOTAD_MAP)) & SBTOPCI1_MASK)); W_REG(osh, sbtopci1, win); addr = (SI_PCI_CFG(port) | ((1 << (dev + PCI_SLOTAD_MAP)) & ~SBTOPCI1_MASK) | (func << PCICFG_FUN_SHIFT) | (off & ~3)); } else { W_REG(osh, sbtopci1, SBTOPCI_CFG0); addr = (SI_PCI_CFG(port) | (dev << PCIECFG_SLOT_SHIFT) | (func << PCIECFG_FUN_SHIFT) | (off & ~3)); } } } else { /* Type 1 transaction */ addr = SI_PCI_CFG(port); if (pci) { addr |= PCI_CONFIG_ADDR(bus, dev, func, (off & ~3)); /* * Higher bus bits (which lets the address exceed the 64MB space) * should be specified in sbtopci1's UpperAddress. */ W_REG(osh, sbtopci1, SBTOPCI_CFG1 | (addr & SBTOPCI1_MASK)); /* To not exceed the 64MB space (by using UA instead) */ addr &= ~SBTOPCI1_MASK; } else { addr |= PCIE_CONFIG_ADDR((bus - 1), dev, func, (off & ~3)); /* * Higher bus bits (which lets the address exceed the 64MB space) * should be specified in sbtopci1's UpperAddress. */ W_REG(osh, sbtopci1, SBTOPCI_CFG1 | (addr & SBTOPCIE1_MASK)); /* To not exceed the 64MB space (by using UA instead) */ addr &= ~SBTOPCIE1_MASK; } } si_setcoreidx(sih, coreidx); return addr; }
static uint32 config_cmd(si_t *sih, uint coreunit, uint bus, uint dev, uint func, uint off) { uint coreidx; sbpciregs_t *pci; uint32 addr = 0, *sbtopci1; osl_t *osh; /* CardBusMode supports only one device */ if (cardbus && dev > 1) return 0; osh = si_osh(sih); coreidx = si_coreidx(sih); pci = (sbpciregs_t *)si_setcore(sih, PCI_CORE_ID, coreunit); if (pci) { sbtopci1 = &pci->sbtopci1; } else { sbpcieregs_t *pcie; pcie = (sbpcieregs_t *)si_setcore(sih, PCIE_CORE_ID, coreunit); /* Issue config commands only when the data link is up (atleast * one external pcie device is present). */ if (pcie && (dev < 2) && (pcie_readreg(sih, pcie, PCIE_PCIEREGS, PCIE_DLLP_LSREG) & PCIE_DLLP_LSREG_LINKUP)) { sbtopci1 = &pcie->sbtopcie1; } else { si_setcoreidx(sih, coreidx); return 0; } } /* Type 0 transaction */ if (!hndpci_is_hostbridge(bus, dev)) { /* Skip unwired slots */ if (dev < PCI_SLOT_MAX) { /* Slide the PCI window to the appropriate slot */ if (pci) { uint32 win; win = (SBTOPCI_CFG0 | ((1 << (dev + PCI_SLOTAD_MAP)) & SBTOPCI1_MASK)); W_REG(osh, sbtopci1, win); addr = (pci_membase_cfg[coreunit] | ((1 << (dev + PCI_SLOTAD_MAP)) & ~SBTOPCI1_MASK) | (func << PCICFG_FUN_SHIFT) | (off & ~3)); } else { W_REG(osh, sbtopci1, SBTOPCI_CFG0); addr = (pci_membase_cfg[coreunit] | (dev << PCIECFG_SLOT_SHIFT) | (func << PCIECFG_FUN_SHIFT) | (off & ~3)); } } } else { /* Type 1 transaction */ W_REG(osh, sbtopci1, SBTOPCI_CFG1); addr = (pci_membase_cfg[coreunit] | (pci ? PCI_CONFIG_ADDR(bus, dev, func, (off & ~3)) : PCIE_CONFIG_ADDR((bus - 1), dev, func, (off & ~3)))); } si_setcoreidx(sih, coreidx); return addr; }