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

📄 ipmi_poweroff.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	send_msg.data = data;	data[0] = 1; /* Power down state */	send_msg.data_len = 1;	rv = ipmi_request_in_rc_mode(user,				     (struct ipmi_addr *) &smi_addr,				     &send_msg);	if (rv)		goto out; out:	return;}/* * ipmi_dell_chassis_detect() * Dell systems with IPMI < 1.5 don't set the chassis capability bit * but they can handle a chassis poweroff or powercycle command. */#define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00}static int ipmi_dell_chassis_detect (ipmi_user_t user){	const char ipmi_version_major = ipmi_version & 0xF;	const char ipmi_version_minor = (ipmi_version >> 4) & 0xF;	const char mfr[3]=DELL_IANA_MFR_ID;	if (!memcmp(mfr, &mfg_id, sizeof(mfr)) &&	    ipmi_version_major <= 1 &&	    ipmi_version_minor < 5)		return 1;	return 0;}/* * Standard chassis support */#define IPMI_NETFN_CHASSIS_REQUEST	0#define IPMI_CHASSIS_CONTROL_CMD	0x02static int ipmi_chassis_detect (ipmi_user_t user){	/* Chassis support, use it. */	return (capabilities & 0x80);}static void ipmi_poweroff_chassis (ipmi_user_t user){	struct ipmi_system_interface_addr smi_addr;	struct kernel_ipmi_msg            send_msg;	int                               rv;	unsigned char                     data[1];        /*         * Configure IPMI address for local access         */        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;        smi_addr.channel = IPMI_BMC_CHANNEL;        smi_addr.lun = 0; powercyclefailed:	printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n",		(poweroff_powercycle ? "cycle" : "down"));	/*	 * Power down	 */	send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST;	send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD;	if (poweroff_powercycle)		data[0] = IPMI_CHASSIS_POWER_CYCLE;	else		data[0] = IPMI_CHASSIS_POWER_DOWN;	send_msg.data = data;	send_msg.data_len = sizeof(data);	rv = ipmi_request_in_rc_mode(user,				     (struct ipmi_addr *) &smi_addr,				     &send_msg);	if (rv) {		if (poweroff_powercycle) {			/* power cycle failed, default to power down */			printk(KERN_ERR PFX "Unable to send chassis power " \			       "cycle message, IPMI error 0x%x\n", rv);			poweroff_powercycle = 0;			goto powercyclefailed;		}		printk(KERN_ERR PFX "Unable to send chassis power " \		       "down message, IPMI error 0x%x\n", rv);	}}/* Table of possible power off functions. */struct poweroff_function {	char *platform_type;	int  (*detect)(ipmi_user_t user);	void (*poweroff_func)(ipmi_user_t user);};static struct poweroff_function poweroff_functions[] = {	{ .platform_type	= "ATCA",	  .detect		= ipmi_atca_detect,	  .poweroff_func	= ipmi_poweroff_atca },	{ .platform_type	= "CPI1",	  .detect		= ipmi_cpi1_detect,	  .poweroff_func	= ipmi_poweroff_cpi1 },	{ .platform_type	= "chassis",	  .detect		= ipmi_dell_chassis_detect,	  .poweroff_func	= ipmi_poweroff_chassis },	/* Chassis should generally be last, other things should override	   it. */	{ .platform_type	= "chassis",	  .detect		= ipmi_chassis_detect,	  .poweroff_func	= ipmi_poweroff_chassis },};#define NUM_PO_FUNCS (sizeof(poweroff_functions) \		      / sizeof(struct poweroff_function))/* Our local state. */static int ready = 0;static ipmi_user_t ipmi_user;static void (*specific_poweroff_func)(ipmi_user_t user) = NULL;/* Holds the old poweroff function so we can restore it on removal. */static void (*old_poweroff_func)(void);/* Called on a powerdown request. */static void ipmi_poweroff_function (void){	if (!ready)		return;	/* Use run-to-completion mode, since interrupts may be off. */	ipmi_user_set_run_to_completion(ipmi_user, 1);	specific_poweroff_func(ipmi_user);	ipmi_user_set_run_to_completion(ipmi_user, 0);}/* Wait for an IPMI interface to be installed, the first one installed   will be grabbed by this code and used to perform the powerdown. */static void ipmi_po_new_smi(int if_num){	struct ipmi_system_interface_addr smi_addr;	struct kernel_ipmi_msg            send_msg;	int                               rv;	int                               i;	if (ready)		return;	rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL,			      &ipmi_user);	if (rv) {		printk(KERN_ERR PFX "could not create IPMI user, error %d\n",		       rv);		return;	}        /*         * Do a get device ide and store some results, since this is	 * used by several functions.         */        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;        smi_addr.channel = IPMI_BMC_CHANNEL;        smi_addr.lun = 0;	send_msg.netfn = IPMI_NETFN_APP_REQUEST;	send_msg.cmd = IPMI_GET_DEVICE_ID_CMD;	send_msg.data = NULL;	send_msg.data_len = 0;	rv = ipmi_request_wait_for_response(ipmi_user,					    (struct ipmi_addr *) &smi_addr,					    &send_msg);	if (rv) {		printk(KERN_ERR PFX "Unable to send IPMI get device id info,"		       " IPMI error 0x%x\n", rv);		goto out_err;	}	if (halt_recv_msg.msg.data_len < 12) {		printk(KERN_ERR PFX "(chassis) IPMI get device id info too,"		       " short, was %d bytes, needed %d bytes\n",		       halt_recv_msg.msg.data_len, 12);		goto out_err;	}	mfg_id = (halt_recv_msg.msg.data[7]		  | (halt_recv_msg.msg.data[8] << 8)		  | (halt_recv_msg.msg.data[9] << 16));	prod_id = (halt_recv_msg.msg.data[10]		   | (halt_recv_msg.msg.data[11] << 8));	capabilities = halt_recv_msg.msg.data[6];	ipmi_version = halt_recv_msg.msg.data[5];	/* Scan for a poweroff method */	for (i = 0; i < NUM_PO_FUNCS; i++) {		if (poweroff_functions[i].detect(ipmi_user))			goto found;	} out_err:	printk(KERN_ERR PFX "Unable to find a poweroff function that"	       " will work, giving up\n");	ipmi_destroy_user(ipmi_user);	return; found:	printk(KERN_INFO PFX "Found a %s style poweroff function\n",	       poweroff_functions[i].platform_type);	specific_poweroff_func = poweroff_functions[i].poweroff_func;	old_poweroff_func = pm_power_off;	pm_power_off = ipmi_poweroff_function;	ready = 1;}static void ipmi_po_smi_gone(int if_num){	/* This can never be called, because once poweroff driver is	   registered, the interface can't go away until the power	   driver is unregistered. */}static struct ipmi_smi_watcher smi_watcher ={	.owner    = THIS_MODULE,	.new_smi  = ipmi_po_new_smi,	.smi_gone = ipmi_po_smi_gone};#ifdef CONFIG_PROC_FS#include <linux/sysctl.h>static ctl_table ipmi_table[] = {	{ .ctl_name	= DEV_IPMI_POWEROFF_POWERCYCLE,	  .procname	= "poweroff_powercycle",	  .data		= &poweroff_powercycle,	  .maxlen	= sizeof(poweroff_powercycle),	  .mode		= 0644,	  .proc_handler	= &proc_dointvec },	{ }};static ctl_table ipmi_dir_table[] = {	{ .ctl_name	= DEV_IPMI,	  .procname	= "ipmi",	  .mode		= 0555,	  .child	= ipmi_table },	{ }};static ctl_table ipmi_root_table[] = {	{ .ctl_name	= CTL_DEV,	  .procname	= "dev",	  .mode		= 0555,	  .child	= ipmi_dir_table },	{ }};static struct ctl_table_header *ipmi_table_header;#endif /* CONFIG_PROC_FS *//* * Startup and shutdown functions. */static int ipmi_poweroff_init (void){	int rv;	printk ("Copyright (C) 2004 MontaVista Software -"		" IPMI Powerdown via sys_reboot.\n");	if (poweroff_powercycle)		printk(KERN_INFO PFX "Power cycle is enabled.\n");#ifdef CONFIG_PROC_FS	ipmi_table_header = register_sysctl_table(ipmi_root_table, 1);	if (!ipmi_table_header) {		printk(KERN_ERR PFX "Unable to register powercycle sysctl\n");		rv = -ENOMEM;		goto out_err;	}#endif	rv = ipmi_smi_watcher_register(&smi_watcher);	if (rv) {		unregister_sysctl_table(ipmi_table_header);		printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);		goto out_err;	} out_err:	return rv;}#ifdef MODULEstatic __exit void ipmi_poweroff_cleanup(void){	int rv;#ifdef CONFIG_PROC_FS	unregister_sysctl_table(ipmi_table_header);#endif	ipmi_smi_watcher_unregister(&smi_watcher);	if (ready) {		rv = ipmi_destroy_user(ipmi_user);		if (rv)			printk(KERN_ERR PFX "could not cleanup the IPMI"			       " user: 0x%x\n", rv);		pm_power_off = old_poweroff_func;	}}module_exit(ipmi_poweroff_cleanup);#endifmodule_init(ipmi_poweroff_init);MODULE_LICENSE("GPL");MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");MODULE_DESCRIPTION("IPMI Poweroff extension to sys_reboot");

⌨️ 快捷键说明

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