Esempio n. 1
0
/*
 * Given an object, verify that it's a reference to a device of some sort,
 * and try to switch it on.
 *
 * XXX replication of off/on function code is bad.
 */
static void
acpi_tz_switch_cooler_on(ACPI_OBJECT *obj, void *arg)
{
    struct acpi_tz_softc	*sc = (struct acpi_tz_softc *)arg;
    ACPI_HANDLE			cooler;
    ACPI_STATUS			status;

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

    cooler = acpi_GetReference(NULL, obj);
    if (cooler == NULL) {
	ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "can't get handle\n"));
	return_VOID;
    }

    ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "called to turn %s on\n",
		     acpi_name(cooler)));
    status = acpi_pwr_switch_consumer(cooler, ACPI_STATE_D0);
    if (ACPI_FAILURE(status)) {
	ACPI_VPRINT(sc->tz_dev, acpi_device_get_parent_softc(sc->tz_dev),
		    "failed to activate %s - %s\n", acpi_name(cooler),
		    AcpiFormatException(status));
    }

    return_VOID;
}
Esempio n. 2
0
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);
}
Esempio n. 4
0
static int
fujitsu_hk_set_backlight(struct fujitsu_hk_softc *sc, bool value)
{
    ACPI_HANDLE hdl = sc->sc_node->ad_handle;
    ACPI_INTEGER args[] = {
        FUJITSU_FUNC_TARGET_BACKLIGHT,
        FUJITSU_FUNC_COMMAND_SET,
        0x4,
        0x0
    };
    ACPI_INTEGER val;
    ACPI_STATUS rv;

    if (!(sc->sc_caps & FUJITSU_HK_CAP_FUNC))
        return ENODEV;

    if (value)
        args[3] = FUJITSU_FUNC_BACKLIGHT_ON;
    else
        args[3] = FUJITSU_FUNC_BACKLIGHT_OFF;

    rv = fujitsu_hk_eval_nary_integer(hdl, "FUNC", args, 4, &val);
    if (ACPI_FAILURE(rv)) {
        aprint_error_dev(sc->sc_dev, "failed to evaluate %s.%s: %s\n",
                         acpi_name(hdl), "FUNC", AcpiFormatException(rv));
        return EIO;
    }

    if (val == FUJITSU_FUNC_INVALID_ARGS)
        return ENODEV;

    return 0;
}
Esempio n. 5
0
/*
 * System power profile may have changed; fetch and notify the
 * thermal zone accordingly.
 *
 * Since this can be called from an arbitrary eventhandler, it needs
 * to get the ACPI lock itself.
 */
static void
acpi_tz_power_profile(void *arg)
{
    ACPI_STATUS			status;
    struct acpi_tz_softc	*sc = (struct acpi_tz_softc *)arg;
    int				state;

    state = power_profile_get_state();
    if (state != POWER_PROFILE_PERFORMANCE && state != POWER_PROFILE_ECONOMY)
	return;

    /* check that we haven't decided there's no _SCP method */
    if ((sc->tz_flags & TZ_FLAG_NO_SCP) == 0) {

	/* Call _SCP to set the new profile */
	status = acpi_SetInteger(sc->tz_handle, "_SCP",
	    (state == POWER_PROFILE_PERFORMANCE) ? 0 : 1);
	if (ACPI_FAILURE(status)) {
	    if (status != AE_NOT_FOUND)
		ACPI_VPRINT(sc->tz_dev,
			    acpi_device_get_parent_softc(sc->tz_dev),
			    "can't evaluate %s._SCP - %s\n",
			    acpi_name(sc->tz_handle),
			    AcpiFormatException(status));
	    sc->tz_flags |= TZ_FLAG_NO_SCP;
	} else {
	    /* We have to re-evaluate the entire zone now */
	    acpi_tz_signal(sc, TZ_FLAG_GETSETTINGS);
	}
    }
}
Esempio n. 6
0
/**
 * Extract \_Sx value from DSDT/SSDT
 *
 * @v rsdt		ACPI root system description table
 * @v signature		Signature (e.g. "_S5_")
 * @ret sx		\_Sx value, or negative error
 */
