示例#1
0
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;
}
示例#2
0
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 = &gtp->gtpci_gtpc;
	struct pci_chipset * const pc = &gtpc->gtpc_pc;
	const int busno = ga->ga_unit;
	uint32_t data;

	GT_PCIFOUND(gt, ga);

	pc->pc_funcs = &gtpci_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(&gtpc->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();

}
示例#3
0
文件: hndpci.c 项目: hajuuk/R7000
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;
}