/*
 * Kernel header file for Linux crash dumps.
 *
 * Created by: Matt Robinson (yakker@sgi.com)
 * Copyright 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
 *
 * vmdump.h to dump.h by: Matt D. Robinson (yakker@sourceforge.net)
 * Copyright 2001 - 2002 Matt D. Robinson.  All rights reserved.
 * Copyright (C) 2002 Free Software Foundation, Inc. All rights reserved.
 *
 * Most of this is the same old stuff from vmdump.h, except now we're
 * actually a stand-alone driver plugged into the block layer interface,
 * with the exception that we now allow for compression modes externally
 * loaded (e.g., someone can come up with their own).
 *
 * This code is released under version 2 of the GNU GPL.
 */

/* This header file includes all structure definitions for crash dumps. */
#ifndef _DUMP_H
#define _DUMP_H

#include <linux/list.h>
#include <linux/notifier.h>

/* define TRUE and FALSE for use in our dump modules */
#ifndef FALSE
#define FALSE 0
#endif

#ifndef TRUE
#define TRUE 1
#endif


/*
 * DUMP_DEBUG: a debug level for the kernel dump code and
 *             the supporting lkcd libraries in user space.
 *
 * 0: FALSE: No Debug Added
 * 1: TRUE:  Break Points
 * .
 * .
 * .
 * 6: Add Debug Data to Structures
 * .
 * .
 * 9: Max
 */
#define DUMP_DEBUG FALSE

#if DUMP_DEBUG
void dump_bp(void);			/* Called when something exceptional occures */
#define DUMP_BP() dump_bp()			/* BreakPoint */
#else
#define DUMP_BP()
#endif

/* 
 * Predefine default DUMP_PAGE constants, asm header may override.
 *
 * On ia64 discontinuous memory systems it's possible for the memory
 * banks to stop at 2**12 page alignments, the smallest possible page
 * size. But the system page size, PAGE_SIZE, is in fact larger.
 */
#define DUMP_PAGE_SHIFT 	PAGE_SHIFT
#define DUMP_PAGE_SIZE		PAGE_SIZE
#define DUMP_PAGE_MASK		PAGE_MASK
#define DUMP_PAGE_ALIGN(addr)	PAGE_ALIGN(addr)
#define DUMP_HEADER_OFFSET	PAGE_SIZE

/* 
 * Predefined default memcpy() to use when copying memory to the dump buffer.
 *
 * On ia64 there is a heads up function that can be called to let the prom
 * machine check monitor know that the current activity is risky and it should
 * ignore the fault (nofault). In this case the ia64 header will redefine this
 * macro to __dump_memcpy() and use it's arch specific version.
 */
#define DUMP_memcpy		memcpy


/* necessary header files */
#include <asm/dump.h>                   /* for architecture-specific header */

/* necessary header definitions in all cases */
#define DUMP_KIOBUF_NUMBER  0xdeadbeef  /* special number for kiobuf maps   */

/* 
 * Size of the buffer that's used to hold:
 *
 *	1. the dump header (paded to fill the complete buffer)
 *	2. the possibly compressed page headers and data
 */
#define DUMP_BUFFER_SIZE        (64 * 1024)  /* size of dump buffer (0x10000) */
#define DUMP_HEADER_SIZE	 DUMP_BUFFER_SIZE

/* header definitions for s390 dump */
#define DUMP_MAGIC_S390     0xa8190173618f23fdULL  /* s390 magic number     */
#define S390_DUMP_HEADER_SIZE     4096

/* standard header definitions */
#define DUMP_MAGIC_NUMBER   0xa8190173618f23edULL  /* dump magic number     */
#define DUMP_MAGIC_LIVE     0xa8190173618f23cdULL  /* live magic number     */
#define DUMP_VERSION_NUMBER   0x7       /* dump version number              */
#define DUMP_PANIC_LEN        0x100     /* dump panic string length         */

/* dump levels - type specific stuff added later -- add as necessary */
#define DUMP_LEVEL_NONE        0x0      /* no dumping at all -- just bail   */
#define DUMP_LEVEL_HEADER      0x1      /* kernel dump header only          */
#define DUMP_LEVEL_KERN        0x2      /* dump header and kernel pages     */
#define DUMP_LEVEL_USED        0x4      /* dump header, kernel/user pages   */
#define DUMP_LEVEL_ALL_RAM     0x8      /* dump header, all RAM pages       */
#define DUMP_LEVEL_ALL        0x10      /* dump all memory RAM and firmware */


/* dump compression options -- add as necessary */
#define DUMP_COMPRESS_NONE     0x0      /* don't compress this dump         */
#define DUMP_COMPRESS_RLE      0x1      /* use RLE compression              */
#define DUMP_COMPRESS_GZIP     0x2      /* use GZIP compression             */

