/*
 * _sio_internal.h
 *
 * SIO Internal Stuff
 *
 * Authors: Khalil Amiri, CMU SCS/ECE, July 18 1997
 *          Sean Levy, CMU SCS, July 1999
 */
/*
 * Copyright (c) of Carnegie Mellon University, 1996,1997,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.
 */

#include <nasd/nasd_options.h>
#include <nasd/nasd_common.h>
#include <nasd/nasd_threadstuff.h>
#include <nasd/nasd_cheops_client.h>
#include <sio_fs.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <_sio_queue.h>

struct _sio_iodesc;
struct _sio_fdesc;

/*
 * "Mount points:" the actual file system operations which manage storage
 * and I/O.
 */

struct _sio_mntpoint {
  TAILQ_ENTRY(_sio_mntpoint) mnt_link;

  void *mnt_cookie;
  char *mnt_name;

  /* operations on not-necessarily-open files */
  sio_return_t (*mnt_createtest) (void *, sio_control_t *, sio_count_t,
				  int *);
  sio_return_t (*mnt_create) (void *, sio_control_t *, sio_count_t,
			      char *, int);
  sio_return_t (*mnt_open) (void *, const char *, sio_mode_t,
			    sio_control_t *, sio_count_t, void **);
  sio_return_t (*mnt_test) (void *, const char *, sio_mode_t,
			    sio_control_t *, sio_count_t);
  sio_return_t (*mnt_unlink) (void *, const char *);

  /* open-file operations */
  sio_return_t (*mnt_control) (void *, sio_control_t *, sio_count_t);
  sio_return_t (*mnt_close) (void *);
  void	 (*mnt_doio) (void *, struct _sio_iodesc *);
};

/* read-only after initialization */
TAILQ_HEAD(_sio_mntpoint_list, _sio_mntpoint);
extern struct _sio_mntpoint_list _sio_mntpoint_list;


/*
 * Reference-counted objects.
 *
 * 'create' creates a reference-counted object, giving it a reference
 * count of 1.  The given size must be at least sizeof (struct _sio_rcobject).
 *
 * 'destroy' destroys a reference-counted object (only if
 * reference count is one.
 *
 * 'ref' adds a reference to a reference-counted object.
 *
 * 'unref' removes a reference from a reference-counted object.
 *
 * 'refcount' gets the reference count of a reference-counted object.
 */

struct _sio_rcobj {		/* reference-counted object */
  NASD_DECLARE_MUTEX(rco_mutex)
  unsigned int	rco_refcnt;
  NASD_DECLARE_COND(rco_refcnt_cond)
};

void		*_sio_rcobj_create(size_t size);
void		_sio_rcobj_destroy(void *objv);
void		_sio_rcobj_ref(void *objv);
void		_sio_rcobj_unref(void *objv);
unsigned int	_sio_rcobj_refcnt(void *objv);
void		_sio_rcobj_waitrefcnt(void *objv, unsigned int refcnt);


/*
 * Externally-represented objects.
 *
 * All externally-represented objects are reference-counted, and
 * can be manipulated with the _sio_rcobj_* functions.
 *
 * Objects are represented externally as integers, the top four bits of
 * which are a value unique to the particular object type, and the bottom
 * bits of which are unique among all externally-registered objects of that
 * type.
 *
 * 'create' and 'destroy' create and destroy external representation tables.
 * 'create' takes the unique value for the object type the table will be
 * describing and the number of objects expected to be in the table.
 * A table may be destroyed only when it contains no registered objects.
 *
 * 'register' and 'unregister' register and unregister objects for external
 * use.  'register' increments the object's reference count, and 'unregister'
 * decrements it.
 *
 * 'externalize' and 'internalize' transform an internal object representation
 * to its external representation, and vice versa.  'externalize' decrements
 * the object's reference count, and 'internalize' increments it.
 */

#define	_SIO_EXTREP_USIZE	4
#define	_SIO_EXTREP_USHIFT	((CHAR_BIT * sizeof(int)) - _SIO_EXTREP_USIZE)
#define _SIO_EXTREP_UNIQ(ext)	((ext) >> _SIO_EXTREP_USHIFT)

void	*_sio_exttable_create(unsigned int tableuniq, unsigned int expected);
void	_sio_exttable_destroy(void *table);
void	_sio_exttable_register(void *table, void *obj);
void	_sio_exttable_unregister(void *table, void *obj);
int	_sio_exttable_externalize(void *table, void *datum);
void	*_sio_exttable_internalize(void *table, int extrep);

#define	_SIO_EXTTABLE_DUMMY_UNIQ	0		/* reserved */
#define	_SIO_EXTTABLE_FILEDESC_UNIQ	1
#define	_SIO_EXTTABLE_ASYNCHANDLE_UNIQ	2


/*
 * File descriptors
 */

struct _sio_fdesc {
  struct _sio_rcobj	fd_rcobj;

  struct _sio_mntpoint 	*fd_mp;
  void			*fd_mp_cookie;
};

struct _sio_fdesc *_sio_fdesc_create(struct _sio_mntpoint *mp, void *cookie);
void	_sio_fdesc_destroy(struct _sio_fdesc *fdesc);


/*
 * Internal I/O descriptions XXX
 */

struct _sio_iodesc {
  /* control information */
  struct _sio_rcobj	iod_rcobj;
  int			iod_flags;

  /* status information */
  sio_transfer_len_t	iod_transferlen;
  sio_return_t		iod_result;

	/* file descriptor */
  struct _sio_fdesc	*iod_fdesc;

  /* i/o description */
  const sio_file_io_list_t *iod_fl;
  sio_count_t		iod_fllen;
  const sio_mem_io_list_t	*iod_ml;
  sio_count_t		iod_mllen;
};

#define	_SIO_IOD_READ		0x01
#define	_SIO_IOD_WRITE		0x02
#define	_SIO_IOD_STATUSWAIT	0x04
#define	_SIO_IOD_GOINGAWAY	0x08
#define	_SIO_IOD_DONE		0x10
#define	_SIO_IOD_CANCELED	0x20

sio_return_t _sio_iodesc_create(struct _sio_fdesc *, int,
	    const sio_file_io_list_t *fl, sio_count_t fllen,
	    const sio_mem_io_list_t *ml, sio_count_t mllen,
	    struct _sio_iodesc **iodescp);
void	_sio_iodesc_doio(nasd_threadarg_t);
void	_sio_iodesc_collect_status(struct _sio_iodesc *iodesc,
	    sio_transfer_len_t *transferlenp, sio_return_t *resultp);
void	_sio_iodesc_destroy(struct _sio_iodesc *iodesc);

/*
 * Utility routines.
 *
 * _sio_warning() prints a warning message to stderr.
 * _sio_panic() prints a warning message to stderr and aborts.
 */

void	_sio_warning(const char *fmt, ...);
void	_sio_panic(const char *fmt, ...);
void	_sio_init(void);


/*
 * Global variables
 */

void		*_sio_exttable_fdescs, *_sio_exttable_asynchandles;
NASD_DECLARE_MUTEX(_sio_async_io_count_mutex);
unsigned int	_sio_async_io_count;


/*
 * Hacks. XXX
 */

struct _sio_mntpoint *_sio_mnt_unixpath_init(const char *, const char *);
struct _sio_mntpoint *_sio_mnt_nasdpath_init(const char *, const char *);









