Esempio n. 1
0
static ACPI_STATUS
acpi_pci_save_handle(ACPI_HANDLE handle, UINT32 level, void *context,
    void **status)
{
	struct acpi_pci_devinfo *dinfo;
	device_t *devlist;
	int devcount, i, func, slot;
	UINT32 address;

	ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);

	if (ACPI_FAILURE(acpi_GetInteger(handle, "_ADR", &address)))
		return_ACPI_STATUS (AE_OK);
	slot = ACPI_ADR_PCI_SLOT(address);
	func = ACPI_ADR_PCI_FUNC(address);
	if (device_get_children((device_t)context, &devlist, &devcount) != 0)
		return_ACPI_STATUS (AE_OK);
	for (i = 0; i < devcount; i++) {
		dinfo = device_get_ivars(devlist[i]);
		if (dinfo->ap_dinfo.cfg.func == func &&
		    dinfo->ap_dinfo.cfg.slot == slot) {
			dinfo->ap_handle = handle;
			acpi_pci_update_device(handle, devlist[i]);
			break;
		}
	}
	free(devlist, M_TEMP);
	return_ACPI_STATUS (AE_OK);
}
Esempio n. 2
0
static void
prt_lookup_device(ACPI_PCI_ROUTING_TABLE *entry, void *arg)
{
    struct prt_lookup_request *pr;

    pr = (struct prt_lookup_request *)arg;
    if (pr->pr_entry != NULL)
	return;

    /*
     * Compare the slot number (high word of Address) and pin number
     * (note that ACPI uses 0 for INTA) to check for a match.
     *
     * Note that the low word of the Address field (function number)
     * is required by the specification to be 0xffff.  We don't risk
     * checking it here.
     */
    if (ACPI_ADR_PCI_SLOT(entry->Address) == pr->pr_slot &&
	entry->Pin == pr->pr_pin)
	    pr->pr_entry = entry;
}
Esempio n. 3
0
static void
prt_attach_devices(ACPI_PCI_ROUTING_TABLE *entry, void *arg)
{
    ACPI_HANDLE handle;
    device_t child, pcib;
    int error;

    /* We only care about entries that reference a link device. */
    if (entry->Source == NULL || entry->Source[0] == '\0')
	return;

    /*
     * In practice, we only see SourceIndex's of 0 out in the wild.
     * When indices != 0 have been found, they've been bugs in the ASL.
     */
    if (entry->SourceIndex != 0)
	return;

    /* Lookup the associated handle and device. */
    pcib = (device_t)arg;
    if (ACPI_FAILURE(AcpiGetHandle(ACPI_ROOT_OBJECT, entry->Source, &handle)))
	return;
    child = acpi_get_device(handle);
    if (child == NULL)
	return;

    /* If the device hasn't been probed yet, force it to do so. */
    error = device_probe_and_attach(child);
    if (error != 0) {
	device_printf(pcib, "failed to force attach of %s\n",
	    acpi_name(handle));
	return;
    }

    /* Add a reference for a specific bus/device/pin tuple. */
    acpi_pci_link_add_reference(child, entry->SourceIndex, pcib,
	ACPI_ADR_PCI_SLOT(entry->Address), entry->Pin);
}
Esempio n. 4
0
static int
acpi_pcib_acpi_attach(device_t dev)
{
    struct acpi_hpcib_softc	*sc;
    ACPI_STATUS			status;
    static int bus0_seen = 0;
    u_int addr, slot, func, busok;
    uint8_t busno;

    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);

    sc = device_get_softc(dev);
    sc->ap_dev = dev;
    sc->ap_handle = acpi_get_handle(dev);

    /*
     * Get our segment number by evaluating _SEG
     * It's OK for this to not exist.
     */
    status = acpi_GetInteger(sc->ap_handle, "_SEG", &sc->ap_segment);
    if (ACPI_FAILURE(status)) {
	if (status != AE_NOT_FOUND) {
	    device_printf(dev, "could not evaluate _SEG - %s\n",
		AcpiFormatException(status));
	    return_VALUE (ENXIO);
	}
	/* If it's not found, assume 0. */
	sc->ap_segment = 0;
    }

    /*
     * Get our base bus number by evaluating _BBN.
     * If this doesn't work, we assume we're bus number 0.
     *
     * XXX note that it may also not exist in the case where we are
     *     meant to use a private configuration space mechanism for this bus,
     *     so we should dig out our resources and check to see if we have
     *     anything like that.  How do we do this?
     * XXX If we have the requisite information, and if we don't think the
     *     default PCI configuration space handlers can deal with this bus,
     *     we should attach our own handler.
     * XXX invoke _REG on this for the PCI config space address space?
     * XXX It seems many BIOS's with multiple Host-PCI bridges do not set
     *     _BBN correctly.  They set _BBN to zero for all bridges.  Thus,
     *     if _BBN is zero and PCI bus 0 already exists, we try to read our
     *     bus number from the configuration registers at address _ADR.
     *     We only do this for domain/segment 0 in the hopes that this is
     *     only needed for old single-domain machines.
     */
    status = acpi_GetInteger(sc->ap_handle, "_BBN", &sc->ap_bus);
    if (ACPI_FAILURE(status)) {
	if (status != AE_NOT_FOUND) {
	    device_printf(dev, "could not evaluate _BBN - %s\n",
		AcpiFormatException(status));
	    return_VALUE (ENXIO);
	} else {
	    /* If it's not found, assume 0. */
	    sc->ap_bus = 0;
	}
    }

    /*
     * If this is segment 0, the bus is zero, and PCI bus 0 already
     * exists, read the bus number via PCI config space.
     */
    busok = 1;
    if (sc->ap_segment == 0 && sc->ap_bus == 0 && bus0_seen) {
	busok = 0;
	status = acpi_GetInteger(sc->ap_handle, "_ADR", &addr);
	if (ACPI_FAILURE(status)) {
	    if (status != AE_NOT_FOUND) {
		device_printf(dev, "could not evaluate _ADR - %s\n",
		    AcpiFormatException(status));
		return_VALUE (ENXIO);
	    } else
		device_printf(dev, "couldn't find _ADR\n");
	} else {
	    /* XXX: We assume bus 0. */
	    slot = ACPI_ADR_PCI_SLOT(addr);
	    func = ACPI_ADR_PCI_FUNC(addr);
	    if (bootverbose)
		device_printf(dev, "reading config registers from 0:%d:%d\n",
		    slot, func);
	    if (host_pcib_get_busno(pci_cfgregread, 0, slot, func, &busno) == 0)
		device_printf(dev, "couldn't read bus number from cfg space\n");
	    else {
		sc->ap_bus = busno;
		busok = 1;
	    }
	}
    }

    /*
     * If nothing else worked, hope that ACPI at least lays out the
     * host-PCI bridges in order and that as a result our unit number
     * is actually our bus number.  There are several reasons this
     * might not be true.
     */
    if (busok == 0) {
	sc->ap_bus = device_get_unit(dev);
	device_printf(dev, "trying bus number %d\n", sc->ap_bus);
    }

    /* If this is bus 0 on segment 0, note that it has been seen already. */
    if (sc->ap_segment == 0 && sc->ap_bus == 0)
	    bus0_seen = 1;

    return (acpi_pcib_attach(dev, &sc->ap_prt, sc->ap_bus));
}