/*                               -*- Mode: C -*- 
 * cw.h -- Include file for driver.
 * 
 * Author          : 
 * Created On      : Mon Feb  1 16:37:17 1999
 * Last Modified By: Peter Bosch
 * Last Modified On: Wed Oct  6 11:55:28 1999
 * Status          : Unknown, Use with caution!
 * 
 * Unless other notices are present in any part of this file
 * explicitly claiming copyrights for other people and/or 
 * organizations, the contents of this file is fully copyright 
 * (C) 1999 Peter Bosch, all rights reserved.
 * 
 */

#ifndef _CW_H
#define _CW_H

#include <linux/version.h>
#include <linux/modversions.h>

#ifndef K
#define K	1024
#endif
#ifndef M
#define M	(K * K)
#endif

#define NUMDP		       1024  /* Max. number of dynamic partitions */
#define DPSSIZE		       512   /* Minimum size of a block */
#define CW_BLKDEV_BLKSIZE      512   /* the blocksize of cw ;
				        shouldn't be larger than 4096*/
#define CWDRIVERNAME	"clockwise"


#define now	cw_now()
typedef unsigned long word_t;

typedef enum { Initializing, Running, Dying, Dead } dstat_t;
typedef enum { Waiting, Done } rstat_t;

typedef struct {
  uint32_t		mb_daddr;	/* Which DP block for meta block? */
  uint32_t		*mb_bm;		/* Bitmap of used meta blocks */
  int			mb_used;	/* Used number of blocks */
} mb_t;

struct _q_t;

typedef struct {
  uint8_t 		*io_buf;	/* Buffer pointer */
  size_t		io_size;	/* Number of bytes */
} iovec_t;
#define NUMIOVEC	2048

typedef struct {
  rstat_t		ud_state;	/* Completion state */
  int			ud_rv;		/* I/O status */
  void			(*ud_f)();	/* Completion function */
  struct request	*ud_req;	/* Request that caused the op. */
  struct wait_queue	*ud_wait;	/* Wait queue */
  iovec_t		*ud_iovec;	/* Simple IO vector for blk devices */
  rk_reserve_t          disk_rsv;       /* disk reservation */
} user_t;

#ifdef CONFIG_RK
/* 
 * Implement 2 level queue.
 * The First level list consists of NRT queues and RT link list, each
 * has RT queues which belongs to the same disk reserve.
 * We differentiate if the queue is NRT queue or RT link list by looking
 * at the flag q_type. It's a NRT queue if its type is q_data. 
 */
typedef enum { q_data, q_list} q_t_type;
typedef struct _q_t {
  struct _q_t 	*q_next;
  struct _q_t   *q_prev;
  q_t_type      q_type;     
  /* If it is q_data queue, this will be replaced 
   * by _q_t_data structure. Otherwise _q_t_list 
   * structure is assumed 
   */
} q_t;

typedef struct _q_t_data {
  struct _q_t   *q_next;
  struct _q_t   *q_prev;
  q_t_type      q_type;
  uint32_t		q_daddr;	/* Disk address */
  uint32_t		q_nbytes;	/* Number of bytes to transfer */
  uint32_t		q_ndone;	/* Number of bytes transferred */
  iovec_t		*q_iovec;	/* IO vector */
  int			q_numvec;	/* Number of entries */
  int			q_rw;		/* READ or WRITE */
  struct request	q_req;		/* ...and the request itself */
  struct buffer_head	*q_bh;		/* All buffer headers */
  struct wait_queue 	*q_wait;	/* Wait queue */
  rstat_t		q_state;	/* Completion state */
  user_t		*q_ud;		/* User data */
  Time_t		q_release;	/* Release time */
  Time_t		q_service;	/* Service time */
  Time_t		q_deadline;	/* Deadline */
  Time_t		q_actualstart;	/* Job's actual start time */
  Time_t		q_qtime;	/* Job's queue time */
  int			q_ooo;		/* Out-of-order scheduling */
  rk_reserve_t          disk_rsv;       /* disk reservation */
} q_t_data;

typedef struct _q_t_list {
  struct _q_t   *q_next;
  struct _q_t   *q_prev;
  q_t_type      q_type;
  rk_reserve_t          disk_rsv;       /* disk reservation */
  struct _q_t   *q_list_head;
  struct _q_t   *q_list_tail;
  unsigned long  q_num_members;          /* number of members in list */
} q_t_list;

#else 
typedef struct _q_t {
  struct _q_t		*q_next;	/* Next element */
  struct _q_t		*q_prev;	/* Previous element */
  uint32_t		q_daddr;	/* Disk address */
  uint32_t		q_nbytes;	/* Number of bytes to transfer */
  uint32_t		q_ndone;	/* Number of bytes transferred */
  iovec_t		*q_iovec;	/* IO vector */
  int			q_numvec;	/* Number of entries */
  int			q_rw;		/* READ or WRITE */
  struct request	q_req;		/* ...and the request itself */
  struct buffer_head	*q_bh;		/* All buffer headers */
  struct wait_queue 	*q_wait;	/* Wait queue */
  rstat_t		q_state;	/* Completion state */
  user_t		*q_ud;		/* User data */
  Time_t		q_release;	/* Release time */
  Time_t		q_service;	/* Service time */
  Time_t		q_deadline;	/* Deadline */
  Time_t		q_actualstart;	/* Job's actual start time */
  Time_t		q_qtime;	/* Job's queue time */
  int			q_ooo;		/* Out-of-order scheduling */
  rk_reserve_t          disk_rsv;       /* disk reservation */
} q_t;
#endif CONFIG_RK

