root/sys/cam/scsi/scsi_enc_internal.h
/*-
 * SPDX-License-Identifier: BSD-2-Clause
 *
 * Copyright (c) 2000 Matthew Jacob
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification, immediately at the beginning of the file.
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * This file contains definitions only intended for use within
 * sys/cam/scsi/scsi_enc*.c, and not in other kernel components.
 */

#ifndef __SCSI_ENC_INTERNAL_H__
#define __SCSI_ENC_INTERNAL_H__

#include <sys/sysctl.h>

typedef struct enc_element {
        u_int    elm_idx;               /* index of element */
        uint8_t  elm_type;              /* element type */
        uint8_t  subenclosure;          /* subenclosure id */
        uint8_t  type_elm_idx;          /* index of element within type */
        uint8_t  svalid;                /* enclosure information valid */
        uint8_t  encstat[4];            /* state && stats */
        u_int    physical_path_len;     /* Length of device path data. */
        uint8_t *physical_path;         /* Device physical path data. */
        void    *elm_private;           /* per-type object data */
        uint16_t priv;
} enc_element_t;

typedef enum {
        ENC_NONE,
        ENC_SES,
        ENC_SES_PASSTHROUGH,
        ENC_SAFT,
        ENC_SEMB_SES,
        ENC_SEMB_SAFT
} enctyp;

/* Platform Independent Driver Internal Definitions for enclosure devices. */
typedef struct enc_softc enc_softc_t;

struct enc_fsm_state;
typedef int fsm_fill_handler_t(enc_softc_t *ssc,
                                struct enc_fsm_state *state,
                                union ccb *ccb,
                                uint8_t *buf);
typedef int fsm_error_handler_t(union ccb *ccb, uint32_t cflags,
                                uint32_t sflags);
typedef int fsm_done_handler_t(enc_softc_t *ssc,
                               struct enc_fsm_state *state, union ccb *ccb,
                               uint8_t **bufp, int error, int xfer_len);

struct enc_fsm_state {
        const char          *name;
        int                  page_code;
        size_t               buf_size;
        uint32_t             timeout;
        fsm_fill_handler_t  *fill;
        fsm_done_handler_t  *done;
        fsm_error_handler_t *error;
};

typedef int (enc_softc_init_t)(enc_softc_t *);
typedef void (enc_softc_invalidate_t)(enc_softc_t *);
typedef void (enc_softc_cleanup_t)(enc_softc_t *);
typedef int (enc_init_enc_t)(enc_softc_t *); 
typedef int (enc_set_enc_status_t)(enc_softc_t *, encioc_enc_status_t, int);
typedef int (enc_get_elm_status_t)(enc_softc_t *, encioc_elm_status_t *, int);
typedef int (enc_set_elm_status_t)(enc_softc_t *, encioc_elm_status_t *, int);
typedef int (enc_get_elm_desc_t)(enc_softc_t *, encioc_elm_desc_t *); 
typedef int (enc_get_elm_devnames_t)(enc_softc_t *, encioc_elm_devnames_t *); 
typedef int (enc_handle_string_t)(enc_softc_t *, encioc_string_t *,
                                  unsigned long);
typedef void (enc_device_found_t)(enc_softc_t *);
typedef void (enc_poll_status_t)(enc_softc_t *);

struct enc_vec {
        enc_softc_invalidate_t  *softc_invalidate;
        enc_softc_cleanup_t     *softc_cleanup;
        enc_init_enc_t          *init_enc;
        enc_set_enc_status_t    *set_enc_status;
        enc_get_elm_status_t    *get_elm_status;
        enc_set_elm_status_t    *set_elm_status;
        enc_get_elm_desc_t      *get_elm_desc;
        enc_get_elm_devnames_t  *get_elm_devnames;
        enc_handle_string_t     *handle_string;
        enc_device_found_t      *device_found;
        enc_poll_status_t       *poll_status;
};

typedef struct enc_cache {
        enc_element_t           *elm_map;       /* objects */
        int                      nelms;         /* number of objects */
        encioc_enc_status_t      enc_status;    /* overall status */
        void                    *private;       /* per-type private data */
} enc_cache_t;

