static void acpi_pci_update_device(ACPI_HANDLE handle, device_t pci_child) { ACPI_STATUS status; device_t child; /* * Occasionally a PCI device may show up as an ACPI device * with a _HID. (For example, the TabletPC TC1000 has a * second PCI-ISA bridge that has a _HID for an * acpi_sysresource device.) In that case, leave ACPI-CA's * device data pointing at the ACPI-enumerated device. */ child = acpi_get_device(handle); if (child != NULL) { KASSERT(device_get_parent(child) == devclass_get_device(devclass_find("acpi"), 0), ("%s: child (%s)'s parent is not acpi0", __func__, acpi_name(handle))); return; } /* * Update ACPI-CA to use the PCI enumerated device_t for this handle. */ status = AcpiAttachData(handle, acpi_fake_objhandler, pci_child); if (ACPI_FAILURE(status)) printf("WARNING: Unable to attach object data to %s - %s\n", acpi_name(handle), AcpiFormatException(status)); }
static ACPI_STATUS acpi_dock_eject_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status) { device_t dock_dev, dev; ACPI_HANDLE dock_handle; dock_dev = *(device_t *)context; dock_handle = acpi_get_handle(dock_dev); if (!acpi_dock_is_ejd_device(dock_handle, handle)) goto out; ACPI_VPRINT(dock_dev, acpi_device_get_parent_softc(dock_dev), "ejecting device for %s\n", acpi_name(handle)); dev = acpi_get_device(handle); if (dev != NULL && device_is_attached(dev)) { mtx_lock(&Giant); device_detach(dev); mtx_unlock(&Giant); } acpi_SetInteger(handle, "_EJ0", 0); out: return (AE_OK); }
static void acpi_pci_update_device(ACPI_HANDLE handle, device_t pci_child) { ACPI_STATUS status; device_t child; /* * Lookup and remove the unused device that acpi0 creates when it walks * the namespace creating devices. */ child = acpi_get_device(handle); if (child != NULL) { if (device_is_alive(child)) { /* * The TabletPC TC1000 has a second PCI-ISA bridge * that has a _HID for an acpi_sysresource device. * In that case, leave ACPI-CA's device data pointing * at the ACPI-enumerated device. */ device_printf(child, "Conflicts with PCI device %d:%d:%d\n", pci_get_bus(pci_child), pci_get_slot(pci_child), pci_get_function(pci_child)); return; } KASSERT(device_get_parent(child) == devclass_get_device(devclass_find("acpi"), 0), ("%s: child (%s)'s parent is not acpi0", __func__, acpi_name(handle))); device_delete_child(device_get_parent(child), child); } /* * Update ACPI-CA to use the PCI enumerated device_t for this handle. */ status = AcpiDetachData(handle, acpi_fake_objhandler); if (ACPI_FAILURE(status)) kprintf("WARNING: Unable to detach object data from %s - %s\n", acpi_name(handle), AcpiFormatException(status)); status = AcpiAttachData(handle, acpi_fake_objhandler, pci_child); if (ACPI_FAILURE(status)) kprintf("WARNING: Unable to attach object data to %s - %s\n", acpi_name(handle), AcpiFormatException(status)); }
static ACPI_STATUS acpi_dock_insert_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status) { device_t dock_dev, dev; ACPI_HANDLE dock_handle; dock_dev = (device_t)context; dock_handle = acpi_get_handle(dock_dev); if (!acpi_dock_is_ejd_device(dock_handle, handle)) goto out; ACPI_VPRINT(dock_dev, acpi_device_get_parent_softc(dock_dev), "inserting device for %s\n", acpi_name(handle)); #if 0 /* * If the system boot up w/o Docking, the devices under the dock * still un-initialized, also control methods such as _INI, _STA * are not executed. * Normal devices are initialized at booting by calling * AcpiInitializeObjects(), however the devices under the dock * need to be initialized here on the scheme of ACPICA. */ ACPI_INIT_WALK_INFO Info; AcpiNsWalkNamespace(ACPI_TYPE_ANY, handle, 100, TRUE, AcpiNsInitOneDevice, &Info, NULL); #endif dev = acpi_get_device(handle); if (dev == NULL) { device_printf(dock_dev, "error: %s has no associated device\n", acpi_name(handle)); goto out; } AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_dock_attach_later, dev); out: return (AE_OK); }
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); }
/* * Route an interrupt for a child of the bridge. */ int acpi_pcib_route_interrupt(device_t pcib, device_t dev, int pin, ACPI_BUFFER *prtbuf) { ACPI_PCI_ROUTING_TABLE *prt; struct prt_lookup_request pr; ACPI_HANDLE lnkdev; int interrupt; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); interrupt = PCI_INVALID_IRQ; /* ACPI numbers pins 0-3, not 1-4 like the BIOS. */ pin--; ACPI_SERIAL_BEGIN(pcib); /* Search for a matching entry in the routing table. */ pr.pr_entry = NULL; pr.pr_pin = pin; pr.pr_slot = pci_get_slot(dev); prt_walk_table(prtbuf, prt_lookup_device, &pr); if (pr.pr_entry == NULL) { device_printf(pcib, "no PRT entry for %d.%d.INT%c\n", pci_get_bus(dev), pci_get_slot(dev), 'A' + pin); goto out; } prt = pr.pr_entry; if (bootverbose) { device_printf(pcib, "matched entry for %d.%d.INT%c", pci_get_bus(dev), pci_get_slot(dev), 'A' + pin); if (prt->Source != NULL && prt->Source[0] != '\0') printf(" (src %s:%u)", prt->Source, prt->SourceIndex); printf("\n"); } /* * If source is empty/NULL, the source index is a global IRQ number * and it's hard-wired so we're done. * * XXX: If the source index is non-zero, ignore the source device and * assume that this is a hard-wired entry. */ if (prt->Source == NULL || prt->Source[0] == '\0' || prt->SourceIndex != 0) { if (bootverbose) device_printf(pcib, "slot %d INT%c hardwired to IRQ %d\n", pci_get_slot(dev), 'A' + pin, prt->SourceIndex); if (prt->SourceIndex) { interrupt = prt->SourceIndex; BUS_CONFIG_INTR(dev, interrupt, INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW); } else device_printf(pcib, "error: invalid hard-wired IRQ of 0\n"); goto out; } /* * We have to find the source device (PCI interrupt link device). */ if (ACPI_FAILURE(AcpiGetHandle(ACPI_ROOT_OBJECT, prt->Source, &lnkdev))) { device_printf(pcib, "couldn't find PCI interrupt link device %s\n", prt->Source); goto out; } interrupt = acpi_pci_link_route_interrupt(acpi_get_device(lnkdev), prt->SourceIndex); if (bootverbose && PCI_INTERRUPT_VALID(interrupt)) device_printf(pcib, "slot %d INT%c routed to irq %d via %s\n", pci_get_slot(dev), 'A' + pin, interrupt, acpi_name(lnkdev)); out: ACPI_SERIAL_END(pcib); return_VALUE(interrupt); }