예제 #1
0
파일: hndpci.c 프로젝트: millken/zhuxianB30
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
파일: 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;
}