int acpi_sx ( userptr_t rsdt, uint32_t signature ) {
	struct acpi_fadt fadtab;
	userptr_t fadt;
	userptr_t dsdt;
	userptr_t ssdt;
	unsigned int i;
	int sx;

	/* Try DSDT first */
	fadt = acpi_find ( rsdt, FADT_SIGNATURE, 0 );
	if ( fadt ) {
		copy_from_user ( &fadtab, fadt, 0, sizeof ( fadtab ) );
		dsdt = phys_to_user ( fadtab.dsdt );
		if ( ( sx = acpi_sx_zsdt ( dsdt, signature ) ) >= 0 )
			return sx;
	}

	/* Try all SSDTs */
	for ( i = 0 ; ; i++ ) {
		ssdt = acpi_find ( rsdt, SSDT_SIGNATURE, i );
		if ( ! ssdt )
			break;
		if ( ( sx = acpi_sx_zsdt ( ssdt, signature ) ) >= 0 )
			return sx;
	}

	DBGC ( rsdt, "RSDT %#08lx could not find \\_Sx \"%s\"\n",
	       user_to_phys ( rsdt, 0 ), acpi_name ( signature ) );
	return -ENOENT;
}
Esempio n. 7
0
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));
}
Esempio n. 8
0
/*
 * PCI power manangement
 */
