/*
 * nasd_drive_io.h
 *
 * common definitions for drive I/O subsystems
 *
 * Author: Jim Zelenka
 */
/*
 * Copyright (c) of Carnegie Mellon University, 1998,1999.
 *
 * Permission to reproduce, use, and prepare derivative works of
 * this software for internal use is granted provided the copyright
 * and "No Warranty" statements are included with all reproductions
 * and derivative works. This software may also be redistributed
 * without charge provided that the copyright and "No Warranty"
 * statements are included in all redistributions.
 *
 * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS.
 * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED
 * TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY
 * OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE
 * MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT
 * TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
 */


#ifndef _NASD__NASD_DRIVE_IO_H_
#define _NASD__NASD_DRIVE_IO_H_

#include <nasd/nasd_options.h>
#include <nasd/nasd_drive_options.h>
#include <nasd/nasd_timer.h>

#define NASD_IO_ASSERT_DIR(_dir_) \
  NASD_ASSERT(((_dir_) == NASD_U_READ) || ((_dir_) == NASD_U_WRITE))

#define NASD_IO_ASSERT_PRI(_pri_) \
  NASD_ASSERT(((_pri_) >= 0) && ((_pri_) < NASD_IO_PRI_NUM))


#if NASD_IO_KEEP_STATS > 0
#define NASD_IO_INC_STAT(_s_) { \
  NASD_ATOMIC_INC64(&nasd_drive_io_stats._s_); \
}
#define NASD_IO_INC_IO_STAT(_s_,_rw_) { \
  NASD_ATOMIC_INC64(&nasd_drive_io_stats.num_io_##_rw_##s); \
  NASD_ATOMIC_INC64(&nasd_drive_io_stats._s_); \
}
#define NASD_IO_INC_SIZE_STAT(_nblocks_,_rw_) { \
  if ((_nblocks_) < NASD_CTRL_IO_SIZEBUCKETS) { \
    NASD_ATOMIC_INC64(&nasd_drive_io_##_rw_##_size_stats.io_sizes[_nblocks_]); \
  } \
  else { \
    NASD_ATOMIC_INC64(&nasd_drive_io_##_rw_##_size_stats.io_sizes[NASD_CTRL_IO_SIZEBUCKETS-1]); \
  } \
}
#else /* NASD_IO_KEEP_STATS > 0 */
#define NASD_IO_INC_STAT(_s_)
#define NASD_IO_INC_IO_STAT(_s_,_rw_)
#define NASD_IO_INC_SIZE_STAT(_s_,_rw_)
#endif /* NASD_IO_KEEP_STATS > 0 */

#define NASD_DIRSTRING(_dir_) (((_dir_) == NASD_U_READ) ? "read":"write")

#define NASD_IO_MODULE_INIT() { \
  bzero((char *)&nasd_drive_io_stats, sizeof(nasd_drive_io_stats)); \
  nasd_drive_io_stats.ctrl_id = NASD_CTRL_DRIVE_INFO; \
  bzero((char *)&nasd_drive_io_read_size_stats, sizeof(nasd_drive_io_read_size_stats)); \
  bzero((char *)&nasd_drive_io_write_size_stats, sizeof(nasd_drive_io_write_size_stats)); \
  nasd_drive_io_read_size_stats.ctrl_id = NASD_CTRL_DRIVE_INFO; \
  nasd_drive_io_write_size_stats.ctrl_id = NASD_CTRL_DRIVE_INFO; \
  nasd_od_io_ios_outstanding = 0; \
  nasd_od_io_last_completed_sect = 0; \
}

#if NASD_DRIVE_IO_MODULE > 0
nasd_ctrl_io_stat_t       nasd_drive_io_stats;
nasd_ctrl_io_size_stat_t  nasd_drive_io_read_size_stats;
nasd_ctrl_io_size_stat_t  nasd_drive_io_write_size_stats;
#else /* NASD_DRIVE_IO_MODULE > 0 */
extern nasd_ctrl_io_stat_t       nasd_drive_io_stats;
extern nasd_ctrl_io_size_stat_t  nasd_drive_io_read_size_stats;
extern nasd_ctrl_io_size_stat_t  nasd_drive_io_write_size_stats;
#endif /* NASD_DRIVE_IO_MODULE > 0 */

#if NASD_IO_TIMERS > 0
#define NASD_IO_TM_ENQ(_l_) { \
  NASD_ATOMIC_INC64(&nasd_drive_io_stats.io_blocks_enqueued); \
  NASD_TM_START(&(_l_)->io_subsys_timer); \
}
#define NASD_IO_TM_LAUNCH(_l_) { \
  NASD_ATOMIC_INC64(&nasd_drive_io_stats.io_blocks_launched); \
  NASD_TM_START(&(_l_)->io_outstanding_timer); \
}
#define NASD_IO_TM_COMPLETE(_l_) { \
  nasd_timespec_t _ts; \
  NASD_TM_STOP(&(_l_)->io_outstanding_timer); \
  NASD_TM_ELAPSED_TS(&(_l_)->io_outstanding_timer, &_ts); \
  NASD_ATOMIC_TIMESPEC_ADD(&nasd_drive_io_stats.io_outstanding_time, &_ts); \
  NASD_ATOMIC_INC64(&nasd_drive_io_stats.io_blocks_finished); \
}
#define NASD_IO_TM_DONE(_l_) { \
  nasd_timespec_t _ts; \
  NASD_TM_STOP(&(_l_)->io_subsys_timer); \
  NASD_TM_ELAPSED_TS(&(_l_)->io_subsys_timer, &_ts); \
  NASD_ATOMIC_TIMESPEC_ADD(&nasd_drive_io_stats.io_subsys_time, &_ts); \
  NASD_ATOMIC_INC64(&nasd_drive_io_stats.io_completion_count); \
}
#else /* NASD_IO_TIMERS > 0 */
#define NASD_IO_TM_ENQ(_l_)
#define NASD_IO_TM_LAUNCH(_l_)
#define NASD_IO_TM_COMPLETE(_l_)
#define NASD_IO_TM_DONE(_l_)
#endif /* NASD_IO_TIMERS > 0 */

#endif /* !_NASD__NASD_DRIVE_IO_H_ */
