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