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]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * ENXS platform-specific functions
40 #include <sys/types.h>
45 /* rmcadm driver file descriptor */
46 static int rsc_fd
= -1;
49 * librsc receive buffer - it is used as temporary buffer to store replies
50 * from the remote side
53 static uchar_t rsc_rx_buffer
[RSC_MAX_RX_BUFFER
];
54 static int rsc_rx_resp_len
= 0;
55 static int rsc_rx_error
= 0;
56 static rsci8 rsc_rx_resp_type
= 0;
59 * Registered boot-protocol message callback routine. This routine will be
60 * called whenever a boot protocol message is received.
62 static rscp_bpmsg_cb_t
*bpmsg_cb
;
66 /* lookup table to match request and response . This is in order to support */
67 /* obsolete functions (rscp_send, rscp_recv) */
69 static req_resp_table_t rr_table
[] = {
71 { DP_GET_DATE_TIME
, DP_GET_DATE_TIME_R
,
72 sizeof (dp_get_date_time_r_t
), RR_TIMEOUT
},
73 { DP_SET_DATE_TIME
, DP_SET_DATE_TIME_R
,
74 sizeof (dp_set_date_time_r_t
), RR_TIMEOUT
},
75 { DP_GET_EVENT_LOG
, DP_GET_EVENT_LOG_R
,
76 sizeof (dp_get_event_log_r_t
), RR_TIMEOUT
},
77 { DP_MODEM_CONNECT
, DP_MODEM_CONNECT_R
,
78 sizeof (dp_modem_connect_r_t
), RR_TIMEOUT
},
79 { DP_MODEM_DISCONNECT
, DP_MODEM_DISCONNECT_R
,
80 sizeof (dp_modem_disconnect_r_t
), RR_TIMEOUT
},
81 { DP_SEND_ALERT
, DP_SEND_ALERT_R
,
82 sizeof (dp_send_alert_r_t
), RR_TIMEOUT
},
83 { DP_SET_CFGVAR
, DP_SET_CFGVAR_R
,
84 sizeof (dp_set_cfgvar_r_t
), RR_TIMEOUT
},
85 { DP_GET_CFGVAR
, DP_GET_CFGVAR_R
,
86 sizeof (dp_get_cfgvar_r_t
), RR_TIMEOUT
},
87 { DP_GET_CFGVAR_NAME
, DP_GET_CFGVAR_NAME_R
,
88 sizeof (dp_get_cfgvar_name_r_t
), RR_TIMEOUT
},
89 { DP_GET_NETWORK_CFG
, DP_GET_NETWORK_CFG_R
,
90 sizeof (dp_get_network_cfg_r_t
), RR_TIMEOUT
},
91 { DP_RSC_STATUS
, DP_RSC_STATUS_R
,
92 sizeof (dp_rsc_status_r_t
), RR_TIMEOUT
},
93 { DP_USER_ADM
, DP_USER_ADM_R
,
94 sizeof (dp_user_adm_r_t
), RR_SEPROM_TIMEOUT
},
95 { DP_RESET_RSC
, DP_NULL_MSG
,
97 { DP_GET_CONSOLE_LOG
, DP_GET_CONSOLE_LOG_R
,
98 sizeof (dp_get_console_log_r_t
), RR_TIMEOUT
},
99 { DP_GET_CONFIG_LOG
, DP_GET_CONFIG_LOG_R
,
100 sizeof (dp_get_config_log_r_t
), RR_TIMEOUT
},
101 { DP_GET_EVENT_LOG2
, DP_GET_EVENT_LOG2_R
,
102 sizeof (dp_get_event_log2_r_t
), RR_TIMEOUT
},
105 static const int rr_table_cnt
= sizeof (rr_table
) / sizeof (rr_table
[0]);
108 /* lookup table to get timeout value for BP cmd reply. This is in order to */
109 /* support obsolete functions (rscp_send_bpmsg, rsc_raw_write) */
111 static req_resp_table_t rr_bp_table
[] = {
113 { BP_OBP_BOOTINIT
, NULL
, sizeof (bp_msg_t
),
114 RR_BOOT_INIT_TIMEOUT
},
115 { BP_OBP_RESET
, NULL
, sizeof (bp_msg_t
),
116 RR_BOOT_RESET_TIMEOUT
}
119 static const int rr_bp_table_cnt
=
120 sizeof (rr_bp_table
) / sizeof (rr_bp_table
[0]);
122 static rsci8 unsupported_cmds
[] = { DP_SET_DATE_TIME
};
124 static int unsupported_cmds_cnt
= sizeof (unsupported_cmds
) /
125 sizeof (unsupported_cmds
[0]);
128 * Protocol version number, used to determine whether ALOM will
129 * time out on unknown commands.
131 static int sdp_version
= -1;
133 /* function prototypes */
135 static req_resp_table_t
*rsc_lookup_rr_table(req_resp_table_t
*, int, rsci8
);
137 static int rsc_check_unsupported_cmd(rsci8
);
139 static int rsc_cmd_response_guaranteed(rsci8
);
142 * Initialize the generic librsc data protocol routines. basically, it
143 * open the rmcadm (pseudo) device and initialize data
148 rscp_msg_t request
, response
;
149 dp_get_sdp_version_r_t version_msg
;
152 * 'erase' the rx buffer
154 (void) memset(rsc_rx_buffer
, 0, sizeof (RSC_MAX_RX_BUFFER
));
157 rsc_rx_resp_type
= DP_NULL_MSG
;
162 if ((rsc_fd
= open(RSC_RMCADM_DRV
, O_RDWR
)) < 0) {
164 printf("rscp_init: Error opening %s, error code = %d\n",
165 RSC_RMCADM_DRV
, errno
);
171 * Fetch the protocol version number in use between the host
174 request
.type
= DP_GET_SDP_VERSION
;
178 response
.type
= DP_GET_SDP_VERSION_R
;
179 response
.len
= sizeof (version_msg
);
180 response
.data
= (caddr_t
)&version_msg
;
182 if ((errno
= rscp_send_recv(&request
, &response
, 0)) != 0)
185 sdp_version
= version_msg
.version
;
188 printf("rscp_init: sdp version number is %d\n", sdp_version
);
195 * send/receive interface: this is the new interface where application
196 * (currently scadm, SunVTS) send a request and wait for a reply in a
197 * single call. If a response is not required (resp=NULL), the function
198 * will only return the status of the request (whether it has been successfully
202 rscp_send_recv(rscp_msg_t
*req
, rscp_msg_t
*resp
, struct timespec
*timeout
)
204 rmcadm_request_response_t rr
;
205 rmcadm_msg_t
*rr_req
= &rr
.req
;
206 rmcadm_msg_t
*rr_resp
= &rr
.resp
;
212 * the request is required, it should not be NULL!
218 * Check if the command is actually supported
219 * if not, return an error
221 if (rsc_check_unsupported_cmd(req
->type
) != 0)
225 * Check if this command will generate a response and if it will not,
228 if (!rsc_cmd_response_guaranteed(req
->type
))
231 rr_req
->msg_type
= req
->type
;
232 rr_req
->msg_len
= req
->len
;
233 rr_req
->msg_buf
= (caddr_t
)req
->data
;
236 rr_resp
->msg_type
= resp
->type
;
237 rr_resp
->msg_len
= resp
->len
;
238 rr_resp
->msg_buf
= (caddr_t
)resp
->data
;
239 rr_resp
->msg_bytes
= 0;
241 rr_resp
->msg_type
= DP_NULL_MSG
;
242 rr_resp
->msg_buf
= (caddr_t
)NULL
;
243 rr_resp
->msg_len
= 0;
244 rr_resp
->msg_bytes
= 0;
247 if (timeout
== NULL
) {
248 rr
.wait_time
= RR_TIMEOUT
;
250 rr
.wait_time
= timeout
->tv_sec
* 1000 +
251 timeout
->tv_nsec
/ 1000000;
255 if (ioctl(rsc_fd
, RMCADM_REQUEST_RESPONSE
, &rr
) < 0) {
257 printf("rscp_send_recv: req. failed, status=%d errno=%d\n",
258 rr_req
->msg_type
, rr
.status
, errno
);
267 * function used to look up at the request/response table. Given a request
268 * type, will return a record which provides the following information:
269 * response expected and a timeout value
271 static req_resp_table_t
*
272 rsc_lookup_rr_table(req_resp_table_t
*rr_table
, int cnt
, rsci8 type
)
277 printf("lookup for type %x, count %d\n", type
, cnt
);
280 for (i
= 0; i
< cnt
; i
++)
281 if (rr_table
[i
].req_type
== type
) {
282 return (rr_table
+ i
);
289 * function to check if a message type is in the list of unsupported commands
290 * If so, will return 1.
293 rsc_check_unsupported_cmd(rsci8 type
)
297 for (i
= 0; i
< unsupported_cmds_cnt
; i
++)
298 if (unsupported_cmds
[i
] == type
) {
306 * Returns 1 if ALOM will generate a response to the given command code,
307 * otherwise it returns 0. If a command is not in the following list,
308 * and the protocol version is 2 or less, then ALOM will not generate
309 * a response to the command. This causes the driver to time out,
310 * and we want to avoid that situation.
313 rsc_cmd_response_guaranteed(rsci8 type
)
316 case DP_GET_ALARM_STATE
:
318 case DP_GET_CFGVAR_NAME
:
319 case DP_GET_CIRCUIT_BRKS
:
320 case DP_GET_DATE_TIME
:
322 case DP_GET_EVENT_LOG
:
323 case DP_GET_FAN_STATUS
:
324 case DP_GET_FRU_STATUS
:
326 case DP_GET_HANDLE_NAME
:
327 case DP_GET_LED_STATE
:
328 case DP_GET_NETWORK_CFG
:
329 case DP_GET_PCMCIA_INFO
:
330 case DP_GET_PSU_STATUS
:
331 case DP_GET_SDP_VERSION
:
334 case DP_GET_TEMPERATURES
:
336 case DP_GET_TOD_CLOCK
:
337 case DP_GET_USER_WATCHDOG
:
339 case DP_MODEM_CONNECT
:
341 case DP_MODEM_DISCONNECT
:
347 case DP_SET_ALARM_STATE
:
349 case DP_SET_CPU_SIGNATURE
:
350 case DP_SET_DATE_TIME
:
351 case DP_SET_DEFAULT_CFG
:
352 case DP_SET_HOST_WATCHDOG
:
353 case DP_SET_LED_STATE
:
354 case DP_SET_USER_WATCHDOG
:
355 case DP_UPDATE_FLASH
:
359 return (sdp_version
>= SDP_RESPONDS_TO_ALL_CMDS
);
364 * RSC hard reset. Returns 0 on success, non-zero on error.
372 if (ioctl(rsc_fd
, RMCADM_RESET_SP
, NULL
) < 0)
379 * functions used (exclusively) for the firmware download
383 * Call this routine to register a callback that will be called by the
384 * generic data protocol routines when a boot protocol message is
385 * received. Only one of these routines may be registered at a time.
386 * Note that receiving a boot protocol message has the effect of
387 * re-initializing the data protocol. Returns 0 on success, or non-
391 rscp_register_bpmsg_cb(rscp_bpmsg_cb_t
*cb
)
396 if (bpmsg_cb
== NULL
) {
405 * This routine un-registers a boot protocol message callback.
408 rscp_unregister_bpmsg_cb(rscp_bpmsg_cb_t
*cb
)
413 if (bpmsg_cb
== cb
) {
417 return (EINPROGRESS
);
422 * Call this routine to send a boot protocol message.
425 rscp_send_bpmsg(bp_msg_t
*bpmsg
)
427 rmcadm_request_response_t rr_bp
;
428 rmcadm_msg_t
*req_bp
= &rr_bp
.req
;
429 rmcadm_msg_t
*resp_bp
= &rr_bp
.resp
;
430 req_resp_table_t
*rr_bp_item
;
431 bp_msg_t bpmsg_reply
;
433 if (rsc_fd
< 0 || bpmsg
== NULL
)
437 * get the timeout value
439 if ((rr_bp_item
= rsc_lookup_rr_table(rr_bp_table
, rr_bp_table_cnt
,
440 bpmsg
->cmd
)) != NULL
) {
442 rr_bp
.wait_time
= rr_bp_item
->timeout
;
446 rr_bp
.wait_time
= RR_BP_TIMEOUT
;
451 req_bp
->msg_len
= sizeof (bp_msg_t
);
452 req_bp
->msg_buf
= (caddr_t
)bpmsg
;
454 if (rr_bp
.wait_time
== 0) {
455 resp_bp
->msg_buf
= (caddr_t
)NULL
;
457 resp_bp
->msg_len
= sizeof (bp_msg_t
);
458 resp_bp
->msg_buf
= (caddr_t
)&bpmsg_reply
;
462 printf("send BP cmd %x, expect reply %x/%d\n",
463 bpmsg
->cmd
, resp_bp
->msg_buf
, resp_bp
->msg_len
);
465 if (ioctl(rsc_fd
, RMCADM_REQUEST_RESPONSE_BP
, &rr_bp
) < 0) {
467 printf("rscp_send_bpmsg: BP cmd %x failed status=%d "
468 "errno=%d\n", bpmsg
->cmd
, rr_bp
.status
, errno
);
474 printf("got BP reply type=%x,%x,%x\n",
475 bpmsg_reply
.cmd
, bpmsg_reply
.dat1
, bpmsg_reply
.dat2
);
479 * reply received. call the registered callback (if any)
481 if (bpmsg_cb
!= NULL
&& resp_bp
->msg_buf
!= NULL
)
482 bpmsg_cb(&bpmsg_reply
);
486 * Write raw characters to the RSC control device. Returns 0 on success,
490 rsc_raw_write(char *buf
, int nbytes
)
492 rmcadm_send_srecord_bp_t srec_bp
;
493 bp_msg_t bpmsg_reply
;
498 srec_bp
.data_len
= (uint_t
)nbytes
;
499 srec_bp
.data_buf
= (caddr_t
)buf
;
500 srec_bp
.resp_bp
.msg_len
= sizeof (bp_msg_t
);
501 srec_bp
.resp_bp
.msg_buf
= (caddr_t
)&bpmsg_reply
;
502 srec_bp
.wait_time
= RR_BOOT_LOAD_TIMEOUT
;
506 printf("send srecord BP len=%d\n", nbytes
);
508 if (ioctl(rsc_fd
, RMCADM_SEND_SRECORD_BP
, &srec_bp
) < 0) {
510 printf("rsc_raw_write: failed. status=%d ioctl error=%d\n",
511 srec_bp
.status
, errno
);
517 printf("got BP reply type=%x\n", bpmsg_reply
.cmd
);
521 * reply received. call the registered callback (if any)
523 if (bpmsg_cb
!= NULL
)
524 bpmsg_cb(&bpmsg_reply
);
530 * obsolete functions provided for backward compatibility
534 * This function is obsolete and it is provided for backward compatibility.
535 * (no-op function). It was used to start up the data protocol. low-level
536 * protocol has moved to the kernel and the rmc_comm driver is responsible
537 * for setting up the data protocol.
550 * This function is obsolete and it is provided for backward compatibility.
551 * Previously, rscp_send() and rscp_recv() where used to send a request and
552 * read a reply respectively. Now, rscp_send_recv() should be used instead
553 * (request/response in one call).
555 * This is used to send a message by making an RMCADM_REQUEST_RESPONSE ioctl
556 * call. A lookup table (rr_table) is used to find out the expected reply
557 * (if any) and the timeout value for a message to be sent. The reply is then
558 * stored in a buffer (rsc_rx_buffer) to be returned by calling rscp_recv()
561 rscp_send(rscp_msg_t
*msgp
)
563 rmcadm_request_response_t rr
;
564 rmcadm_msg_t
*req
= &rr
.req
;
565 rmcadm_msg_t
*resp
= &rr
.resp
;
566 req_resp_table_t
*rr_item
;
578 * Check if the command is actually supported
579 * if not, return an error
581 if (rsc_check_unsupported_cmd(msgp
->type
) != 0)
585 * Check if this command will generate a response and if it will not,
588 if (!rsc_cmd_response_guaranteed(msgp
->type
))
597 req
->msg_type
= msgp
->type
;
598 req
->msg_len
= msgp
->len
;
599 req
->msg_buf
= msgp
->data
;
601 if ((rr_item
= rsc_lookup_rr_table(rr_table
, rr_table_cnt
,
602 msgp
->type
)) != NULL
) {
603 resp
->msg_type
= rr_item
->resp_type
;
604 if (rr_item
->resp_type
== DP_NULL_MSG
) {
606 * no reply expected. so, no reply buffer needed
610 resp
->msg_buf
= (caddr_t
)NULL
;
612 resp
->msg_len
= RSC_MAX_RX_BUFFER
;
613 resp
->msg_buf
= (caddr_t
)rsc_rx_buffer
;
616 rr
.wait_time
= rr_item
->timeout
;
617 rsc_rx_resp_type
= rr_item
->resp_type
;
624 printf("request/response %x/%x\n", req
->msg_type
, resp
->msg_type
);
626 if (ioctl(rsc_fd
, RMCADM_REQUEST_RESPONSE
, &rr
) < 0) {
628 printf("rscp_send: req %x failed, status=%d errno=%d\n",
629 rr
.req
.msg_type
, rr
.status
, errno
);
631 rsc_rx_error
= errno
;
637 * reply received. get the number of bytes effectively returned
639 rsc_rx_resp_len
= resp
->msg_bytes
;
640 rsc_rx_resp_type
= resp
->msg_type
;
643 printf("got reply type=%x len=%d\n", rsc_rx_resp_type
, rsc_rx_resp_len
);
650 * This function is obsolete and it is provided for backward compatibility
651 * Previously, rscp_send() and rscp_recv() where used to send a request and
652 * read a reply repectively. Now, rscp_send_recv() should be used instead
653 * (request/response in one call).
655 * This function returns the reply received when a request was previously sent
656 * using the rscp_send() function (stored in the rsc_rx_buffer buffer). If a
657 * reply was not received, then an error is returned.
659 * timeout parameter is declared for backward compatibility but it is not used.
663 rscp_recv(rscp_msg_t
*msgp
, struct timespec
*timeout
)
676 if (rsc_rx_error
< 0) {
677 msgp
->type
= DP_NULL_MSG
;
684 msgp
->type
= rsc_rx_resp_type
;
685 msgp
->len
= rsc_rx_resp_len
;
686 msgp
->data
= rsc_rx_buffer
;
690 printf("read reply. type=%x, err=%d\n", msgp
->type
, err
);
695 rsc_rx_resp_type
= DP_NULL_MSG
;
701 * used to free up a (received) message. no-op function
705 rscp_free_msg(rscp_msg_t
*msgp
)