コード例 #1
0
ファイル: gic_v3_acpi.c プロジェクト: derekmarcotte/freebsd
static int
gic_v3_acpi_probe(device_t dev)
{

	switch((uintptr_t)acpi_get_private(dev)) {
	case ACPI_MADT_GIC_VERSION_V3:
		break;
	default:
		return (ENXIO);
	}

	device_set_desc(dev, GIC_V3_DEVSTR);
	return (BUS_PROBE_NOWILDCARD);
}
コード例 #2
0
ファイル: gic_acpi.c プロジェクト: FreeBSDFoundation/freebsd
static int
gic_acpi_probe(device_t dev)
{

	switch((uintptr_t)acpi_get_private(dev)) {
	case ACPI_MADT_GIC_VERSION_NONE:
	case ACPI_MADT_GIC_VERSION_V1:
	case ACPI_MADT_GIC_VERSION_V2:
		break;
	default:
		return (ENXIO);
	}

	device_set_desc(dev, "ARM Generic Interrupt Controller");
	return (BUS_PROBE_NOWILDCARD);
}
コード例 #3
0
ファイル: acpi_cpu.c プロジェクト: Digital-Chaos/freebsd
static int
acpi_cpu_attach(device_t dev)
{
    ACPI_BUFFER		   buf;
    ACPI_OBJECT		   arg, *obj;
    ACPI_OBJECT_LIST	   arglist;
    struct pcpu		   *pcpu_data;
    struct acpi_cpu_softc *sc;
    struct acpi_softc	  *acpi_sc;
    ACPI_STATUS		   status;
    u_int		   features;
    int			   cpu_id, drv_count, i;
    driver_t 		  **drivers;
    uint32_t		   cap_set[3];

    /* UUID needed by _OSC evaluation */
    static uint8_t cpu_oscuuid[16] = { 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29,
				       0xBE, 0x47, 0x9E, 0xBD, 0xD8, 0x70,
				       0x58, 0x71, 0x39, 0x53 };

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

    sc = device_get_softc(dev);
    sc->cpu_dev = dev;
    sc->cpu_handle = acpi_get_handle(dev);
    cpu_id = (int)(intptr_t)acpi_get_private(dev);
    cpu_softc[cpu_id] = sc;
    pcpu_data = pcpu_find(cpu_id);
    pcpu_data->pc_device = dev;
    sc->cpu_pcpu = pcpu_data;
    cpu_smi_cmd = AcpiGbl_FADT.SmiCommand;
    cpu_cst_cnt = AcpiGbl_FADT.CstControl;

    buf.Pointer = NULL;
    buf.Length = ACPI_ALLOCATE_BUFFER;
    status = AcpiEvaluateObject(sc->cpu_handle, NULL, NULL, &buf);
    if (ACPI_FAILURE(status)) {
	device_printf(dev, "attach failed to get Processor obj - %s\n",
		      AcpiFormatException(status));
	return (ENXIO);
    }
    obj = (ACPI_OBJECT *)buf.Pointer;
    sc->cpu_p_blk = obj->Processor.PblkAddress;
    sc->cpu_p_blk_len = obj->Processor.PblkLength;
    sc->cpu_acpi_id = obj->Processor.ProcId;
    AcpiOsFree(obj);
    ACPI_DEBUG_PRINT((ACPI_DB_INFO, "acpi_cpu%d: P_BLK at %#x/%d\n",
		     device_get_unit(dev), sc->cpu_p_blk, sc->cpu_p_blk_len));

    /*
     * If this is the first cpu we attach, create and initialize the generic
     * resources that will be used by all acpi cpu devices.
     */
    if (device_get_unit(dev) == 0) {
	/* Assume we won't be using generic Cx mode by default */
	cpu_cx_generic = FALSE;

	/* Install hw.acpi.cpu sysctl tree */
	acpi_sc = acpi_device_get_parent_softc(dev);
	sysctl_ctx_init(&cpu_sysctl_ctx);
	cpu_sysctl_tree = SYSCTL_ADD_NODE(&cpu_sysctl_ctx,
	    SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, "cpu",
	    CTLFLAG_RD, 0, "node for CPU children");
    }

    /*
     * Before calling any CPU methods, collect child driver feature hints
     * and notify ACPI of them.  We support unified SMP power control
     * so advertise this ourselves.  Note this is not the same as independent
     * SMP control where each CPU can have different settings.
     */
    sc->cpu_features = ACPI_CAP_SMP_SAME | ACPI_CAP_SMP_SAME_C3 |
      ACPI_CAP_C1_IO_HALT;

#if defined(__i386__) || defined(__amd64__)
    /*
     * Ask for MWAIT modes if not disabled and interrupts work
     * reasonable with MWAIT.
     */
    if (!acpi_disabled("mwait") && cpu_mwait_usable())
	sc->cpu_features |= ACPI_CAP_SMP_C1_NATIVE | ACPI_CAP_SMP_C3_NATIVE;
#endif

    if (devclass_get_drivers(acpi_cpu_devclass, &drivers, &drv_count) == 0) {
	for (i = 0; i < drv_count; i++) {
	    if (ACPI_GET_FEATURES(drivers[i], &features) == 0)
		sc->cpu_features |= features;
	}
	free(drivers, M_TEMP);
    }

    /*
     * CPU capabilities are specified in
     * Intel Processor Vendor-Specific ACPI Interface Specification.
     */
    if (sc->cpu_features) {
	cap_set[1] = sc->cpu_features;
	status = acpi_EvaluateOSC(sc->cpu_handle, cpu_oscuuid, 1, 2, cap_set,
	    cap_set, false);
	if (ACPI_SUCCESS(status)) {
	    if (cap_set[0] != 0)
		device_printf(dev, "_OSC returned status %#x\n", cap_set[0]);
	}
	else {
	    arglist.Pointer = &arg;
	    arglist.Count = 1;
	    arg.Type = ACPI_TYPE_BUFFER;
	    arg.Buffer.Length = sizeof(cap_set);
	    arg.Buffer.Pointer = (uint8_t *)cap_set;
	    cap_set[0] = 1; /* revision */
	    cap_set[1] = 1; /* number of capabilities integers */
	    cap_set[2] = sc->cpu_features;
	    AcpiEvaluateObject(sc->cpu_handle, "_PDC", &arglist, NULL);
	}
    }

    /* Probe for Cx state support. */
    acpi_cpu_cx_probe(sc);

    return (0);
}
コード例 #4
0
ファイル: acpi_ec.c プロジェクト: AhmadTux/DragonFlyBSD
static int
acpi_ec_attach(device_t dev)
{
    struct acpi_ec_softc	*sc;
    struct acpi_ec_params	*params;
    ACPI_STATUS			Status;

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

    /* Fetch/initialize softc (assumes softc is pre-zeroed). */
    sc = device_get_softc(dev);
    params = acpi_get_private(dev);
    sc->ec_dev = dev;
    sc->ec_handle = acpi_get_handle(dev);
    ACPI_SERIAL_INIT(ec);

    /* Retrieve previously probed values via device ivars. */
    sc->ec_glk = params->glk;
    sc->ec_gpebit = params->gpe_bit;
    sc->ec_gpehandle = params->gpe_handle;
    sc->ec_uid = params->uid;
    sc->ec_suspending = FALSE;
    acpi_set_private(dev, NULL);
    kfree(params, M_TEMP);

    /* Attach bus resources for data and command/status ports. */
    sc->ec_data_rid = 0;
    sc->ec_data_res = bus_alloc_resource_any(sc->ec_dev, SYS_RES_IOPORT,
			&sc->ec_data_rid, RF_ACTIVE);
    if (sc->ec_data_res == NULL) {
	device_printf(dev, "can't allocate data port\n");
	goto error;
    }
    sc->ec_data_tag = rman_get_bustag(sc->ec_data_res);
    sc->ec_data_handle = rman_get_bushandle(sc->ec_data_res);

    sc->ec_csr_rid = 1;
    sc->ec_csr_res = bus_alloc_resource_any(sc->ec_dev, SYS_RES_IOPORT,
			&sc->ec_csr_rid, RF_ACTIVE);
    if (sc->ec_csr_res == NULL) {
	device_printf(dev, "can't allocate command/status port\n");
	goto error;
    }
    sc->ec_csr_tag = rman_get_bustag(sc->ec_csr_res);
    sc->ec_csr_handle = rman_get_bushandle(sc->ec_csr_res);

    /*
     * Install a handler for this EC's GPE bit.  We want edge-triggered
     * behavior.
     */
    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching GPE handler\n"));
    Status = AcpiInstallGpeHandler(sc->ec_gpehandle, sc->ec_gpebit,
		ACPI_GPE_EDGE_TRIGGERED, &EcGpeHandler, sc);
    if (ACPI_FAILURE(Status)) {
	device_printf(dev, "can't install GPE handler for %s - %s\n",
		      acpi_name(sc->ec_handle), AcpiFormatException(Status));
	goto error;
    }

    /*
     * Install address space handler
     */
    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching address space handler\n"));
    Status = AcpiInstallAddressSpaceHandler(sc->ec_handle, ACPI_ADR_SPACE_EC,
		&EcSpaceHandler, &EcSpaceSetup, sc);
    if (ACPI_FAILURE(Status)) {
	device_printf(dev, "can't install address space handler for %s - %s\n",
		      acpi_name(sc->ec_handle), AcpiFormatException(Status));
	goto error;
    }

    /* Enable runtime GPEs for the handler */
    Status = AcpiEnableGpe(sc->ec_gpehandle, sc->ec_gpebit);
    if (ACPI_FAILURE(Status)) {
	device_printf(dev, "AcpiEnableGpe failed: %s\n",
		      AcpiFormatException(Status));
	goto error;
    }

    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "acpi_ec_attach complete\n"));
    return (0);

