Ejemplo n.º 1
0
/*
 * 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);
}
Ejemplo n.º 2
0
/*
 *
 * 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);
	}
}
Ejemplo n.º 3
0
/*
 * 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);
}