/*
** VMEM.H - header file for VMEM
**
** Version 0.1 ©1990 by Edward Hutchins
** Based in part on the SetCPU program by Dave Haynie
** Authors:
**
**	Edward Hutchins: eah1@cec1.wustl.edu
**	Loren Rittle: l-rittle@uiuc.edu
**
** Revisions:
** 12/19/91 code released as freeware under the GNU general public license - Ed.
**
**    This program is free software; you can redistribute it and/or modify
**    it under the terms of the GNU General Public License as published by
**    the Free Software Foundation; either version 1, or (at your option)
**    any later version.
**
**    This program is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**    GNU General Public License for more details.
**
**    You should have received a copy of the GNU General Public License
**    along with this program; if not, write to the Free Software
**    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdio.h>
#include <exec/types.h>
#include <exec/exec.h>
#include <exec/execbase.h>
#include <exec/tasks.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <devices/timer.h>
#include <graphics/gfx.h>
#include <graphics/rastport.h>
#include <intuition/intuition.h>
#include <proto/all.h>

/*
** external declarations for the assembly routines
*/

IMPORT VOID SetCRP(ULONG *);
IMPORT VOID GetCRP(ULONG *);
IMPORT VOID SetTC(ULONG);
IMPORT ULONG GetTC(VOID);
IMPORT VOID SetCACR(ULONG);
IMPORT ULONG GetCACR(VOID);
IMPORT ULONG GetCPUType(VOID);
IMPORT ULONG GetMMUType(VOID);
IMPORT ULONG GetFPUType(VOID);
IMPORT VOID InsertFaultHandler(VOID);

/*
** Define all bit components used for manipulation of the Cache Control
** Register.
*/

#define CACR_INST	(1L<<0)
#define CACR_DATA	(1L<<8)

#define CACR_WALLOC	5
#define CACR_BURST	4
#define CACR_CLEAR	3
#define CACR_ENTRY	2
#define CACR_FREEZE	1
#define CACR_ENABLE	0

/*
** Define important bits used in various MMU registers.
*/

/*
** Here are the CRP definitions.  The CRP register is 64 bits long, but
** only the first 32 bits are control bits, the next 32 bits provide the
** base address of the table.
*/

#define	CRP_UPPER		(1L<<31)					/* Upper/lower limit mode */
#define CRP_LIMIT(x)	((ULONG)((x)&0x7fff)<<16)	/* Upper/lower limit value */
#define CRP_SG			(1L<<9)						/* Indicates shared space */
#define CRP_DT_INVALID	0x00						/* Invalid root descriptor */
#define	CRP_DT_PAGE		0x01						/* Fixed offset, auto-genned */
#define CRP_DT_V4BYTE	0x02						/* Short root descriptor */
#define	CRP_DT_V8BYTE	0x03						/* Long root descriptor */
#define CRP_DT_MASK		0x03

/*
** Here are the TC definitions.  The TC register is 32 bits long.
*/

#define	TC_ENB			(1L<<31)					/* Enable the MMU */
#define	TC_SRE			(1L<<25)					/* For separate Supervisor */
#define	TC_FCL			(1L<<24)					/* Use function codes? */
#define	TC_PS(x)		((ULONG)((x)&0x0f)<<20)		/* Page Size */
#define TC_IS(x)		((ULONG)((x)&0x0f)<<16)		/* Initial Shift */
#define	TC_TIA(x)		((ULONG)((x)&0x0f)<<12)		/* Table level A index */
#define	TC_TIB(x)		((ULONG)((x)&0x0f)<<8)		/* Table level B index */
#define TC_TIC(x)		((ULONG)((x)&0x0f)<<4)		/* Table level C index */
#define	TC_TID(x)		((ULONG)((x)&0x0f)<<0)		/* Table level D index */

/*
** Here are the page descriptor definitions, for short descriptors only,
** since that's all I'm using at this point.
*/

#define	PD_ADDR(x)		((ULONG)(x)&~0x0F)			/* Translated Address */
#define PD_ADDR_MASK	(0xFFFFFFF0)				/* address bits */
#define	PD_WP			(1<<2)						/* Write protect it! */
#define PD_USED			(1<<3)						/* page referenced */
#define PD_MOD			(1<<4)						/* page "dirty" */
#define PD_CI			(1<<6)						/* cache inhibit */
#define PD_DT_INVALID	0x00						/* Invalid root descriptor */
#define	PD_DT_PAGE		0x01						/* Fixed offset, auto-gen */
#define PD_DT_V4BYTE	0x02						/* Short root descriptor */
#define	PD_DT_V8BYTE	0x03						/* Long root descriptor */
#define PD_DT_MASK		0x03						/* DT mask */

/* short page descriptor format */
typedef ULONG PD_SHORT;
typedef PD_SHORT *PPD_SHORT;

