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 + -
显示快捷键?