#define NUMQ		512

typedef struct {
  Time_t		t_service;	/* Task service time */
  Time_t		t_period;	/* Task period */
  Time_t		t_srt;		/* Start real-time period */
  Time_t		t_ert;		/* End real-time period */
} task_t;

typedef struct {
  uint32_t		z_start;	/* Zone start address */
  uint32_t		z_spt;		/* Number of sectors per track */
  uint32_t		z_ntracks;	/* Number of tracks in zone */
  int			z_numrio;	/* Read I/O performance tab length */
  cwiotime_t		*z_rio;		/* Read I/O performance tab */
  int			z_numwio;	/* Write I/O performance tab length */
  cwiotime_t		*z_wio;		/* Write I/O performance tab */
} zone_t;
  
typedef struct {
  char			dt_name[CW_MAXDTYPE + 1];	/* Disk type */
  uint32_t		dt_nheads;	/* Number of heads */
  uint32_t		dt_ncyls;	/* Number of cylinders */
  int			dt_nzones;	/* Number of zones */
  zone_t		*dt_zones;	/* Zone information */
  int			dt_numse;	/* Seek performance table length */
  cwsetime_t		*dt_se;		/* Seek performance table */
  uint32_t		dt_rpm;		/* Rotations per minute */
  Time_t		dt_rotdelay;	/* Rotational delay */
} dtype_t;

typedef struct {
  Time_t 		dl_deltal;	/* The delta L value itself */
  Time_t		dl_stime;	/* Start time */
  Time_t		dl_etime;	/* End time */
} deltal_t;

typedef struct {
  kdev_t		di_pdevice;	/* Physical device ID */
  uint32_t		di_bsize;	/* Used block size */
  struct request	*di_reqs;	/* Queued requests */
  cwsb_t		di_sb;		/* Local copy of super block */
  dstat_t		di_stat;	/* Drive status */
  spinlock_t		di_bmlock;	/* Protect the bitmap */
  uint32_t		*di_bm;		/* Bitmap of allocated blocks */
  spinlock_t		di_metalock;	/* Protect the bitmap */
  int			di_nmb;		/* Number of meta blocks on disk */
  mb_t			*di_mb;		/* The meta-blocks themselves */
  q_t			*di_bef_f;	/* Best-effort queue */
  q_t			*di_bef_l;	/* Last element */
  q_t			*di_rt_f;	/* Real-time queue */
  q_t			*di_rt_l;	/* Last real-time queue */
  spinlock_t		di_qlock;	/* Queue lock */
  int			di_nqueued;	/* Number of queud requests */
  struct wait_queue	*di_qwait;	/* Wait queue */
  spinlock_t		di_tasklock;	/* To lock the task list */
  int			di_ntasks;	/* Number of admitted tasks */
  task_t		*di_tasks;	/* The tasks themselves */
  deltal_t		*di_dllist;	/* List of delta L's */
  int			di_ndllist;	/* Number of entries */
  Time_t		di_unusedl;	/* Unused delta l */
  Time_t		di_nextpoint;	/* Next scheduling point */
  dtype_t		*di_type;	/* Disk type */
  uint32_t		di_curcyl;	/* Current cylinder */
/* #define NUMSCATTER	256	*/	/* See ncr53c8xx.h */
#define NUMSCATTER      1               /* ide */
  int			di_scatter;	/* Max. scatter */
} perdisk_t;

typedef struct {
  int			it_nusers;		/* Number of users */
  cwdinode_t		*it_inode;		/* The inode itself */
} itab_t;

typedef enum { MetaBlock, DataBlock } block_t;

#define NUMFTABENTRIES	255
#define CW_TBSIZE	(128 * K)	/* Synch. transfer buffer size */

#define used(bm, block)	\
                         ((bm)[(block) / (sizeof(uint32_t) * 8)] |= \
                         (1 << ((block) % (sizeof(uint32_t) * 8))))
#define unused(bm, block) \
	                 ((bm)[(block) / (sizeof(uint32_t) * 8)] &= \
                         ~(1 << ((block) % (sizeof(uint32_t) * 8))))
#define isused(bm, block) \
                         ((bm)[(block) / (sizeof(uint32_t) * 8)] & \
                         (1 << ((block) % (sizeof(uint32_t) * 8))))

#ifndef boffs
#define boffs(a, b, c)	(((a) * (b)) / (c))
#endif
#ifndef nblocks
#define nblocks(a, b)	(((a) + (b) - 1) / (b))
#endif
#ifndef roundup
#define roundup(a, b)	(nblocks((a), (b)) * (b))
#endif

#define NUMASYNCH	10

typedef struct {
  uint32_t		u_dpnum;		/* Opened dynamic partition */
  uint32_t		u_oflags;		/* Open flags */
  struct {
    Time_t		up_period;		/* Job's period */
    Time_t		up_service;		/* Job's service time */
    Time_t		up_ldeadline;		/* Job's last deadline */
    Time_t		up_srt;			/* Start RT period */
    Time_t		up_ert;			/* End RT period */
    uint32_t		up_fb;			/* First RT block */
    uint32_t		up_nb;			/* Number RT blocks */
  } u_perdisk[NUMDISKS];
  struct {
    user_t		*us_ud;			/* Wait point */
    cwrelease_t		us_rel;			/* I/O request */
    Time_t		us_release;		/* Request release time */
  } u_asynch[NUMASYNCH];
} userstate_t;

#define USCALE 1000

#ifndef min
#define min(a, b)	(((a) < (b))? (a): (b))
#endif

#endif
