scan.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,076 行 · 第 1/2 页

C
1,076
字号
	/* Presence of _CID indicates 'compatible_ids' */	status = acpi_get_handle(device->handle, "_CID", &temp);	if (ACPI_SUCCESS(status))		device->flags.compatible_ids = 1;	/* Presence of _RMV indicates 'removable' */	status = acpi_get_handle(device->handle, "_RMV", &temp);	if (ACPI_SUCCESS(status))		device->flags.removable = 1;	/* Presence of _EJD|_EJ0 indicates 'ejectable' */	status = acpi_get_handle(device->handle, "_EJD", &temp);	if (ACPI_SUCCESS(status))		device->flags.ejectable = 1;	else {		status = acpi_get_handle(device->handle, "_EJ0", &temp);		if (ACPI_SUCCESS(status))			device->flags.ejectable = 1;	}	/* Presence of _LCK indicates 'lockable' */	status = acpi_get_handle(device->handle, "_LCK", &temp);	if (ACPI_SUCCESS(status))		device->flags.lockable = 1;	/* Presence of _PS0|_PR0 indicates 'power manageable' */	status = acpi_get_handle(device->handle, "_PS0", &temp);	if (ACPI_FAILURE(status))		status = acpi_get_handle(device->handle, "_PR0", &temp);	if (ACPI_SUCCESS(status))		device->flags.power_manageable = 1;	/* Presence of _PRW indicates wake capable */	status = acpi_get_handle(device->handle, "_PRW", &temp);	if (ACPI_SUCCESS(status))		device->flags.wake_capable = 1;	/* TBD: Peformance management */	return_VALUE(0);}static void acpi_device_get_busid(struct acpi_device * device, acpi_handle handle, int type){	char			bus_id[5] = {'?',0};	struct acpi_buffer	buffer = {sizeof(bus_id), bus_id};	int			i = 0;	/*	 * Bus ID	 * ------	 * The device's Bus ID is simply the object name.	 * TBD: Shouldn't this value be unique (within the ACPI namespace)?	 */	switch (type) {	case ACPI_BUS_TYPE_SYSTEM:		strcpy(device->pnp.bus_id, "ACPI");		break;	case ACPI_BUS_TYPE_POWER_BUTTON:		strcpy(device->pnp.bus_id, "PWRF");		break;	case ACPI_BUS_TYPE_SLEEP_BUTTON:		strcpy(device->pnp.bus_id, "SLPF");		break;	default:		acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);		/* Clean up trailing underscores (if any) */		for (i = 3; i > 1; i--) {			if (bus_id[i] == '_')				bus_id[i] = '\0';			else				break;		}		strcpy(device->pnp.bus_id, bus_id);		break;	}}static void acpi_device_set_id(struct acpi_device * device, struct acpi_device * parent,			       acpi_handle handle, int type){	struct acpi_device_info	*info;	struct acpi_buffer	buffer = {ACPI_ALLOCATE_BUFFER, NULL};	char			*hid = NULL;	char			*uid = NULL;	struct acpi_compatible_id_list *cid_list = NULL;	acpi_status		status;	switch (type) {	case ACPI_BUS_TYPE_DEVICE:		status = acpi_get_object_info(handle, &buffer);		if (ACPI_FAILURE(status)) {			printk("%s: Error reading device info\n",__FUNCTION__);			return;		}		info = buffer.pointer;		if (info->valid & ACPI_VALID_HID)			hid = info->hardware_id.value;		if (info->valid & ACPI_VALID_UID)			uid = info->unique_id.value;		if (info->valid & ACPI_VALID_CID)			cid_list = &info->compatibility_id;		if (info->valid & ACPI_VALID_ADR) {			device->pnp.bus_address = info->address;			device->flags.bus_address = 1;		}		break;	case ACPI_BUS_TYPE_POWER:		hid = ACPI_POWER_HID;		break;	case ACPI_BUS_TYPE_PROCESSOR:		hid = ACPI_PROCESSOR_HID;		break;	case ACPI_BUS_TYPE_SYSTEM:		hid = ACPI_SYSTEM_HID;		break;	case ACPI_BUS_TYPE_THERMAL:		hid = ACPI_THERMAL_HID;		break;	case ACPI_BUS_TYPE_POWER_BUTTON:		hid = ACPI_BUTTON_HID_POWERF;		break;	case ACPI_BUS_TYPE_SLEEP_BUTTON:		hid = ACPI_BUTTON_HID_SLEEPF;		break;	}	/* 	 * \_SB	 * ----	 * Fix for the system root bus device -- the only root-level device.	 */	if ((parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) {		hid = ACPI_BUS_HID;		strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME);		strcpy(device->pnp.device_class, ACPI_BUS_CLASS);	}	if (hid) {		strcpy(device->pnp.hardware_id, hid);		device->flags.hardware_id = 1;	}	if (uid) {		strcpy(device->pnp.unique_id, uid);		device->flags.unique_id = 1;	}	if (cid_list) {		device->pnp.cid_list = kmalloc(cid_list->size, GFP_KERNEL);		if (device->pnp.cid_list)			memcpy(device->pnp.cid_list, cid_list, cid_list->size);		else			printk(KERN_ERR "Memory allocation error\n");	}	acpi_os_free(buffer.pointer);}int acpi_device_set_context(struct acpi_device * device, int type){	acpi_status status = AE_OK;	int result = 0;	/*	 * Context	 * -------	 * Attach this 'struct acpi_device' to the ACPI object.  This makes	 * resolutions from handle->device very efficient.  Note that we need	 * to be careful with fixed-feature devices as they all attach to the	 * root object.	 */	if (type != ACPI_BUS_TYPE_POWER_BUTTON && 	    type != ACPI_BUS_TYPE_SLEEP_BUTTON) {		status = acpi_attach_data(device->handle,			acpi_bus_data_handler, device);		if (ACPI_FAILURE(status)) {			printk("Error attaching device data\n");			result = -ENODEV;		}	}	return result;}void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle, int type){#ifdef CONFIG_ACPI_DEBUG_OUTPUT	char		*type_string = NULL;	char		name[80] = {'?','\0'};	acpi_buffer	buffer = {sizeof(name), name};	switch (type) {	case ACPI_BUS_TYPE_DEVICE:		type_string = "Device";		acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);		break;	case ACPI_BUS_TYPE_POWER:		type_string = "Power Resource";		acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);		break;	case ACPI_BUS_TYPE_PROCESSOR:		type_string = "Processor";		acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);		break;	case ACPI_BUS_TYPE_SYSTEM:		type_string = "System";		acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);		break;	case ACPI_BUS_TYPE_THERMAL:		type_string = "Thermal Zone";		acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);		break;	case ACPI_BUS_TYPE_POWER_BUTTON:		type_string = "Power Button";		sprintf(name, "PWRB");		break;	case ACPI_BUS_TYPE_SLEEP_BUTTON:		type_string = "Sleep Button";		sprintf(name, "SLPB");		break;	}	printk(KERN_DEBUG "Found %s %s [%p]\n", type_string, name, handle);#endif /*CONFIG_ACPI_DEBUG_OUTPUT*/}static int acpi_bus_add (	struct acpi_device	**child,	struct acpi_device	*parent,	acpi_handle		handle,	int			type){	int			result = 0;	struct acpi_device	*device = NULL;	ACPI_FUNCTION_TRACE("acpi_bus_add");	if (!child)		return_VALUE(-EINVAL);	device = kmalloc(sizeof(struct acpi_device), GFP_KERNEL);	if (!device) {		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Memory allocation error\n"));		return_VALUE(-ENOMEM);	}	memset(device, 0, sizeof(struct acpi_device));	device->handle = handle;	device->parent = parent;	acpi_device_get_busid(device,handle,type);	/*	 * Flags	 * -----	 * Get prior to calling acpi_bus_get_status() so we know whether	 * or not _STA is present.  Note that we only look for object	 * handles -- cannot evaluate objects until we know the device is	 * present and properly initialized.	 */	result = acpi_bus_get_flags(device);	if (result)		goto end;	/*	 * Status	 * ------	 * See if the device is present.  We always assume that non-Device()	 * objects (e.g. thermal zones, power resources, processors, etc.) are	 * present, functioning, etc. (at least when parent object is present).	 * Note that _STA has a different meaning for some objects (e.g.	 * power resources) so we need to be careful how we use it.	 */	switch (type) {	case ACPI_BUS_TYPE_DEVICE:		result = acpi_bus_get_status(device);		if (ACPI_FAILURE(result) || !device->status.present) {			result = -ENOENT;			goto end;		}		break;	default:		STRUCT_TO_INT(device->status) = 0x0F;		break;	}	/*	 * Initialize Device	 * -----------------	 * TBD: Synch with Core's enumeration/initialization process.	 */	/*	 * Hardware ID, Unique ID, & Bus Address	 * -------------------------------------	 */	acpi_device_set_id(device,parent,handle,type);	/*	 * Power Management	 * ----------------	 */	if (device->flags.power_manageable) {		result = acpi_bus_get_power_flags(device);		if (result)			goto end;	} 	/*	 * Wakeup device management	 *-----------------------	 */	if (device->flags.wake_capable) {		result = acpi_bus_get_wakeup_device_flags(device);		if (result)			goto end;	}	/*	 * Performance Management	 * ----------------------	 */	if (device->flags.performance_manageable) {		result = acpi_bus_get_perf_flags(device);		if (result)			goto end;	}	if ((result = acpi_device_set_context(device,type)))		goto end;	acpi_device_get_debug_info(device,handle,type);	acpi_device_register(device,parent);	/*	 * Bind _ADR-Based Devices	 * -----------------------	 * If there's a a bus address (_ADR) then we utilize the parent's 	 * 'bind' function (if exists) to bind the ACPI- and natively-	 * enumerated device representations.	 */	if (device->flags.bus_address) {		if (device->parent && device->parent->ops.bind)			device->parent->ops.bind(device);	}	/*	 * Locate & Attach Driver	 * ----------------------	 * If there's a hardware id (_HID) or compatible ids (_CID) we check	 * to see if there's a driver installed for this kind of device.  Note	 * that drivers can install before or after a device is enumerated.	 *	 * TBD: Assumes LDM provides driver hot-plug capability.	 */	acpi_bus_find_driver(device);end:	if (!result)		*child = device;	else {		if (device->pnp.cid_list)			kfree(device->pnp.cid_list);		kfree(device);	}	return_VALUE(result);}static int acpi_bus_scan (struct acpi_device	*start){	acpi_status		status = AE_OK;	struct acpi_device	*parent = NULL;	struct acpi_device	*child = NULL;	acpi_handle		phandle = NULL;	acpi_handle		chandle = NULL;	acpi_object_type	type = 0;	u32			level = 1;	ACPI_FUNCTION_TRACE("acpi_bus_scan");	if (!start)		return_VALUE(-EINVAL);	parent = start;	phandle = start->handle;		/*	 * Parse through the ACPI namespace, identify all 'devices', and	 * create a new 'struct acpi_device' for each.	 */	while ((level > 0) && parent) {		status = acpi_get_next_object(ACPI_TYPE_ANY, phandle,			chandle, &chandle);		/*		 * If this scope is exhausted then move our way back up.		 */		if (ACPI_FAILURE(status)) {			level--;			chandle = phandle;			acpi_get_parent(phandle, &phandle);			if (parent->parent)				parent = parent->parent;			continue;		}		status = acpi_get_type(chandle, &type);		if (ACPI_FAILURE(status))			continue;		/*		 * If this is a scope object then parse it (depth-first).		 */		if (type == ACPI_TYPE_LOCAL_SCOPE) {			level++;			phandle = chandle;			chandle = NULL;			continue;		}		/*		 * We're only interested in objects that we consider 'devices'.		 */		switch (type) {		case ACPI_TYPE_DEVICE:			type = ACPI_BUS_TYPE_DEVICE;			break;		case ACPI_TYPE_PROCESSOR:			type = ACPI_BUS_TYPE_PROCESSOR;			break;		case ACPI_TYPE_THERMAL:			type = ACPI_BUS_TYPE_THERMAL;			break;		case ACPI_TYPE_POWER:			type = ACPI_BUS_TYPE_POWER;			break;		default:			continue;		}		status = acpi_bus_add(&child, parent, chandle, type);		if (ACPI_FAILURE(status))			continue;		/*		 * If the device is present, enabled, and functioning then		 * parse its scope (depth-first).  Note that we need to		 * represent absent devices to facilitate PnP notifications		 * -- but only the subtree head (not all of its children,		 * which will be enumerated when the parent is inserted).		 *		 * TBD: Need notifications and other detection mechanisms		 *	in place before we can fully implement this.		 */		if (child->status.present) {			status = acpi_get_next_object(ACPI_TYPE_ANY, chandle,						      NULL, NULL);			if (ACPI_SUCCESS(status)) {				level++;				phandle = chandle;				chandle = NULL;				parent = child;			}		}	}	return_VALUE(0);}static intacpi_bus_scan_fixed (	struct acpi_device	*root){	int			result = 0;	struct acpi_device	*device = NULL;	ACPI_FUNCTION_TRACE("acpi_bus_scan_fixed");	if (!root)		return_VALUE(-ENODEV);	/*	 * Enumerate all fixed-feature devices.	 */	if (acpi_fadt.pwr_button == 0)		result = acpi_bus_add(&device, acpi_root, 			NULL, ACPI_BUS_TYPE_POWER_BUTTON);	if (acpi_fadt.sleep_button == 0)		result = acpi_bus_add(&device, acpi_root, 			NULL, ACPI_BUS_TYPE_SLEEP_BUTTON);	return_VALUE(result);}static int __init acpi_scan_init(void){	int result;	ACPI_FUNCTION_TRACE("acpi_scan_init");	if (acpi_disabled)		return_VALUE(0);	kset_register(&acpi_namespace_kset);	/*	 * Create the root device in the bus's device tree	 */	result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT, 		ACPI_BUS_TYPE_SYSTEM);	if (result)		goto Done;	/*	 * Enumerate devices in the ACPI namespace.	 */	result = acpi_bus_scan_fixed(acpi_root);	if (!result) 		result = acpi_bus_scan(acpi_root);	if (result)		acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); Done:	return_VALUE(result);}subsys_initcall(acpi_scan_init);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?