/*
 * Copyright (c) 1999 Kungliga Tekniska Högskolan
 * (Royal Institute of Technology, Stockholm, Sweden).
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by the Kungliga Tekniska
 *      Högskolan and its contributors.
 * 
 * 4. Neither the name of the Institute nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef _XFS_XFS_LOCL_H
#define _XFS_XFS_LOCL_H

#include <stdio.h>
#include <ntddk.h>
#include <ntifs.h>
#include <stdarg.h>

#include <xfs_type.h>
#include <xfs/xfs_message.h>
#include <xfs_deb.h>

struct XFS_VCB;
struct xfs_node;
struct XFS_CCB;

/* try-finally simulation */
#define try_return(S)	{ S; goto try_exit; }
#define try_return1(S)	{ S; goto try_exit1; }
#define try_return2(S)	{ S; goto try_exit2; }

#define XFS_DEV_DATA_MAGIC	0x4711C00E

#define XFS_SETFLAGS(v,f) ((v) |= (f))
#define XFS_RESETFLAGS(v,f) ((v) &= ~(f))
#define XFS_TESTFLAGS(v,f) (((v) & (f)) == (f))

/*
 *
 */

struct xfs_link {
    u_int32_t		sequence_num;
    int			flags;
#define	XFS_LINK_NOT_FROM_ZONE				(0x00000001)
    KEVENT		event;
    struct xfs_link 	*next;
    struct xfs_link 	*prev;
    struct xfs_message_header *message;
    u_int 		error_or_size; /* error on sleepq and size on */
};

/*
 * CCB structure for XFS
 */

typedef struct XFS_CCB {
    LIST_ENTRY	    NextCCB;		/* Link of CCB's */
    struct xfs_node *node;		/* pointer to xfs_node */
    PFILE_OBJECT    FileObject;	        /* File Object */
    u_int32_t	    ByteOffset;		/* Offset when in directory searches */
    PSTRING	    SearchPattern;	/* Save search pattern i dir searches */
    u_int32_t	    Time;		/* User time */
    u_int32_t	    flags;
} XFS_CCB;

#define	XFS_CCB_OPENED_FOR_SYNC_ACCESS			(0x00000002)
#define	XFS_CCB_OPENED_FOR_SEQ_ACCESS			(0x00000004)
#define	XFS_CCB_CLEANED					(0x00000008)
#define	XFS_CCB_ACCESSED				(0x00000010)
#define	XFS_CCB_MODIFIED				(0x00000020)
#define	XFS_CCB_ACCESS_TIME_SET				(0x00000040)
#define	XFS_CCB_MODIFY_TIME_SET				(0x00000080)
#define	XFS_CCB_CREATE_TIME_SET				(0x00000100)

#define	XFS_CCB_NOT_FROM_ZONE				(0x80000000)

#define	XFS_CCB_VOLUME_OPEN				(0x00000100)

/*
 * The xfs_node is really a FCB
 */

struct xfs_node {
    FSRTL_COMMON_FCB_HEADER fcb;	/* fcb */

    struct xfs_channel *chan;

    struct xfs_node *next;		/* next node on this device */
    struct xfs_node *prev;		/* prev node on this device */

    u_int32_t	    HoldCount;		/* xfs internal refcount */
    u_int32_t       ReferenceCount;	/* -- on IRP_MJ_CLOSE free when == 0 */
    u_int32_t	    OpenHandleCount;	/* -- on IRP_MJ_CLEANUP */
    u_int32_t	    flags;		/* the state of the node */
    
    struct xfs_attr attr;		/* XXX attr */

    u_int32_t	    tokens;		/* tokens */

    xfs_pag_t 	    id[MAXRIGHTS];
    u_char	    rights[MAXRIGHTS];
    u_char          anonrights;    

    xfs_handle 	    handle;
    FILE_OBJECT	    *data;		/* pointer to cache node */
    
    XFS_CCB	    *ccb;    

} XFS_FCB;

