scan.c

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

C
1,500
字号
 * @device: the device to add and initialize * @driver: driver for the device * * Used to initialize a device via its device driver.  Called whenever a  * driver is bound to a device.  Invokes the driver's add() ops. */static intacpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver){	int result = 0;	if (!device || !driver)		return -EINVAL;	if (!driver->ops.add)		return -ENOSYS;	result = driver->ops.add(device);	if (result) {		device->driver = NULL;		acpi_driver_data(device) = NULL;		return result;	}	device->driver = driver;	/*	 * TBD - Configuration Management: Assign resources to device based	 * upon possible configuration and currently allocated resources.	 */	ACPI_DEBUG_PRINT((ACPI_DB_INFO,			  "Driver successfully bound to device\n"));	return 0;}static int acpi_start_single_object(struct acpi_device *device){	int result = 0;	struct acpi_driver *driver;	if (!(driver = device->driver))		return 0;	if (driver->ops.start) {		result = driver->ops.start(device);		if (result && driver->ops.remove)			driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL);	}	return result;}/** * acpi_bus_register_driver - register a driver with the ACPI bus * @driver: driver being registered * * Registers a driver with the ACPI bus.  Searches the namespace for all * devices that match the driver's criteria and binds.  Returns zero for * success or a negative error status for failure. */int acpi_bus_register_driver(struct acpi_driver *driver){	int ret;	if (acpi_disabled)		return -ENODEV;	driver->drv.name = driver->name;	driver->drv.bus = &acpi_bus_type;	driver->drv.owner = driver->owner;	ret = driver_register(&driver->drv);	return ret;}EXPORT_SYMBOL(acpi_bus_register_driver);/** * acpi_bus_unregister_driver - unregisters a driver with the APIC bus * @driver: driver to unregister * * Unregisters a driver with the ACPI bus.  Searches the namespace for all * devices that match the driver's criteria and unbinds. */void acpi_bus_unregister_driver(struct acpi_driver *driver){	driver_unregister(&driver->drv);}EXPORT_SYMBOL(acpi_bus_unregister_driver);/* --------------------------------------------------------------------------                                 Device Enumeration   -------------------------------------------------------------------------- */acpi_statusacpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd){	acpi_status status;	acpi_handle tmp;	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};	union acpi_object *obj;	status = acpi_get_handle(handle, "_EJD", &tmp);	if (ACPI_FAILURE(status))		return status;	status = acpi_evaluate_object(handle, "_EJD", NULL, &buffer);	if (ACPI_SUCCESS(status)) {		obj = buffer.pointer;		status = acpi_get_handle(NULL, obj->string.pointer, ejd);		kfree(buffer.pointer);	}	return status;}EXPORT_SYMBOL_GPL(acpi_bus_get_ejd);void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context){	/* TBD */	return;}static int acpi_bus_get_perf_flags(struct acpi_device *device){	device->performance.state = ACPI_STATE_UNKNOWN;	return 0;}static acpi_statusacpi_bus_extract_wakeup_device_power_package(struct acpi_device *device,					     union acpi_object *package){	int i = 0;	union acpi_object *element = NULL;	if (!device || !package || (package->package.count < 2))		return AE_BAD_PARAMETER;	element = &(package->package.elements[0]);	if (!element)		return AE_BAD_PARAMETER;	if (element->type == ACPI_TYPE_PACKAGE) {		if ((element->package.count < 2) ||		    (element->package.elements[0].type !=		     ACPI_TYPE_LOCAL_REFERENCE)		    || (element->package.elements[1].type != ACPI_TYPE_INTEGER))			return AE_BAD_DATA;		device->wakeup.gpe_device =		    element->package.elements[0].reference.handle;		device->wakeup.gpe_number =		    (u32) element->package.elements[1].integer.value;	} else if (element->type == ACPI_TYPE_INTEGER) {		device->wakeup.gpe_number = element->integer.value;	} else		return AE_BAD_DATA;	element = &(package->package.elements[1]);	if (element->type != ACPI_TYPE_INTEGER) {		return AE_BAD_DATA;	}	device->wakeup.sleep_state = element->integer.value;	if ((package->package.count - 2) > ACPI_MAX_HANDLES) {		return AE_NO_MEMORY;	}	device->wakeup.resources.count = package->package.count - 2;	for (i = 0; i < device->wakeup.resources.count; i++) {		element = &(package->package.elements[i + 2]);		if (element->type != ACPI_TYPE_ANY) {			return AE_BAD_DATA;		}		device->wakeup.resources.handles[i] = element->reference.handle;	}	return AE_OK;}static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device){	acpi_status status = 0;	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };	union acpi_object *package = NULL;	struct acpi_device_id button_device_ids[] = {		{"PNP0C0D", 0},		{"PNP0C0C", 0},		{"PNP0C0E", 0},		{"", 0},	};	/* _PRW */	status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer);	if (ACPI_FAILURE(status)) {		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW"));		goto end;	}	package = (union acpi_object *)buffer.pointer;	status = acpi_bus_extract_wakeup_device_power_package(device, package);	if (ACPI_FAILURE(status)) {		ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package"));		goto end;	}	kfree(buffer.pointer);	device->wakeup.flags.valid = 1;	/* Power button, Lid switch always enable wakeup */	if (!acpi_match_device_ids(device, button_device_ids))		device->wakeup.flags.run_wake = 1;      end:	if (ACPI_FAILURE(status))		device->flags.wake_capable = 0;	return 0;}static int acpi_bus_get_power_flags(struct acpi_device *device){	acpi_status status = 0;	acpi_handle handle = NULL;	u32 i = 0;	/*	 * Power Management Flags	 */	status = acpi_get_handle(device->handle, "_PSC", &handle);	if (ACPI_SUCCESS(status))		device->power.flags.explicit_get = 1;	status = acpi_get_handle(device->handle, "_IRC", &handle);	if (ACPI_SUCCESS(status))		device->power.flags.inrush_current = 1;	/*	 * Enumerate supported power management states	 */	for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) {		struct acpi_device_power_state *ps = &device->power.states[i];		char object_name[5] = { '_', 'P', 'R', '0' + i, '\0' };		/* Evaluate "_PRx" to se if power resources are referenced */		acpi_evaluate_reference(device->handle, object_name, NULL,					&ps->resources);		if (ps->resources.count) {			device->power.flags.power_resources = 1;			ps->flags.valid = 1;		}		/* Evaluate "_PSx" to see if we can do explicit sets */		object_name[2] = 'S';		status = acpi_get_handle(device->handle, object_name, &handle);		if (ACPI_SUCCESS(status)) {			ps->flags.explicit_set = 1;			ps->flags.valid = 1;		}		/* State is valid if we have some power control */		if (ps->resources.count || ps->flags.explicit_set)			ps->flags.valid = 1;		ps->power = -1;	/* Unknown - driver assigned */		ps->latency = -1;	/* Unknown - driver assigned */	}	/* Set defaults for D0 and D3 states (always valid) */	device->power.states[ACPI_STATE_D0].flags.valid = 1;	device->power.states[ACPI_STATE_D0].power = 100;	device->power.states[ACPI_STATE_D3].flags.valid = 1;	device->power.states[ACPI_STATE_D3].power = 0;	/* TBD: System wake support and resource requirements. */	device->power.state = ACPI_STATE_UNKNOWN;	return 0;}static int acpi_bus_get_flags(struct acpi_device *device){	acpi_status status = AE_OK;	acpi_handle temp = NULL;	/* Presence of _STA indicates 'dynamic_status' */	status = acpi_get_handle(device->handle, "_STA", &temp);	if (ACPI_SUCCESS(status))		device->flags.dynamic_status = 1;	/* 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 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 intacpi_video_bus_match(struct acpi_device *device){	acpi_handle h_dummy1;	acpi_handle h_dummy2;	acpi_handle h_dummy3;	if (!device)		return -EINVAL;	/* Since there is no HID, CID for ACPI Video drivers, we have	 * to check well known required nodes for each feature we support.	 */	/* Does this device able to support video switching ? */	if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy1)) &&	    ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy2)))		return 0;	/* Does this device able to retrieve a video ROM ? */	if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy1)))		return 0;	/* Does this device able to configure which video head to be POSTed ? */	if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy1)) &&	    ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy2)) &&	    ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3)))		return 0;	return -ENODEV;}/* * acpi_bay_match - see if a device is an ejectable driver bay * * If an acpi object is ejectable and has one of the ACPI ATA methods defined, * then we can safely call it an ejectable drive bay */static int acpi_bay_match(struct acpi_device *device){	acpi_status status;	acpi_handle handle;	acpi_handle tmp;	acpi_handle phandle;	handle = device->handle;	status = acpi_get_handle(handle, "_EJ0", &tmp);	if (ACPI_FAILURE(status))		return -ENODEV;	if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||		(ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||		(ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||		(ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))		return 0;	if (acpi_get_parent(handle, &phandle))		return -ENODEV;        if ((ACPI_SUCCESS(acpi_get_handle(phandle, "_GTF", &tmp))) ||                (ACPI_SUCCESS(acpi_get_handle(phandle, "_GTM", &tmp))) ||                (ACPI_SUCCESS(acpi_get_handle(phandle, "_STM", &tmp))) ||                (ACPI_SUCCESS(acpi_get_handle(phandle, "_SDD", &tmp))))                return 0;	return -ENODEV;}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;		}		if(!(info->valid & (ACPI_VALID_HID | ACPI_VALID_CID))){			status = acpi_video_bus_match(device);			if(ACPI_SUCCESS(status))				hid = ACPI_VIDEO_HID;			status = acpi_bay_match(device);			if (ACPI_SUCCESS(status))				hid = ACPI_BAY_HID;		}		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:

⌨️ 快捷键说明

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