/*
 * nasd_ioqueue.h
 *
 * Structures for disk queues for NASD drive
 *
 * 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_IOQUEUE_H_
#define _NASD_IOQUEUE_H_

#include <nasd/nasd_options.h>
#include <nasd/nasd_security.h>
#include <nasd/nasd_threadstuff.h>
#include <nasd/nasd_od.h>
#include <nasd/nasd_sys.h>
#include <nasd/nasd_control.h>
#include <nasd/nasd_shutdown.h>
#include <nasd/nasd_cache.h>

typedef struct nasd_ioqueue_switch_s  nasd_ioqueue_switch_t;

/*
 * Init queue type
 */
typedef nasd_status_t (*nasd_ioq_init_func_t)(
  nasd_od_config_t  *config);

/*
 * Enqueues a list of blocks sorted by ascending block number.
 */
typedef nasd_status_t (*nasd_ioq_enq_sorted_func_t)(
  nasd_odc_ent_t  *entlist,
  int              dir,
  int              pri,
  char            *file,
  int              line);

/*
 * Enqueue a list of blocks unsorted.
 */
typedef nasd_status_t (*nasd_ioq_enq_func_t)(
  nasd_odc_ent_t  *entlist,
  int              dir,
  int              pri,
  char            *file,
  int              line);

/*
 * Dequeue the next logical I/O.
 */
typedef nasd_status_t (*nasd_ioq_deq_next_func_t)(
  nasd_odc_ent_t  **entlist,
  char             *file,
  int               line);

/*
 * Dequeue an entry pending I/O.
 */
typedef nasd_status_t (*nasd_ioq_deq_ent_func_t)(
  nasd_odc_ent_t  *ent,
  char            *file,
  int              line);

/*
 * If possible, raise the priority of an I/O.
 */
typedef nasd_status_t (*nasd_ioq_try_raise_pri_func_t)(
  nasd_odc_ent_t  *ent,
  int              newpri);

/*
 * Callback to queue that a synchronous I/O has launched.
 */
typedef nasd_status_t (*nasd_ioq_sync_launched_t)(
  nasd_sectno_t last_sector);

struct nasd_ioqueue_switch_s {
  nasd_ioqueue_type_t             ioq_type;
  char                           *ioq_name;
  nasd_ioq_init_func_t            ioq_init;
  nasd_ioq_enq_sorted_func_t      ioq_enq_sorted;
  nasd_ioq_enq_func_t             ioq_enq;
  nasd_ioq_deq_next_func_t        ioq_deq_next;
  nasd_ioq_deq_ent_func_t         ioq_deq_ent;
  nasd_ioq_try_raise_pri_func_t   ioq_try_raise_pri;
  nasd_ioq_sync_launched_t        ioq_sync_launched;
};

#define nasd_od_io_deq_next(_entlistp_,_io_lock_held_) \
  _nasd_od_io_deq_next(_entlistp_,_io_lock_held_,__FILE__,__LINE__)

NASD_DECLARE_EXTERN_MUTEX(nasd_od_io_lock)

#if NASD_IO_LOCK_DEBUG > 0
extern nasd_thread_id_t nasd_od_io_lock_holder;
extern int nasd_od_io_lock_try(void);

#define NASD_IO_LOCK() { \
  NASD_LOCK_MUTEX(nasd_od_io_lock); \
  NASD_ASSERT(nasd_od_io_lock_holder == NASD_THREAD_ID_NULL); \
  nasd_od_io_lock_holder = nasd_thread_self(); \
}

#define NASD_IO_UNLOCK() { \
  NASD_ASSERT(nasd_od_io_lock_holder == nasd_thread_self()); \
  nasd_od_io_lock_holder = NASD_THREAD_ID_NULL; \
  NASD_UNLOCK_MUTEX(nasd_od_io_lock); \
}

#define NASD_IO_LOCK_TRY() nasd_od_io_lock_try()

