/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* ENXS platform-specific functions
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <fcntl.h>
#include <errno.h>
#include "librsc.h"
/* rmcadm driver file descriptor */
/*
* librsc receive buffer - it is used as temporary buffer to store replies
* from the remote side
*/
static int rsc_rx_resp_len = 0;
static int rsc_rx_error = 0;
/*
* Registered boot-protocol message callback routine. This routine will be
* called whenever a boot protocol message is received.
*/
/* lookup table to match request and response . This is in order to support */
/* obsolete functions (rscp_send, rscp_recv) */
sizeof (dp_get_date_time_r_t), RR_TIMEOUT },
sizeof (dp_set_date_time_r_t), RR_TIMEOUT },
sizeof (dp_get_event_log_r_t), RR_TIMEOUT },
sizeof (dp_modem_connect_r_t), RR_TIMEOUT },
sizeof (dp_modem_disconnect_r_t), RR_TIMEOUT },
sizeof (dp_send_alert_r_t), RR_TIMEOUT },
sizeof (dp_set_cfgvar_r_t), RR_TIMEOUT },
sizeof (dp_get_cfgvar_r_t), RR_TIMEOUT },
sizeof (dp_get_cfgvar_name_r_t), RR_TIMEOUT },
sizeof (dp_get_network_cfg_r_t), RR_TIMEOUT },
sizeof (dp_rsc_status_r_t), RR_TIMEOUT },
sizeof (dp_user_adm_r_t), RR_SEPROM_TIMEOUT},
0, 1 },
sizeof (dp_get_console_log_r_t), RR_TIMEOUT },
sizeof (dp_get_config_log_r_t), RR_TIMEOUT },
sizeof (dp_get_event_log2_r_t), RR_TIMEOUT },
};
/* lookup table to get timeout value for BP cmd reply. This is in order to */
/* support obsolete functions (rscp_send_bpmsg, rsc_raw_write) */
};
static const int rr_bp_table_cnt =
sizeof (rr_bp_table) / sizeof (rr_bp_table[0]);
sizeof (unsupported_cmds[0]);
/*
* Protocol version number, used to determine whether ALOM will
* time out on unknown commands.
*/
/* function prototypes */
static int rsc_check_unsupported_cmd(rsci8);
static int rsc_cmd_response_guaranteed(rsci8);
/*
* Initialize the generic librsc data protocol routines. basically, it
* open the rmcadm (pseudo) device and initialize data
*/
int
rscp_init(void)
{
/*
* 'erase' the rx buffer
*/
rsc_rx_resp_len = 0;
rsc_rx_error = 0;
/*
* open rmcadm driver
*/
#ifdef DEBUG
printf("rscp_init: Error opening %s, error code = %d\n",
#endif
return (errno);
}
/*
* Fetch the protocol version number in use between the host
* and ALOM.
*/
return (errno);
#ifdef DEBUG
#endif
return (0);
}
/*
* (currently scadm, SunVTS) send a request and wait for a reply in a
* single call. If a response is not required (resp=NULL), the function
* will only return the status of the request (whether it has been successfully
* or not).
*/
int
{
if (rsc_fd < 0)
return (EBADF);
/*
* the request is required, it should not be NULL!
*/
return (EINVAL);
/*
* Check if the command is actually supported
* if not, return an error
*/
return (ENOTSUP);
/*
* Check if this command will generate a response and if it will not,
* return an error.
*/
return (ENOTSUP);
} else {
}
} else {
}
#ifdef DEBUG
printf("rscp_send_recv: req. failed, status=%d errno=%d\n",
#endif
return (errno);
}
return (0);
}
/*
* type, will return a record which provides the following information:
* response expected and a timeout value
*/
static req_resp_table_t *
{
int i;
#ifdef DEBUG
#endif
for (i = 0; i < cnt; i++)
return (rr_table + i);
}
return (NULL);
}
/*
* function to check if a message type is in the list of unsupported commands
* If so, will return 1.
*/
static int
{
int i;
for (i = 0; i < unsupported_cmds_cnt; i++)
if (unsupported_cmds[i] == type) {
return (1);
}
return (0);
}
/*
* Returns 1 if ALOM will generate a response to the given command code,
* otherwise it returns 0. If a command is not in the following list,
* and the protocol version is 2 or less, then ALOM will not generate
* a response to the command. This causes the driver to time out,
* and we want to avoid that situation.
*/
static int
{
switch (type) {
case DP_GET_ALARM_STATE:
case DP_GET_CFGVAR:
case DP_GET_CFGVAR_NAME:
case DP_GET_CIRCUIT_BRKS:
case DP_GET_DATE_TIME:
case DP_GET_DEVICE:
case DP_GET_EVENT_LOG:
case DP_GET_FAN_STATUS:
case DP_GET_FRU_STATUS:
case DP_GET_HANDLE:
case DP_GET_HANDLE_NAME:
case DP_GET_LED_STATE:
case DP_GET_NETWORK_CFG:
case DP_GET_PCMCIA_INFO:
case DP_GET_PSU_STATUS:
case DP_GET_SDP_VERSION:
case DP_GET_SYSINFO:
case DP_GET_TEMP:
case DP_GET_TEMPERATURES:
case DP_GET_TICKCNT:
case DP_GET_TOD_CLOCK:
case DP_GET_USER_WATCHDOG:
case DP_GET_VOLTS:
case DP_MODEM_CONNECT:
case DP_MODEM_DATA:
case DP_MODEM_DISCONNECT:
case DP_RESET_RSC:
case DP_RMC_EVENTS:
case DP_RSC_STATUS:
case DP_RUN_TEST:
case DP_SEND_ALERT:
case DP_SET_ALARM_STATE:
case DP_SET_CFGVAR:
case DP_SET_CPU_SIGNATURE:
case DP_SET_DATE_TIME:
case DP_SET_DEFAULT_CFG:
case DP_SET_HOST_WATCHDOG:
case DP_SET_LED_STATE:
case DP_SET_USER_WATCHDOG:
case DP_UPDATE_FLASH:
case DP_USER_ADM:
return (1);
default:
return (sdp_version >= SDP_RESPONDS_TO_ALL_CMDS);
}
}
/*
* RSC hard reset. Returns 0 on success, non-zero on error.
*/
int
rsc_nmi(void)
{
if (rsc_fd < 0)
return (EBADF);
return (errno);
return (0);
}
/*
* functions used (exclusively) for the firmware download
*/
/*
* Call this routine to register a callback that will be called by the
* generic data protocol routines when a boot protocol message is
* received. Only one of these routines may be registered at a time.
* Note that receiving a boot protocol message has the effect of
* re-initializing the data protocol. Returns 0 on success, or non-
* zero on failure.
*/
int
{
if (rsc_fd < 0)
return (EBADF);
return (0);
} else {
return (EALREADY);
}
}
/*
* This routine un-registers a boot protocol message callback.
*/
int
{
if (rsc_fd < 0)
return (EBADF);
return (0);
} else {
return (EINPROGRESS);
}
}
/*
* Call this routine to send a boot protocol message.
*/
void
{
return;
/*
* get the timeout value
*/
} else {
}
} else {
}
#ifdef DEBUG
printf("send BP cmd %x, expect reply %x/%d\n",
#endif
#ifdef DEBUG
printf("rscp_send_bpmsg: BP cmd %x failed status=%d "
#endif
return;
}
#ifdef DEBUG
printf("got BP reply type=%x,%x,%x\n",
#endif
/*
* reply received. call the registered callback (if any)
*/
}
/*
* Write raw characters to the RSC control device. Returns 0 on success,
* non-zero on error.
*/
int
{
if (rsc_fd < 0)
return (EBADF);
#ifdef DEBUG
#endif
#ifdef DEBUG
printf("rsc_raw_write: failed. status=%d ioctl error=%d\n",
#endif
return (errno);
}
#ifdef DEBUG
#endif
/*
* reply received. call the registered callback (if any)
*/
return (0);
}
/*
* obsolete functions provided for backward compatibility
*/
/*
* This function is obsolete and it is provided for backward compatibility.
* (no-op function). It was used to start up the data protocol. low-level
* protocol has moved to the kernel and the rmc_comm driver is responsible
* for setting up the data protocol.
* (obsolete)
*/
int
rscp_start(void)
{
if (rsc_fd < 0)
return (EBADF);
return (0);
}
/*
* This function is obsolete and it is provided for backward compatibility.
* Previously, rscp_send() and rscp_recv() where used to send a request and
* read a reply respectively. Now, rscp_send_recv() should be used instead
*
* This is used to send a message by making an RMCADM_REQUEST_RESPONSE ioctl
* call. A lookup table (rr_table) is used to find out the expected reply
* (if any) and the timeout value for a message to be sent. The reply is then
* stored in a buffer (rsc_rx_buffer) to be returned by calling rscp_recv()
*/
int
{
if (rsc_fd < 0)
return (EBADF);
/*
* sanity check
*/
return (EINVAL);
/*
* Check if the command is actually supported
* if not, return an error
*/
return (ENOTSUP);
/*
* Check if this command will generate a response and if it will not,
* return an error.
*/
return (ENOTSUP);
/*
* init rx buffer
*/
rsc_rx_resp_len = 0;
rsc_rx_error = 0;
/*
* no reply expected. so, no reply buffer needed
* (set to NULL)
*/
} else {
}
} else {
return (ENOTSUP);
}
#ifdef DEBUG
#endif
#ifdef DEBUG
printf("rscp_send: req %x failed, status=%d errno=%d\n",
#endif
return (errno);
}
/*
* reply received. get the number of bytes effectively returned
*/
#ifdef DEBUG
#endif
return (0);
}
/*
* This function is obsolete and it is provided for backward compatibility
* Previously, rscp_send() and rscp_recv() where used to send a request and
* read a reply repectively. Now, rscp_send_recv() should be used instead
*
* This function returns the reply received when a request was previously sent
* using the rscp_send() function (stored in the rsc_rx_buffer buffer). If a
* reply was not received, then an error is returned.
*
* timeout parameter is declared for backward compatibility but it is not used.
*/
/*ARGSUSED*/
int
{
int err = 0;
if (rsc_fd < 0)
return (EBADF);
/*
* sanity check
*/
return (EINVAL);
if (rsc_rx_error < 0) {
err = rsc_rx_error;
} else {
}
#ifdef DEBUG
#endif
rsc_rx_resp_len = 0;
rsc_rx_error = 0;
return (err);
}
/*
* used to free up a (received) message. no-op function
*/
/*ARGSUSED*/
int
{
if (rsc_fd < 0)
return (EBADF);
return (0);
}