/* Enclosure instance toplevel structure */
struct enc_softc {
        enctyp                   enc_type;      /* type of enclosure */
        struct enc_vec           enc_vec;       /* vector to handlers */
        void                    *enc_private;   /* per-type private data */

        /**
         * "Published" configuration and state data available to
         * external consumers.
         */
        enc_cache_t              enc_cache;

        /**
         * Configuration and state data being actively updated
         * by the enclosure daemon.
         */
        enc_cache_t              enc_daemon_cache;

        struct sx                enc_cache_lock;
        uint8_t                  enc_flags;
#define ENC_FLAG_INVALID        0x01
#define ENC_FLAG_INITIALIZED    0x02
#define ENC_FLAG_SHUTDOWN       0x04
        struct cdev             *enc_dev;
        struct cam_periph       *periph;
        int                      open_count;

        /* Bitmap of pending operations. */
        uint32_t                 pending_actions;

        /* The action on which the state machine is currently working. */
        uint32_t                 current_action;
#define ENC_UPDATE_NONE         0x00
#define ENC_UPDATE_INVALID      0xff

        /* Callout for auto-updating enclosure status */
        struct callout           status_updater;

        struct proc             *enc_daemon;

        struct enc_fsm_state    *enc_fsm_states;

#define         ENC_ANNOUNCE_SZ         400
        char                    announce_buf[ENC_ANNOUNCE_SZ];
};

static inline enc_cache_t *
enc_other_cache(enc_softc_t *enc, enc_cache_t *primary)
{
        return (primary == &enc->enc_cache
              ? &enc->enc_daemon_cache : &enc->enc_cache);
}

/* SES Management mode page - SES2r20 Table 59 */
struct ses_mgmt_mode_page {
        struct scsi_mode_header_6 header;
        struct scsi_mode_blk_desc blk_desc;
        uint8_t byte0;  /* ps : 1, spf : 1, page_code : 6 */
#define SES_MGMT_MODE_PAGE_CODE 0x14
        uint8_t length;
#define SES_MGMT_MODE_PAGE_LEN  6
        uint8_t reserved[3];
        uint8_t byte5;  /* reserved : 7, enbltc : 1 */
#define SES_MGMT_TIMED_COMP_EN  0x1
        uint8_t max_comp_time[2];
};

/* Enclosure core interface for sub-drivers */
int  enc_runcmd(struct enc_softc *, char *, int, char *, int *);
void enc_log(struct enc_softc *, const char *, ...);
int  enc_error(union ccb *, uint32_t, uint32_t);
void enc_update_request(enc_softc_t *, uint32_t);

/* SES Native interface */
enc_softc_init_t        ses_softc_init;

/* SAF-TE interface */
enc_softc_init_t        safte_softc_init;

SYSCTL_DECL(_kern_cam_enc);
extern int enc_verbose;

/* Helper macros */
MALLOC_DECLARE(M_SCSIENC);
#define ENC_CFLAGS              CAM_RETRY_SELTO
#define ENC_FLAGS               SF_NO_PRINT | SF_RETRY_UA
#define STRNCMP                 strncmp
#define PRINTF                  printf
#define ENC_LOG                 enc_log
#if defined(DEBUG) || defined(ENC_DEBUG)
#define ENC_DLOG                enc_log
#else
#define ENC_DLOG                if (0) enc_log
#endif
#define ENC_VLOG                if (enc_verbose) enc_log
#define ENC_MALLOC(amt)         malloc(amt, M_SCSIENC, M_NOWAIT)
#define ENC_MALLOCZ(amt)        malloc(amt, M_SCSIENC, M_ZERO|M_NOWAIT)
/* Cast away const avoiding GCC warnings. */
#define ENC_FREE(ptr)           free((void *)((uintptr_t)ptr), M_SCSIENC)
#define ENC_FREE_AND_NULL(ptr)  do {    \
        if (ptr != NULL) {              \
                ENC_FREE(ptr);          \
                ptr = NULL;             \
        }                               \
} while(0)
#define MEMZERO                 bzero
#define MEMCPY(dest, src, amt)  bcopy(src, dest, amt)

#endif  /* __SCSI_ENC_INTERNAL_H__ */