/*
 * Copyright (c) 2004 Sun Microsystems, Inc.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * Redistribution of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * Redistribution in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of
 * contributors may be used to endorse or promote products derived
 * from this software without specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind.
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 */

#ifndef FREEIPMI_BMC_INTF_H
#define FREEIPMI_BMC_INTF_H

/* achu: removing pragma for FreeIPMI */
#if 0
#pragma ident   "@(#)bmc_intf.h 1.2     05/03/07 SMI"
#endif

#ifdef __cplusplus
extern "C" {
#endif

#define BMC_SUCCESS             0x0
#define BMC_FAILURE             0x1

#define BMC_NETFN_CHASSIS               0x0
#define BMC_NETFN_BRIDGE                0x2
#define BMC_NETFN_SE                    0x4
#define BMC_NETFN_APP                   0x6
#define BMC_NETFN_FIRMWARE              0x8
#define BMC_NETFN_STORAGE               0xa
#define BMC_NETFN_TRANSPORT             0xc

#define SEND_MAX_PAYLOAD_SIZE           34      /* MAX payload */
#define RECV_MAX_PAYLOAD_SIZE           33      /* MAX payload */
#define BMC_MIN_RESPONSE_SIZE           3
#define BMC_MIN_REQUEST_SIZE            2
#define BMC_MAX_RESPONSE_SIZE   (BMC_MIN_RESPONSE_SIZE + RECV_MAX_PAYLOAD_SIZE)
#define BMC_MAX_REQUEST_SIZE    (BMC_MIN_REQUEST_SIZE + BMC_MAX_RESPONSE_SIZE)

#define BUF_SIZE 256
#define MAX_BUF_SIZE                    256

/*
 * Useful macros
 */
#define FORM_NETFNLUN(net, lun) ((((net) << 2) | ((lun) & 0x3)))
#define GET_NETFN(netfn)        (((netfn) >> 2) & 0x3f)
#define GET_LUN(netfn)          (netfn & 0x3)
#define RESP_NETFN(nflun)       ((nflun) | 1)
#define ISREQUEST(nl)           (((nl) & 1) == 0)       /* test for request */
#define ISRESPONSE(nl)          (((nl) & 1) == 1)       /* test for response */


/* for checking BMC specific stuff */
#define BMC_GET_DEVICE_ID               0x1     /* GET DEVICE ID COMMAND */
#define BMC_IPMI_15_VER         0x51    /* IPMI 1.5 definion */

/* BMC Completion Code and OEM Completion Code */
#define BMC_IPMI_UNSPECIFIC_ERROR       0xFF    /* Unspecific Error */
#define BMC_IPMI_INVALID_COMMAND        0xC1    /* Invalid Command */
#define BMC_IPMI_COMMAND_TIMEOUT        0xC3    /* Command Timeout */
#define BMC_IPMI_DATA_LENGTH_EXCEED     0xC8    /* DataLength exceeded limit */
#define BMC_IPMI_OEM_FAILURE_SENDBMC    0x7E    /* Cannot send BMC req */


#define IOCTL_IPMI_KCS_ACTION           0x01
#define IOCTL_IPMI_INTERFACE_METHOD     0x02

/* Interface methods returned from IOCTL_IPMI_INTERFACE_METHOD ioctl: */

#define BMC_IOCTL_METHOD                0       /* Not returned from ioctl, */
                                                /* but can be used by   */
                                                /* applications that want to */
                                                /* compare against an   */
                                                /* alternative method.  */
#define BMC_PUTMSG_METHOD               1

/*
 * bmc_req_t is the data structure to send
 * request packet from applications to the driver
 * module.
 *
 * the request pkt is mainly for KCS-interface-BMC
 * messages. Since the system interface is session-less
 * connections, the packet won't have any session
 * information.
 *
 * the data payload will be 2 bytes less than max
 * BMC supported packet size.
 * the address of the responder is always BMC and so
 * rsSa field is not required.
 */
typedef struct bmc_req {
        uint8_t fn;                     /* netFn for command */
        uint8_t lun;                    /* logical unit on responder */
        uint8_t cmd;                    /* command */
        uint8_t datalength;             /* length of following data */
        uint8_t data[SEND_MAX_PAYLOAD_SIZE]; /* request data */
} bmc_req_t;

/*
 * bmc_rsp_t is the data structure to send
 * respond packet from applications to the driver
 * module.
 *
 * the respond pkt is mainly for KCS-interface-BMC
 * messages. Since the system interface is session-less
 * connections, the packet won't have any session
 * information.
 *
 * the data payload will be 2 bytes less than max
 * BMC supported packet size.
 */
typedef struct bmc_rsp {
        uint8_t fn;                     /* netFn for command */
        uint8_t lun;                    /* logical unit on responder */
        uint8_t cmd;                    /* command */
        uint8_t ccode;                  /* completion code */
        uint8_t datalength;             /* Length */
        uint8_t data[RECV_MAX_PAYLOAD_SIZE]; /* response */
} bmc_rsp_t;

/*
 * the data structure for synchronous operation via ioctl (DEPRECATED)
 */
typedef struct bmc_reqrsp {
        bmc_req_t       req;                    /* request half */
        bmc_rsp_t       rsp;                    /* response half */
} bmc_reqrsp_t;


/*
 * The new way of communicating with the bmc driver is to use putmsg() to
 * send a message of a particular type.  Replies from the driver also have this
 * form, and will require the user to process the type field before examining
 * the rest of the reply.
 *
 * The only change that must be observed when using the request and response
 * structures defined above is as follows:
 * when sending messages to the bmc driver, the data portion is now variable
 * (the caller must allocate enough space to store the all structure members,
 * plus enough space to cover the amount of data in the request), e.g.:
 *
 * bmc_msg_t *msg = malloc(offsetof(bmc_msg_t, msg) + sizeof(bmc_req_t) + 10);
 *
 * The amount allocated for the message is (# of bytes before the msg field) +
 * the size of a bmc_req_t (which includes SEND_MAX_PAYLOAD_SIZE
 * bytes in the data field), plus an additional 10 bytes for the data
 * field (so the data field would occupy (SEND_MAX_PAYLOAD_SIZE + 10)
 * bytes).  The datalength member must reflect the amount of data in the
 * request's data field (as was required when using the ioctl interface).
 */
typedef struct bmc_msg {
        uint8_t         m_type;         /* Message type (see below) */
        uint32_t        m_id;           /* Message ID */
        uint8_t         reserved[32];
        uint8_t         msg[1];         /* Variable length message data */
} bmc_msg_t;


/*
 * An error response passed back from the bmc driver will have its m_id
 * field set to BMC_UNKNOWN_MSG_ID if a message is sent to it that is not
 * at least as large as a bmc_msg_t.
 */
#define BMC_UNKNOWN_MSG_ID      ~((uint32_t)0)


/*
 * Possible values for the m_type field in bmc_msg_t:
 */
#define BMC_MSG_REQUEST         1       /* BMC request (as above, sent to the */
                                        /* driver by the user), bmc_msg.msg */
                                        /* begins with the bmc_req_t    */
                                        /* structure.                   */
#define BMC_MSG_RESPONSE        2       /* BMC response (sent by the driver) */
                                        /* bmc_msg.msg begins with the  */
                                        /* bmc_rsp_t structure.         */
#define BMC_MSG_ERROR           3       /* Error while processing a user msg */
                                        /* msg[0] is the error code     */
                                        /* (interpret as an errno value) */

#ifdef  __cplusplus
}
#endif

#endif /* FREEIPMI_BMC_INTF_H */
