scan.c

来自「linux 内核源代码」· C语言 代码 · 共 1,500 行 · 第 1/3 页

C
1,500
字号
		hid = ACPI_BUTTON_HID_SLEEPF;		break;	}	/* 	 * \_SB	 * ----	 * Fix for the system root bus device -- the only root-level device.	 */	if (((acpi_handle)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");	}	kfree(buffer.pointer);}static 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;}static int acpi_bus_remove(struct acpi_device *dev, int rmdevice){	if (!dev)		return -EINVAL;	dev->removal_type = ACPI_BUS_REMOVAL_EJECT;	device_release_driver(&dev->dev);	if (!rmdevice)		return 0;	/*	 * unbind _ADR-Based Devices when hot removal	 */	if (dev->flags.bus_address) {		if ((dev->parent) && (dev->parent->ops.unbind))			dev->parent->ops.unbind(dev);	}	acpi_device_unregister(dev, ACPI_BUS_REMOVAL_EJECT);	return 0;}static intacpi_add_single_object(struct acpi_device **child,		       struct acpi_device *parent, acpi_handle handle, int type,			struct acpi_bus_ops *ops){	int result = 0;	struct acpi_device *device = NULL;	if (!child)		return -EINVAL;	device = kzalloc(sizeof(struct acpi_device), GFP_KERNEL);	if (!device) {		printk(KERN_ERR PREFIX "Memory allocation error\n");		return -ENOMEM;	}	device->handle = handle;	device->parent = parent;	device->bus_ops = *ops; /* workround for not call .start */	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	 * and non-Processor objects (e.g. thermal zones, power resources,	 * 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_PROCESSOR:	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) =		    ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |		    ACPI_STA_DEVICE_UI      | ACPI_STA_DEVICE_FUNCTIONING;		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;	result = acpi_device_register(device, parent);	/*	 * Bind _ADR-Based Devices when hot add	 */	if (device->flags.bus_address) {		if (device->parent && device->parent->ops.bind)			device->parent->ops.bind(device);	}      end:	if (!result)		*child = device;	else {		kfree(device->pnp.cid_list);		kfree(device);	}	return result;}static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops){	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;	if (!start)		return -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;		}		if (ops->acpi_op_add)			status = acpi_add_single_object(&child, parent,				chandle, type, ops);		else			status = acpi_bus_get_device(chandle, &child);		if (ACPI_FAILURE(status))			continue;		if (ops->acpi_op_start && !(ops->acpi_op_add)) {			status = acpi_start_single_object(child);			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 0;}intacpi_bus_add(struct acpi_device **child,	     struct acpi_device *parent, acpi_handle handle, int type){	int result;	struct acpi_bus_ops ops;	memset(&ops, 0, sizeof(ops));	ops.acpi_op_add = 1;	result = acpi_add_single_object(child, parent, handle, type, &ops);	if (!result)		result = acpi_bus_scan(*child, &ops);	return result;}EXPORT_SYMBOL(acpi_bus_add);int acpi_bus_start(struct acpi_device *device){	int result;	struct acpi_bus_ops ops;	if (!device)		return -EINVAL;	result = acpi_start_single_object(device);	if (!result) {		memset(&ops, 0, sizeof(ops));		ops.acpi_op_start = 1;		result = acpi_bus_scan(device, &ops);	}	return result;}EXPORT_SYMBOL(acpi_bus_start);int acpi_bus_trim(struct acpi_device *start, int rmdevice){	acpi_status status;	struct acpi_device *parent, *child;	acpi_handle phandle, chandle;	acpi_object_type type;	u32 level = 1;	int err = 0;	parent = start;	phandle = start->handle;	child = chandle = NULL;	while ((level > 0) && parent && (!err)) {		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);			child = parent;			parent = parent->parent;			if (level == 0)				err = acpi_bus_remove(child, rmdevice);			else				err = acpi_bus_remove(child, 1);			continue;		}		status = acpi_get_type(chandle, &type);		if (ACPI_FAILURE(status)) {			continue;		}		/*		 * If there is a device corresponding to chandle then		 * parse it (depth-first).		 */		if (acpi_bus_get_device(chandle, &child) == 0) {			level++;			phandle = chandle;			chandle = NULL;			parent = child;		}		continue;	}	return err;}EXPORT_SYMBOL_GPL(acpi_bus_trim);static int acpi_bus_scan_fixed(struct acpi_device *root){	int result = 0;	struct acpi_device *device = NULL;	struct acpi_bus_ops ops;	if (!root)		return -ENODEV;	memset(&ops, 0, sizeof(ops));	ops.acpi_op_add = 1;	ops.acpi_op_start = 1;	/*	 * Enumerate all fixed-feature devices.	 */	if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) {		result = acpi_add_single_object(&device, acpi_root,						NULL,						ACPI_BUS_TYPE_POWER_BUTTON,						&ops);	}	if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) {		result = acpi_add_single_object(&device, acpi_root,						NULL,						ACPI_BUS_TYPE_SLEEP_BUTTON,						&ops);	}	return result;}int __init acpi_boot_ec_enable(void);static int __init acpi_scan_init(void){	int result;	struct acpi_bus_ops ops;	if (acpi_disabled)		return 0;	memset(&ops, 0, sizeof(ops));	ops.acpi_op_add = 1;	ops.acpi_op_start = 1;	result = bus_register(&acpi_bus_type);	if (result) {		/* We don't want to quit even if we failed to add suspend/resume */		printk(KERN_ERR PREFIX "Could not register bus type\n");	}	/*	 * Create the root device in the bus's device tree	 */	result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT,					ACPI_BUS_TYPE_SYSTEM, &ops);	if (result)		goto Done;	/*	 * Enumerate devices in the ACPI namespace.	 */	result = acpi_bus_scan_fixed(acpi_root);	/* EC region might be needed at bus_scan, so enable it now */	acpi_boot_ec_enable();	if (!result)		result = acpi_bus_scan(acpi_root, &ops);	if (result)		acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);      Done:	return result;}subsys_initcall(acpi_scan_init);

⌨️ 快捷键说明

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