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 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
38 #include <sys/bmc_intf.h>
40 #include "ipmi_impl.h"
43 * IPMI transport for /dev/bmc
46 typedef struct ipmi_bmc
{
47 ipmi_handle_t
*ib_ihp
; /* ipmi handle */
48 int ib_fd
; /* /dev/bmc filedescriptor */
49 uint32_t ib_msgseq
; /* message sequence number */
50 bmc_msg_t
*ib_msg
; /* message buffer */
51 size_t ib_msglen
; /* size of message buffer */
54 #define BMC_DEV "/dev/bmc"
57 ipmi_bmc_close(void *data
)
59 ipmi_bmc_t
*ibp
= data
;
61 ipmi_free(ibp
->ib_ihp
, ibp
->ib_msg
);
63 (void) close(ibp
->ib_fd
);
65 ipmi_free(ibp
->ib_ihp
, ibp
);
69 ipmi_bmc_open(ipmi_handle_t
*ihp
)
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
= (bmc_msg_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
;
107 * The length of the message structure is equal to the size of the
108 * bmc_req_t structure, PLUS any additional data space in excess of
109 * the data space already reserved in the data member + <n> for
110 * the rest of the members in the bmc_msg_t structure.
112 msgsz
= offsetof(bmc_msg_t
, msg
) + sizeof (bmc_req_t
) +
113 ((cmd
->ic_dlen
> SEND_MAX_PAYLOAD_SIZE
) ?
114 (cmd
->ic_dlen
- SEND_MAX_PAYLOAD_SIZE
) : 0);
116 /* construct and send the message */
117 if ((msg
= ipmi_zalloc(ibp
->ib_ihp
, msgsz
)) == NULL
)
119 bmcreq
= (bmc_req_t
*)&msg
->msg
[0];
121 msg
->m_type
= BMC_MSG_REQUEST
;
122 msg
->m_id
= ibp
->ib_msgseq
++;
123 bmcreq
->fn
= cmd
->ic_netfn
;
124 bmcreq
->lun
= cmd
->ic_lun
;
125 bmcreq
->cmd
= cmd
->ic_cmd
;
126 bmcreq
->datalength
= cmd
->ic_dlen
;
127 (void) memcpy(bmcreq
->data
, cmd
->ic_data
, cmd
->ic_dlen
);
129 sb
.buf
= (char *)msg
;
131 if (putmsg(ibp
->ib_fd
, NULL
, &sb
, 0) < 0) {
132 ipmi_free(ibp
->ib_ihp
, msg
);
133 (void) ipmi_set_error(ibp
->ib_ihp
, EIPMI_BMC_PUTMSG
, "%s",
138 ipmi_free(ibp
->ib_ihp
, msg
);
140 /* get the response from the BMC */
141 sb
.buf
= (char *)ibp
->ib_msg
;
142 sb
.maxlen
= ibp
->ib_msglen
;
144 if (getmsg(ibp
->ib_fd
, NULL
, &sb
, &flags
) < 0) {
145 (void) ipmi_set_error(ibp
->ib_ihp
, EIPMI_BMC_GETMSG
, "%s",
150 switch (ibp
->ib_msg
->m_type
) {
151 case BMC_MSG_RESPONSE
:
152 bmcrsp
= (bmc_rsp_t
*)&ibp
->ib_msg
->msg
[0];
154 response
->ic_netfn
= bmcrsp
->fn
;
155 response
->ic_lun
= bmcrsp
->lun
;
156 response
->ic_cmd
= bmcrsp
->cmd
;
157 if (bmcrsp
->ccode
!= 0) {
158 *completion
= bmcrsp
->ccode
;
159 response
->ic_dlen
= 0;
160 response
->ic_data
= NULL
;
163 response
->ic_dlen
= bmcrsp
->datalength
;
164 response
->ic_data
= bmcrsp
->data
;
169 (void) ipmi_set_error(ibp
->ib_ihp
, EIPMI_BMC_RESPONSE
, "%s",
170 strerror(ibp
->ib_msg
->msg
[0]));
174 (void) ipmi_set_error(ibp
->ib_ihp
, EIPMI_BMC_RESPONSE
,
175 "unknown BMC message type %d", ibp
->ib_msg
->m_type
);
182 ipmi_transport_t ipmi_transport_bmc
= {