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.
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.
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]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012 Joyent, Inc. All rights reserved.
39 #include "ipmi_impl.h"
42 * IPMI transport for the local BMC at /dev/ipmi0.
45 typedef struct ipmi_bmc
{
46 ipmi_handle_t
*ib_ihp
; /* ipmi handle */
47 int ib_fd
; /* /dev/ipmi0 filedescriptor */
48 uint32_t ib_msgseq
; /* message sequence number */
49 uint8_t *ib_msg
; /* message buffer */
50 size_t ib_msglen
; /* size of message buffer */
53 #define BMC_DEV "/dev/ipmi0"
56 ipmi_bmc_close(void *data
)
58 ipmi_bmc_t
*ibp
= data
;
60 ipmi_free(ibp
->ib_ihp
, ibp
->ib_msg
);
62 (void) close(ibp
->ib_fd
);
64 ipmi_free(ibp
->ib_ihp
, ibp
);
69 ipmi_bmc_open(ipmi_handle_t
*ihp
, nvlist_t
*params
)
73 if ((ibp
= ipmi_zalloc(ihp
, sizeof (ipmi_bmc_t
))) == NULL
)
78 if ((ibp
->ib_fd
= open(BMC_DEV
, O_RDWR
)) < 0) {
80 (void) ipmi_set_error(ihp
, EIPMI_BMC_OPEN_FAILED
, "%s",
85 if ((ibp
->ib_msg
= (uint8_t *)ipmi_zalloc(ihp
, BUFSIZ
)) == NULL
) {
89 ibp
->ib_msglen
= BUFSIZ
;
95 ipmi_bmc_send(void *data
, ipmi_cmd_t
*cmd
, ipmi_cmd_t
*response
,
98 ipmi_bmc_t
*ibp
= data
;
100 struct ipmi_recv recv
;
101 struct ipmi_addr addr
;
103 struct ipmi_system_interface_addr bmc_addr
;
105 bmc_addr
.addr_type
= IPMI_SYSTEM_INTERFACE_ADDR_TYPE
;
106 bmc_addr
.channel
= IPMI_BMC_CHANNEL
;
107 bmc_addr
.lun
= cmd
->ic_lun
;
109 (void) memset(&req
, 0, sizeof (struct ipmi_req
));
111 req
.addr
= (unsigned char *) &bmc_addr
;
112 req
.addr_len
= sizeof (bmc_addr
);
114 req
.msgid
= ibp
->ib_msgseq
++;
115 req
.msg
.netfn
= cmd
->ic_netfn
;
116 req
.msg
.cmd
= cmd
->ic_cmd
;
117 req
.msg
.data
= cmd
->ic_data
;
118 req
.msg
.data_len
= cmd
->ic_dlen
;
120 if (ioctl(ibp
->ib_fd
, IPMICTL_SEND_COMMAND
, &req
) < 0) {
121 (void) ipmi_set_error(ibp
->ib_ihp
, EIPMI_BMC_PUTMSG
, "%s",
126 /* get the response from the BMC */
129 FD_SET(ibp
->ib_fd
, &rset
);
131 if (select(ibp
->ib_fd
+ 1, &rset
, NULL
, NULL
, NULL
) < 0) {
132 (void) ipmi_set_error(ibp
->ib_ihp
, EIPMI_BMC_GETMSG
, "%s",
136 if (FD_ISSET(ibp
->ib_fd
, &rset
) == 0) {
137 (void) ipmi_set_error(ibp
->ib_ihp
, EIPMI_BMC_GETMSG
, "%s",
138 "No data available");
142 recv
.addr
= (unsigned char *) &addr
;
143 recv
.addr_len
= sizeof (addr
);
144 recv
.msg
.data
= (unsigned char *)ibp
->ib_msg
;
145 recv
.msg
.data_len
= ibp
->ib_msglen
;
148 if (ioctl(ibp
->ib_fd
, IPMICTL_RECEIVE_MSG_TRUNC
, &recv
) < 0) {
149 (void) ipmi_set_error(ibp
->ib_ihp
, EIPMI_BMC_GETMSG
, "%s",
154 if (recv
.recv_type
!= IPMI_RESPONSE_RECV_TYPE
) {
155 (void) ipmi_set_error(ibp
->ib_ihp
, EIPMI_BMC_RESPONSE
,
156 "unknown BMC message type %d", recv
.recv_type
);
160 response
->ic_netfn
= recv
.msg
.netfn
;
161 /* The lun is not returned in addr, return the lun passed in */
162 response
->ic_lun
= cmd
->ic_lun
;
163 response
->ic_cmd
= recv
.msg
.cmd
;
164 if (recv
.msg
.data
[0] != 0) {
165 *completion
= recv
.msg
.data
[0];
166 response
->ic_dlen
= 0;
167 response
->ic_data
= NULL
;
170 response
->ic_dlen
= (recv
.msg
.data_len
> 0) ?
171 recv
.msg
.data_len
- 1 : 0;
172 response
->ic_data
= &(recv
.msg
.data
[1]);
178 ipmi_transport_t ipmi_transport_bmc
= {