/* * Query ACPI processor ID by evaluating ACPI _MAT, _UID, and PROCESSOR * objects. */ static ACPI_STATUS acpidev_cpu_get_procid(acpidev_walk_info_t *infop, uint32_t *idp) { int id; ACPI_HANDLE hdl; struct acpidev_cpu_MAT_arg mat; if (infop->awi_info->Type != ACPI_TYPE_PROCESSOR && infop->awi_info->Type != ACPI_TYPE_DEVICE) { ACPIDEV_DEBUG(CE_WARN, "!acpidev: object %s is not PROCESSOR or DEVICE.", infop->awi_name); return (AE_BAD_PARAMETER); } hdl = infop->awi_hdl; /* * First try to evaluate _MAT. * According to the ACPI Spec3.0b, it's legal for ACPI PROCESSOR objects * to have ACPI method objects. */ bzero(&mat, sizeof (mat)); (void) acpidev_walk_apic(NULL, hdl, ACPIDEV_METHOD_NAME_MAT, acpidev_cpu_query_MAT, &mat); if (mat.found) { *idp = mat.proc_id; return (AE_OK); } /* Then evalute PROCESSOR object. */ if (infop->awi_info->Type == ACPI_TYPE_PROCESSOR) { ACPI_BUFFER rb; rb.Pointer = NULL; rb.Length = ACPI_ALLOCATE_BUFFER; if (ACPI_SUCCESS(AcpiEvaluateObjectTyped(hdl, NULL, NULL, &rb, ACPI_TYPE_PROCESSOR))) { *idp = ((ACPI_OBJECT *)rb.Pointer)->Processor.ProcId; AcpiOsFree(rb.Pointer); return (AE_OK); } else { ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to evaluate ACPI object %s.", infop->awi_name); } } /* * Finally, try to evalute the _UID method. * According to the ACPI Spec3.0b, it's legal for ACPI PROCESSOR objects * to have ACPI method objects. * The CPU _UID method should return Processor Id as an integer on x86. */ if (ACPI_SUCCESS(acpica_eval_int(hdl, METHOD_NAME__UID, &id))) { *idp = id; return (AE_OK); } return (AE_NOT_FOUND); }
/* * * If the interrupt link device is already configured, * stores polarity and sensitivity in the structure pointed to by * intr_flagp, and irqno in the value pointed to by pci_irqp. * * Returns: * ACPI_PSM_SUCCESS if the interrupt link device is already configured. * ACPI_PSM_PARTIAL if configuration is needed. * ACPI_PSM_FAILURE in case of error. * * When two devices share the same interrupt link device, and the * link device is already configured (i.e. found in the irq cache) * we need to use the already configured irq instead of reconfiguring * the link device. */ static int acpi_eval_lnk(dev_info_t *dip, char *lnkname, int *pci_irqp, iflag_t *intr_flagp, acpi_psm_lnk_t *acpipsmlnkp) { ACPI_HANDLE tmpobj; ACPI_HANDLE lnkobj; int status; /* * Convert the passed-in link device name to a handle */ if (AcpiGetHandle(NULL, lnkname, &lnkobj) != AE_OK) { return (ACPI_PSM_FAILURE); } /* * Assume that the link device is invalid if no _CRS method * exists, since _CRS method is a required method */ if (AcpiGetHandle(lnkobj, "_CRS", &tmpobj) != AE_OK) { return (ACPI_PSM_FAILURE); } ASSERT(acpipsmlnkp != NULL); acpipsmlnkp->lnkobj = lnkobj; if ((acpi_get_irq_lnk_cache_ent(lnkobj, pci_irqp, intr_flagp)) == ACPI_PSM_SUCCESS) { PSM_VERBOSE_IRQ((CE_CONT, "!psm: link object found from cache " " for device %s, instance #%d, irq no %d\n", ddi_get_name(dip), ddi_get_instance(dip), *pci_irqp)); return (ACPI_PSM_SUCCESS); } else { if (acpica_eval_int(lnkobj, "_STA", &status) == AE_OK) { acpipsmlnkp->device_status = (uchar_t)status; } return (ACPI_PSM_PARTIAL); } }
/* * Sets the irq resource of the lnk object to the requested irq value. * * Returns ACPI_PSM_SUCCESS on success, ACPI_PSM_FAILURE upon failure. */ int acpi_set_irq_resource(acpi_psm_lnk_t *acpipsmlnkp, int irq) { ACPI_BUFFER rsb; ACPI_RESOURCE *resp; ACPI_RESOURCE *srsp; ACPI_HANDLE lnkobj; int srs_len, status; ASSERT(acpipsmlnkp != NULL); lnkobj = acpipsmlnkp->lnkobj; /* * Fetch the possible resources for the link */ rsb.Pointer = NULL; rsb.Length = ACPI_ALLOCATE_BUFFER; status = AcpiGetPossibleResources(lnkobj, &rsb); if (status != AE_OK) { cmn_err(CE_WARN, "!psm: set_irq: _PRS failed"); return (ACPI_PSM_FAILURE); } /* * Find an IRQ resource descriptor to use as template */ srsp = NULL; for (resp = rsb.Pointer; resp->Type != ACPI_RESOURCE_TYPE_END_TAG; resp = ACPI_NEXT_RESOURCE(resp)) { if ((resp->Type == ACPI_RESOURCE_TYPE_IRQ) || (resp->Type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ)) { ACPI_RESOURCE *endtag; /* * Allocate enough room for this resource entry * and one end tag following it */ srs_len = resp->Length + sizeof (*endtag); srsp = kmem_zalloc(srs_len, KM_SLEEP); bcopy(resp, srsp, resp->Length); endtag = ACPI_NEXT_RESOURCE(srsp); endtag->Type = ACPI_RESOURCE_TYPE_END_TAG; endtag->Length = 0; break; /* drop out of the loop */ } } /* * We're done with the PRS values, toss 'em lest we forget */ AcpiOsFree(rsb.Pointer); if (srsp == NULL) return (ACPI_PSM_FAILURE); /* * The Interrupts[] array is always at least one entry * long; see the definition of ACPI_RESOURCE. */ switch (srsp->Type) { case ACPI_RESOURCE_TYPE_IRQ: srsp->Data.Irq.InterruptCount = 1; srsp->Data.Irq.Interrupts[0] = irq; break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: srsp->Data.ExtendedIrq.InterruptCount = 1; srsp->Data.ExtendedIrq.Interrupts[0] = irq; break; } rsb.Pointer = srsp; rsb.Length = srs_len; status = AcpiSetCurrentResources(lnkobj, &rsb); kmem_free(srsp, srs_len); if (status != AE_OK) { cmn_err(CE_WARN, "!psm: set_irq: _SRS failed"); return (ACPI_PSM_FAILURE); } if (acpica_eval_int(lnkobj, "_STA", &status) == AE_OK) { acpipsmlnkp->device_status = (uchar_t)status; return (ACPI_PSM_SUCCESS); } else return (ACPI_PSM_FAILURE); }