/* dump flags - any dump-type specific flags -- add as necessary */
#define DUMP_FLAGS_NONE        0x0      /* no flags are set for this dump   */
#define DUMP_FLAGS_NONDISRUPT  0x1      /* try to keep running after dump   */

/* dump header flags -- add as necessary */
#define DUMP_DH_FLAGS_NONE     0x0      /* no flags set (error condition!)  */
#define DUMP_DH_RAW            0x1      /* raw page (no compression)        */
#define DUMP_DH_COMPRESSED     0x2      /* page is compressed               */
#define DUMP_DH_END            0x4      /* end marker on a full dump        */
#define DUMP_DH_TRUNCATED      0x8	/* dump is incomplete               */
#define DUMP_DH_TEST_PATTERN   0x10	/* dump page is a test pattern      */
#define DUMP_DH_NOT_USED       0x20	/* 1st bit not used in flags        */

/* names for various dump tunables (they are now all read-only) */
#define DUMP_ROOT_NAME         "sys/dump"
#define DUMP_DEVICE_NAME       "dump_device"
#define DUMP_COMPRESS_NAME     "dump_compress"
#define DUMP_LEVEL_NAME        "dump_level"
#define DUMP_FLAGS_NAME        "dump_flags"

/* page size for gzip compression -- buffered slightly beyond hardware PAGE_SIZE used by DUMP */
#define DUMP_DPC_PAGE_SIZE     (DUMP_PAGE_SIZE + 512)

/* dump ioctl() control options */
#define DIOSDUMPDEV		1       /* set the dump device              */
#define DIOGDUMPDEV		2       /* get the dump device              */
#define DIOSDUMPLEVEL		3       /* set the dump level               */
#define DIOGDUMPLEVEL		4       /* get the dump level               */
#define DIOSDUMPFLAGS		5       /* set the dump flag parameters     */
#define DIOGDUMPFLAGS		6       /* get the dump flag parameters     */
#define DIOSDUMPCOMPRESS	7       /* set the dump compress level       */
#define DIOGDUMPCOMPRESS	8       /* get the dump compress level        */
#define DIODUMPTEST		99      /* test the dump facility (panic/dump) */

/* the major number used for the dumping device */
#ifndef DUMP_MAJOR
#define DUMP_MAJOR              227
#endif

/*
 * Structure: dump_header_t
 *  Function: This is the header dumped at the top of every valid crash
 *            dump.  
 *            easy reassembly of each crash dump page.  The address bits
 *            are split to make things easier for 64-bit/32-bit system
 *            conversions.
 */
typedef struct _dump_header_s {
	/* the dump magic number -- unique to verify dump is valid */
	uint64_t             dh_magic_number;

	/* the version number of this dump */
	uint32_t             dh_version;

	/* the size of this header (in case we can't read it) */
	uint32_t             dh_header_size;

	/* the level of this dump (just a header?) */
	uint32_t             dh_dump_level;

	/* 
	 * The size of a hardware/physical memory page (DUMP_PAGE_SIZE).
	 * NB: Not the configurable system page (PAGE_SIZE) (4K, 8K, 16K, etc.) 
	 */
	uint32_t             dh_dump_page_size;

	/* the size of all physical memory */
	uint64_t             dh_memory_size;

	/* the start of physical memory */
	uint64_t             dh_memory_start;

	/* the end of physical memory */
	uint64_t             dh_memory_end;

#if DUMP_DEBUG >= 6
	/* the number of bytes in this dump specifically */
	uint64_t             dh_num_bytes;
#endif

	/* the number of hardware/physical pages in this dump specifically */
	uint32_t             dh_num_dump_pages;

	/* the panic string, if available */
	char                 dh_panic_string[DUMP_PANIC_LEN];

	/* the time of the system crash */
	struct timeval       dh_time;

	/* the NEW utsname (uname) information -- in character form */
	/* we do this so we don't have to include utsname.h         */
	/* plus it helps us be more architecture independent        */
	/* now maybe one day soon they'll make the [65] a #define!  */
	char                 dh_utsname_sysname[65];
	char                 dh_utsname_nodename[65];
	char                 dh_utsname_release[65];
	char                 dh_utsname_version[65];
	char                 dh_utsname_machine[65];
	char                 dh_utsname_domainname[65];

	/* the address of current task (OLD = task_struct *, NEW = void *) */
	void                *dh_current_task;

	/* what type of compression we're using in this dump (if any) */
	uint32_t             dh_dump_compress;

	/* any additional flags */
	uint32_t             dh_dump_flags;

	/* any additional flags */
	uint32_t             dh_dump_device;

} dump_header_t;