#define XFS_FCB_IN_INIT			(0x00000001)
#define	XFS_FCB_IN_TEARDOWN		(0x00000002)
#define	XFS_FCB_PAGE_FILE		(0x00000004)
#define	XFS_FCB_DIRECTORY		(0x00000008)
#define	XFS_FCB_ROOT_DIRECTORY		(0x00000018)
#define	XFS_FCB_WRITE_THROUGH		(0x00000020)
#define	XFS_FCB_MAPPED			(0x00000040)
#define	XFS_FCB_FAST_IO_READ_IN_PROGESS	(0x00000080)
#define	XFS_FCB_FAST_IO_WRITE_IN_PROGESS	(0x00000100)
#define	XFS_FCB_DELETE_ON_CLOSE		(0x00000200)
#define	XFS_FCB_MODIFIED		(0x00000400)
#define	XFS_FCB_ACCESSED		(0x00000800)
#define	XFS_FCB_READ_ONLY		(0x00001000)
#define	XFS_INITIALIZED_MAIN_RESOURCE	(0x00002000)
#define	XFS_INITIALIZED_PAGING_IO_RESOURCE	(0x00004000)
#define	XFS_FCB_NOT_FROM_ZONE		(0x80000000)

#define XFS_VALID_DATAHANDLE(n) ((n)->data != NULL)

#define DATA_FROM_XNODE(t) (t)->data 

/*
 *
 */

struct xfs_channel {
    int32_t		magic;		/* magic */
    ERESOURCE		GlobalLock;	/* global lock */
    PDRIVER_OBJECT	DriverObject;	/* created by I/O mgr*/
    PDEVICE_OBJECT	DeviceObject;	/* to be able to do IOCTL*/
    CACHE_MANAGER_CALLBACKS CacheMgrCallBacks; /* for callbacks fr. cachemgr */
    u_int32_t		flags;		/* varius flags */
#define XFSCHAN_FLAGS_GLOBALLOCK 	0x01
#define XFSCHAN_FLAGS_OPEN		0x02
#define XFSCHAN_CHANNEL_WAITING		0x04

    /*
     *
     */

    int			init_event;
    int 		pending_count;
    KEVENT		pending_event;

    u_int32_t		nsequence;

    KSEMAPHORE		message_sem;
    struct xfs_link	messageq;
    
    KSEMAPHORE		sleep_sem;
    struct xfs_link	sleepq;

    /*
     * xfs_nodes
     */

    struct xfs_node	*root;
    struct xfs_node	nodes;
    KSPIN_LOCK		NodeListSpinLock;

    /*
     * Zones for memory allocation.
     */

    KSPIN_LOCK		ZoneAllocationSpinLock;
    ZONE_HEADER		CCBZoneHeader;
    void		*CCBZone;
    ZONE_HEADER		NodeZoneHeader;
    void		*NodeZone;
    ZONE_HEADER		LinkZoneHeader;
    void		*LinkZone;

    /* XXX FastIOPath and some other junk here */

};

extern struct xfs_channel XFSGlobalData;	/* global data for xfs driver */

/*
 *
 */

typedef struct XFS_VCB {
    ERESOURCE		VCBResource;
    LIST_ENTRY		NextVCB;
    VPB			*VPB;
    u_int32_t		flags;
    u_int32_t		OpenCount;
    LIST_ENTRY		NextFCB;	/* All FCB on the VCB */ 
    PDEVICE_OBJECT	devObj;		/* the device we are  */
    PDEVICE_OBJECT	target_devObj;	/* device we are mounted on */
    u_int8_t		VolumePath;	/* The driverletter we are on */

    /* Supposely used by CM */
    LARGE_INTEGER	AllocationSize;
    LARGE_INTEGER	FileSize;
    LARGE_INTEGER	ValidDataLength;
} XFS_VCB;

#define	XFS_VCB_FLAGS_VOLUME_MOUNTED	(0x00000001)
#define	XFS_VCB_FLAGS_VOLUME_LOCKED	(0x00000002)
#define	XFS_VCB_FLAGS_BEING_DISMOUNTED	(0x00000004)
#define	XFS_VCB_FLAGS_SHUTDOWN		(0x00000008)
#define	XFS_VCB_FLAGS_VOLUME_READ_ONLY	(0x00000010)
#define	XFS_VCB_FLAGS_VCB_INITIALIZED	(0x00000020)


#define XFS_PANIC_IDENTIFIER 0x47111147

#define	XFSPanic(arg1, arg2, arg3)					\
	(KeBugCheckEx(XFS_PANIC_IDENTIFIER, __LINE__, 			\
        (u_int32_t)(arg1), (u_int32_t)(arg2), (u_int32_t)(arg3)))


#include <xfs_proto.h>
#include <xfs_ioctl.h>
#include <xfs_dev.h>
#include <xfs_node.h>
#include <xfs_dnlc.h>

#define bcopy(s,d,l)	memcpy((d),(s),(l))
#define bzero(d,l)	memset((d),0,(l))

#endif /* _XFS_XFS_LOCL_H */