static int
acpi_pci_set_powerstate_method(device_t dev, device_t child, int state)
{
	ACPI_HANDLE h;
	ACPI_STATUS status;
	int old_state, error;

	error = 0;
	if (state < ACPI_STATE_D0 || state > ACPI_STATE_D3)
		return (EINVAL);

	/*
	 * We set the state using PCI Power Management outside of setting
	 * the ACPI state.  This means that when powering down a device, we
	 * first shut it down using PCI, and then using ACPI, which lets ACPI
	 * try to power down any Power Resources that are now no longer used.
	 * When powering up a device, we let ACPI set the state first so that
	 * it can enable any needed Power Resources before changing the PCI
	 * power state.
	 */
	ACPI_SERIAL_BEGIN(pci_powerstate);
	old_state = pci_get_powerstate(child);
	if (old_state < state && pci_do_power_suspend) {
		error = pci_set_powerstate_method(dev, child, state);
		if (error)
			goto out;
	}
	h = acpi_get_handle(child);
	status = acpi_pwr_switch_consumer(h, state);
	if (ACPI_SUCCESS(status)) {
		if (bootverbose)
			device_printf(dev, "set ACPI power state D%d on %s\n",
			    state, acpi_name(h));
	} else if (status != AE_NOT_FOUND)
		device_printf(dev,
		    "failed to set ACPI power state D%d on %s: %s\n",
		    state, acpi_name(h), AcpiFormatException(status));
	if (old_state > state && pci_do_power_resume)
		error = pci_set_powerstate_method(dev, child, state);

out:
	ACPI_SERIAL_END(pci_powerstate);
	return (error);
}
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);
}
Esempio n. 10
0
static ACPI_STATUS
sony_walk_cb(ACPI_HANDLE hnd, UINT32 v, void *context, void **status)
{
	struct sony_acpi_softc *sc = (void *)context;
	const struct sysctlnode *node, *snode;
	const char *name = acpi_name(hnd);
	ACPI_INTEGER acpi_val;
	char buf[SYSCTL_NAMELEN + 1], *ptr;
	int rv;

	if ((name = strrchr(name, '.')) == NULL)
		return AE_OK;

	name++;
	if ((*name != 'G') && (*name != 'S'))
		return AE_OK;

	(void)strlcpy(buf, name, sizeof(buf));
	*buf = 'G';

	/*
	 * We assume that if the 'get' of the name as an integer is
	 * successful it is ok.
	 */
	if (acpi_eval_integer(sc->sc_node->ad_handle, buf, &acpi_val))
		return AE_OK;

	for (ptr = buf; *ptr; ptr++)
		*ptr = tolower(*ptr);

	if ((rv = sysctl_createv(&sc->sc_log, 0, NULL, &node, CTLFLAG_PERMANENT,
	    CTLTYPE_NODE, "hw", NULL, NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0)
		goto out;

	if ((rv = sysctl_createv(&sc->sc_log, 0, &node, &snode, 0,
	    CTLTYPE_NODE, device_xname(sc->sc_dev),
	    SYSCTL_DESCR("sony controls"),
	    NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
		goto out;

	if ((rv = sysctl_createv(&sc->sc_log, 0, &snode, &node,
	    CTLFLAG_READWRITE, CTLTYPE_INT, buf + 1, NULL,
	    sony_sysctl_helper, 0, sc, 0, CTL_CREATE, CTL_EOL)) != 0)
		goto out;

out:
#ifdef DIAGNOSTIC
	if (rv)
		printf("%s: sysctl_createv failed (rv = %d)\n",
		    device_xname(sc->sc_dev), rv);
#endif
	return AE_OK;
}
Esempio n. 11
0
static int
acpi_pci_child_location_str_method(device_t cbdev, device_t child, char *buf,
    size_t buflen)
{
    struct acpi_pci_devinfo *dinfo = device_get_ivars(child);

    pci_child_location_str_method(cbdev, child, buf, buflen);
    
    if (dinfo->ap_handle) {
	strlcat(buf, " handle=", buflen);
	strlcat(buf, acpi_name(dinfo->ap_handle), buflen);
    }
    return (0);
}
Esempio n. 12
0
/*
 * Read/debug-print a parameter, default it to -1.
 */
static void
acpi_tz_getparam(struct acpi_tz_softc *sc, char *node, int *data)
{

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

    if (ACPI_FAILURE(acpi_GetInteger(sc->tz_handle, node, data))) {
	*data = -1;
    } else {
	ACPI_DEBUG_PRINT((ACPI_DB_VALUES, "%s.%s = %d\n",
			 acpi_name(sc->tz_handle), node, *data));
    }

    return_VOID;
}
Esempio n. 13
0
int
acpi_pcib_attach(device_t dev, ACPI_BUFFER *prt, int busno)
{
    ACPI_STATUS status;
    int error;

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

    /*
     * Don't attach if we're not really there.
     *
     * XXX: This isn't entirely correct since we may be a PCI bus
     * on a hot-plug docking station, etc.
     */
    if (!acpi_DeviceIsPresent(dev))
	return_VALUE(ENXIO);

    /*
     * Get the PCI interrupt routing table for this bus.  If we can't
     * get it, this is not an error but may reduce functionality.  There
     * are several valid bridges in the field that do not have a _PRT, so
     * only warn about missing tables if bootverbose is set.
     */
    prt->Length = ACPI_ALLOCATE_BUFFER;
    status = AcpiGetIrqRoutingTable(acpi_get_handle(dev), prt);
    if (ACPI_FAILURE(status) && (bootverbose || status != AE_NOT_FOUND))
	device_printf(dev,
	    "could not get PCI interrupt routing table for %s - %s\n",
	    acpi_name(acpi_get_handle(dev)), AcpiFormatException(status));

    /*
     * Attach the PCI bus proper.
     */
    if (device_add_child(dev, "pci", busno) == NULL) {
	device_printf(device_get_parent(dev), "couldn't attach pci bus\n");
	return_VALUE(ENXIO);
    }

    /*
     * Now go scan the bus.
     */
    prt_walk_table(prt, prt_attach_devices, dev);

    error = bus_generic_attach(dev);
    return_VALUE(error);
}
Esempio n. 14
0
int
acpi_pcib_attach(device_t dev, ACPI_BUFFER *prt, int busno)
{
    device_t			child;
    ACPI_STATUS			status;

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

    if (!acpi_DeviceIsPresent(dev)) {
    	/* Caller should already have checked it */
	panic("%s device is not present", __func__);
    }

    ACPI_SERIAL_INIT(pcib);

    /*
     * Get the PCI interrupt routing table for this bus.  If we can't
     * get it, this is not an error but may reduce functionality.  There
     * are several valid bridges in the field that do not have a _PRT, so
     * only warn about missing tables if bootverbose is set.
     */
    prt->Length = ACPI_ALLOCATE_BUFFER;
    status = AcpiGetIrqRoutingTable(acpi_get_handle(dev), prt);
    if (ACPI_FAILURE(status) && (bootverbose || status != AE_NOT_FOUND))
	device_printf(dev,
	    "could not get PCI interrupt routing table for %s - %s\n",
	    acpi_name(acpi_get_handle(dev)), AcpiFormatException(status));

    /*
     * Attach the PCI bus proper.
     */
    if ((child = device_add_child(dev, "pci", busno)) == NULL) {
	device_printf(device_get_parent(dev), "couldn't attach pci bus\n");
	return_VALUE(ENXIO);
    }

    /*
     * Now go scan the bus.
     */
    prt_walk_table(prt, prt_attach_devices, dev);

    return_VALUE (bus_generic_attach(dev));
}
Esempio n. 15
0
/*
 * Given an object, verify that it's a reference to a device of some sort,
 * and try to switch it off.
 */
static void
acpi_tz_switch_cooler_off(ACPI_OBJECT *obj, void *arg)
{
    ACPI_HANDLE			cooler;

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

    cooler = acpi_GetReference(NULL, obj);
    if (cooler == NULL) {
	ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "can't get handle\n"));
	return_VOID;
    }

    ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "called to turn %s off\n",
		     acpi_name(cooler)));
    acpi_pwr_switch_consumer(cooler, ACPI_STATE_D3);

    return_VOID;
}
Esempio n. 16
0
/*
 * Fetch a device's resources and associate them with the device.
 *
 * Note that it might be nice to also locate ACPI-specific resource items, such
 * as GPE bits.
 *
 * We really need to split the resource-fetching code out from the
 * resource-parsing code, since we may want to use the parsing
 * code for _PRS someday.
 */
ACPI_STATUS
acpi_parse_resources(device_t dev, ACPI_HANDLE handle,
		     struct acpi_parse_resource_set *set, void *arg)
{
    struct acpi_resource_context arc;
    ACPI_STATUS		status;

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

    set->set_init(dev, arg, &arc.context);
    arc.set = set;
    arc.dev = dev;
    status = AcpiWalkResources(handle, "_CRS", acpi_parse_resource, &arc);
    if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
	printf("can't fetch resources for %s - %s\n",
	    acpi_name(handle), AcpiFormatException(status));
	return_ACPI_STATUS (status);
    }
    set->set_done(dev, arc.context);
    return_ACPI_STATUS (AE_OK);
}
Esempio n. 17
0
static int
fujitsu_hk_get_irb(struct fujitsu_hk_softc *sc, uint32_t *valuep)
{
    ACPI_HANDLE hdl = sc->sc_node->ad_handle;
    ACPI_INTEGER val;
    ACPI_STATUS rv;

    if (!(sc->sc_caps & FUJITSU_HK_CAP_GIRB))
        return ENODEV;

    rv = acpi_eval_integer(hdl, "GIRB", &val);
    if (ACPI_FAILURE(rv)) {
        aprint_error_dev(sc->sc_dev, "failed to evaluate %s.%s: %s\n",
                         acpi_name(hdl), "GIRB", AcpiFormatException(rv));
        return EIO;
    }

    *valuep = (uint32_t)val;

    return 0;
}
Esempio n. 18
0
static int
acpi_pci_child_location_str_method(device_t cbdev, device_t child, char *buf,
    size_t buflen)
{
    struct acpi_pci_devinfo *dinfo = device_get_ivars(child);
    int pxm;
    char buf2[32];

    pci_child_location_str_method(cbdev, child, buf, buflen);

    if (dinfo->ap_handle) {
        strlcat(buf, " handle=", buflen);
        strlcat(buf, acpi_name(dinfo->ap_handle), buflen);

        if (ACPI_SUCCESS(acpi_GetInteger(dinfo->ap_handle, "_PXM", &pxm))) {
                snprintf(buf2, 32, " _PXM=%d", pxm);
                strlcat(buf, buf2, buflen);
        }
    }
    return (0);
}
Esempio n. 19
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. 20
0
/**
 * Locate ACPI table
 *
 * @v rsdt		ACPI root system description table
 * @v signature		Requested table signature
 * @v index		Requested index of table with this signature
 * @ret table		Table, or UNULL if not found
 */