/*
 * Structure: dump_page_t
 *  Function: To act as the header associated to each physical page of
 *            memory saved in the system crash dump.  This allows for
 *            easy reassembly of each crash dump page.  The address bits
 *            are split to make things easier for 64-bit/32-bit system
 *            conversions.
 *
 * dp_byte_offset and dp_page_index are landmarks that are helpfull when
 * looking at a hexdump of /dev/vmdump,
 */
typedef struct _dump_page_s {

#if DUMP_DEBUG >= 6
	/* byte offset */
	uint64_t		dp_byte_offset;

	/* page index */
	uint64_t		dp_page_index;
#endif
	/* the address of this dump page */
	uint64_t             dp_address;

	/* the size of this dump page */
	uint32_t             dp_size;

	/* flags (currently DUMP_COMPRESSED, DUMP_RAW or DUMP_END) */
	uint32_t             dp_flags;
} dump_page_t;

/*
 * This structure contains information needed for the lkcdutils
 * package (particularly lcrash) to determine what information is
 * associated to this kernel, specifically.
 */
typedef struct lkcdinfo_s {
	int             arch;
	int             ptrsz;
	int             byte_order;
	int             linux_release;
	int             page_shift;
	int             page_size;
	uint64_t        page_mask;
	uint64_t        page_offset;
	int             stack_offset;
} lkcdinfo_t;

#ifdef __KERNEL__

/*
 * Structure: dump_compress_t
 *  Function: This is what an individual compression mechanism can use
 *            to plug in their own compression techniques.  It's always
 *            best to build these as individual modules so that people
 *            can put in whatever they want.
 */
typedef struct dump_compress_s {
	/* the list_head structure for list storage */
	struct list_head list;

	/* the type of compression to use (DUMP_COMPRESS_XXX) */
        int compress_type;

	/* the compression function to call */
        int (*compress_func)(char *, int, char *, int);
} dump_compress_t;

/* functions for dump compression registration */
extern void dump_register_compression(dump_compress_t *);
extern void dump_unregister_compression(int);

/*
 * Structure dump_mbank[]:
 *
 * For CONFIG_DISCONTIGMEM systems this array specifies the
 * memory banks/chunks that need to be dumped after a panic.
 *
 * For clasic systems it specifies a single set of pages from
 * 0 to max_mapnr.
 */
typedef struct dump_mbank {
        u64 		start;
        u64 		end;
	int		type;
	int		pad1;
	long		pad2;
} dump_mbank_t;

#define DUMP_MBANK_TYPE_CONVENTIONAL_MEMORY		1
#define DUMP_MBANK_TYPE_OTHER				2


#define MAXCHUNKS 256
extern int dump_mbanks;
extern dump_mbank_t dump_mbank[MAXCHUNKS];

extern struct notifier_block *dump_notifier_list;
extern int register_dump_notifier(struct notifier_block *);
extern int unregister_dump_notifier(struct notifier_block *);

/* notification codes */
#define DUMP_BEGIN	0x0001	/* Notify of dump beginning */
#define DUMP_END	0x0002	/* Notify of dump ending */

extern int dump_init(void);
int dump_execute(char *, struct pt_regs *);
extern volatile int dump_in_progress;
extern volatile int dumping_cpu;
extern int (*dump_function_ptr)(char *, struct pt_regs *);

#if defined(CONFIG_X86) || defined(CONFIG_ALPHA)
extern int page_is_ram(unsigned long);
#endif

#if defined(CONFIG_DUMP) || defined(CONFIG_DUMP_MODULE)
static inline void dump(char * str, struct pt_regs * regs)
{
	if (dump_function_ptr) {
		dump_function_ptr((char *)str, regs);
	}
}
#else
static inline void dump(char * str, struct pt_regs * regs)
{
}
#endif /* CONFIG_DUMP */

/*
 * Common Arch Specific Functions should be declared here.
 * This allows the C compiler to detect discrepancies.
 */
extern void 		__dump_open(void);
extern void 		__dump_cleanup(void);
extern void 		__dump_init(uint64_t);
extern int 		__dump_configure_header(struct pt_regs *);
extern unsigned int  	__dump_silence_system(unsigned int);
extern unsigned int  	__dump_resume_system(unsigned int);
#endif /* __KERNEL__ */

struct dump_dev {
	char type_name[32]; /* block, net-poll etc */
	unsigned long device_id; /* interpreted differently for various types */
	struct dump_dev_ops *ops;
	struct list_head list;
	loff_t curr_offset;
};

#endif /* _DUMP_H */
