root/usr/src/uts/common/io/comstar/lu/stmf_sbd/ats_copy_mgr.h
/*
 * This file and its contents are supplied under the terms of the
 * Common Development and Distribution License ("CDDL"), version 1.0.
 * You may only use this file in accordance with the terms of version
 * 1.0 of the CDDL.
 *
 * A full copy of the text of the CDDL should have accompanied this
 * source.  A copy of the CDDL is also available via the Internet at
 * http://www.illumos.org/license/CDDL.
 */

/*
 * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
 */

#ifndef _ATS_COPY_MGR_H
#define _ATS_COPY_MGR_H

#ifdef  __cplusplus
extern "C" {
#endif

/* ATS structures and functions. */

typedef struct ats_state_s {
        /*
         * We actually dont allow I/O which conflicts with current ats.
         * The conflicting_rw_count is for those I/Os which are currently
         * running and are potentally conflicting.
         */
        list_node_t     as_next;
        uint8_t         as_cmd;
        uint32_t        as_conflicting_rw_count;
        uint32_t        as_non_conflicting_rw_count;
        uint32_t        as_ats_gen_ndx;
        uint32_t        as_cur_ats_handle;
        uint64_t        as_cur_ats_lba;
        uint64_t        as_cur_ats_lba_end;
        uint64_t        as_cur_ats_len;         /* in nblks */
        struct scsi_task *as_cur_ats_task;
} ats_state_t;

/* Since we're technically part of stmf_sbd.h, use some defines here. */
#define sl_conflicting_rw_count sl_ats_state.as_conflicting_rw_count
#define sl_non_conflicting_rw_count sl_ats_state.as_non_conflicting_rw_count
#define sl_ats_gen_ndx sl_ats_state.as_ats_gen_ndx
#define sl_cur_ats_handle sl_ats_state.as_cur_ats_handle
#define sl_cur_ats_lba sl_ats_state.as_cur_ats_lba
#define sl_cur_ats_len sl_ats_state.as_cur_ats_len
#define sl_cur_ats_task sl_ats_state.as_cur_ats_task

struct sbd_cmd;
struct sbd_lu;

void sbd_handle_ats_xfer_completion(struct scsi_task *, struct sbd_cmd *,
    struct stmf_data_buf *, uint8_t);
void sbd_do_ats_xfer(struct scsi_task *, struct sbd_cmd *,
    struct stmf_data_buf *, uint8_t);
void sbd_handle_ats(scsi_task_t *, struct stmf_data_buf *);
void sbd_handle_recv_copy_results(struct scsi_task *, struct stmf_data_buf *);
void sbd_free_ats_handle(struct scsi_task *, struct sbd_cmd *);
void sbd_handle_ats(scsi_task_t *, struct stmf_data_buf *);
uint8_t sbd_ats_max_nblks(void);
void sbd_ats_remove_by_task(scsi_task_t *);
sbd_status_t sbd_ats_handling_before_io(scsi_task_t *task, struct sbd_lu *sl,
    uint64_t lba, uint64_t count);

/* Block-copy structures and functions. */

struct scsi_task;
typedef void *cpmgr_handle_t;

#define CPMGR_INVALID_HANDLE            ((cpmgr_handle_t)NULL)

#define CPMGR_DEFAULT_TIMEOUT           30

#define CPMGR_PARAM_HDR_LEN             16
#define CPMGR_IDENT_TARGET_DESCRIPTOR   0xE4
#define CPMGR_MAX_TARGET_DESCRIPTORS    2
#define CPMGR_TARGET_DESCRIPTOR_SIZE    32

#define CPMGR_B2B_SEGMENT_DESCRIPTOR            2
#define CPMGR_MAX_SEGMENT_DESCRIPTORS           1
#define CPMGR_B2B_SEGMENT_DESCRIPTOR_SIZE       28

/*
 * SCSI errors before copy starts.
 */
#define CPMGR_PARAM_LIST_LEN_ERROR              0x051A00
#define CPMGR_INVALID_FIELD_IN_PARAM_LIST       0x052600
#define CPMGR_TOO_MANY_TARGET_DESCRIPTORS       0x052606
#define CPMGR_UNSUPPORTED_TARGET_DESCRIPTOR     0x052607
#define CPMGR_TOO_MANY_SEGMENT_DESCRIPTORS      0x052608
#define CPMGR_UNSUPPORTED_SEGMENT_DESCRIPTOR    0x052609
#define CPMGR_COPY_TARGET_NOT_REACHABLE         0x050D02
#define CPMGR_INSUFFICIENT_RESOURCES            0x0B5503

/*
 * SCSI errors after copy has started.
 */
#define CPMGR_LBA_OUT_OF_RANGE                  0x0A2100
#define CPMGR_THIRD_PARTY_DEVICE_FAILURE        0x0A0D01

/*
 * SCSI errors which dont result in STATUS_CHECK.
 * Use and invalid sense key to mark these.
 */
#define CPMGR_RESERVATION_CONFLICT              0xF00001

typedef enum cm_state {
        CM_STARTING = 0,
        CM_COPYING,
        CM_COMPLETE
} cm_state_t;

#define CPMGR_XFER_BUF_SIZE             (128 * 1024)

typedef struct cm_target_desc {
        stmf_lu_t       *td_lu;
        uint32_t        td_disk_block_len;
        uint8_t         td_lbasize_shift;
} cm_target_desc_t;

/*
 * Current implementation supports 2 target descriptors (identification type)
 * for src and dst and one segment descriptor (block -> block).
 */
typedef struct cpmgr {
        cm_target_desc_t        cm_tds[CPMGR_MAX_TARGET_DESCRIPTORS];
        uint8_t                 cm_td_count;
        uint16_t                cm_src_td_ndx;
        uint16_t                cm_dst_td_ndx;
        cm_state_t              cm_state;
        uint32_t                cm_status;
        uint64_t                cm_src_offset;
        uint64_t                cm_dst_offset;
        uint64_t                cm_copy_size;
        uint64_t                cm_size_done;
        void                    *cm_xfer_buf;
        scsi_task_t             *cm_task;
} cpmgr_t;

#define cpmgr_done(cm)  (((cpmgr_t *)(cm))->cm_state == CM_COMPLETE)
#define cpmgr_status(cm) (((cpmgr_t *)(cm))->cm_status)

cpmgr_handle_t cpmgr_create(struct scsi_task *task, uint8_t *params);
void cpmgr_destroy(cpmgr_handle_t h);
void cpmgr_run(cpmgr_t *cm, clock_t preemption_point);
void cpmgr_abort(cpmgr_t *cm, uint32_t s);
void sbd_handle_xcopy_xfer(scsi_task_t *, uint8_t *);
void sbd_handle_xcopy(scsi_task_t *, stmf_data_buf_t *);

#ifdef  __cplusplus
}
#endif

#endif /* _ATS_COPY_MGR_H */