userptr_t acpi_find ( userptr_t rsdt, uint32_t signature, unsigned int index ) {
	struct acpi_header acpi;
	struct acpi_rsdt *rsdtab;
	typeof ( rsdtab->entry[0] ) entry;
	userptr_t table;
	size_t len;
	unsigned int count;
	unsigned int i;

	/* Read RSDT header */
	copy_from_user ( &acpi, rsdt, 0, sizeof ( acpi ) );
	if ( acpi.signature != cpu_to_le32 ( RSDT_SIGNATURE ) ) {
		DBGC ( rsdt, "RSDT %#08lx has invalid signature:\n",
		       user_to_phys ( rsdt, 0 ) );
		DBGC_HDA ( rsdt, user_to_phys ( rsdt, 0 ), &acpi,
			   sizeof ( acpi ) );
		return UNULL;
	}
	len = le32_to_cpu ( acpi.length );
	if ( len < sizeof ( rsdtab->acpi ) ) {
		DBGC ( rsdt, "RSDT %#08lx has invalid length:\n",
		       user_to_phys ( rsdt, 0 ) );
		DBGC_HDA ( rsdt, user_to_phys ( rsdt, 0 ), &acpi,
			   sizeof ( acpi ) );
		return UNULL;
	}

	/* Calculate number of entries */
	count = ( ( len - sizeof ( rsdtab->acpi ) ) / sizeof ( entry ) );

	/* Search through entries */
	for ( i = 0 ; i < count ; i++ ) {

		/* Get table address */
		copy_from_user ( &entry, rsdt,
				 offsetof ( typeof ( *rsdtab ), entry[i] ),
				 sizeof ( entry ) );

		/* Read table header */
		table = phys_to_user ( entry );
		copy_from_user ( &acpi.signature, table, 0,
				 sizeof ( acpi.signature ) );

		/* Check table signature */
		if ( acpi.signature != cpu_to_le32 ( signature ) )
			continue;

		/* Check index */
		if ( index-- )
			continue;

		DBGC ( rsdt, "RSDT %#08lx found %s at %08lx\n",
		       user_to_phys ( rsdt, 0 ), acpi_name ( signature ),
		       user_to_phys ( table, 0 ) );
		return table;
	}

	DBGC ( rsdt, "RSDT %#08lx could not find %s\n",
	       user_to_phys ( rsdt, 0 ), acpi_name ( signature ) );
	return UNULL;
}
Esempio n. 21
0
/**
 * Extract \_Sx value from DSDT/SSDT
 *
 * @v zsdt		DSDT or SSDT
 * @v signature		Signature (e.g. "_S5_")
 * @ret sx		\_Sx value, or negative error
 *
 * In theory, extracting the \_Sx value from the DSDT/SSDT requires a
 * full ACPI parser plus some heuristics to work around the various
 * broken encodings encountered in real ACPI implementations.
 *
 * In practice, we can get the same result by scanning through the
 * DSDT/SSDT for the signature (e.g. "_S5_"), extracting the first
 * four bytes, removing any bytes with bit 3 set, and treating
 * whatever is left as a little-endian value.  This is one of the
 * uglier hacks I have ever implemented, but it's still prettier than
 * the ACPI specification itself.
 */
