⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 acpiphp_glue.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
	list_for_each (l, &slot->funcs) {		func = list_entry(l, struct acpiphp_func, sibling);		if (func->flags & FUNC_HAS_STA) {			status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta);			if (ACPI_SUCCESS(status) && sta)				break;		} else {			pci_bus_read_config_dword(slot->bridge->pci_bus,						  PCI_DEVFN(slot->device,							    func->function),						  PCI_VENDOR_ID, &dvid);			if (dvid != 0xffffffff) {				sta = ACPI_STA_ALL;				break;			}		}	}	return (unsigned int)sta;}/** * acpiphp_check_bridge - re-enumerate devices * * Iterate over all slots under this bridge and make sure that if a * card is present they are enabled, and if not they are disabled. */static int acpiphp_check_bridge(struct acpiphp_bridge *bridge){	struct acpiphp_slot *slot;	int retval = 0;	int enabled, disabled;	enabled = disabled = 0;	for (slot = bridge->slots; slot; slot = slot->next) {		unsigned int status = get_slot_status(slot);		if (slot->flags & SLOT_ENABLED) {			if (status == ACPI_STA_ALL)				continue;			retval = acpiphp_disable_slot(slot);			if (retval) {				err("Error occurred in disabling\n");				goto err_exit;			}			disabled++;		} else {			if (status != ACPI_STA_ALL)				continue;			retval = acpiphp_enable_slot(slot);			if (retval) {				err("Error occurred in enabling\n");				goto err_exit;			}			enabled++;		}	}	dbg("%s: %d enabled, %d disabled\n", __FUNCTION__, enabled, disabled); err_exit:	return retval;}/* * ACPI event handlers *//** * handle_hotplug_event_bridge - handle ACPI event on bridges * * @handle: Notify()'ed acpi_handle * @type: Notify code * @context: pointer to acpiphp_bridge structure * * handles ACPI event notification on {host,p2p} bridges * */static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *context){	struct acpiphp_bridge *bridge;	char objname[64];	struct acpi_buffer buffer = { .length = sizeof(objname),				      .pointer = objname };	bridge = (struct acpiphp_bridge *)context;	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);	switch (type) {	case ACPI_NOTIFY_BUS_CHECK:		/* bus re-enumerate */		dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);		acpiphp_check_bridge(bridge);		break;	case ACPI_NOTIFY_DEVICE_CHECK:		/* device check */		dbg("%s: Device check notify on %s\n", __FUNCTION__, objname);		acpiphp_check_bridge(bridge);		break;	case ACPI_NOTIFY_DEVICE_WAKE:		/* wake event */		dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname);		break;	case ACPI_NOTIFY_EJECT_REQUEST:		/* request device eject */		dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);		break;	case ACPI_NOTIFY_FREQUENCY_MISMATCH:		printk(KERN_ERR "Device %s cannot be configured due"				" to a frequency mismatch\n", objname);		break;	case ACPI_NOTIFY_BUS_MODE_MISMATCH:		printk(KERN_ERR "Device %s cannot be configured due"				" to a bus mode mismatch\n", objname);		break;	case ACPI_NOTIFY_POWER_FAULT:		printk(KERN_ERR "Device %s has suffered a power fault\n",				objname);		break;	default:		warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);		break;	}}/** * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots) * * @handle: Notify()'ed acpi_handle * @type: Notify code * @context: pointer to acpiphp_func structure * * handles ACPI event notification on slots * */static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context){	struct acpiphp_func *func;	char objname[64];	struct acpi_buffer buffer = { .length = sizeof(objname),				      .pointer = objname };	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);	func = (struct acpiphp_func *)context;	switch (type) {	case ACPI_NOTIFY_BUS_CHECK:		/* bus re-enumerate */		dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);		acpiphp_enable_slot(func->slot);		break;	case ACPI_NOTIFY_DEVICE_CHECK:		/* device check : re-enumerate from parent bus */		dbg("%s: Device check notify on %s\n", __FUNCTION__, objname);		acpiphp_check_bridge(func->slot->bridge);		break;	case ACPI_NOTIFY_DEVICE_WAKE:		/* wake event */		dbg("%s: Device wake notify on %s\n", __FUNCTION__, objname);		break;	case ACPI_NOTIFY_EJECT_REQUEST:		/* request device eject */		dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);		acpiphp_disable_slot(func->slot);		break;	default:		warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);		break;	}}static struct acpi_pci_driver acpi_pci_hp_driver = {	.add =		add_bridge,	.remove =	remove_bridge,};/** * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures * */int __init acpiphp_glue_init(void){	int num;	if (list_empty(&pci_root_buses))		return -1;	num = acpi_pci_register_driver(&acpi_pci_hp_driver);	if (num <= 0)		return -1;	return 0;}/** * acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures * * This function frees all data allocated in acpiphp_glue_init() */void __exit acpiphp_glue_exit(void){	struct list_head *l1, *l2, *n1, *n2;	struct acpiphp_bridge *bridge;	struct acpiphp_slot *slot, *next;	struct acpiphp_func *func;	acpi_status status;	list_for_each_safe (l1, n1, &bridge_list) {		bridge = (struct acpiphp_bridge *)l1;		slot = bridge->slots;		while (slot) {			next = slot->next;			list_for_each_safe (l2, n2, &slot->funcs) {				func = list_entry(l2, struct acpiphp_func, sibling);				acpiphp_free_resource(&func->io_head);				acpiphp_free_resource(&func->mem_head);				acpiphp_free_resource(&func->p_mem_head);				acpiphp_free_resource(&func->bus_head);				status = acpi_remove_notify_handler(func->handle,								    ACPI_SYSTEM_NOTIFY,								    handle_hotplug_event_func);				if (ACPI_FAILURE(status))					err("failed to remove notify handler\n");				kfree(func);			}			kfree(slot);			slot = next;		}		status = acpi_remove_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY,						    handle_hotplug_event_bridge);		if (ACPI_FAILURE(status))			err("failed to remove notify handler\n");		acpiphp_free_resource(&bridge->io_head);		acpiphp_free_resource(&bridge->mem_head);		acpiphp_free_resource(&bridge->p_mem_head);		acpiphp_free_resource(&bridge->bus_head);		kfree(bridge);	}	acpi_pci_unregister_driver(&acpi_pci_hp_driver);}/** * acpiphp_get_num_slots - count number of slots in a system */int __init acpiphp_get_num_slots(void){	struct list_head *node;	struct acpiphp_bridge *bridge;	int num_slots;	num_slots = 0;	list_for_each (node, &bridge_list) {		bridge = (struct acpiphp_bridge *)node;		dbg("Bus%d %dslot(s)\n", bridge->bus, bridge->nr_slots);		num_slots += bridge->nr_slots;	}	dbg("Total %dslots\n", num_slots);	return num_slots;}#if 0/** * acpiphp_for_each_slot - call function for each slot * @fn: callback function * @data: context to be passed to callback function * */static int acpiphp_for_each_slot(acpiphp_callback fn, void *data){	struct list_head *node;	struct acpiphp_bridge *bridge;	struct acpiphp_slot *slot;	int retval = 0;	list_for_each (node, &bridge_list) {		bridge = (struct acpiphp_bridge *)node;		for (slot = bridge->slots; slot; slot = slot->next) {			retval = fn(slot, data);			if (!retval)				goto err_exit;		}	} err_exit:	return retval;}#endif/* search matching slot from id  */struct acpiphp_slot *get_slot_from_id(int id){	struct list_head *node;	struct acpiphp_bridge *bridge;	struct acpiphp_slot *slot;	list_for_each (node, &bridge_list) {		bridge = (struct acpiphp_bridge *)node;		for (slot = bridge->slots; slot; slot = slot->next)			if (slot->id == id)				return slot;	}	/* should never happen! */	err("%s: no object for id %d\n", __FUNCTION__, id);	WARN_ON(1);	return NULL;}/** * acpiphp_enable_slot - power on slot */int acpiphp_enable_slot(struct acpiphp_slot *slot){	int retval;	down(&slot->crit_sect);	/* wake up all functions */	retval = power_on_slot(slot);	if (retval)		goto err_exit;	if (get_slot_status(slot) == ACPI_STA_ALL)		/* configure all functions */		retval = enable_device(slot); err_exit:	up(&slot->crit_sect);	return retval;}/** * acpiphp_disable_slot - power off slot */int acpiphp_disable_slot(struct acpiphp_slot *slot){	int retval = 0;	down(&slot->crit_sect);	/* unconfigure all functions */	retval = disable_device(slot);	if (retval)		goto err_exit;	/* power off all functions */	retval = power_off_slot(slot);	if (retval)		goto err_exit;	acpiphp_resource_sort_and_combine(&slot->bridge->io_head);	acpiphp_resource_sort_and_combine(&slot->bridge->mem_head);	acpiphp_resource_sort_and_combine(&slot->bridge->p_mem_head);	acpiphp_resource_sort_and_combine(&slot->bridge->bus_head);	dbg("Available resources:\n");	acpiphp_dump_resource(slot->bridge); err_exit:	up(&slot->crit_sect);	return retval;}/* * slot enabled:  1 * slot disabled: 0 */u8 acpiphp_get_power_status(struct acpiphp_slot *slot){	unsigned int sta;	sta = get_slot_status(slot);	return (sta & ACPI_STA_ENABLED) ? 1 : 0;}/* * latch closed:  1 * latch   open:  0 */u8 acpiphp_get_latch_status(struct acpiphp_slot *slot){	unsigned int sta;	sta = get_slot_status(slot);	return (sta & ACPI_STA_SHOW_IN_UI) ? 1 : 0;}/* * adapter presence : 1 *          absence : 0 */u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot){	unsigned int sta;	sta = get_slot_status(slot);	return (sta == 0) ? 0 : 1;}/* * pci address (seg/bus/dev) */u32 acpiphp_get_address(struct acpiphp_slot *slot){	u32 address;	address = ((slot->bridge->seg) << 16) |		  ((slot->bridge->bus) << 8) |		  slot->device;	return address;}

⌨️ 快捷键说明

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