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 2009 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 boolean_t 54 ipmi_is_sun_ilom(ipmi_deviceid_t *dp) 55 { 56 return (ipmi_devid_manufacturer(dp) == IPMI_OEM_SUN && 57 dp->id_product == IPMI_PROD_SUN_ILOM); 58 } 59 60 static int 61 check_sunoem(ipmi_handle_t *ipmi_hdl) 62 { 63 ipmi_deviceid_t *devid; 64 65 if ((devid = ipmi_get_deviceid(ipmi_hdl)) == NULL) 66 return (-1); 67 68 if (!ipmi_is_sun_ilom(devid)) 69 return (-2); 70 71 return (0); 72 } 73 74 /*ARGSUSED*/ 75 static void 76 send_fma_cap(fmd_hdl_t *hdl, id_t id, void *data) 77 { 78 ipmi_handle_t *ipmi_hdl; 79 ipmi_cmd_t cmd; 80 uint8_t oem_data[OEM_DATA_LENGTH]; 81 82 ipmi_hdl = fmd_hdl_getspecific(hdl); 83 84 oem_data[0] = CORE_TUNNEL_SUBCMD_HOSTFMACAP; 85 oem_data[1] = VERSION; 86 oem_data[2] = HOST_CAPABILITY; 87 88 cmd.ic_netfn = IPMI_NETFN_OEM; 89 cmd.ic_lun = 0; 90 cmd.ic_cmd = CMD_SUNOEM_CORE_TUNNEL; 91 cmd.ic_dlen = OEM_DATA_LENGTH; 92 cmd.ic_data = oem_data; 93 94 if (ipmi_send(ipmi_hdl, &cmd) == NULL) { 95 fmd_hdl_debug(hdl, "Failed to send Solaris FMA " 96 "capability to fdd: %s", ipmi_errmsg(ipmi_hdl)); 97 } 98 99 ipmi_close(ipmi_hdl); 100 fmd_hdl_setspecific(hdl, NULL); 101 fmd_hdl_unregister(hdl); 102 } 103 104 static const fmd_hdl_ops_t fmd_ops = { 105 NULL, /* fmdo_recv */ 106 send_fma_cap, /* fmdo_timeout */ 107 NULL, /* fmdo_close */ 108 NULL, /* fmdo_stats */ 109 NULL, /* fmdo_gc */ 110 }; 111 112 static const fmd_prop_t fmd_props[] = { 113 { "interval", FMD_TYPE_TIME, "1s" }, 114 { NULL, 0, NULL } 115 }; 116 117 static const fmd_hdl_info_t fmd_info = { 118 "fdd Messenger", "1.0", &fmd_ops, fmd_props 119 }; 120 121 void 122 _fmd_init(fmd_hdl_t *hdl) 123 { 124 ipmi_handle_t *ipmi_hdl; 125 int error; 126 char *msg; 127 128 if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) 129 return; 130 131 if ((ipmi_hdl = ipmi_open(&error, &msg)) == NULL) { 132 /* 133 * If /dev/bmc doesn't exist on the system, then unload the 134 * module without doing anything. 135 */ 136 if (error != EIPMI_BMC_OPEN_FAILED) 137 fmd_hdl_abort(hdl, "Failed to initialize IPMI " 138 "connection: %s\n", msg); 139 fmd_hdl_debug(hdl, "Failed to load: no IPMI connection " 140 "present"); 141 fmd_hdl_unregister(hdl); 142 return; 143 } 144 145 /* 146 * Check if it's Sun ILOM 147 */ 148 if (check_sunoem(ipmi_hdl) != 0) { 149 fmd_hdl_debug(hdl, "Service Processor does not run " 150 "Sun ILOM"); 151 ipmi_close(ipmi_hdl); 152 fmd_hdl_unregister(hdl); 153 return; 154 } 155 156 fmd_hdl_setspecific(hdl, ipmi_hdl); 157 158 /* 159 * Setup the timer. 160 */ 161 (void) fmd_timer_install(hdl, NULL, NULL, 0); 162 } 163 164 void 165 _fmd_fini(fmd_hdl_t *hdl) 166 { 167 ipmi_handle_t *ipmi_hdl = fmd_hdl_getspecific(hdl); 168 169 if (ipmi_hdl) { 170 ipmi_close(ipmi_hdl); 171 } 172 } 173