Esempio n. 1
0
/*
 * This function is called to emulate the various settings in a P2P or CardBus
 * bridge's control register using one of a 460GX's SAC host bridges.
 */
static CARD16
Control460GXBridge(int bus, CARD16 mask, CARD16 value)
{
    pciConfigPtr pPCI;
    PCITAG tag;
    CARD16 current = 0;
    CARD8  tmp;

    if ((pPCI = Verify460GXBus(bus))) {
	/* Start with VGA enablement */
	tmp = pciReadByte(pPCI->tag, VGASE);
	if (tmp & 0x01) {
	    current |= PCI_PCI_BRIDGE_VGA_EN;
	    if ((mask & PCI_PCI_BRIDGE_VGA_EN) &&
		!(value & PCI_PCI_BRIDGE_VGA_EN))
		pciWriteByte(pPCI->tag, VGASE, tmp & ~0x01);
	} else {
	    if (mask & value & PCI_PCI_BRIDGE_VGA_EN)
		pciWriteByte(pPCI->tag, VGASE, tmp | 0x01);
	}

	/* Move on to master abort failure enablement */
	if (has_err_460gx[pPCI->devnum - 0x10]) {
	    tag = PCI_MAKE_TAG(pPCI->busnum, pPCI->devnum, pPCI->funcnum + 1);
	    tmp = pciReadByte(tag, ERRCMD);
	    if (tmp & 0x01) {
		current |= PCI_PCI_BRIDGE_MASTER_ABORT_EN;
		if ((mask & PCI_PCI_BRIDGE_MASTER_ABORT_EN) &&
		    !(value & PCI_PCI_BRIDGE_MASTER_ABORT_EN))
		    pciWriteByte(tag, ERRCMD, tmp & ~0x01);
	    } else {
		if (mask & value & PCI_PCI_BRIDGE_MASTER_ABORT_EN)
		    pciWriteByte(tag, ERRCMD, tmp | 0x01);
	    }
	}

	/* Put emulation of any other P2P bridge control here */
    }

    return (current & ~mask) | (value & mask);
}
Esempio n. 2
0
static Bool
ix86PciBusCheck(void)
{
    PCITAG tag;
    CARD32 id, class;
    CARD8 device;

    for (device = 0; device < ix86Pci0.numDevices; device++) {
        tag = PCI_MAKE_TAG(0, device, 0);
        id = (*ix86Pci0.funcs->pciReadLong)(tag, PCI_ID_REG);

        if ((CARD16)(id + 1U) <= (CARD16)1UL)
            continue;

        /* The rest of this is inspired by the Linux kernel */
        class = (*ix86Pci0.funcs->pciReadLong)(tag, PCI_CLASS_REG);

        /* Ignore revision id and programming interface */
        switch (class >> 16) {
        case (PCI_CLASS_PREHISTORIC << 8) | PCI_SUBCLASS_PREHISTORIC_MISC:
            /* Check for vendors of known buggy chipsets */
            id &= 0x0000ffff;
            if ((id == PCI_VENDOR_INTEL) || (id == PCI_VENDOR_COMPAQ))
                return TRUE;
            continue;

        case (PCI_CLASS_PREHISTORIC << 8) | PCI_SUBCLASS_PREHISTORIC_VGA:
        case (PCI_CLASS_DISPLAY << 8) | PCI_SUBCLASS_DISPLAY_VGA:
        case (PCI_CLASS_BRIDGE << 8) | PCI_SUBCLASS_BRIDGE_HOST:
            return TRUE;

        default:
            break;
        }
    }
    return FALSE;
}
Esempio n. 3
0
/* This does some 460GX-related processing after the PCI bus scan */
void
xf86PostScan460GX(void)
{
    pciConfigPtr pPCI, *ppPCI;
    pciBusInfo_t *pBusInfo;
    int i, j, devno;

    if (cbn_460gx <= 0)
	return;

    /* Set up our extra bus functions */
    BusFuncs_460gx = *(pciBusInfo[0]->funcs);
    BusFuncs_460gx.pciControlBridge = Control460GXBridge;
    BusFuncs_460gx.pciGetBridgeBusses = Get460GXBridgeBusses;
    BusFuncs_460gx.pciGetBridgeResources = Get460GXBridgeResources;

    /*
     * Mark all host bridges so that they are ignored by the upper-level
     * xf86GetPciBridgeInfo() function.  This marking is later clobbered by the
     * tail end of xf86scanpci() for those bridges that actually have bus
     * segments associated with them.
     */
    ppPCI = xf86scanpci(0);	/* Recursion is only apparent */
    while ((pPCI = *ppPCI++)) {
	if ((pPCI->pci_base_class == PCI_CLASS_BRIDGE) &&
	    (pPCI->pci_sub_class == PCI_SUBCLASS_BRIDGE_HOST))
	    pPCI->businfo = HOST_NO_BUS;
    }

    ppPCI = xf86scanpci(0);	/* Recursion is only apparent */
    j = 0;

    /*
     * Fix up CBN bus linkage.  This is somewhat arbitrary.  The bridge chosen
     * for this must be a CBN device so that bus CBN can be recognised as the
     * root segment.  It also cannot be any of the bus expanders (devices
     * CBN:0x10:0 through CBN:0x17:0 nor any of their functions).  For now, we
     * chose the SAC host bridge at CBN:0:0.
     */
    pBusInfo = pciBusInfo[cbn_460gx];
    pBusInfo->bridge = pciBusInfo[0]->bridge;	/* Just in case */
    while ((pPCI = *ppPCI++)) {
	if (pPCI->busnum < cbn_460gx)
	    continue;
	if (pPCI->busnum > cbn_460gx)
	    break;
	if (pPCI->devnum < 0)
	    continue;
	if (pPCI->devnum > 0)
	    break;
	if (pPCI->funcnum < 0)
	    continue;
	if (pPCI->funcnum > 0)
	    break;

	pBusInfo->bridge = pPCI;
	pBusInfo->secondary = FALSE;
	pBusInfo->primary_bus = cbn_460gx;
	break;
    }

    for (i = 0, devno = 0x10;  devno <= 0x17;  i++, devno++) {
	/* Restore ERRCMD registers */
	if (err_460gx[i] & 0x01)
	    pciWriteByte(PCI_MAKE_TAG(cbn_460gx, devno, 1),
			 ERRCMD, err_460gx[i]);

	if (!(cbdevs_460gx & (1 << devno))) {
	    while ((pPCI = *ppPCI++)) {
		if (pPCI->busnum < cbn_460gx)
		    continue;
		if (pPCI->busnum > cbn_460gx)
		    break;
		if (pPCI->devnum < devno)
		    continue;
		if (pPCI->devnum > devno)
		    break;
		if (pPCI->funcnum < 0)
		    continue;
		if (pPCI->funcnum > 0)
		    break;

		if ((pBusInfo = pciBusInfo[busno_460gx[i]]))
		    break;

		/* Fix bus linkage */
		pBusInfo->bridge = pPCI;
		pBusInfo->secondary = TRUE;
		pBusInfo->primary_bus = cbn_460gx;

		/* Plug in chipset routines */
		pBusInfo->funcs = &BusFuncs_460gx;
		break;
	    }
	}

	/* Decode IOR registers */
	for(;  j <= (ior_460gx[i] & 0x0F);  j++)
	    iomap_460gx[j] = devno;
    }

    /* The bottom 4k of I/O space is always routed to PCI0a */
    iomap_460gx[0] = 0x10;

    /* Decode IORD register */
    for (j = 1;  j <= 0x0F;  j++)
	if (iord_460gx & (1 << j))
	    iomap_460gx[j] = 0x10;
}
Esempio n. 4
0
/*
 * This checks for, and validates, the presence of the 460GX chipset, and sets
 * cbn_460gx to a positive value accordingly.  This function returns TRUE if
 * the chipset scan is to be stopped, or FALSE if the scan is to move on to the
 * next chipset.
 */
