1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * fdd messenger 29 * 30 * This module sends fdd running on service processor a message which 31 * indicates the Solaris host FMA capability when fmd is started. The 32 * message is sent via the BMC driver (KCS interface) to the IPMI stack 33 * of ILOM using the IPMI Sun OEM core tunnel command. The sub-command 34 * is CORE_TUNNEL_SUBCMD_HOSTCAP. The IPMI stack posts an host FMA 35 * capability event to the event manager upon receiving this message. 36 * fdd subscribes to the event manager for this event. Upon receving 37 * this event, fdd will adjust its configuration. 38 * 39 */ 40 41 #include <errno.h> 42 #include <stdio.h> 43 #include <strings.h> 44 #include <libipmi.h> 45 #include <fm/fmd_api.h> 46 47 #define CMD_SUNOEM_CORE_TUNNEL 0x44 48 #define CORE_TUNNEL_SUBCMD_HOSTFMACAP 2 49 #define OEM_DATA_LENGTH 3 50 #define VERSION 0x10 51 #define HOST_CAPABILITY 2 52 53 static int 54 check_sunoem(ipmi_handle_t *ipmi_hdl) 55 { 56 ipmi_deviceid_t *devid; 57 58 if ((devid = ipmi_get_deviceid(ipmi_hdl)) == NULL) 59 return (-1); 60 61 if (!ipmi_is_sun_ilom(devid)) 62 return (-2); 63 64 return (0); 65 } 66 67 /*ARGSUSED*/ 68 static void 69 send_fma_cap(fmd_hdl_t *hdl, id_t id, void *data) 70 { 71 ipmi_handle_t *ipmi_hdl; 72 ipmi_cmd_t cmd; 73 uint8_t oem_data[OEM_DATA_LENGTH]; 74 75 ipmi_hdl = fmd_hdl_getspecific(hdl); 76 77 oem_data[0] = CORE_TUNNEL_SUBCMD_HOSTFMACAP; 78 oem_data[1] = VERSION; 79 oem_data[2] = HOST_CAPABILITY; 80 81 cmd.ic_netfn = IPMI_NETFN_OEM; 82 cmd.ic_lun = 0; 83 cmd.ic_cmd = CMD_SUNOEM_CORE_TUNNEL; 84 cmd.ic_dlen = OEM_DATA_LENGTH; 85 cmd.ic_data = oem_data; 86 87 if (ipmi_send(ipmi_hdl, &cmd) == NULL) { 88 fmd_hdl_debug(hdl, "Failed to send Solaris FMA " 89 "capability to fdd: %s", ipmi_errmsg(ipmi_hdl)); 90 } 91 92 ipmi_close(ipmi_hdl); 93 fmd_hdl_setspecific(hdl, NULL); 94 fmd_hdl_unregister(hdl); 95 } 96 97 static const fmd_hdl_ops_t fmd_ops = { 98 NULL, /* fmdo_recv */ 99 send_fma_cap, /* fmdo_timeout */ 100 NULL, /* fmdo_close */ 101 NULL, /* fmdo_stats */ 102 NULL, /* fmdo_gc */ 103 }; 104 105 static const fmd_prop_t fmd_props[] = { 106 { "interval", FMD_TYPE_TIME, "1s" }, 107 { NULL, 0, NULL } 108 }; 109 110 static const fmd_hdl_info_t fmd_info = { 111 "fdd Messenger", "1.0", &fmd_ops, fmd_props 112 }; 113 114 void 115 _fmd_init(fmd_hdl_t *hdl) 116 { 117 ipmi_handle_t *ipmi_hdl; 118 int error; 119 char *msg; 120 121 if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) 122 return; 123 124 if ((ipmi_hdl = ipmi_open(&error, &msg, IPMI_TRANSPORT_BMC, NULL)) 125 == NULL) { 126 /* 127 * If /dev/bmc doesn't exist on the system, then unload the 128 * module without doing anything. 129 */ 130 if (error != EIPMI_BMC_OPEN_FAILED) 131 fmd_hdl_abort(hdl, "Failed to initialize IPMI " 132 "connection: %s\n", msg); 133 fmd_hdl_debug(hdl, "Failed to load: no IPMI connection " 134 "present"); 135 fmd_hdl_unregister(hdl); 136 return; 137 } 138 139 /* 140 * Check if it's Sun ILOM 141 */ 142 if (check_sunoem(ipmi_hdl) != 0) { 143 fmd_hdl_debug(hdl, "Service Processor does not run " 144 "Sun ILOM"); 145 ipmi_close(ipmi_hdl); 146 fmd_hdl_unregister(hdl); 147 return; 148 } 149 150 fmd_hdl_setspecific(hdl, ipmi_hdl); 151 152 /* 153 * Setup the timer. 154 */ 155 (void) fmd_timer_install(hdl, NULL, NULL, 0); 156 } 157 158 void 159 _fmd_fini(fmd_hdl_t *hdl) 160 { 161 ipmi_handle_t *ipmi_hdl = fmd_hdl_getspecific(hdl); 162 163 if (ipmi_hdl) { 164 ipmi_close(ipmi_hdl); 165 } 166 } 167