Files
hisi_SS524V100_SDK/mpp/sample/ser2net-3.5.2/sol.c
T

1014 lines
23 KiB
C

/*
* ser2net - A program for allowing telnet connection to serial ports
* Copyright (C) 2001 Corey Minyard <minyard@acm.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* This code handles IPMI SOL. */
#include <errno.h>
#include "devio.h"
#ifdef HAVE_OPENIPMI
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/stat.h>
#include <syslog.h>
#include <OpenIPMI/ipmiif.h>
#include <OpenIPMI/ipmi_smi.h>
#include <OpenIPMI/ipmi_err.h>
#include <OpenIPMI/ipmi_auth.h>
#include <OpenIPMI/ipmi_lan.h>
#include <OpenIPMI/ipmi_posix.h>
#include <OpenIPMI/internal/ipmi_int.h>
#include <OpenIPMI/ipmi_sol.h>
#include <OpenIPMI/ipmi_debug.h>
#include "ser2net.h"
#include "selector.h"
#include "utils.h"
#include "dataxfer.h"
static os_handler_t *os_hnd;
struct solcfg_data {
/* Information about the terminal device. */
char *devname; /* The full path to the device */
int devfd; /* The file descriptor for the
device, only valid if the
TCP port is open. */
ipmi_sol_conn_t *sol;
ipmi_con_t *ipmi;
int last_any_port_up;
int closed;
int speed;
unsigned char read_data[1024];
unsigned int read_start;
unsigned int read_end;
int write_ready_enabled;
int read_ready_enabled;
int except_ready_enabled;
int exception_pending;
int ready;
unsigned int nacks_sent;
/* Holds whether break is on or not. */
int break_set;
/* Disable break-commands */
int disablebreak;
struct devio *io;
ipmi_args_t *args;
/* SOL parms */
int authenticated;
int encrypted;
int ack_timeout;
int ack_retries;
int deassert_CTS_DCD_DSR_on_connect;
int shared_serial_alert_behavior;
};
static struct baud_rates_s {
int real_rate;
int val;
int cisco_ios_val;
} baud_rates[] =
{
{ 9600, IPMI_SOL_BIT_RATE_9600, 8 },
{ 19200, IPMI_SOL_BIT_RATE_19200, 10 },
{ 38400, IPMI_SOL_BIT_RATE_38400, 12 },
{ 57600, IPMI_SOL_BIT_RATE_57600, 13 },
{ 115200, IPMI_SOL_BIT_RATE_115200, 14 },
};
#define BAUD_RATES_LEN ((sizeof(baud_rates) / sizeof(struct baud_rates_s)))
static int
get_baud_rate(int rate, int cisco, int *val)
{
unsigned int i;
for (i = 0; i < BAUD_RATES_LEN; i++) {
if (cisco) {
if (rate == baud_rates[i].cisco_ios_val) {
*val = baud_rates[i].val;
return 1;
}
} else {
if (rate == baud_rates[i].real_rate) {
*val = baud_rates[i].val;
return 1;
}
}
}
return 0;
}
static int
get_rate_from_sol_baud_rate(int baud_rate, int cisco)
{
unsigned int i;
int val = 0;
for (i = 0; i < BAUD_RATES_LEN; i++) {
if (baud_rate == baud_rates[i].val) {
if (cisco) {
if (baud_rates[i].cisco_ios_val < 0)
/* We are at a baud rate unsupported by the
enumeration, just return zero. */
val = 0;
else
val = baud_rates[i].cisco_ios_val;
} else {
val = baud_rates[i].real_rate;
}
break;
}
}
return val;
}
static char *
baud_string(int speed)
{
char *str;
switch (speed) {
case IPMI_SOL_BIT_RATE_9600: str = "9600"; break;
case IPMI_SOL_BIT_RATE_19200: str = "19200"; break;
case IPMI_SOL_BIT_RATE_38400: str = "38400"; break;
case IPMI_SOL_BIT_RATE_57600: str = "57600"; break;
case IPMI_SOL_BIT_RATE_115200: str = "115200"; break;
default: str = "unknown speed";
}
return str;
}
static void
solcfg_serparm_to_str(struct devio *io, char *str, int strlen)
{
struct solcfg_data *d = io->my_data;
snprintf(str, strlen, "%s", baud_string(d->speed));
}
/* Send the serial port device configuration to the control port. */
static void
solcfg_show_solcfg(struct devio *io, struct absout *out)
{
struct solcfg_data *d = io->my_data;
out->out(out, "%s", baud_string(d->speed));
}
static int
solcfg_set_devcontrol(struct devio *io, const char *instr)
{
return -1; /* FIXME */
}
static void
solcfg_show_devcontrol(struct devio *io, struct absout *out)
{
}
static void check_write_handler(struct solcfg_data *d)
{
while (d->ready && d->write_ready_enabled)
d->io->write_handler(d->io);
}
static void check_read_handler(struct solcfg_data *d)
{
while (d->ready && d->read_ready_enabled && (d->read_start != d->read_end))
d->io->read_handler(d->io);
}
static void check_except_handler(struct solcfg_data *d, int set)
{
if (set)
d->exception_pending = 1;
if (d->except_ready_enabled && d->exception_pending) {
d->exception_pending = 0;
d->io->except_handler(d->io);
}
}
static int solcfg_read(struct devio *io, void *buf, size_t size)
{
struct solcfg_data *d = io->my_data;
unsigned int left;
int rv = 0;
if (size == 0)
return 0;
if (d->read_end == d->read_start) {
errno = EAGAIN;
return -1;
}
if (d->read_end < d->read_start)
/* Amount of data to the end of the buffer. If the data wraps
we handle that in a check below. */
left = sizeof(d->read_data) - d->read_start;
else
/* Total amount in buffer */
left = d->read_end - d->read_start;
read_rest:
if (left > size)
left = size;
memcpy(buf, d->read_data + d->read_start, left);
rv += left;
size -= left;
d->read_start += left;
if (d->read_start >= sizeof(d->read_data)) {
/* We wrapped, get the data at the beginning of the buffer now. */
d->read_start = 0;
left = d->read_end;
goto read_rest;
}
if (d->nacks_sent > 0) {
/* Calculate the data used. */
if (d->read_end < d->read_start)
left = sizeof(d->read_data) - d->read_start + d->read_end;
else
left = d->read_end - d->read_start;
/* Convert to free space */
left = sizeof(d->read_data) - left;
/* Only release the NACK if we have sufficient free space left */
if (left > 128) { /* FIXME - magic number */
while (d->nacks_sent > 0) {
if (ipmi_sol_release_nack(d->sol) != 0)
goto out;
d->nacks_sent--;
}
}
}
out:
return rv;
}
struct sol_tc {
unsigned int size;
struct solcfg_data *d;
};
static void
transmit_complete(ipmi_sol_conn_t *conn,
int error,
void *cb_data)
{
struct sol_tc *tc = cb_data;
struct solcfg_data *d = tc->d;
if (error) {
check_except_handler(d, 1);
goto out;
}
check_write_handler(d);
out:
free(tc);
}
static int solcfg_write(struct devio *io, void *buf, size_t size)
{
struct solcfg_data *d = io->my_data;
int rv;
struct sol_tc *tc;
if (!d->ready) {
errno = EAGAIN;
return -1;
}
if (size == 0)
return 0;
tc = malloc(sizeof(*tc));
if (!tc) {
errno = ENOMEM;
return -1;
}
tc->size = size;
tc->d = d;
rv = ipmi_sol_write(d->sol, buf, size, transmit_complete, tc);
if (rv) {
free(tc);
if (rv == ENOMEM) {
errno = EAGAIN;
return 0;
}
errno = EINVAL; /* Just a guess */
return -1;
}
return size;
}
static void solcfg_read_handler_enable(struct devio *io, int enabled)
{
struct solcfg_data *d = io->my_data;
d->read_ready_enabled = enabled;
check_read_handler(d);
}
static void solcfg_write_handler_enable(struct devio *io, int enabled)
{
struct solcfg_data *d = io->my_data;
d->write_ready_enabled = enabled;
check_write_handler(d);
}
static void solcfg_except_handler_enable(struct devio *io, int enabled)
{
struct solcfg_data *d = io->my_data;
d->except_ready_enabled = enabled;
check_except_handler(d, 0);
}
static void sol_send_break_cb(ipmi_sol_conn_t *conn, int error, void *cb_data)
{
struct solcfg_data *d = cb_data;
if (error)
check_except_handler(d, 1);
}
static int solcfg_send_break(struct devio *io)
{
struct solcfg_data *d = io->my_data;
ipmi_sol_send_break(d->sol, sol_send_break_cb, d);
return 0;
}
static int solcfg_get_modem_state(struct devio *io, unsigned char *modemstate)
{
return -1;
}
static int solcfg_baud_rate(struct devio *io, int *val, int cisco, int *bps)
{
struct solcfg_data *d = io->my_data;
int sol_rate = 0;
if (*val != 0) {
int err = get_baud_rate(*val, cisco, &sol_rate);
if (!err)
ipmi_sol_set_bit_rate(d->sol, sol_rate);
}
sol_rate = ipmi_sol_get_bit_rate(d->sol);
*val = get_rate_from_sol_baud_rate(sol_rate, cisco);
*bps = get_rate_from_sol_baud_rate(sol_rate, 0);
return 0;
}
static int solcfg_data_size(struct devio *io, unsigned char *val, int *bpc)
{
*val = 8;
*bpc = 10;
return 0;
}
static int solcfg_parity(struct devio *io, unsigned char *val, int *bpc)
{
*val = 1; /* NONE */
*bpc = 10;
return 0;
}
static int solcfg_stop_size(struct devio *io, unsigned char *val, int *bpc)
{
*val = 1; /* 1 stop bit. */
*bpc = 10;
return 0;
}
static int solcfg_flow_control(struct devio *io, unsigned char val)
{
return -1;
}
static int solcfg_control(struct devio *io, unsigned char *val)
{
return -1;
}
static int solcfg_flush(struct devio *io, int *val)
{
return 0;
}
static int sol_data_received(ipmi_sol_conn_t *conn,
const void *idata, size_t count, void *user_data)
{
struct solcfg_data *d = user_data;
const char *data = idata;
int space;
if (d->read_end >= d->read_start)
/* Amount of data to the end of the buffer plus the buffer beginning. */
space = sizeof(d->read_data) - d->read_start + d->read_end;
else /* Wrapped */
space = d->read_start - d->read_end;
space -= 1; /* Can't use the last byte in the buffer, or we can't
tell full from empty. */
if (count > space)
goto send_nack;
if (d->read_end >= d->read_start &&
count >= (sizeof(d->read_data) - d->read_end)) {
/* New data will cause a wrap, handle copying to the end of
the buffer first. */
space = sizeof(d->read_data) - d->read_end;
memcpy(d->read_data + d->read_end, data, space);
data += space;
count -= space;
d->read_end = 0;
}
memcpy(d->read_data + d->read_end, data, count);
d->read_end += count;
check_read_handler(d);
return 0;
send_nack:
d->nacks_sent++;
return 1;
}
static void sol_break_detected(ipmi_sol_conn_t *conn, void *user_data)
{
}
static void bmc_transmit_overrun(ipmi_sol_conn_t *conn, void *user_data)
{
}
static void finish_close_connection(struct solcfg_data *d)
{
if (ser2net_debug_level > 0)
printf("Finish close: %d %p\n", d->closed, d->ipmi);
if (d->sol)
ipmi_sol_free(d->sol);
d->sol = NULL;
if (d->ipmi)
d->ipmi->close_connection(d->ipmi);
d->ipmi = NULL;
d->closed = 1;
d->ready = 0;
}
static void sol_connection_state(ipmi_sol_conn_t *conn, ipmi_sol_state state,
int error, void *cb_data)
{
struct solcfg_data *d = cb_data;
if (ser2net_debug_level > 0)
printf("sol_con_change: %d %d\n", state, error);
if (error) {
finish_close_connection(d);
if (d->io)
check_except_handler(d, 1);
else
free(d);
return;
}
switch (state) {
case ipmi_sol_state_closed:
finish_close_connection(d);
if (!d->io)
free(d);
break;
case ipmi_sol_state_connecting:
break;
case ipmi_sol_state_connected:
d->ready = 1;
check_read_handler(d);
check_write_handler(d);
break;
case ipmi_sol_state_connected_ctu:
break;
case ipmi_sol_state_closing:
d->ready = 0;
break;
}
}
static void conn_changed(ipmi_con_t *ipmi,
int err,
unsigned int port_num,
int any_port_up,
void *cb_data)
{
struct solcfg_data *d = cb_data;
if (ser2net_debug_level > 0)
printf("con_change: %d %d\n", any_port_up, err);
if (any_port_up == d->last_any_port_up)
return;
d->last_any_port_up = any_port_up;
if (!d->sol) {
finish_close_connection(d);
if (!d->io)
free(d);
return;
}
if (err) {
check_except_handler(d, 1);
return;
}
if (!d->ready && any_port_up) {
ipmi_sol_open(d->sol);
}
}
static int solcfg_setup(struct devio *io, const char *name, const char **errstr,
int *bps, int *bpc)
{
int rv;
struct solcfg_data *d = io->my_data;
if (!d->closed) {
*errstr = "Connection still in use";
return -1;
}
rv = ipmi_args_setup_con(d->args, os_hnd, NULL, &d->ipmi);
if (rv) {
*errstr = "Error setting up SOL connection";
goto out;
}
rv = ipmi_sol_create(d->ipmi, &d->sol);
if (rv) {
d->ipmi->close_connection(d->ipmi);
d->ipmi = NULL;
*errstr = "Error creating SOL connection";
goto out;
}
rv = ipmi_sol_register_data_received_callback(d->sol, sol_data_received, d);
if (rv) {
*errstr = "Error registering data callback";
goto out;
}
rv = ipmi_sol_register_break_detected_callback(d->sol,
sol_break_detected, d);
if (rv) {
*errstr = "Error registering break detected callback";
goto out;
}
rv = ipmi_sol_register_bmc_transmit_overrun_callback(d->sol,
bmc_transmit_overrun,
d);
if (rv) {
*errstr = "Error registering transmit overrun callback";
goto out;
}
rv = ipmi_sol_register_connection_state_callback(d->sol,
sol_connection_state, d);
if (rv) {
*errstr = "Error registering connection state callback";
goto out;
}
ipmi_sol_set_ACK_retries(d->sol, d->ack_retries);
ipmi_sol_set_ACK_timeout(d->sol, d->ack_timeout);
ipmi_sol_set_use_authentication(d->sol, d->authenticated);
ipmi_sol_set_use_encryption(d->sol, d->encrypted);
ipmi_sol_set_shared_serial_alert_behavior(d->sol,
d->shared_serial_alert_behavior);
ipmi_sol_set_deassert_CTS_DCD_DSR_on_connect(d->sol,
d->deassert_CTS_DCD_DSR_on_connect);
ipmi_sol_set_bit_rate(d->sol, d->speed);
*bps = get_rate_from_sol_baud_rate(d->speed, 0);
*bpc = 10;
d->ready = 0;
d->last_any_port_up = -1;
rv = d->ipmi->add_con_change_handler(d->ipmi, conn_changed, d);
if (rv) {
*errstr = "Error adding connection change handler";
goto out;
}
d->ipmi->start_con(d->ipmi);
d->closed = 0;
out:
if (rv) {
rv = -1;
if (d->sol) {
ipmi_sol_close(d->sol);
ipmi_sol_free(d->sol);
d->sol = NULL;
}
if (d->ipmi) {
d->ipmi->close_connection(d->ipmi);
d->ipmi = NULL;
}
}
return rv;
}
static void solcfg_shutdown(struct devio *io,
void (*shutdown_done)(struct devio *))
{
struct solcfg_data *d = io->my_data;
if (d->sol) {
ipmi_sol_close(d->sol);
d->ready = 0;
}
shutdown_done(io);
}
static void solcfg_free(struct devio *io)
{
struct solcfg_data *d = io->my_data;
if (d->args)
ipmi_free_args(d->args);
io->f = NULL;
io->my_data = NULL;
d->io = NULL;
if (!d->ipmi)
free(d);
}
/* Configure a serial port control structure based upon input strings
in instr. These strings are described in the man page for this
program. */
static int
solconfig(struct solcfg_data *d, struct absout *eout, const char *instr,
int (*otherconfig)(void *data, struct absout *eout, const char *item),
void *data)
{
char *str = NULL;
char *pos, *endpos;
char *strtok_data;
int rv = 0;
int argc, curr_arg = 0;
char **argv;
ipmi_args_t *args = NULL;
int speed;
if (strncmp(d->io->devname + 4, "lan ", 4) != 0) {
eout->out(eout, "SOL config must start with 'lan ', it was %s",
d->io->devname + 4);
return -1;
}
speed = find_default_int("speed");
switch (speed) {
case 9600: d->speed = IPMI_SOL_BIT_RATE_9600; break;
case 19200: d->speed = IPMI_SOL_BIT_RATE_19200; break;
case 38400: d->speed = IPMI_SOL_BIT_RATE_38400; break;
case 57600: d->speed = IPMI_SOL_BIT_RATE_57600; break;
case 115200: d->speed = IPMI_SOL_BIT_RATE_115200; break;
default:
eout->out(eout, "Invalid default speed for SOL %s: %d",
d->io->devname + 4, speed);
return -1;
}
/* Enable authentication and encryption by default. */
d->authenticated = find_default_int("authenticated");
d->encrypted = find_default_int("encrypted");
d->disablebreak = find_default_int("nobreak");
d->ack_timeout = find_default_int("ack-timeout");
d->ack_retries = find_default_int("ack-retries");
d->shared_serial_alert_behavior = find_default_int("shared-serial-alert");
d->deassert_CTS_DCD_DSR_on_connect =
find_default_int("deassert_CTS_DCD_DSR_on_connect");
rv = str_to_argv(d->io->devname + 4, &argc, &argv, NULL);
if (rv == -ENOMEM) {
eout->out(eout, "Out of memory parsing SOL string");
return -1;
} else if (rv) {
eout->out(eout, "Invalid SOL string: %s", d->io->devname + 4);
return -1;
} else if (argc == 0) {
eout->out(eout, "No SOL string given");
return -1;
}
rv = ipmi_parse_args2(&curr_arg, argc, argv, &args);
if (rv) {
eout->out(eout, "Invalid SOL arguments");
str_to_argv_free(argc, argv);
goto out;
}
if (curr_arg != argc) {
eout->out(eout, "Extra SOL arguments starting with '%s'",
argv[curr_arg]);
str_to_argv_free(argc, argv);
rv = -1;
goto out;
}
str_to_argv_free(argc, argv);
str = strdup(instr);
if (str == NULL) {
rv = -1;
goto out;
}
pos = strtok_r(str, " \t", &strtok_data);
while (pos != NULL) {
if (strcmp(pos, "9600") == 0) {
d->speed = IPMI_SOL_BIT_RATE_9600;
} else if (strcmp(pos, "19200") == 0) {
d->speed = IPMI_SOL_BIT_RATE_19200;
} else if (strcmp(pos, "38400") == 0) {
d->speed = IPMI_SOL_BIT_RATE_38400;
} else if (strcmp(pos, "57600") == 0) {
d->speed = IPMI_SOL_BIT_RATE_57600;
} else if (strcmp(pos, "115200") == 0) {
d->speed = IPMI_SOL_BIT_RATE_115200;
} else if (strcmp(pos, "-NOBREAK") == 0) {
d->disablebreak = 0;
} else if (strcmp(pos, "NOBREAK") == 0) {
d->disablebreak = 1;
} else if (strcmp(pos, "-authenticated") == 0) {
d->authenticated = 0;
} else if (strcmp(pos, "authenticated") == 0) {
d->authenticated = 1;
} else if (strcmp(pos, "-encrypted") == 0) {
d->encrypted = 0;
} else if (strcmp(pos, "encrypted") == 0) {
d->encrypted = 1;
} else if (strcmp(pos, "-deassert_CTS_DCD_DSR_on_connect") == 0) {
d->deassert_CTS_DCD_DSR_on_connect = 0;
} else if (strcmp(pos, "deassert_CTS_DCD_DSR_on_connect") == 0) {
d->deassert_CTS_DCD_DSR_on_connect = 1;
} else if (strcmp(pos, "shared_serial_alert_fail") == 0) {
d->shared_serial_alert_behavior = ipmi_sol_serial_alerts_fail;
} else if (strcmp(pos, "shared_serial_alert_deferred") == 0) {
d->shared_serial_alert_behavior = ipmi_sol_serial_alerts_deferred;
} else if (strcmp(pos, "shared_serial_alert_succeed") == 0) {
d->shared_serial_alert_behavior = ipmi_sol_serial_alerts_succeed;
} else if (strncmp(pos, "ack-timeout=", 12) == 0) {
d->ack_timeout = strtoul(pos + 12, &endpos, 10);
if (endpos == pos + 12 || *endpos != '\0') {
eout->out(eout, "Invalid number for ack-timeout: %s\n",
pos + 12);
goto out;
}
} else if (strncmp(pos, "ack-retries=", 12) == 0) {
d->ack_retries = strtoul(pos + 12, &endpos, 10);
if (endpos == pos + 12 || *endpos != '\0') {
eout->out(eout, "Invalid number for ack-retries: %s\n",
pos + 12);
goto out;
}
} else {
if (otherconfig(data, eout, pos) == -1)
goto out;
}
pos = strtok_r(NULL, " \t", &strtok_data);
}
out:
if (rv && args)
ipmi_free_args(args);
if (!rv) {
if (d->args)
ipmi_free_args(d->args);
d->args = args;
}
if (str)
free(str);
return rv;
}
static int
solcfg_reconfig(struct devio *io, struct absout *eout, const char *instr,
int (*otherconfig)(void *data, struct absout *eout,
const char *item),
void *data)
{
struct solcfg_data *d = io->my_data;
return solconfig(d, eout, instr, otherconfig, data);
}
static struct devio_f solcfg_io_f = {
.setup = solcfg_setup,
.shutdown = solcfg_shutdown,
.reconfig = solcfg_reconfig,
.read = solcfg_read,
.write = solcfg_write,
.read_handler_enable = solcfg_read_handler_enable,
.write_handler_enable = solcfg_write_handler_enable,
.except_handler_enable = solcfg_except_handler_enable,
.send_break = solcfg_send_break,
.get_modem_state = solcfg_get_modem_state,
.set_devcontrol = solcfg_set_devcontrol,
.show_devcontrol = solcfg_show_devcontrol,
.show_devcfg = solcfg_show_solcfg,
.baud_rate = solcfg_baud_rate,
.data_size = solcfg_data_size,
.parity = solcfg_parity,
.stop_size = solcfg_stop_size,
.control = solcfg_control,
.flow_control = solcfg_flow_control,
.flush = solcfg_flush,
.free = solcfg_free,
.serparm_to_str = solcfg_serparm_to_str
};
static void
sol_ipmi_log(os_handler_t *hnd, enum ipmi_log_type_e log_type,
const char *format, va_list ap)
{
int slevel = -1;
switch (log_type) {
case IPMI_LOG_INFO:
if (ser2net_debug_level > 0)
slevel = LOG_INFO;
break;
case IPMI_LOG_WARNING:
slevel = LOG_WARNING;
break;
case IPMI_LOG_SEVERE:
slevel = LOG_ERR;
break;
case IPMI_LOG_FATAL:
slevel = LOG_CRIT;
break;
case IPMI_LOG_ERR_INFO:
slevel = LOG_NOTICE;
break;
case IPMI_LOG_DEBUG:
case IPMI_LOG_DEBUG_START:
case IPMI_LOG_DEBUG_CONT:
case IPMI_LOG_DEBUG_END:
if (!ser2net_debug)
return;
slevel = LOG_DEBUG;
}
if (slevel < 0)
return;
switch (log_type) {
case IPMI_LOG_DEBUG_START:
case IPMI_LOG_DEBUG_CONT:
vfprintf(stderr, format, ap);
break;
case IPMI_LOG_DEBUG:
case IPMI_LOG_DEBUG_END:
vfprintf(stderr, format, ap);
fprintf(stderr, "\n");
break;
default:
vsyslog(slevel, format, ap);
}
}
int
sol_init(void)
{
#ifdef USE_PTHREADS
os_hnd = ipmi_posix_thread_get_os_handler2(ser2net_wake_sig);
#else
os_hnd = ipmi_posix_get_os_handler();
#endif
if (!os_hnd)
return -ENOMEM;
os_hnd->vlog = sol_ipmi_log;
#ifdef USE_PTHREADS
ipmi_posix_thread_os_handler_set_sel(os_hnd, ser2net_sel);
#else
ipmi_posix_os_handler_set_sel(os_hnd, ser2net_sel);
#endif
ipmi_init(os_hnd);
return 0;
}
void
sol_shutdown(void)
{
ipmi_shutdown();
os_hnd->free_os_handler(os_hnd);
}
int
solcfg_init(struct devio *io, struct absout *eout, const char *instr,
int (*otherconfig)(void *data, struct absout *eout,
const char *item),
void *data)
{
struct solcfg_data *d;
d = malloc(sizeof(*d));
if (!d)
return -1;
memset(d, 0, sizeof(*d));
io->my_data = d;
io->f = &solcfg_io_f;
d->io = io;
d->closed = 1;
if (solconfig(d, eout, instr, otherconfig, data) == -1) {
io->my_data = NULL;
io->f = NULL;
free(d);
return -1;
}
return 0;
}
#else
int
sol_init(void)
{
return 0;
}
int
solcfg_init(struct devio *io, struct absout *eout, const char *instr,
int (*otherconfig)(void *data, struct absout *eout,
const char *item),
void *data)
{
return -ENOSYS;
}
void
sol_shutdown(void)
{
}
#endif