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

📄 ipmi_poweroff.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * ipmi_poweroff.c * * MontaVista IPMI Poweroff extension to sys_reboot * * Author: MontaVista Software, Inc. *         Steven Dake <sdake@mvista.com> *         Corey Minyard <cminyard@mvista.com> *         source@mvista.com * * Copyright 2002,2004 MontaVista Software Inc. * *  This program is free software; you can redistribute it and/or modify it *  under the terms of the GNU General Public License as published by the *  Free Software Foundation; either version 2 of the License, or (at your *  option) any later version. * * *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *  You should have received a copy of the GNU General Public License along *  with this program; if not, write to the Free Software Foundation, Inc., *  675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/config.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/proc_fs.h>#include <linux/string.h>#include <linux/completion.h>#include <linux/kdev_t.h>#include <linux/ipmi.h>#include <linux/ipmi_smi.h>#define PFX "IPMI poweroff: "/* Where to we insert our poweroff function? */extern void (*pm_power_off)(void);/* Definitions for controlling power off (if the system supports it).  It * conveniently matches the IPMI chassis control values. */#define IPMI_CHASSIS_POWER_DOWN		0	/* power down, the default. */#define IPMI_CHASSIS_POWER_CYCLE	0x02	/* power cycle *//* the IPMI data command */static int poweroff_powercycle;/* parameter definition to allow user to flag power cycle */module_param(poweroff_powercycle, int, 0644);MODULE_PARM_DESC(poweroff_powercycle, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");/* Stuff from the get device id command. */static unsigned int mfg_id;static unsigned int prod_id;static unsigned char capabilities;static unsigned char ipmi_version;/* We use our own messages for this operation, we don't let the system   allocate them, since we may be in a panic situation.  The whole   thing is single-threaded, anyway, so multiple messages are not   required. */static void dummy_smi_free(struct ipmi_smi_msg *msg){}static void dummy_recv_free(struct ipmi_recv_msg *msg){}static struct ipmi_smi_msg halt_smi_msg ={	.done = dummy_smi_free};static struct ipmi_recv_msg halt_recv_msg ={	.done = dummy_recv_free};/* * Code to send a message and wait for the reponse. */static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data){	struct completion *comp = recv_msg->user_msg_data;	if (comp)		complete(comp);}static struct ipmi_user_hndl ipmi_poweroff_handler ={	.ipmi_recv_hndl = receive_handler};static int ipmi_request_wait_for_response(ipmi_user_t            user,					  struct ipmi_addr       *addr,					  struct kernel_ipmi_msg *send_msg){	int               rv;	struct completion comp;	init_completion(&comp);	rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &comp,				      &halt_smi_msg, &halt_recv_msg, 0);	if (rv)		return rv;	wait_for_completion(&comp);	return halt_recv_msg.msg.data[0];}/* We are in run-to-completion mode, no completion is desired. */static int ipmi_request_in_rc_mode(ipmi_user_t            user,				   struct ipmi_addr       *addr,				   struct kernel_ipmi_msg *send_msg){	int rv;	rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL,				      &halt_smi_msg, &halt_recv_msg, 0);	if (rv)		return rv;	return halt_recv_msg.msg.data[0];}/* * ATCA Support */#define IPMI_NETFN_ATCA			0x2c#define IPMI_ATCA_SET_POWER_CMD		0x11#define IPMI_ATCA_GET_ADDR_INFO_CMD	0x01#define IPMI_PICMG_ID			0static int ipmi_atca_detect (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;	/*	 * Use get address info to check and see if we are ATCA	 */	send_msg.netfn = IPMI_NETFN_ATCA;	send_msg.cmd = IPMI_ATCA_GET_ADDR_INFO_CMD;	data[0] = IPMI_PICMG_ID;	send_msg.data = data;	send_msg.data_len = sizeof(data);	rv = ipmi_request_wait_for_response(user,					    (struct ipmi_addr *) &smi_addr,					    &send_msg);	return !rv;}static void ipmi_poweroff_atca (ipmi_user_t user){	struct ipmi_system_interface_addr smi_addr;	struct kernel_ipmi_msg            send_msg;	int                               rv;	unsigned char                     data[4];        /*         * 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;	printk(KERN_INFO PFX "Powering down via ATCA power command\n");	/*	 * Power down	 */	send_msg.netfn = IPMI_NETFN_ATCA;	send_msg.cmd = IPMI_ATCA_SET_POWER_CMD;	data[0] = IPMI_PICMG_ID;	data[1] = 0; /* FRU id */	data[2] = 0; /* Power Level */	data[3] = 0; /* Don't change saved presets */	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) {		printk(KERN_ERR PFX "Unable to send ATCA powerdown message,"		       " IPMI error 0x%x\n", rv);		goto out;	} out:	return;}/* * CPI1 Support */#define IPMI_NETFN_OEM_1				0xf8#define OEM_GRP_CMD_SET_RESET_STATE		0x84#define OEM_GRP_CMD_SET_POWER_STATE		0x82#define IPMI_NETFN_OEM_8				0xf8#define OEM_GRP_CMD_REQUEST_HOTSWAP_CTRL	0x80#define OEM_GRP_CMD_GET_SLOT_GA			0xa3#define IPMI_NETFN_SENSOR_EVT			0x10#define IPMI_CMD_GET_EVENT_RECEIVER		0x01#define IPMI_CPI1_PRODUCT_ID		0x000157#define IPMI_CPI1_MANUFACTURER_ID	0x0108static int ipmi_cpi1_detect (ipmi_user_t user){	return ((mfg_id == IPMI_CPI1_MANUFACTURER_ID)		&& (prod_id == IPMI_CPI1_PRODUCT_ID));}static void ipmi_poweroff_cpi1 (ipmi_user_t user){	struct ipmi_system_interface_addr smi_addr;	struct ipmi_ipmb_addr             ipmb_addr;	struct kernel_ipmi_msg            send_msg;	int                               rv;	unsigned char                     data[1];	int                               slot;	unsigned char                     hotswap_ipmb;	unsigned char                     aer_addr;	unsigned char                     aer_lun;        /*         * 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;	printk(KERN_INFO PFX "Powering down via CPI1 power command\n");	/*	 * Get IPMI ipmb address	 */	send_msg.netfn = IPMI_NETFN_OEM_8 >> 2;	send_msg.cmd = OEM_GRP_CMD_GET_SLOT_GA;	send_msg.data = NULL;	send_msg.data_len = 0;	rv = ipmi_request_in_rc_mode(user,				     (struct ipmi_addr *) &smi_addr,				     &send_msg);	if (rv)		goto out;	slot = halt_recv_msg.msg.data[1];	hotswap_ipmb = (slot > 9) ? (0xb0 + 2 * slot) : (0xae + 2 * slot);	/*	 * Get active event receiver	 */	send_msg.netfn = IPMI_NETFN_SENSOR_EVT >> 2;	send_msg.cmd = IPMI_CMD_GET_EVENT_RECEIVER;	send_msg.data = NULL;	send_msg.data_len = 0;	rv = ipmi_request_in_rc_mode(user,				     (struct ipmi_addr *) &smi_addr,				     &send_msg);	if (rv)		goto out;	aer_addr = halt_recv_msg.msg.data[1];	aer_lun = halt_recv_msg.msg.data[2];	/*	 * Setup IPMB address target instead of local target	 */	ipmb_addr.addr_type = IPMI_IPMB_ADDR_TYPE;	ipmb_addr.channel = 0;	ipmb_addr.slave_addr = aer_addr;	ipmb_addr.lun = aer_lun;	/*	 * Send request hotswap control to remove blade from dpv	 */	send_msg.netfn = IPMI_NETFN_OEM_8 >> 2;	send_msg.cmd = OEM_GRP_CMD_REQUEST_HOTSWAP_CTRL;	send_msg.data = &hotswap_ipmb;	send_msg.data_len = 1;	ipmi_request_in_rc_mode(user,				(struct ipmi_addr *) &ipmb_addr,				&send_msg);	/*	 * Set reset asserted	 */	send_msg.netfn = IPMI_NETFN_OEM_1 >> 2;	send_msg.cmd = OEM_GRP_CMD_SET_RESET_STATE;	send_msg.data = data;	data[0] = 1; /* Reset asserted state */	send_msg.data_len = 1;	rv = ipmi_request_in_rc_mode(user,				     (struct ipmi_addr *) &smi_addr,				     &send_msg);	if (rv)		goto out;	/*	 * Power down	 */	send_msg.netfn = IPMI_NETFN_OEM_1 >> 2;	send_msg.cmd = OEM_GRP_CMD_SET_POWER_STATE;

⌨️ 快捷键说明

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