/*
 * simulator.h external declarations and stuff for the simulator.
 * 
 */

#ifndef SIMULATOR_H
#define SIMULATOR_H

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define min(a,b)  (((a) < (b)) ? (a) : (b))
#define max(a,b)  (((a) > (b)) ? (a) : (b))

/* Boolean values. */

typedef enum {
FALSE = 0, TRUE = 1} bool;

/* machine exceptions */

typedef enum {
	SyscallException,		/* A program executed a system call. */
	PageFaultException,		/* Valid bit in PTE not set. */
	BusErrorException,		/* Translation gave invalid address. */
	AddressErrorException,		/* Unaligned or OOB addr ref. */
	OverflowException,		/* Integer overflow in add or sub. */
	IllegalInstrException,		/* Unimplemented or reserved instr. */

	NumExceptionTypes
}               ExceptionType;

/* exception handler called by the simulator with above type */

void            exceptionHandler(ExceptionType which);

/* interrupt types */

typedef enum {
	TimerInt, DiskInt, ConsoleWriteInt, ConsoleReadInt,
	NetworkSendInt, NetworkRecvInt
}               IntType;

/* interrupt handler called by the simulator when interrupt occurs */

void            interruptHandler(IntType which);

/* external variables which students can access memory */

#define PageSize                512
#define NumPhysicalPages        2048
#define MemorySize              (NumPhysicalPages * PageSize)

extern
char           *main_memory;

/*
 * Page table entries.  These are used to map from the addresses in the
 * address space to real, physical addresses.  We keep PTE's in a big array
 * for each address space.
 */

typedef struct {
	int             physicalFrame;	/* The page number in real memory. */
	bool            valid;		/* Is this page valid?  (I.e., is it
					 * in memory?) */
	bool            dirty;		/* Has this page been written to? */
	bool            use;		/* Has this page been accessed at
					 * all? */
}               PTE;

typedef struct {
	PTE           **table;
	int             tableSize;
}               PageTable;

/* returns sbrk(0) if successful, -1 otherwise */
int
                size_user_program(char *filename);
int
                load_user_program(char *filename, PageTable * pageTable);
void
                run_user_code(int registers[], PageTable * pageTable);

/* functions to read/write to the console */

#define console_read		ConsoleGetChar
#define console_write		ConsolePutChar
#define console_read2		ConsoleGetChar2
#define console_write2		ConsolePutChar2

extern
int             which_console;

/* functions and handy constants to read/write registers */

int             examine_registers(int buf[40]);

#define StackReg	29
#define RetAddrReg	31
#define NumGPRegs	32
#define HiReg		32
#define LoReg		33
#define PCReg		34
#define NextPCReg	35
#define PrevPCReg	36
#define LoadReg		37		/* The register target of a delayed
					 * load. */
#define LoadValueReg 	38		/* The value to be loaded by a
					 * delayed load. */
#define BadVAddrReg	39
#define NumTotalRegs 	40


/* function call to do nothing, NOTE: this function does NOT return */

void            noop();

#define SYS_halt        0
#define SYS_exit        1
#define SYS_fork        2
#define SYS_read        3
#define SYS_write       4
#define SYS_close       6
#define SYS_wait        7
#define SYS_getpid      20
#define SYS_getppid     39
#define SYS_dup         41
#define SYS_pipe        42
#define SYS_ioctl       54
#define SYS_execve      59
#define SYS_fstat       62
#define SYS_getpagesize 64
#define SYS_sbrk        69
#define SYS_getdtablesize       89
#define SYS_dup2        90


struct JOStermios {
	long            c_iflag;	/* Input Modes          */
	long            c_oflag;	/* Output Modes         */
	long            c_cflag;	/* Control Modes        */
	long            c_lflag;	/* Local Modes          */
	char            c_cc[19];	/* Control Characters   */
	char            c_line;		/* line disc. -local ext */
};

#define JOS_IOCPARM_MASK   0x7f		/* Parameters are < 128 bytes   */
#define JOS_IOC_VOID       (int)0x20000000	/* No parameters        */
#define JOS_IOC_OUT        (int)0x40000000	/* Copy out parameters  */
#define JOS_IOC_IN         (int)0x80000000	/* Copy in parameters   */
#define JOS_IOC_INOUT      (int)(JOS_IOC_IN|JOS_IOC_OUT)
#define JOS_IO(x,y)        (int)(JOS_IOC_VOID|(x<<8)|y)
#define JOS_IOR(x,y,t)     (int)(JOS_IOC_OUT|((sizeof(t)&JOS_IOCPARM_MASK)<<16)|(x<<8)|y)
#define JOS_IOW(x,y,t)     (int)(JOS_IOC_IN|((sizeof(t)&JOS_IOCPARM_MASK)<<16)|(x<<8)|y)
#define JOS_IOWR(x,y,t)    (int)(JOS_IOC_INOUT|((sizeof(t)&JOS_IOCPARM_MASK)<<16)|(x<<8)|y)

#define JOS_TCGETP          JOS_IOR('t',85,struct JOStermios)	/* Get parameters    */

struct JOSstat {
	short           st_dev;
	long            st_ino;
	short           st_mode;
	short           st_nlink;
	short           st_uid;
	short           st_gid;
	short           st_rdev;
	int             st_size;
	int             st_atime;
	int             st_spare1;
	int             st_mtime;
	int             st_spare2;
	int             st_ctime;
	int             st_spare3;
	long            st_blksize;
	long            st_blocks;
	unsigned long   st_gennum;
	long            st_spare4;
};

void
		ioctl_console_fill(PageTable *pageTable, int vaddr);
void
		stat_buf_fill(PageTable *pageTable, int vaddr, int blk_size);

#define SectorSize              512	/* number of bytes per disk sector */
#define SectorsPerTrack         32	/* number of sectors per disk track */
#define NumTracks               512	/* number of tracks per disk */
#define NumSectors              (SectorsPerTrack * NumTracks)
#define DiskSize                (NumSectors * SectorSize)

void
                disk_write(int sector, char *data);
void
                disk_read(int sector, char *data);

#endif