static int acpi_sx_zsdt ( userptr_t zsdt, uint32_t signature ) {
	struct acpi_header acpi;
	union {
		uint32_t dword;
		uint8_t byte[4];
	} buf;
	size_t offset;
	size_t len;
	unsigned int sx;
	uint8_t *byte;

	/* Read table header */
	copy_from_user ( &acpi, zsdt, 0, sizeof ( acpi ) );
	len = le32_to_cpu ( acpi.length );

	/* Locate signature */
	for ( offset = sizeof ( acpi ) ;
	      ( ( offset + sizeof ( buf ) /* signature */ + 3 /* pkg header */
		  + sizeof ( buf ) /* value */ ) < len ) ;
	      offset++ ) {

		/* Check signature */
		copy_from_user ( &buf, zsdt, offset, sizeof ( buf ) );
		if ( buf.dword != cpu_to_le32 ( signature ) )
			continue;
		DBGC ( zsdt, "DSDT/SSDT %#08lx found %s at offset %#zx\n",
		       user_to_phys ( zsdt, 0 ), acpi_name ( signature ),
		       offset );
		offset += sizeof ( buf );

		/* Read first four bytes of value */
		copy_from_user ( &buf, zsdt, ( offset + 3 /* pkg header */ ),
				 sizeof ( buf ) );
		DBGC ( zsdt, "DSDT/SSDT %#08lx found %s containing "
		       "%02x:%02x:%02x:%02x\n", user_to_phys ( zsdt, 0 ),
		       acpi_name ( signature ), buf.byte[0], buf.byte[1],
		       buf.byte[2], buf.byte[3] );

		/* Extract \Sx value.  There are three potential
		 * encodings that we might encounter:
		 *
		 * - SLP_TYPa, SLP_TYPb, rsvd, rsvd
		 *
		 * - <byteprefix>, SLP_TYPa, <byteprefix>, SLP_TYPb, ...
		 *
		 * - <dwordprefix>, SLP_TYPa, SLP_TYPb, 0, 0
		 *
		 * Since <byteprefix> and <dwordprefix> both have bit
		 * 3 set, and valid SLP_TYPx must have bit 3 clear
		 * (since SLP_TYPx is a 3-bit field), we can just skip
		 * any bytes with bit 3 set.
		 */
		byte = &buf.byte[0];
		if ( *byte & 0x08 )
			byte++;
		sx = *(byte++);
		if ( *byte & 0x08 )
			byte++;
		sx |= ( *byte << 8 );
		return sx;
	}

	return -ENOENT;
}
Esempio n. 22
0
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);
}
Esempio n. 23
0
static int
acpi_ec_attach(device_t dev)
{
    struct acpi_ec_softc	*sc;
    ACPI_STATUS			Status;
    int errval = 0;

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

    /*
     * Fetch/initialise softc
     */
    sc = device_get_softc(dev);
    bzero(sc, sizeof(*sc));
    sc->ec_dev = dev;
    sc->ec_handle = acpi_get_handle(dev);

    /* 
     * Attach bus resources
     */
    sc->ec_data_rid = 0;
    if ((sc->ec_data_res = bus_alloc_resource(sc->ec_dev, SYS_RES_IOPORT, &sc->ec_data_rid,
					      0, ~0, 1, RF_ACTIVE)) == NULL) {
	device_printf(dev, "can't allocate data port\n");
	errval = ENXIO;
	goto out;
    }
    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;
    if ((sc->ec_csr_res = bus_alloc_resource(sc->ec_dev, SYS_RES_IOPORT, &sc->ec_csr_rid,
					     0, ~0, 1, RF_ACTIVE)) == NULL) {
	device_printf(dev, "can't allocate command/status port\n");
	errval = ENXIO;
	goto out;
    }
    sc->ec_csr_tag = rman_get_bustag(sc->ec_csr_res);
    sc->ec_csr_handle = rman_get_bushandle(sc->ec_csr_res);

    /*
     * Install GPE handler
     *
     * Evaluate the _GPE method to find the GPE bit used by the EC to signal
     * status (SCI).
     */
    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching GPE\n"));
    if (ACPI_FAILURE(Status = acpi_EvaluateInteger(sc->ec_handle, "_GPE", &sc->ec_gpebit))) {
	device_printf(dev, "can't evaluate _GPE - %s\n", AcpiFormatException(Status));
	errval =ENXIO;
	goto out;
    }

    /*
     * Install a handler for this EC's GPE bit.  Note that EC SCIs are 
     * treated as both edge- and level-triggered interrupts; in other words
     * we clear the status bit immediately after getting an EC-SCI, then
     * again after we're done processing the event.  This guarantees that
     * events we cause while performing a transaction (e.g. IBE/OBF) get 
     * cleared before re-enabling the GPE.
     */
    if (ACPI_FAILURE(Status = AcpiInstallGpeHandler(sc->ec_gpebit,
						    ACPI_EVENT_LEVEL_TRIGGERED |
						    ACPI_EVENT_EDGE_TRIGGERED, 
						    EcGpeHandler, sc))) {
	device_printf(dev, "can't install GPE handler for %s - %s\n",
		      acpi_name(sc->ec_handle), AcpiFormatException(Status));
	errval = ENXIO;
	goto out;
    }

    /* 
     * Install address space handler
     */
    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching address space handler\n"));
    if (ACPI_FAILURE(Status = AcpiInstallAddressSpaceHandler(sc->ec_handle,
							     ACPI_ADR_SPACE_EC,
							     EcSpaceHandler,
							     EcSpaceSetup,
							     sc))) {
	device_printf(dev, "can't install address space handler for %s - %s\n",
		      acpi_name(sc->ec_handle), AcpiFormatException(Status));
	panic("very suck");
	errval = ENXIO;
	goto out;
    }
    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attach complete\n"));
    return_VALUE(0);
 out:
    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_VALUE(errval);
}
Esempio n. 24
0
/*
 * 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);
}
Esempio n. 25
0
/*
 * Fetch a device's resources and associate them with the device.
 *
 * Note that it might be nice to also locate ACPI-specific resource items, such
 * as GPE bits.
 *
 * We really need to split the resource-fetching code out from the
 * resource-parsing code, since we may want to use the parsing
 * code for _PRS someday.
 */