/* long page descriptor format */
typedef struct
{
	UWORD				Limit;
	UWORD				Status;
	ULONG				Address;
} PD_LONG;
typedef PD_LONG *PPD_LONG;

/* page frame descriptor stuff (for the ageing table) */
typedef struct
{
	UWORD				Age;						/* page age in daemon ticks */
	UWORD				PageIndex;					/* index into PageTable */
} FRAME_DESC;
typedef FRAME_DESC *PFRAME_DESC;

/* maximum age allowed by law */
#define AGE_MAX 0xFFFF

/* weighted average age, since dirty pages cost twice what clean ones do */
#define WAGE(p) (((PageTable[(p)->PageIndex])&PD_MOD)?((p)->Age/2):((p)->Age))

/*
** Here's the FASTROM support stuff.
*/

#define ROMBASE			0x00FC0000
#define ROMSIZE			0x00040000

/*
** Bus Error exception stack frames
*/

/* fault format numbers are in VectorOffset */
#define SF_FORMAT_MASK	0xF000
#define SSF_SIZE		0x20
#define SSF_FORMAT		0xA000
#define LSF_SIZE		0x5C
#define LSF_FORMAT		0xB000

/* short bus cycle fault (16 words) - format $a */
typedef struct
{
	UWORD				StatusReg;
	CPTR				PC;
	UWORD				VectorOffset;	/* bits 12-15 are the frame ID (1010) */
	UWORD				InternReg1;
	UWORD				SpecialStatusReg;
	UWORD				InstPipeC;
	UWORD				InstPipeB;
	CPTR				DataCycleFaultAddr;
	UWORD				InternReg2[2];
	ULONG				DataOutputBuffer;
	UWORD				InternReg3[2];
} ShortBusFault;
typedef ShortBusFault *PShortBusFault;

/* long bus cycle fault (46 words) - format $b */
typedef struct
{
	UWORD				StatusReg;
	CPTR				PC;
	UWORD				VectorOffset;	/* bits 12-15 are the frame ID (1010) */
	UWORD				InternReg1;
	UWORD				SpecialStatusReg;
	UWORD				InstPipeC;
	UWORD				InstPipeB;
	CPTR				DataCycleFaultAddr;
	UWORD				InternReg2[2];
	ULONG				DataOutputBuffer; /* same as short frame to here */
	UWORD				InternReg3[4];
	CPTR				StageBAddress;
	UWORD				InternReg4[2];
	ULONG				DataInputBuffer;
	UWORD				InternReg5[3];
	UWORD				InternalInformation;	/* version # in bits 12-15 */
	UWORD				InternReg6[18];
} LongBusFault;
typedef LongBusFault *PLongBusFault;

/* special status bits */
#define SSTAT_FC		0x8000	/* fault on stage C of the instruction pipe */
#define SSTAT_FB		0x4000	/* fault on stage B */
#define SSTAT_RC		0x2000	/* stage C re-run */
#define SSTAT_RB		0x1000	/* stage B re-run */
#define SSTAT_DF		0x0100	/* data fault */
#define SSTAT_RM		0x0080	/* read-modify-write cycle */
#define SSTAT_RW		0x0040	/* read/write indicator */
#define SSTAT_SIZE_MASK	0x0030	/* size of data transfer */

/* the exception could be either one of these */
typedef union
{
	ShortBusFault		S;
	LongBusFault		L;
} BusFault;
typedef BusFault *PBusFault;

/*
** FaultNode - a recorded page fault
*/

typedef struct
{
	struct MinNode		Next;						/* page fault list */
	ULONG				OldRegs[15];				/* d0-d7/a0-a6 */
	ULONG				OldUSP;						/* previous USP */
	struct Task			*FaultedTask;				/* the task with the fault */
	UBYTE				RestartSigNum;				/* signal bit number */
	UBYTE				Pad[3];						/* longword padding */
	BusFault			Fault;						/* copied fault */
} FaultNode;
typedef FaultNode *PFaultNode;

/*
** This is what a fault node contains:
**
**			low memory
** |----------------------------|	start of FaultNode
** |FaultNode					|	real fault frame copied from system stack
** |----------------------------|	end of fake user stack
** |////////////////////////////|	padding (hopefully)
** |/// Task Context saved by //|
** |///// Signal() or Wait() ///|
** |----------------------------|	this is where the fake USP is left pointing
** |///// return address ///////|	fake return address pointing to RestartHandler
** |----------------------------|	top of fake user stack
**			high memory
*/

/* allocate this much space for the FaultNode and the fake user stack */
#define FAULTNODE_SIZE 0x400

/*
** Ageing timer stuff
*/

typedef struct timerequest TIMER_REQ;
typedef TIMER_REQ *PTIMER_REQ;

/*
** function prototypes
*/

extern struct Window *OpenScrn(WORD w, WORD h, WORD d, ULONG IDCMP, ULONG Flags);
extern void CloseScrn(struct Window * window);