error:
    AcpiRemoveGpeHandler(sc->ec_gpehandle, sc->ec_gpebit, &EcGpeHandler);
    AcpiRemoveAddressSpaceHandler(sc->ec_handle, ACPI_ADR_SPACE_EC,
	EcSpaceHandler);
    if (sc->ec_csr_res)
	bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_csr_rid,
			     sc->ec_csr_res);
    if (sc->ec_data_res)
	bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_data_rid,
			     sc->ec_data_res);
    return (ENXIO);
}
コード例 #5
0
ファイル: acpi_ec.c プロジェクト: AhmadTux/DragonFlyBSD
static int
acpi_ec_probe(device_t dev)
{
    ACPI_BUFFER buf;
    ACPI_HANDLE h;
    ACPI_OBJECT *obj;
    ACPI_STATUS status;
    device_t	peer;
    char	desc[64];
    int		ecdt;
    int		ret;
    struct acpi_ec_params *params;
    static char *ec_ids[] = { "PNP0C09", NULL };

    /* Check that this is a device and that EC is not disabled. */
    if (acpi_get_type(dev) != ACPI_TYPE_DEVICE || acpi_disabled("ec"))
	return (ENXIO);

    /*
     * If probed via ECDT, set description and continue.  Otherwise,
     * we can access the namespace and make sure this is not a
     * duplicate probe.
     */
    ret = ENXIO;
    ecdt = 0;
    buf.Pointer = NULL;
    buf.Length = ACPI_ALLOCATE_BUFFER;
    params = acpi_get_private(dev);
    if (params != NULL) {
	ecdt = 1;
	ret = 0;
    } else if (ACPI_ID_PROBE(device_get_parent(dev), dev, ec_ids)) {
	params = kmalloc(sizeof(struct acpi_ec_params), M_TEMP,
			M_WAITOK | M_ZERO);
	h = acpi_get_handle(dev);

	/*
	 * Read the unit ID to check for duplicate attach and the
	 * global lock value to see if we should acquire it when
	 * accessing the EC.
	 */
	status = acpi_GetInteger(h, "_UID", &params->uid);
	if (ACPI_FAILURE(status))
	    params->uid = 0;
	status = acpi_GetInteger(h, "_GLK", &params->glk);
	if (ACPI_FAILURE(status))
	    params->glk = 0;

	/*
	 * Evaluate the _GPE method to find the GPE bit used by the EC to
	 * signal status (SCI).  If it's a package, it contains a reference
	 * and GPE bit, similar to _PRW.
	 */
	status = AcpiEvaluateObject(h, "_GPE", NULL, &buf);
	if (ACPI_FAILURE(status)) {
	    device_printf(dev, "can't evaluate _GPE - %s\n",
			  AcpiFormatException(status));
	    goto out;
	}
	obj = (ACPI_OBJECT *)buf.Pointer;
	if (obj == NULL)
	    goto out;

	switch (obj->Type) {
	case ACPI_TYPE_INTEGER:
	    params->gpe_handle = NULL;
	    params->gpe_bit = obj->Integer.Value;
	    break;
	case ACPI_TYPE_PACKAGE:
	    if (!ACPI_PKG_VALID(obj, 2))
		goto out;
	    params->gpe_handle =
		acpi_GetReference(NULL, &obj->Package.Elements[0]);
	    if (params->gpe_handle == NULL ||
		acpi_PkgInt32(obj, 1, &params->gpe_bit) != 0)
		goto out;
	    break;
	default:
	    device_printf(dev, "_GPE has invalid type %d\n", obj->Type);
	    goto out;
	}

	/* Store the values we got from the namespace for attach. */
	acpi_set_private(dev, params);

	/*
	 * Check for a duplicate probe.  This can happen when a probe
	 * via ECDT succeeded already.  If this is a duplicate, disable
	 * this device.
	 */
	peer = devclass_get_device(acpi_ec_devclass, params->uid);
	if (peer == NULL || !device_is_alive(peer))
	    ret = 0;
	else
	    device_disable(dev);
    }

out:
    if (ret == 0) {
	ksnprintf(desc, sizeof(desc), "Embedded Controller: GPE %#x%s%s",
		 params->gpe_bit, (params->glk) ? ", GLK" : "",
		 ecdt ? ", ECDT" : "");
	device_set_desc_copy(dev, desc);
    }

    if (ret > 0 && params)
	kfree(params, M_TEMP);
    if (buf.Pointer)
	AcpiOsFree(buf.Pointer);
    return (ret);
}