#define NASD_IO_LOCK_ASSERT_HELD() { \
  NASD_ASSERT(nasd_od_io_lock_holder == nasd_thread_self()); \
}

#define NASD_IO_LOCK_ASSERT_NOT_HELD() { \
  NASD_ASSERT(nasd_od_io_lock_holder == NASD_THREAD_ID_NULL); \
}

#else /* NASD_IO_LOCK_DEBUG > 0 */

#define NASD_IO_LOCK()                 NASD_LOCK_MUTEX(nasd_od_io_lock)
#define NASD_IO_LOCK_TRY()             NASD_TRY_LOCK_MUTEX(nasd_od_io_lock)
#define NASD_IO_UNLOCK()               NASD_UNLOCK_MUTEX(nasd_od_io_lock)
#define NASD_IO_LOCK_ASSERT_HELD() 
#define NASD_IO_LOCK_ASSERT_NOT_HELD() 

#endif /* NASD_IO_LOCK_DEBUG > 0 */

extern nasd_ctrl_ioqueue_stat_t nasd_drive_ioqueue_stats;

/*
 * Tunable parameters (nasd_drive_tunable.c)
 */
extern int nasd_drive_io_max_coalesce;
extern int nasd_drive_io_cluster_align;

/*
 * Declarations for individual queueing policies below here
 */

#if NASD_DRIVE_IOQUEUE_INCLUDE_FIFO > 0
extern nasd_status_t nasd_ioqueue_fifo_init(
  nasd_od_config_t  *config);
extern nasd_status_t nasd_ioqueue_fifo_enq_sorted(
  nasd_odc_ent_t  *entlist,
  int              dir,
  int              pri,
  char            *file,
  int              line);
extern nasd_status_t nasd_ioqueue_fifo_enq(
  nasd_odc_ent_t  *entlist,
  int              dir,
  int              pri,
  char            *file,
  int              line);
extern nasd_status_t nasd_ioqueue_fifo_deq_next(
  nasd_odc_ent_t  **entlist,
  char             *file,
  int               line);
extern nasd_status_t nasd_ioqueue_fifo_deq_ent(
  nasd_odc_ent_t  *ent,
  char            *file,
  int              line);
extern nasd_status_t nasd_ioqueue_fifo_try_raise_pri(
  nasd_odc_ent_t  *ent,
  int              newpri);
extern nasd_status_t nasd_ioqueue_fifo_sync_launched(
  nasd_sectno_t  sector);
#endif /* NASD_DRIVE_IOQUEUE_INCLUDE_FIFO > 0 */

#if NASD_DRIVE_IOQUEUE_INCLUDE_CSCAN > 0
extern nasd_status_t nasd_ioqueue_cscan_init(
  nasd_od_config_t  *config);
extern nasd_status_t nasd_ioqueue_cscan_enq_sorted(
  nasd_odc_ent_t  *entlist,
  int              dir,
  int              pri,
  char            *file,
  int              line);
extern nasd_status_t nasd_ioqueue_cscan_enq(
  nasd_odc_ent_t  *entlist,
  int              dir,
  int              pri,
  char            *file,
  int              line);
extern nasd_status_t nasd_ioqueue_cscan_deq_next(
  nasd_odc_ent_t  **entlist,
  char             *file,
  int               line);
extern nasd_status_t nasd_ioqueue_cscan_deq_ent(
  nasd_odc_ent_t  *ent,
  char            *file,
  int              line);
extern nasd_status_t nasd_ioqueue_cscan_try_raise_pri(
  nasd_odc_ent_t  *ent,
  int              newpri);
extern nasd_status_t nasd_ioqueue_cscan_sync_launched(
  nasd_sectno_t  sector);
#endif /* NASD_DRIVE_IOQUEUE_INCLUDE_CSCAN > 0 */

#endif /* !_NASD_IOQUEUE_H_ */

/* Local Variables:  */
/* indent-tabs-mode: nil */
/* tab-width: 2 */
/* End: */
