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; }
void gtpci_attach(struct device *parent, struct device *self, void *aux) { struct pcibus_attach_args pba; struct gt_attach_args * const ga = aux; struct gt_softc * const gt = device_private(parent); struct gtpci_softc * const gtp = device_private(self); struct gtpci_chipset * const gtpc = >p->gtpci_gtpc; struct pci_chipset * const pc = >pc->gtpc_pc; const int busno = ga->ga_unit; uint32_t data; GT_PCIFOUND(gt, ga); pc->pc_funcs = >pci_functions; pc->pc_parent = self; gtpc->gtpc_busno = busno; gtpc->gtpc_cfgaddr = PCI_CONFIG_ADDR(busno); gtpc->gtpc_cfgdata = PCI_CONFIG_DATA(busno); gtpc->gtpc_syncreg = PCI_SYNC_REG(busno); gtpc->gtpc_gt_memt = ga->ga_memt; gtpc->gtpc_gt_memh = ga->ga_memh; /* * Let's find out where we are located. */ data = gtpci_read(gtpc, PCI_P2P_CONFIGURATION(gtpc->gtpc_busno)); gtpc->gtpc_self = gtpci_make_tag(>pc->gtpc_pc, PCI_P2PCFG_BusNum_GET(data), PCI_P2PCFG_DevNum_GET(data), 0); switch (busno) { case 0: gtpc->gtpc_io_bs = gt->gt_pci0_iot; gtpc->gtpc_mem_bs = gt->gt_pci0_memt; gtpc->gtpc_host = gt->gt_pci0_host; break; case 1: gtpc->gtpc_io_bs = gt->gt_pci1_iot; gtpc->gtpc_mem_bs = gt->gt_pci1_memt; gtpc->gtpc_host = gt->gt_pci1_host; break; default: break; } /* * If no bus_spaces exist, then it's been disabled. */ if (gtpc->gtpc_io_bs == NULL && gtpc->gtpc_mem_bs == NULL) { aprint_normal(": disabled\n"); return; } aprint_normal("\n"); /* * clear any pre-existing error interrupt(s) * clear latched pci error registers * establish ISRs for PCI errors * enable PCI error interrupts */ gtpci_write(gtpc, PCI_ERROR_MASK(gtpc->gtpc_busno), 0); gtpci_write(gtpc, PCI_ERROR_CAUSE(gtpc->gtpc_busno), 0); (void)gtpci_read(gtpc, PCI_ERROR_DATA_LOW(gtpc->gtpc_busno)); (void)gtpci_read(gtpc, PCI_ERROR_DATA_HIGH(gtpc->gtpc_busno)); (void)gtpci_read(gtpc, PCI_ERROR_COMMAND(gtpc->gtpc_busno)); (void)gtpci_read(gtpc, PCI_ERROR_ADDRESS_HIGH(gtpc->gtpc_busno)); (void)gtpci_read(gtpc, PCI_ERROR_ADDRESS_LOW(gtpc->gtpc_busno)); if (gtpc->gtpc_host) { intr_establish(pci_irqs[gtpc->gtpc_busno][0], IST_LEVEL, IPL_VM, gtpci_error_intr, pc); intr_establish(pci_irqs[gtpc->gtpc_busno][1], IST_LEVEL, IPL_VM, gtpci_error_intr, pc); intr_establish(pci_irqs[gtpc->gtpc_busno][2], IST_LEVEL, IPL_VM, gtpci_error_intr, pc); aprint_normal_dev(pc->pc_parent, "%s%d error interrupts at irqs %s, %s, %s\n", "pci", busno, intr_string(pci_irqs[gtpc->gtpc_busno][0]), intr_string(pci_irqs[gtpc->gtpc_busno][1]), intr_string(pci_irqs[gtpc->gtpc_busno][2])); gtpci_write(gtpc, PCI_ERROR_MASK(gtpc->gtpc_busno), PCI_SERRMSK_ALL_ERRS); } /* * Fill in the pci_bus_attach_args */ pba.pba_pc = pc; pba.pba_bus = 0; pba.pba_iot = gtpc->gtpc_io_bs; pba.pba_memt = gtpc->gtpc_mem_bs; pba.pba_dmat = gt->gt_dmat; pba.pba_flags = 0; if (pba.pba_iot != NULL) pba.pba_flags |= PCI_FLAGS_IO_ENABLED; if (pba.pba_memt != NULL) pba.pba_flags |= PCI_FLAGS_MEM_ENABLED; data = gtpci_read(gtpc, PCI_COMMAND(gtpc->gtpc_busno)); if (data & PCI_CMD_MRdMul) pba.pba_flags |= PCI_FLAGS_MRM_OKAY; if (data & PCI_CMD_MRdLine) pba.pba_flags |= PCI_FLAGS_MRL_OKAY; pba.pba_flags |= PCI_FLAGS_MWI_OKAY; gt_watchdog_service(); /* * Configure the pci bus. */ config_found_ia(self, "pcibus", &pba, gtpci_cfprint); gt_watchdog_service(); }
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; }