ACPI_STATUS
acpi_parse_resources(device_t dev, ACPI_HANDLE handle,
		     struct acpi_parse_resource_set *set, void *arg)
{
    ACPI_BUFFER		buf;
    ACPI_RESOURCE	*res;
    char		*curr, *last;
    ACPI_STATUS		status;
    void		*context;

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

    /*
     * Special-case some devices that abuse _PRS/_CRS to mean
     * something other than "I consume this resource".
     *
     * XXX do we really need this?  It's only relevant once
     *     we start always-allocating these resources, and even
     *     then, the only special-cased device is likely to be
     *     the PCI interrupt link.
     */

    /* Fetch the device's current resources. */
    buf.Length = ACPI_ALLOCATE_BUFFER;
    if (ACPI_FAILURE((status = AcpiGetCurrentResources(handle, &buf)))) {
	if (status != AE_NOT_FOUND && status != AE_TYPE)
	    kprintf("can't fetch resources for %s - %s\n",
		   acpi_name(handle), AcpiFormatException(status));
	return_ACPI_STATUS (status);
    }
    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s - got %ld bytes of resources\n",
		     acpi_name(handle), (long)buf.Length));
    set->set_init(dev, arg, &context);

    /* Iterate through the resources */
    curr = buf.Pointer;
    last = (char *)buf.Pointer + buf.Length;
    while (curr < last) {
	res = (ACPI_RESOURCE *)curr;
	curr += res->Length;

	/* Handle the individual resource types */
	switch(res->Type) {
	case ACPI_RESOURCE_TYPE_END_TAG:
	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n"));
	    curr = last;
	    break;
	case ACPI_RESOURCE_TYPE_FIXED_IO:
	    if (res->Data.FixedIo.AddressLength <= 0)
		break;
	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n",
			     res->Data.FixedIo.Address,
			     res->Data.FixedIo.AddressLength));
	    set->set_ioport(dev, context,
			    res->Data.FixedIo.Address,
			    res->Data.FixedIo.AddressLength);
	    break;
	case ACPI_RESOURCE_TYPE_IO:
	    if (res->Data.Io.AddressLength <= 0)
		break;
	    if (res->Data.Io.Minimum == res->Data.Io.Maximum) {
		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n",
				 res->Data.Io.Minimum,
				 res->Data.Io.AddressLength));
		set->set_ioport(dev, context,
				res->Data.Io.Minimum,
				res->Data.Io.AddressLength);
	    } else {
		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n",
				 res->Data.Io.Minimum,
				 res->Data.Io.Maximum, 
				 res->Data.Io.AddressLength));
		set->set_iorange(dev, context,
				 res->Data.Io.Minimum,
				 res->Data.Io.Maximum, 
				 res->Data.Io.AddressLength,
				 res->Data.Io.Alignment);
	    }
	    break;
	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
	    if (res->Data.FixedMemory32.AddressLength <= 0)
		break;
	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n",
			      res->Data.FixedMemory32.Address, 
			      res->Data.FixedMemory32.AddressLength));
	    set->set_memory(dev, context,
			    res->Data.FixedMemory32.Address, 
			    res->Data.FixedMemory32.AddressLength);
	    break;
	case ACPI_RESOURCE_TYPE_MEMORY32:
	    if (res->Data.Memory32.AddressLength <= 0)
		break;
	    if (res->Data.Memory32.Minimum ==
		res->Data.Memory32.Maximum) {

		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n",
				  res->Data.Memory32.Minimum, 
				  res->Data.Memory32.AddressLength));
		set->set_memory(dev, context,
				res->Data.Memory32.Minimum,
				res->Data.Memory32.AddressLength);
	    } else {
		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n",
				 res->Data.Memory32.Minimum, 
				 res->Data.Memory32.Maximum,
				 res->Data.Memory32.AddressLength));
		set->set_memoryrange(dev, context,
				     res->Data.Memory32.Minimum,
				     res->Data.Memory32.Maximum,
				     res->Data.Memory32.AddressLength,
				     res->Data.Memory32.Alignment);
	    }
	    break;
	case ACPI_RESOURCE_TYPE_MEMORY24:
	    if (res->Data.Memory24.AddressLength <= 0)
		break;
	    if (res->Data.Memory24.Minimum ==
		res->Data.Memory24.Maximum) {

		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n",
				 res->Data.Memory24.Minimum, 
				 res->Data.Memory24.AddressLength));
		set->set_memory(dev, context, res->Data.Memory24.Minimum,
				res->Data.Memory24.AddressLength);
	    } else {
		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n",
				 res->Data.Memory24.Minimum, 
				 res->Data.Memory24.Maximum,
				 res->Data.Memory24.AddressLength));
		set->set_memoryrange(dev, context,
				     res->Data.Memory24.Minimum,
				     res->Data.Memory24.Maximum,
				     res->Data.Memory24.AddressLength,
				     res->Data.Memory24.Alignment);
	    }
	    break;
	case ACPI_RESOURCE_TYPE_IRQ:
	    /*
	     * from 1.0b 6.4.2 
	     * "This structure is repeated for each separate interrupt
	     * required"
	     */
	    set->set_irq(dev, context, res->Data.Irq.Interrupts,
		res->Data.Irq.InterruptCount, res->Data.Irq.Triggering,
		res->Data.Irq.Polarity);
	    break;
	case ACPI_RESOURCE_TYPE_DMA:
	    /*
	     * from 1.0b 6.4.3 
	     * "This structure is repeated for each separate dma channel
	     * required"
	     */
	    set->set_drq(dev, context, res->Data.Dma.Channels,
			 res->Data.Dma.ChannelCount);
	    break;
	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependent functions\n"));
	    set->set_start_dependent(dev, context,
				     res->Data.StartDpf.CompatibilityPriority);
	    break;
	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependent functions\n"));
	    set->set_end_dependent(dev, context);
	    break;
	case ACPI_RESOURCE_TYPE_ADDRESS32:
	    if (res->Data.Address32.AddressLength <= 0)
		break;
	    if (res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) {
		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
		    "ignored Address32 %s producer\n",
		    res->Data.Address32.ResourceType == ACPI_IO_RANGE ?
		    "IO" : "Memory"));
		break;
	    }
	    if (res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE &&
		res->Data.Address32.ResourceType != ACPI_IO_RANGE) {
		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
		    "ignored Address32 for non-memory, non-I/O\n"));
		break;
	    }

	    if (res->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED &&
		res->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED) {

		if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
				     "Address32/Memory 0x%x/%d\n",
				     res->Data.Address32.Minimum,
				     res->Data.Address32.AddressLength));
		    set->set_memory(dev, context,
				    res->Data.Address32.Minimum,
				    res->Data.Address32.AddressLength);
		} else {
		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
				     "Address32/IO 0x%x/%d\n",
				     res->Data.Address32.Minimum,
				     res->Data.Address32.AddressLength));
		    set->set_ioport(dev, context,
				    res->Data.Address32.Minimum,
				    res->Data.Address32.AddressLength);
		}
	    } else {
		if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) {
		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
				     "Address32/Memory 0x%x-0x%x/%d\n",
				     res->Data.Address32.Minimum,
				     res->Data.Address32.Maximum,
				     res->Data.Address32.AddressLength));
		    set->set_memoryrange(dev, context,
					  res->Data.Address32.Minimum,
					  res->Data.Address32.Maximum,
					  res->Data.Address32.AddressLength,
					  res->Data.Address32.Granularity);
		} else {
		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
				     "Address32/IO 0x%x-0x%x/%d\n",
				     res->Data.Address32.Minimum,
				     res->Data.Address32.Maximum,
				     res->Data.Address32.AddressLength));
		    set->set_iorange(dev, context,
				     res->Data.Address32.Minimum,
				     res->Data.Address32.Maximum,
				     res->Data.Address32.AddressLength,
				     res->Data.Address32.Granularity);
		}
	    }		    
	    break;
	case ACPI_RESOURCE_TYPE_ADDRESS16:
	    if (res->Data.Address16.AddressLength <= 0)
		break;
	    if (res->Data.Address16.ProducerConsumer != ACPI_CONSUMER) {
		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
		    "ignored Address16 %s producer\n",
		    res->Data.Address16.ResourceType == ACPI_IO_RANGE ?
		    "IO" : "Memory"));
		break;
	    }
	    if (res->Data.Address16.ResourceType != ACPI_MEMORY_RANGE &&
		res->Data.Address16.ResourceType != ACPI_IO_RANGE) {
		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
			"ignored Address16 for non-memory, non-I/O\n"));
		break;
	    }

	    if (res->Data.Address16.MinAddressFixed == ACPI_ADDRESS_FIXED &&
		res->Data.Address16.MaxAddressFixed == ACPI_ADDRESS_FIXED) {

		if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
				     "Address16/Memory 0x%x/%d\n",
				     res->Data.Address16.Minimum,
				     res->Data.Address16.AddressLength));
		    set->set_memory(dev, context,
				    res->Data.Address16.Minimum,
				    res->Data.Address16.AddressLength);
		} else {
		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
				     "Address16/IO 0x%x/%d\n",
				     res->Data.Address16.Minimum,
				     res->Data.Address16.AddressLength));
		    set->set_ioport(dev, context,
				    res->Data.Address16.Minimum,
				    res->Data.Address16.AddressLength);
		}
	    } else {
		if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) {
		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
				     "Address16/Memory 0x%x-0x%x/%d\n",
				     res->Data.Address16.Minimum,
				     res->Data.Address16.Maximum,
				     res->Data.Address16.AddressLength));
		    set->set_memoryrange(dev, context,
					  res->Data.Address16.Minimum,
					  res->Data.Address16.Maximum,
					  res->Data.Address16.AddressLength,
					  res->Data.Address16.Granularity);
		} else {
		    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
				     "Address16/IO 0x%x-0x%x/%d\n",
				     res->Data.Address16.Minimum,
				     res->Data.Address16.Maximum,
				     res->Data.Address16.AddressLength));
		    set->set_iorange(dev, context,
				     res->Data.Address16.Minimum,
				     res->Data.Address16.Maximum,
				     res->Data.Address16.AddressLength,
				     res->Data.Address16.Granularity);
		}
	    }		    
	    break;
	case ACPI_RESOURCE_TYPE_ADDRESS64:
	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
			     "unimplemented Address64 resource\n"));
	    break;
	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
	    if (res->Data.ExtendedIrq.ProducerConsumer != ACPI_CONSUMER) {
		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
		    "ignored ExtIRQ producer\n"));
		break;
	    }
	    set->set_ext_irq(dev, context, res->Data.ExtendedIrq.Interrupts,
		res->Data.ExtendedIrq.InterruptCount,
		res->Data.ExtendedIrq.Triggering,
		res->Data.ExtendedIrq.Polarity);
	    break;
	case ACPI_RESOURCE_TYPE_VENDOR:
	    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
			     "unimplemented VendorSpecific resource\n"));
	    break;
	default:
	    break;
	}
    }    

    AcpiOsFree(buf.Pointer);
    set->set_done(dev, context);
    return_ACPI_STATUS (AE_OK);
}