Bool
xf86PreScan460GX(void)
{
    pciBusInfo_t *pBusInfo;
    PCITAG tag;
    CARD32 tmp;
    int i, devno;

    /* Bus zero should already be set up */
    if (!(pBusInfo = pciBusInfo[0])) {
	cbn_460gx = -1;
	return FALSE;
    }

    /* First look for a 460GX's primary host bridge */
    tag = PCI_MAKE_TAG(0, 0x10, 0);
    if (pciReadLong(tag, PCI_ID_REG) != DEVID(INTEL, 460GX_SAC)) {
	cbn_460gx = -1;
	return FALSE;
    }

    /* Get CBN (Chipset bus number) */
    if (!(cbn_460gx = (unsigned int)pciReadByte(tag, CBN))) {
	/* Sanity check failed */
	cbn_460gx = -1;
	return TRUE;
    }

    if (pciNumBuses <= cbn_460gx)
	pciNumBuses = cbn_460gx + 1;

    /* Set up bus CBN */
    if (!pciBusInfo[cbn_460gx]) {
	pciBusInfo[cbn_460gx] = xnfalloc(sizeof(pciBusInfo_t));
	*pciBusInfo[cbn_460gx] = *pBusInfo;
    }

    tag = PCI_MAKE_TAG(cbn_460gx, 0, 0);
    if (pciReadLong(tag, PCI_ID_REG) != DEVID(INTEL, 460GX_SAC)) {
	/* Sanity check failed */
	cbn_460gx = -1;
	return TRUE;
    }

    /*
     * Find out which CBN devices the firmware thinks are present.  Of these,
     * we are only interested in devices 0x10 through 0x17.
     */
    cbdevs_460gx = pciReadLong(tag, DEVNPRES);

    for (i = 0, devno = 0x10;  devno <= 0x17;  i++, devno++) {
	tag = PCI_MAKE_TAG(cbn_460gx, devno, 0);
	if (pciReadLong(tag, PCI_ID_REG) != DEVID(INTEL, 460GX_SAC)) {
	    /* Sanity check failed */
	    cbn_460gx = -1;
	    return TRUE;
	}

	if (devno == 0x10)
	    iord_460gx = pciReadWord(tag, IORD);

	busno_460gx[i] = (unsigned int)pciReadByte(tag, BUSNO);
	subno_460gx[i] = (unsigned int)pciReadByte(tag, SUBNO);
	pcis_460gx[i] = pciReadByte(tag, PCIS);
	ior_460gx[i] = pciReadByte(tag, IOR);

	has_err_460gx[i] = err_460gx[i] = 0;	/* Insurance */

	tag = PCI_MAKE_TAG(cbn_460gx, devno, 1);
	tmp = pciReadLong(tag, PCI_ID_REG);
	switch (tmp) {
	case DEVID(INTEL, 460GX_PXB):
	case DEVID(INTEL, 460GX_WXB):
	    if (cbdevs_460gx & (1 << devno)) {
		/* Sanity check failed */
		cbn_460gx = -1;
		return TRUE;
	    }

	    /*
	     * XXX  I don't have WXB docs, but PCI register dumps indicate that
	     * the registers we are interested in are consistent with those of
	     * the PXB.
	     */
	    err_460gx[i] = pciReadByte(tag, ERRCMD);
	    has_err_460gx[i] = 1;
	    break;

	case DEVID(INTEL, 460GX_GXB_1):
	    if (cbdevs_460gx & (1 << devno)) {
		/* Sanity check failed */
		cbn_460gx = -1;
		return TRUE;
	    }

	    /*
	     * XXX  GXB isn't documented to have an ERRCMD register, nor any
	     * other means of failing master aborts.  For now, assume master
	     * aborts are always allowed to complete normally.
	     */
	    break;

	default:
	    if (((CARD16)(tmp + 1U) <= (CARD16)1U) &&
		(cbdevs_460gx & (1U << devno)))
		break;
	    /* Sanity check failed */
	    cbn_460gx = -1;
	    return TRUE;
	}
    }

    /* Allow master aborts to complete normally */
    for (i = 0, devno = 0x10;  devno <= 0x17;  i++, devno++) {
	if (!(err_460gx[i] & 0x01))
	    continue;

	pciWriteByte(PCI_MAKE_TAG(cbn_460gx, devno, 1),
		     ERRCMD, err_460gx[i] & ~0x01);
    }

    /*
     * The 460GX spec says that any access to busses higher than CBN will be
     * master-aborted.  It seems possible however that this is not the case in
     * all 460GX implementations.  For now, limit the bus scan to CBN, unless
     * we have already found a higher bus number.
     */
    for (i = 0;  subno_460gx[i] < cbn_460gx;  ) {
	if (++i < 8)
	    continue;

	pciMaxBusNum = cbn_460gx + 1;
	break;
    }

    return TRUE;
}