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