/*
 * include/linux/dipc.h
 *
 * Copyright (C) Kamran Karimi
 */
#ifndef _LINUX_DIPC_H
#define _LINUX_DIPC_H 
#ifdef __KERNEL__
#include <linux/sched.h>
#endif

extern int dipc(int first, int cmd, void *ptr);

#define DIPC_VERSION "1.1"
 
#define SHM 0
#define MSG 1
#define SEM 2

#define NO  0
#define YES 1

#define DIPC_SUCCESS 0
#define DIPC_FAIL -1

#define DIPC_REMPROT  2 /* remove protection bits */
#define DIPC_DEFPROT  3 /* set protection to default */

#define DIPC_SLEEP    6 /* sleep till there is work */

#define DIPC_SETMNG  10 /* set the dsm manager task */
#define DIPC_REMMNG  11 /* remove the dsm manager */
#define DIPC_GETWORK 13 /* get a work */
#define DIPC_RETWORK 14 /* return the result of the work done */

#define DISABLE_RD 50
#define DISABLE_WR 51

#define WANTRD     61
#define WANTWR     62
#define DETACH     63
#define AK         64

#define WRPROT_SND 72
#define RDPROT     73
#define RDPROT_SND 74 /* first read-protect, then send the contents */
#define NOP_SND    75 /* nop, just send the contents to third party */
#define RCV        76
#define TSTGET     77

#define RMID       81
#define DELKEY     82
#define SEARCH     83
#define COMMIT     84

#define SEM_EXIT   90

#define NOT_FOUND   0
#define FOUND_IPC   1
#define FOUND_DIPC  2
#define IS_SEGMENT  4

#define SEGMENT 0
#define PAGE    1

struct dipc_info {
	int key;
	int type; /* SHM, SEM or MSG */
	int pid; /* pid of the requesting task */
	int uid; /* uid of the requesting task */
	int func; /* what to do? (MSGCTL, SEMOP,...) */
	int arg1; /* arg1 to arg4 are the original arguments */
	int arg2; /* some of them may not be used */
	int arg3;
	int arg4;
	int dsize; /* is there any data? */
	int owner; /* network address of the owner;
               assuming 4 byte int! */
};

#ifdef __KERNEL__

struct dipc_request {
	struct dipc_info info;
	int working; /* shows if this request is already in works */
	char *data; /* data for this request */
	struct wait_queue *lock; /* requesting task will sleep here */
	struct dipc_request *next, *prev;
};

extern asmlinkage int sys_dipc(int first, int cmd, void *ptr);
 
extern int dipc_can_act(key_t key, struct task_struct *task);
extern int dipc_manager(struct task_struct *task);
extern int dipc_search_key(int key,int type,int distrib,int *size);
extern int dipc_commit_key(int key, int type, int size, int mode);
extern int dipc_test_key(int key, int type, int size, int flag);
extern int dipc_del_key(int key, int type);
extern int dipc_rmid_key(int key, int type);

extern void dipc_add_request(struct dipc_request *dr);
extern long dipc_find_owner_address(key_t key, int type, int silent);

extern void dipc_excl(int key, int type);
extern int dipc_check(int key, int type);
extern void dipc_wake(int key, int type);

extern void dipc_shm_init(int key, int val, int size);
extern void dipc_shm_del(int key);
extern void dipc_shm_enable(int key, int val, int offset, int size);
extern void dipc_shm_disable(int key, int val, int offset, int size);
extern int dipc_shm_readable(int key, int address);
extern int dipc_shm_writable(int key, int address);

#endif

/* the rest should be accessible to user programs */
#define DIPC_SIG_WRITER  SIGPWR
#define DIPC_SIG_READER  SIGURG

/* repeat the number in all bytes, so that endian-ness is avoided */
#define LINUX_i386  0x01010101
#define LINUX_m68k  0x02020202
#define LINUX_ALPHA 0x03030303
#define LINUX_SPARC 0x04040404
#define LINUX_MIPS  0x05050505
#define LINUX_PPC   0x06060606
#define LINUX_ARM   0x07070707

#define LINUX_LITTLE_32 0x80808080
#define LINUX_LITTLE_64 0x80808080
#define LINUX_BIG_32    0x90909090
#define LINUX_BIG_64    0x90909090

#define LINUX_NBOR  0xffffffff

/* define architecture, according to build definitions - add new archs here! */
#if defined(__i386__)
#define MY_DIPC_ARCH LINUX_LITTLE_32
#define DIPC_PAGE_RW(x) ((x) |  _PAGE_RW)
#define DIPC_PAGE_RO(x) ((x) & ~_PAGE_RW)
#elif defined(__mc68000__)
#define MY_DIPC_ARCH LINUX_BIG_32
#define DIPC_PAGE_RW(x) ((x) & ~_PAGE_RONLY)
#define DIPC_PAGE_RO(x) ((x) |  _PAGE_RONLY)
#else
#error "unsupported DIPC architecture!"
#endif

/* Back door definitions */
#define REFEREE_BACKDOOR "referee_backdoor"
#define SHM_BACKDOOR "shm_man_backdoor"

#define BACK_DOOR_INFO   1
#define BACK_DOOR_REMOVE 2
#define BACK_DOOR_EXIT   3

struct back_door_message {
	int cmd; /* command */
	int arg1; /* type (shm, sem, msg) or (WANT_ACCESS, PENDING, ACCESSOR */
	int arg2; /* key, or (SHM_READER, SHM_WRITER) */
	int arg3; /* size or unused */
	int arg4; /* distributed? or unused */
	int arg5; /* address */
};
/* end of Back door definitions */

#endif /* _LINUX_DIPC_H */
