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