#KILLALL
/***********************************************************************
* ******************************************************************** *
* *																					 	* *		
* *	Universal BIOS for Z-World/Rabbit Semiconductor Rabbit 2000    * *		
* *	CPU based boards.                                              * *		
* *																						* *		
* * 	Copyright (c)  1999-2001 Z-World.                              * *		
* *																						* *							
* *	Assumes ATMEL compatible flash algorithms                      * *		
* *                                                                  * *						
* *******************************************************************  *
************************************************************************/

/////// BEGIN USER MODIFYABLE MACROS /////////////////////////////////

//***** Miscellaneous Information *******************************************
#define PRODUCT_NAME	"Universal Rabbit BIOS Version 7.06"	

#define CLOCK_DOUBLED  1         // Set to 1 to double clock if XTAL<=12.9MHz,
											//  or to 0 to always disable clock doubler
 
#define CS1_ALWAYS_ON  0         // Keeping CS1 active is useful if your
                                 // system is pushing the limits of RAM
                                 // access time. It will increase power
                                 // consumption a little. Set to 0 to
                                 // disable, 1 to enable
											                                                                     
//***** File System Information *******************************************
#define XMEM_RESERVE_SIZE 0x0000L // Amount of space in the first flash to
                                 //  reserve. Dynamic C will not use this
                                 //  much flash for xmemory code space.
                                 //  This allows the filesystem to be used on
                                 //  the first flash.

#define FS2_RAM_RESERVE (0*4096) // Amount to reserve for filesystem II
                                 //  battery-backed RAM extent. Leave this at
                                 //  zero if not using RAM filesystem. Otherwise,
                                 //  define to a suitable multiple of 4096 bytes.

//***** Error Logging information *******************************************
//   Extend RAM for the error logging is pre-allocated in chunks of 4096.
//   The default configuration (when ENABLE_ERROR_LOGGING is 1) uses
//   one 4096 chunk.      
#define ENABLE_ERROR_LOGGING   0 // Enable error logging, set to 1 to enable
#define ERRLOG_USE_REG_DUMP    1 //  Include register dump in log entries
#define ERRLOG_STACKDUMP_SIZE 16 //  Include stack dump of this size in entries
#define ERRLOG_USE_MESSAGE     0 // Use this to include an 8 byte message in the
                                 //  log entries. The default exception handler
                                 //  currently makes no use of this.

#define ERRLOG_NUM_ENTRIES    78 // For best use of RAM space, choose a value that
                                 //  that will make a log size close to a multiple
                                 //  of 4096 
#ifdef _RAM_
#if (ENABLE_ERROR_LOGGING==1)
#warns "Error logging not available when compiling to RAM"
#undef ENABLE_ERROR_LOGGING
#define ENABLE_ERROR_LOGGING 0
#endif
#endif

//***** Cloning information *******************************************
#define ENABLECLONING       0    // Set to 1 to enable cloning. Needed for
                                 // both normal and fast cloning. See fast 
                                 // cloning option below. 

#define ENABLE_FAST_CLONING 0    // Use a special method to clone faster.
                                 //   Unlike normal cloning mode, the LED on
                                 //   the cloning will blink when cloning is
                                 //   UNsuccessful. It will go off when
                                 //   cloning begins, and stay lit continuosly
                                 //   after successful cloning is finished.
                                 // Restrictions:
                                 //   The program being cloned must be fit into
                                 //   the primary RAM on the cloned board with
                                 //   2000h bytes to spare. The cloning master's
                                 //   crystal should be least as fast as the
                                 //   slave's. One flash only will be copied.
                                 //   See FASTCLONE.LIB for more
                                 //   fast cloning options.

#define CLONINGBAUDRATE	1        // Set to 0 for 57600 baud, 1 for 115200 baud
                                 //   Not applicable to fast cloning
											//   NOTE that the serial rate in Dynamic C
											//   must be set to the same value!
                                 
#define CLONEWHOLEFLASH	0        // Set to 1 to copy entire flash device to clone
                                 //   Not applicable to fast cloning


//***** Memory mapping information ************************************
//#define USE_2NDFLASH_CODE		// Uncomment this only if you have a
                                 //  a board with 2 256K flashes and you
                                 //  want to use the second flash for extra
                                 //  code space. The file system is not
                                 //  compatible with using the second flash
                                 //  for code. Do not uncomment this if
                                 //  you are compiling a secondary program 
                                 //  to the second flash, only uncomment it 
                                 //  if the primary program is bigger than 
                                 //  the first flash.

#define DATAORG      0x6000      // Begining logical address for data seg.
                                 // A user with a lot of root code
                                 // and not alot of root data can increase
                                 // this in increments of 0x1000 to as high
                                 // as 0xB000 to allow more root code space.
                                 // OR, root data space can be increased by
                                 // lowering this to as low as 0x3000.

#if (_RAM_SIZE_==0x80)           // Number of 4k pages of RAM. _RAM_SIZE_  
#define RAM_SIZE 0x40            // is defined internally by Dynamic C
#else										// during the coldboot stage, but can
#define RAM_SIZE _RAM_SIZE_      // changed here. If _RAM_SIZE_ is 0x80 (512K)
#endif                           // we reserve the upper half for xalloc
                                 // and map top of DATA to the top of the
                                 // lower half of RAM. The xalloc initialization
                                 // code will recognize that the space is
                                 // available if RAM_SIZE < _RAM_SIZE_.

#define FLASH_SIZE _FLASH_SIZE_  // Number of 4k pages of flash. _FLASH_SIZE_  
                                 // is defined internally by Dynamic C during
                                 // the coldboot stage by reading the flash ID
                                 // int from the flash on CS0, but can changed
			          				   // here.

#define DISABLE_FLSH_IF_RAM 0    // This macro only has any effect when
                                 // a user compiles to RAM...
                                 // Setting this to one causes the program
                                 // previously compiled to flash to be
                                 // disabled. This is to prevent accidental
                                 // deployment of an old program residing 
                                 // in flash. If this is set to zero and
                                 // power is recycled with the programming
                                 // cable disconnected, whatever program
                                 // previously put in flash will run. 
                                 // This does NOT mean that the program
                                 // in RAM will run when power is recycled.
                                 // compiling to RAM is for debugging only.

#define WATCHCODESIZE    0x200   // Number of root RAM bytes for Watch Code

//********************************************************************
//  Advanced configuration items follow
//  (Primarily of interest to board makers)
//********************************************************************

//***** Starting 4k page for RAM physical addresses *******************
#ifdef _FLASH_
#define RAM_START       0x80     // RAM normally starts at 0x80000
#else          
#define RAM_START       0x0      //	RAM starts at 00000 if compiling to RAM 
#endif 

//***** Wait States for the memory devices ****************************
#define NUM_RAM_WAITST	 0       
#define NUM_FLASH_WAITST 0
#define NUM_CS2_WAITST   0

//***** Chip selects/write enables for the memory devices *************
#define CS_FLASH			0x00    // CS0/OE0/WE0   
#define CS_RAM				0x05	  // CS1/OE1/WE1	
#define CS_FLASH2			0x02    // CS2/OE0/WE0

//***** Inversion bits for bank control registers *********************
#define MB0CR_INVRT_A18  0
#define MB1CR_INVRT_A18  0
#define MB2CR_INVRT_A18  0
#define MB3CR_INVRT_A18  0
#define MB0CR_INVRT_A19  0
#define MB1CR_INVRT_A19  0
#define MB2CR_INVRT_A19  0
#define MB3CR_INVRT_A19  0

////////// END OF USER-MODIFIABLE MACROS /////////////////////////////////

//**** These are redefinitions which are done if the macro 
//****  COMPILE_SECONDARY_PROG is defined. These cause the RAM 
//****  to be split, and the top half used, and they map
//****  quadrant 0 to  CS2/OE0/WE0. This for situations where 2
//****  co-resident programs are used on two different flashes
//****  such as a downloader and a downloaded program. The 
//****  downloaded program should generally be the secondary
//****  program. This can also be used for a single 256K 
//****  flash if A18 off the processor is connected to A17
//****  on the flash, in which case INVERT_A18_ON_PRIMARY_FLASH
//****  must be defined also.
#ifdef  COMPILE_SECONDARY_PROG
	#undef  RAM_SIZE
   #undef  CS_FLASH
   #define CS_FLASH	0x02    
	#ifdef  INVERT_A18_ON_PRIMARY_FLASH
		#undef  MB0CR_INVRT_A18
		#define MB0CR_INVRT_A18  1
	   #undef  CS_FLASH
   	#define CS_FLASH	0x00    
	   #undef  FLASH_SIZE
      #define FLASH_SIZE 0x20
   #endif		
   #if (_RAM_SIZE_==0x80)
	   #undef _RAM_SIZE_
      #define _RAM_SIZE_ 0x40
   #else
      #if (_RAM_SIZE_==0x40)
		   #undef _RAM_SIZE_
 	      #define _RAM_SIZE_ 0x20
      #else
         #if (_RAM_SIZE_==0x20)
 	         #undef _RAM_SIZE_
		      #define _RAM_SIZE_ 0x10
         #else
            #error "unknown RAM size" 
         #endif
	  #endif
   #endif
   #undef  RAM_START
   #define RAM_SIZE _RAM_SIZE_
   #define RAM_START 0x80+RAM_SIZE
#endif

//**** These are redefinitions which are done if the macro 
//****  COMPILE_PRIMARY_PROG is defined. These cause the RAM 
//****  to be split, and the bottom half used. This for situations 
//****  where 2 co-resident programs are used ONLY, such as a downloader
//****  and a downloaded program. The downloader program should
//****  generally be the primary program. 
#ifdef  COMPILE_PRIMARY_PROG
	#ifdef  INVERT_A18_ON_PRIMARY_FLASH
	   #undef  FLASH_SIZE
      #define FLASH_SIZE 0x20
   #endif		
   #if (_RAM_SIZE_==0x80)
	   #undef _RAM_SIZE_
      #define _RAM_SIZE_ 0x40
   #else
      #if (_RAM_SIZE_==0x40)
	 	   #undef _RAM_SIZE_
   	   #define _RAM_SIZE_ 0x20
      #else
         #if (_RAM_SIZE_==0x20)
   			#undef _RAM_SIZE_
	         #define _RAM_SIZE_ 0x10
		   #else
   	      #error "Unknown RAM size" 
         #endif
      #endif
   #endif
   #undef RAM_SIZE
   #define RAM_SIZE _RAM_SIZE_
#endif

struct _regBuffer {
	unsigned _AF;
	unsigned _BC;
	unsigned _DE;
	unsigned _HL;
	unsigned _SP;
	unsigned _PC;
	unsigned _XPC;
	unsigned _IX;
	unsigned _IY;
	unsigned _AFprime;
	unsigned _BCprime;
	unsigned _DEprime;
	unsigned _HLprime;	
};


typedef struct {
	unsigned short addr;  // address
	unsigned char base;   // base (BBR or CBR)
}	ADDR24_S;

typedef union { unsigned long l;    // long for increment/decrement 
					struct { ADDR24_S a; // the address itself 
								char flags; // flags associated 
						 } aaa;
}	ADDR24;

struct _errLogEntry
{
	long secTimer;
	ADDR24 address;
	char   errType;
#if (ERRLOG_USE_MESSAGE==1)
	char   message[8];
#endif
#if (ERRLOG_USE_REG_DUMP==1)
	struct _regBuffer regDump;
#endif
#if (ERRLOG_STACKDUMP_SIZE!=0)
	char stackDump[ERRLOG_STACKDUMP_SIZE];
#endif
	char  checksum; 
};

struct _errLogInfo
{
	char     status;
	unsigned ExceptionIndex;
	unsigned ExceptionIndexMod;
	unsigned errorsSinceDeployment;
	unsigned HWresetsSinceDeployment;
	unsigned WDTOsSinceDeployment;
	unsigned SWresetsSinceDeployment;
	char     headerChecksum;
};

#if (ENABLE_ERROR_LOGGING==1)
#define ERRLOG_LOG_SIZE (ERRLOG_NUM_ENTRIES*sizeof(struct _errLogEntry)+sizeof(struct _errLogInfo))
#if (0x10000ul <= ERRLOG_LOG_SIZE)
#error "Error log size too big"
#endif
#else
#define ERRLOG_LOG_SIZE 0
#endif 

#if (ENABLE_ERROR_LOGGING==1)
#define ERRLOG_NBLOCKS (1+ERRLOG_LOG_SIZE/4096)
#else
#define ERRLOG_NBLOCKS 0
#endif

#define USE115KBAUD   _USE115KBAUD_				// _USE115KBAUD_ set internally by DC

//***** Settings for bank control registers ***************************
#ifdef _FLASH_		// running in flash
  #define MB0CR_SETTING	FLASH_WSTATES | CS_FLASH  | (MB0CR_INVRT_A18<<4) | (MB0CR_INVRT_A19<<5)
  #if (_FLASH_SIZE_ == 0x80)
    #define MB1CR_SETTING	FLASH_WSTATES | CS_FLASH  | (MB1CR_INVRT_A18<<4) | (MB1CR_INVRT_A19<<5)
  #else
    #define MB1CR_SETTING	FLASH_WSTATES | CS_FLASH2 | (MB1CR_INVRT_A18<<4) | (MB1CR_INVRT_A19<<5)
  #endif

#define MB2CR_SETTING	RAM_WSTATES | CS_RAM | (MB2CR_INVRT_A18<<4) | (MB2CR_INVRT_A19<<5)
#define MB3CR_SETTING	RAM_WSTATES | CS_RAM | (MB3CR_INVRT_A18<<4) | (MB3CR_INVRT_A19<<5)

#else  // running in RAM
#define MB0CR_SETTING	RAM_WSTATES | CS_RAM | (MB0CR_INVRT_A18<<4) | (MB0CR_INVRT_A19<<5)
#define MB1CR_SETTING	RAM_WSTATES | CS_RAM | (MB1CR_INVRT_A18<<4) | (MB1CR_INVRT_A19<<5)
#define MB2CR_SETTING	RAM_WSTATES | CS_RAM | (MB2CR_INVRT_A18<<4) | (MB2CR_INVRT_A19<<5)
#define MB3CR_SETTING	RAM_WSTATES | CS_RAM | (MB3CR_INVRT_A18<<4) | (MB3CR_INVRT_A19<<5)
#endif

#define STACKORG  		0xD000	// Begining logical address for stack segment

//***** Compute the MMU segment registers *****
//***** the 1 represents space for a 4K flash transfer buffer
#define DATASEGVAL   RAM_START + RAM_SIZE - (STACKORG>>12) - (1+ERRLOG_NBLOCKS+FS2_RAM_RESERVE/4096)

#define XMEMSEGVAL	(0xff & ((DATAORG-0xe000)/4096))

#ifdef _RAM_
  #ifdef USE_2NDFLASH_CODE
    #undef USE_2NDFLASH_CODE
    #warns "USE_2NDFLASH_CODE is disabled when compiling to RAM."
  #endif
#endif

#ifdef USE_2NDFLASH_CODE
#define XMEMSEGVAL2 	(0xff & ((-0xE000)/4096 + FLASH_SIZE))
#endif

#define MEMBREAK    0+(STACKORG/256) + (DATAORG/4096)  // SEGSIZE reg value


//***** Compute Code and Data ORGs ************************************
#ifndef FS_RESERVE_SIZE
#define FS_RESERVE_SIZE 0	// default to no space reserved for the FS in the first flash
#endif
#define WATCHCODEORG 	STACKORG-(0x0200+WATCHCODESIZE)
#define ROOTCODEORG  	0x0000
#define XMEMORYORG   	0xE000

#ifdef _FLASH_
#ifdef USE_2NDFLASH_CODE
#define XMEMORYSIZE2		FLASH_SIZE*4096L
#endif
#define XMEMORYSIZE   	FLASH_SIZE*4096L-DATAORG-0x4000-FS2_RAM_RESERVE-ERRLOG_NBLOCKS*4096-XMEM_RESERVE_SIZE
#endif

#ifdef _RAM_
#define XMEMORYSIZE   	RAM_SIZE*4096L-0xE000-FS2_RAM_RESERVE
#endif

#define ROOTCODESIZE  	DATAORG   
#define ROOTDATAORG  	WATCHCODEORG-0x0001
#define ROOTDATASIZE  	STACKORG-(DATAORG+0x200+WATCHCODESIZE)

/* marker for where the end of XMEM is */
#define END_OF_XMEMORY	(((XMEMSEGVAL<<12L)+(long)XMEMORYORG+(long)XMEMORYSIZE)&0xFFFFF)

//***** This is to let Dynamic C programs know we are running in Flash or RAM.
//***** _RAM_, and _FLASH_ are defined by the compiler.  RUN_IN_RAM
//***** predates these compiler generated macros.
#ifdef _FLASH_
#define RUN_IN_RAM 0					
#else
#define RUN_IN_RAM 1
#endif

//***** Tell the compiler this is a BIOS 
#pragma Rabbit CompileBIOS 	

#ifdef USE_2NDFLASH_CODE
#if FS_RESERVE_SIZE > 0
#error "Using second flash for both code and a filesystem is not currently supported."
#endif
#endif

/*-------------------------------------------------------------------
**  CODE ORG statements to determine code locations in physical and
**  logical memory space.
**
**  Type Name     Segment       Bottom       Size			  	   Use
--------------------------------------------------------------------*/
#rcodorg rootcode	0x00          ROOTCODEORG  ROOTCODESIZE		apply


#ifdef USE_2NDFLASH_CODE
#xcodorg xmemcode (XMEMSEGVAL)  XMEMORYORG	XMEMORYSIZE			apply
#xcodorg xmemcod2 (XMEMSEGVAL2) XMEMORYORG 	XMEMORYSIZE2 		follows xmemcode splitbin
#else
#xcodorg xmemcode	(XMEMSEGVAL)  XMEMORYORG   XMEMORYSIZE       apply
#endif

#wcodorg	watcode  (DATASEGVAL)  WATCHCODEORG WATCHCODESIZE     apply

/*--------------------------------------------------------------------
**  DATA ORG statements to determine data locations in physical and
**  logical memory space.
**
**  Type Name     Segment        Top          Size			  	 Use
-------------------------------------------------------------------*/
#rvarorg rootdata	(DATASEGVAL) 	ROOTDATAORG  ROOTDATASIZE 	 apply


//**** internal and external vector table locations *****************
#define XINTVEC_BASE  STACKORG-0x100
#define INTVEC_BASE STACKORG-0x200


/************************** LOGICAL MEMORY MAP **********************

  FFFF                          ---------------			
                                |             |
                                |             |
                                ~             ~
                                     Xmem
                                ~             ~
                                |             |
                                |             |
  E000                          ---------------
                                | Stack Top   |
                                |             |
                                ~             ~
                                     Stack
                                ~             ~
                                |             |
                                |             |
  STACKORG                      ---------------	
                                | external    |
                                | vector tabl.|
  STACKORG-100h                 ---------------				
                                | internal    |
                                | vector tabl.|
  STACKORG-200h                 ---------------
                                |     |       |
                                |    /|\      |
                                |     |       |
                                ~             ~
                                  Watch Code
                                ~             ~
                                |     |       |
                                |    \|/      |
   WATCHCODEORG                 |     |       |
                                ---------------
   ROOTDATAORG                  |     |       |
                                |    /|\      |
                                |     |       |
                                ~             ~
                                   Root Data
                                ~             ~
                                |     |       |
                                |    \|/      |
                                |     |       |
                                ---------------
                                |     |       |
                                |    /|\      |
                                |     |       |
                                ~             ~
                                   Root Code
                                ~             ~
                                |     |       |
                                |    \|/      |
                                |     |       |
  ROOTCODEORG (0000)            ---------------
    
*******************************************************************/


//***** Libraries needed by the BIOS *********************************
#use BIOSFSM.LIB 						// The communication Finite State Machine
#use SYSIO.LIB 						// IO register assignemnts and functions
#use DBUGKERN.LIB						// The debug kernel
#use CSUPPORT.lib						// Some C support functions
#use FLASHWR.lib						// The flash writing functions
#use STACK.lib							// The stack initialization functions
#use IDBLOCK.LIB						// Flash ID block access fcns (and CRC).
#use ERRORS.LIB						// Runtime error handling

#if (ENABLECLONING == 1)
#if (ENABLE_FAST_CLONING==1)
#use FASTCLONE.LIB					// Contains fast cloning support functions
#else
#use CLONE.LIB							// Contains cloning support functions
#endif
#endif

/********************************************************************
*********************************************************************
*
*	BIOS internals follow
*
*********************************************************************
*********************************************************************/
#if (NUM_FLASH_WAITST==0)
#define FLASH_WSTATES 0xc0
#else
#if (NUM_FLASH_WAITST==1)
#define FLASH_WSTATES 0x80
#else
#if (NUM_FLASH_WAITST==2)
#define FLASH_WSTATES 0x40
#else
#if (NUM_FLASH_WAITST==4)
#define FLASH_WSTATES 0x00
#endif
#endif
#endif
#endif

#if (NUM_RAM_WAITST==0)
#define RAM_WSTATES 0xc0
#else
#if (NUM_RAM_WAITST==1)
#define RAM_WSTATES 0x80
#else
#if (NUM_RAM_WAITST==2)
#define RAM_WSTATES 0x40
#else
#if (NUM_RAM_WAITST==4)
#define RAM_WSTATES 0x00
#endif
#endif
#endif
#endif

#if (NUM_CS2_WAITST==0)
#define CS2_WSTATES 0xc0
#else
#if (NUM_CS2_WAITST==1)
#define CS2_WSTATES 0x80
#else
#if (NUM_CS2_WAITST==2)
#define CS2_WSTATES 0x40
#else
#if (NUM_CS2_WAITST==4)
#define CS2_WSTATES 0x00
#endif
#endif
#endif
#endif

#define SIZESTDIOBUFF 130

#define HW_MEMBREAK 0xe2

/*** end of macro definitions */

/*** variable definitions */
#define BIOSSTACKSIZE 40
char dbXPC;

void *dkcState;			//	the address (state) of  debugger kernel comm machine
char BiosStack[BIOSSTACKSIZE]; // initial stack for bios in data the segment
char commBuffer[256];	//	communication buffer
char stdioCommBuff[SIZESTDIOBUFF];
char watchBuffer[8];		//	buffer for watch expression results

struct _fcTable fcTable;			//	RAM location to store the fctable
char stepRelay[3];		//	ram location for rst28 relay

struct _dcParam DCParam;

struct _DCSrcDebug DCSrcDebug;
char  OPMODE, _dkfirst, cloningNow;

/*** do not change the order of definition */
struct _dkControl dkControlFlags;
struct _regBuffer registers;			//	RAM location to store the registers
char _dkenable28,_dkdisable28; 		// byte to store at RST28 enable, disable
int _SectorSize;
char	freq_divider;						// time constant for 19200 baud

#if (ENABLECLONING == 1)
char XCE_base;
int	biosCRC, XCE_addr;
#endif

// store value of GCSR register to determine reset reason
char	reset_status;					

// the internal I/O registers -the shadows
// parallel ports
char PADRShadow, PBDRShadow, PCDRShadow, PCFRShadow;
char PDDRShadow, PDCRShadow, PDFRShadow, PDDCRShadow, PDDDRShadow;
char PEDRShadow, PECRShadow, PEFRShadow, PEDDRShadow;

char GCSRShadow; 	// global control status register
char GOCRShadow; 	// global control
char GCDRShadow; 	// clock doubler

char MMIDRShadow; // memory management aux reg
char MB3CRShadow, MB2CRShadow, MB1CRShadow, MB0CRShadow; // mem bank cntrl regs
char IB0CRShadow, IB1CRShadow, IB2CRShadow, IB3CRShadow, IB4CRShadow, 
     IB5CRShadow, IB6CRShadow, IB7CRShadow;
char I0CRShadow, I1CRShadow;
char TACSRShadow, TACRShadow, TAT1RShadow, TAT4RShadow, TAT5RShadow,
	  TAT6RShadow, TAT7RShadow;
char TBCSRShadow, TBCRShadow;
char SPCRShadow, SACRShadow, SBCRShadow, SCCRShadow, SDCRShadow;

char NewPrintConFlag;

struct progStruct {
	ADDR24      RCB,RCE,    // root code (Begin and End)
					XCB,XCE,    // extended code (Begin and End)
					RDB,RDE,    // root data (Begin and End)
					XDB,XDE;		// extended data (RAM) (Begin and End)
	unsigned short  auxStkB,// aux stack Begin
					auxStkE,    // end
					stkB,       // stack begin
					stkE,       // end
					freeB,      // free begin
					freeE,      // end
					heapB,      // heap begin
					heapE;      // end
	}; 

// dc_timestamp and prog_param are defined by the compiler.	
extern struct progStruct prog_param;
// date/time stamp at the end of the compile (seconds since Jan. 1 1980)
extern long dc_timestamp; 

#if (ERRLOG_USE_MESSAGE==1)
	char   errlogMessage[8];
#endif
#if (ENABLE_ERROR_LOGGING==1)

struct _errLogInfo  errLogInfo;
struct _errLogEntry  errLogEntry;

#endif  // end if error logging enabled

/*** end of contiguous definition */

/*** end of variable definitions */
/*Begin Header prototypes**************/
 root void biosmain();
 root void dkInit();
 root void WaitSettle();
 root void dkInitTC();
 root void dkWriteMem();
 root void dkSerialISR();
 root void dkReadProgPort();
 root void dkWriteProgPort();
 root void divider19200();
 root void dkInitFCTable();
 root void dkDoMsg();
 root void __bp_init();
 root void dkBPInit();
 root void _xexit2();
 root void _xexit();
 root void dkSetIntVecTabP();
 root void dkSetIntVecTabR();
 root void dkStartup();
 root void dkEnd();
 root void symTab();
 root void AUX_STACK_LIMIT();
 root void AUX_STACK_PTR();
 root void STACK_LIMIT();
 root void symTabEnd();
/*End Header***************************/
#ifndef _TARGETLESS_COMPILE_
#define _TARGETLESS_COMPILE_ 0
#endif
#if (NUM_RAM_WAITST!=0)
#pragma DATAWAITSUSED on
#endif
#asm nodebug
biosmain::

// don't insert any code inbetween this label and the jp
// or the jp and the dw!!!
#ifdef _FLASH_
#if _TARGETLESS_COMPILE_ == 1
	jp		InFlashNow
#else
	jp		InRAMNow		;	jump to debugger kernel start up code
#endif
#else
	jp		InRAMNow
#endif
	dw		fcTable		;	pointer to the RAM-based fcTable	
divider19200::
#if _TARGETLESS_COMPILE_ == 1
	db 	_FREQ_DIV_19200_
#else
	db		00h			;  frequency divider for 19200 baud (value from coldloader)
#endif
loaderParameters:
	dw		BIOSCodeEnd	;	store BIOS size, RAM start location, and
	dw		InRAMNow    ;  dkBPInit entry point for use by loading utility.
	dw		dkBPInit

ErrLogConfiguration::
	dw 	0,0,0,0,0,0,0
ErrLogLastHeader::
	dw 	0,0,0,0,0,0
	dw 	0,0,0,0,0,0,0

I_am_a_fast_clone::
	dw    0
I_am_a_sterile_clone::
	db    0

InFlashNow::
#ifdef _FLASH_ 
dkInit::
	; set STATUS pin low and CLK pin off
	ld		a,0xA0
	ioi 	ld		(GOCR),a
	ld		a,00001000b	;	normal oscilator, processor and peri.
								;	from main clock, no periodic interrupt
	ioi   ld	(GCSR),a

#if (CLOCK_DOUBLED == 1)
	ld		a, (divider19200)
	cp		22					; 21 * 0.6144 = 12.9MHz (doubling cutoff)
	jr		c, canDouble
	xor	a
	jr		setGCDR
canDouble:
	ld		a, 07h			; 20ns nominal Low time, best for osc < 14MHz
setGCDR:
#else
	xor	a					; user says clock not doubled
#endif
	ioi	ld (GCDR), a	; if nonzero, clock is doubled
#endif


#ifdef _RAM_
InRAMNow::
	ld		hl,0x4001 	; reset BIOS flag
	xor   a
	ld    (I_am_a_fast_clone),a
	ld		(hl),a

	;; get frequency divider for 19200 baud from where coldloader stored it in RAM
	ld		a, (04002h)			; get FREQADDR, xtal frequency/0.6144MHz (from coldload)
	ld		(divider19200), a	; save in BIOS so it will be saved to flash

	ipset 3

//****** a slight delay for things to settle
	ld    b,50
	ld    de,0e8h        ; the upper 3 bits turn over every 1/1024 s
	ld    h,0
oloop:
	ld    a, 0x5a
	ioi 	ld (WDTCR),a	
	ld		a,0ffh			;write any value to 0r to capture count
	ioi	ld (RTC0R),a
	ld		iy,RTC0R
	ioi	ld L,(iy)
	and   hl,de
loop:	
	ld		a,0ffh			;capture and compare
	ioi	ld (RTC0R),a
	ld		iy,RTC0R
	ioi	ld a,(iy)
	and   e
	cp    L
	jr    z,loop
	djnz  oloop         ; loop until the first value reached  


	; set STATUS pin low and CLK pin off
	ld		a,0xA0
	ioi 	ld		(GOCR),a
	ld		a,00001000b		;	normal oscilator, processor and peri.
								;	from main clock, no periodic interrupt
	ioi   ld	(GCSR),a

#if (CLOCK_DOUBLED == 1)
	ld		a, (divider19200)
	cp		22					; 21 * 0.6144 = 12.9MHz (doubling cutoff)
	jr		c, canDouble2
	xor	a
	jr		setGCDR2
canDouble2:
	ld		a, 07h			; 20ns nominal Low time, best for osc < 14MHz
setGCDR2:
#else
	xor	a					; user says clock not doubled
#endif
	ioi	ld (GCDR), a	; if nonzero, clock is doubled
#endif

dkSetMMU:
	ld 	a,MEMBREAK
	ioi 	ld (SEGSIZE), a
	ld 	a, DATASEGVAL
	ioi 	ld (DATASEG), a	

#if (CS1_ALWAYS_ON==0)
	xor 	a
#else	
	ld 	a, 0x10
#endif
	ioi 	ld (MMIDR),a

	;; set up temporary stack in RAM
	ld		hl, BiosStack
	ld		de, BIOSSTACKSIZE-1
	add	hl, de
	ld		sp, hl

#ifdef _FLASH_
	ld 	a, MB0CR_SETTING
	ioi 	ld (MB0CR),a
	ld 	a, MB1CR_SETTING
	ioi 	ld (MB1CR),a
	ld 	a, MB2CR_SETTING
	ioi 	ld (MB2CR),a
	ld 	a, MB3CR_SETTING
	ioi 	ld (MB3CR),a

#if (CS1_ALWAYS_ON==0)
	xor 	a
#else	
	ld 	a, 0x10
#endif
	ld 	hl,MMIDRShadow
	ld    (hl),a
	ld 	a, MB0CR_SETTING
	ld 	hl,MB0CRShadow
	ld    (hl),a
	ld 	a, MB1CR_SETTING
	ld 	hl,MB1CRShadow
	ld    (hl),a
	ld 	a, MB2CR_SETTING
	ld 	hl,MB2CRShadow
	ld    (hl),a
	ld 	a, MB3CR_SETTING
	ld 	hl,MB3CRShadow
	ld    (hl),a
	ioi	ld a, (GCSR)
	
#if (ENABLE_ERROR_LOGGING==1)
	call  errlogRecordStartStatus
#endif

	ld		(reset_status), a		; save bits in GCSR to determine reason for reset

	// if the bank select jumper is enabled, we want to look
	// at the second memory quadrant with A18 not inverted
	ld		a, FLASH_WSTATES | 0x00
	ioi	ld (MB1CR), a 			// set up MB1 to point to primary flash
	ld		a, (MB1CRShadow)

	ld		hl, 0x01 | 0x02
	call	_readIDBlock

	ld		a, MB1CR_SETTING			// restore MB1CR
	ld		(MB1CRShadow), a
	ioi	ld (MB1CR), a

	bool	hl
	jr		z, idBlockOk
	;; erase SysIDBlock if error retured
	ld		hl, SysIDBlock
	ld		b, SysIDBlock+marker+6-SysIDBlock
	xor	a
blockEraseLoop:
	ld		(hl), a
	inc	hl
	djnz	blockEraseLoop
idBlockOk:

#if (_FLASH_SIZE_ == 0x80)
	ld		hl, 0x01 | 0x02
#else
	ld		hl, 0x01
#endif
	call	_InitFlashDriver

#endif // end of FLASH section


#ifdef _RAM_
	ld 	a, MB0CR_SETTING
	ioi 	ld (MB0CR),a
	ld 	a, MB1CR_SETTING
	ioi 	ld (MB1CR),a
	ld 	a, FLASH_WSTATES | CS_FLASH
	ioi 	ld (MB2CR),a
	ld 	a, FLASH_WSTATES | CS_FLASH
	ioi 	ld (MB3CR),a

	ld 	a, MB0CR_SETTING
	ld 	hl,MB0CRShadow
	ld    (hl),a
	ld 	a, MB1CR_SETTING
	ld 	hl,MB1CRShadow
	ld    (hl),a
	ld 	a, FLASH_WSTATES | CS_FLASH
	ld 	hl,MB2CRShadow
	ld    (hl),a
	ld 	a, FLASH_WSTATES | CS_FLASH
	ld 	hl,MB3CRShadow
	ld    (hl),a

//  Before we disable the flash, disable any existing
//  flash BIOS by writing a tight loop to the start 
//  of flash. This ensures that runmode will not work
//  until the BIOS and user program have been recompiled
//  to flash. This prevents the user from deploying a board
//  when he just compiled and debugged to RAM, because when
//  power cycles and the programming cable is not connected,
//  the previously loaded flash BIOS, if it exists, will run
//  the previously loaded user program, if it exists.

	ld		hl, 0x04 | 0x08
	call	_readIDBlock
	bool	hl
	jr		z, idBlockOk
	;; erase SysIDBlock if error retured
	ld		hl, SysIDBlock
	ld		b, SysIDBlock+marker+6-SysIDBlock
	xor	a
blockEraseLoop:
	ld		(hl), a
	inc	hl
	djnz	blockEraseLoop
idBlockOk:

#if DISABLE_FLSH_IF_RAM==1
	ld		hl, 0x04 | 0x08
	call	_InitFlashDriver

	;; load FlshTransferBuf with tight jump
	ld		a, FLASH_BUF_1619
	ld		ix, FLASH_BUF_0015
	ld		hl, 0xFE18
	ldp	(ix), hl
	
	;; write block to flash
	ld		a, (_FlashInfo+flashXPC)
	ld		de, 0xE000
	call	_WriteFlash
#endif
		
	// this will disable the flash,
	// everything mapped to RAM now.
	ld 	a, MB2CR_SETTING
	ioi 	ld (MB2CR),a
	ld 	a, MB3CR_SETTING
	ioi 	ld (MB3CR),a

#if (CS1_ALWAYS_ON==0)
	xor 	a
#else	
	ld 	a, 0x10
#endif
	ld 	hl,MMIDRShadow
	ld    (hl),a
	ld 	a, RAM_WSTATES   | 0x05 | (MB2CR_INVRT_A18<<4) | (MB2CR_INVRT_A19<<5)   
	ld 	hl,MB2CRShadow
	ld    (hl),a
	ld 	a, RAM_WSTATES   | 0x05 | (MB3CR_INVRT_A18<<4) | (MB3CR_INVRT_A19<<5)   
	ld 	hl,MB3CRShadow
	ld    (hl),a

#endif // end of RAM section

	; set STATUS pin low and CLK pin off
	ld		a, 0xA0
	ld		hl, GOCRShadow
	ld		(hl), a

	ld		a,00001000b			;	normal oscilator, processor and peri.
	ld 	hl, GCSRShadow
	ld    (hl), a

#if (CLOCK_DOUBLED == 1)
	ld		a, (divider19200)
	cp		22					; 21 * 0.6144 = 12.9MHz (doubling cutoff)
	jr		c, canDouble3
	xor	a
	jr		setGCDR3
canDouble3:
	ld		a, 07h			; 20ns nominal Low time, best for osc < 14MHz
setGCDR3:
#else
	xor	a					; user says clock not doubled
#endif
	ld		hl, GCDRShadow
	ld		(hl), a
	ld		a, 0c0h
	ioi	ld (PCFR), a	; as initialized in pilot
	ld 	hl, PCFRShadow	
	ld    (hl), a			

	ld    a,0xA0h
	ld		(statusPinState),a
	
	ld 	a,88h
	ld   	(OPMODE),a

	ld 	a,0
	ld   	(_dkfirst),a

#if (ENABLECLONING==1)
	;; check to see if cloning cable is attached
	ld 	a, 0x02
	ld		hl, PBDR
	ioi 	and a, (hl)
	ld 	hl, cloningNow
	jr 	nz, noCloneCable
	ld    (hl), 0x01
	jr    endCloneCheck
noCloneCable:
	ld    (hl), 0x00
endCloneCheck:
#else
	ld 	hl, cloningNow
	ld    (hl), 0x00
#endif

	ld b,SIZESTDIOBUFF
	ld hl,stdioCommBuff
clear_stdio:	
	ld (hl),0
	inc hl
	djnz clear_stdio

dkSetTimer:

	;	initialize baud rate generator
	;	for main clock at 8MHz, the calculation follows:
	;	timer A4 to clock serial port A
	;	timer A5 to clock serial port B
	;	timer A6 to clock serial port C
	;	timer A7 to clock serial port D

	;	make timers tick
	ld 	a, 00000001b
	ioi 	ld (TACSR),a
	ld 	hl,TACSRShadow
	ld    (hl),a

	;	make timer A4 clocked by main clock
	;	disable interrupt
	ld 	a, 00000000b
	ioi 	ld (TACR),a
	ld 	hl,TACRShadow
	ld    (hl),a

	;	Read the time constant for 19200 baud calculated by the coldloader...
	ld		a, (divider19200)
	ld		b, a
checkDoubled:
 ;; is clock doubled?
	ld		a, (GCDRShadow)	; get clock doubler register
	or		a
	jr		z, checkDiv			; if zero, clock not doubled
	sla	b						; if clock doubled, multiply constant by two
checkDiv:
 ;; is clock divided by eight?
	ld		a, (GCSRShadow)	; get global control/status register
	and	018h					; mask off unnecessary bits
	jr		nz, saveFreq		; if nonzero, periph clock not divided by 8
	srl	b
	srl	b						; divide by eight
	srl	b
saveFreq:
	ld		a, b
	ld		(freq_divider), a	; save for later use	

setDCbaudrate:
  ;; set up proper baud rate for Dynamic C communication by doing some
  ;; 		fixed-point arithmetic to get 57600 rate (= 19200 rate / 3)
	ld		c, 0					; bc = FREQADDR (b = integer part, c = fraction)
	ld		de, 055h				; de = ~1/3
	mul							; multiply it out
	ld		c, l					; keep integer part
	inc	c						; round up since 055h is actually slightly less than 1/3

check115k:
#if (USE115KBAUD==1)
	srl   c					 	; if 115200 baud wanted, divide by two
#endif

setBaudRate:
	dec	c						; put divider-1 into timer scaling registers
	ld		a, c
	ioi	ld (TAT4R),a		; save scaledown for 57600 baud
	ld 	hl,TAT4RShadow
	ld    (hl),a

#ifdef _RAM_ 
;******************************************************************************
; Enter here for sofware reset requested by Dynamic C
; to turn off periodic interrupt
dkInit::
	ipset 3	
	ld		a,00001000b		;	normal oscilator, processor and peri.
								;	from main clock, no periodic interrupt
	ioi   ld	(GCSR),a

;*******************************************************************************
#endif

	;	initialize comm ports now
	;	at port a, async, 8-bit, interrupt priority 1
	; make sure other serial ports are disabled
	ld		a, 0x00
	ioi	ld (SBCR), a
	ioi	ld (SCCR), a
	ioi	ld (SDCR), a
	ld		a, 0x01
	ioi 	ld (SACR),a
	ld 	hl,SACRShadow
	ld    (hl),a

dkSetSP:
	ld		hl,BiosStack			; Set up a temporary stack to perform call.
	ld    de,BIOSSTACKSIZE-1   ; Note that stack segment register is not setup here,
	add    hl,de					; but in _ProgStkSwitch.  _ProgStkSwitch is normally
	ld		sp,hl						; called in premain after stack alloc init.
	xor	a  						; zero the xpc
	ld    xpc,a

dkSetComm:
	ld		hl,dkcIState
	ld		(dkcState),hl		;	move to initial state
	call	dkInitTC
	call	dkSetIntVecTabP

dkSetProgPort:
	;	parallel port D, bit 6,0 as output lines
	ld		a,0xc3		;	jump instruction
	ld		(INTVEC_BASE+SERA_OFS),a
	ld		hl,dkSerialISR
	ld		(INTVEC_BASE+SERA_OFS+1),hl
#ifdef _FLASH_
	jp 	SkipRAMInit		

InRAMNow::						; this symbol must be global for cloning code!
	ipset 3
	xor    a
	ld    (I_am_a_fast_clone),a
	ld		hl,0x4001 	; reset BIOS flag
	ld		(hl),0
	ld 	hl,InFlashNow
	ld 	(biosmain+1),hl
	ioi	ld a, (GCSR); read reset status bits now so later they'll be cleared

	;; get frequency divider for 19200 baud from where coldloader stored it in RAM
	ld		a, (04002h)			; get FREQADDR, xtal frequency/0.6144MHz (from coldload)
	ld		(divider19200), a	; save in BIOS so it will be saved to flash

	; set status pin low
	ld		a,0xA0
	ioi 	ld		(GOCR),a


	;; map lower three quadrants to RAM, top one to flash
	;; 	flash quadrant has bits A18 and A19 inverted so it still points to
	;; 	flash address 0x0000 even if it's a 512kb flash!

	ld		a, 0xC8
	ioi	ld (SEGSIZE), a		
	xor	a
	ioi 	ld (DATASEG), a
	ioi	ld (STACKSEG), a

	ld    a, RAM_WSTATES   | CS_RAM
	ioi 	ld (MB0CR),a
	ld    a, RAM_WSTATES   | CS_RAM
	ioi 	ld (MB1CR),a
	ld    a, RAM_WSTATES   | CS_RAM
	ioi 	ld (MB2CR),a
	ld    a, FLASH_WSTATES | CS_FLASH | 0x30  	; invert A18 and A19
	ioi 	ld (MB3CR),a

	ld    a, RAM_WSTATES   | CS_RAM
	ld		(MB0CRShadow),a
	ld    a, RAM_WSTATES   | CS_RAM
	ld		(MB1CRShadow),a
	ld    a, RAM_WSTATES   | CS_RAM
	ld		(MB2CRShadow),a
	ld    a, FLASH_WSTATES | CS_FLASH | 0x30		; invert A18 and A19
	ld		(MB3CRShadow),a

	;; set up temporary BIOS stack
	ld		hl, BiosStack
	ld		de, BIOSSTACKSIZE-1
	add	hl, de
	ld		sp, hl

#if (ENABLE_ERROR_LOGGING==1)
	call InitializeErrorLog	
#endif

	// look for ID block on flash
	ld		hl, 0x08
	call	_readIDBlock
	bool	hl
	jr		z, idBlockOk0
	;; erase SysIDBlock if error retured
	ld		hl, SysIDBlock
	ld		b, SysIDBlock+marker+6-SysIDBlock
	xor	a
blockEraseLoop0:
	ld		(hl), a
	inc	hl
	djnz	blockEraseLoop0
idBlockOk0:
	ld 	de,(SysIDBlock+userBlockSize)
	ld 	hl,(SysIDBlock+idBlockSize)
	add   hl,de
	ld    (_store_ID_Block_Size),hl

	// set up bitmap of flash quadrants and initialize flash driver
	ld		hl, 0x08
	call	_InitFlashDriver

	;***** Compute number of BIOS sectors
	ld		hl, (_FlashInfo+sectorSize)
	ex		de, hl
	ld		hl, BIOSCodeEnd
	add	hl, de					; bump value up above next sector edge
	ld		a, d
	cp		001h						; does sector size = 0100h?
	jr		z, cont					; if so, don't need to change h = counter
	cp		002h						; does sector size = 0200h?
	jr		z, sec512
	cp		004h						; does sector size = 0400h?
	jr		z, sec1024
	cp		010h						; does sector size = 1000h?
	jr		z, sec4096
sec128:								; assume sector size = 0080h
	sla	h							; multiply by two
	jr		cont
sec4096:
	srl	h
	srl	h
sec1024:
	srl	h							; divide by two
sec512:
	srl	h							; divide by two
cont:
	inc	h							; add one for a safety buffer
	;;	h now contains number of sectors to copy!

	; initialize ldir parameters
	ld 	iy, 00000h				; source
	ld		a, (_FlashInfo+flashXPC)
	ld 	de, 0E000h				; destination in a:de

loop:
	push	hl
	ld		bc, (_FlashInfo+sectorSize)
	push	iy							; save source address
	call	_copyToFlashBuf
	pop	iy							; restore source address
	call	_WriteFlash

	ld		bc, (_FlashInfo+sectorSize)
	add	iy, bc

	ex 	af,af'
	call  bioshitwd

	xor	a
	cp		d							; have we left xmem window?
	jr		nz, keepGoing
	ex		af, af'
	add	a, 0x02					; increment XPC
	ld		de, 0xE000				; reset destination to start of xmem window
	ex		af, af'
keepGoing:
	ex 	af,af'

	pop	hl
	dec	h	
	jr    nz,loop

	call  bioshitwd

	ld    a, MEMBREAK
	ioi 	ld (SEGSIZE),a	

	ld    a, DATASEGVAL 
	ioi 	ld (DATASEG),a	

	jp InFlashNow
	
SkipRAMInit:
#endif

#if (ENABLECLONING == 1)
	ld    a,(I_am_a_sterile_clone)
	or    a
	jr    nz,_skip_clone_check

	;; see if cloning cable is attached (was PB1 low?)
	ld		a, (cloningNow)
	or		a
	jr		z, NotCloning
#if (ENABLE_FAST_CLONING==1)
	jp		FastCloneMode
#else
	jp		CloneMode
#endif
NotCloning:
#endif

_skip_clone_check:

	// initialize registers that come up in unknown states
	//		(and their shadow variables)
	xor	a
	ioi	ld (PADR), a
	ld		(PADRShadow), a
	ioi	ld (PBDR), a
	ld		(PBDRShadow), a
	ioi	ld (PCDR), a
	ld		(PCDRShadow), a

	ioi	ld	(PDDDR),a
	ld		(PDDDRShadow),a
	ioi	ld (PDDR), a
	ld		(PDDRShadow), a
	ioi	ld (PDFR), a
	ld		(PDFRShadow), a
	ioi	ld (PDDCR), a
	ld		(PDDCRShadow), a
	ioi	ld	(PEDDR),a
	ld		(PEDDRShadow),a
	ioi	ld (PEDR), a
	ld		(PEDRShadow), a
	ioi	ld (PEFR), a
	ld		(PEFRShadow), a

	ioi	ld (TBCSR), a
	ld		(TBCSRShadow), a
	ioi	ld (TBCR), a
	ioi	ld (TBCRShadow), a
	
	// initialize shadow variables for registers that come up in
	// known states (and haven't been set by the BIOS already)
	xor	a
	ld		(SPCRShadow), a
	ld		(PDCRShadow), a
	ld		(PECRShadow), a
	ld		(IB0CRShadow), a
	ld		(IB1CRShadow), a
	ld		(IB2CRShadow), a
	ld		(IB3CRShadow), a
	ld		(IB4CRShadow), a
	ld		(IB5CRShadow), a
	ld		(IB6CRShadow), a
	ld		(IB7CRShadow), a
	ld		(I0CRShadow), a
	ld		(I1CRShadow), a
	ld		(TAT1RShadow), a
	ld		(TBCRShadow), a
	ld		(SBCRShadow), a
	ld		(SCCRShadow), a
	ld		(SDCRShadow), a
		
	// Ignore SMODE pins
	//  Dynamic C does this, but need to do it running stand alone too.
	ld    a,0x80
	ioi	ld (SPCR), a
	ld		(SPCRShadow), a

	// check for run mode		
	ioi ld a,(SPCR)
	and 60h
	cp  60h
	jr  nz,RunMode 
	; Reset 

#if (ENABLE_FAST_CLONING==1)
	ld a,(I_am_a_fast_clone)
	or a
	jr nz,RunMode
#endif

dkLoop:
	call  bioshitwd
	ld 	hl,0
	ld 	(dkControlFlags+commAttn),hl          ; clear tables
	ld 	(dkControlFlags+breakLock),hl
	ld 	(dkControlFlags+watchReq),hl
	ld 	hl,dkControlFlags+keyReq
	ld 	(hl),0ffh      ; clear key request
	xor   a              ; 10-10-95
	ld 	hl,dkControlFlags+hardBreak
	ld    (hl), a        ; 10-10-95, 0 clear hard break flag
	inc   hl
	ld    (hl), a        ; 10-10-95, 0 clear doreset flag
	inc   hl
	ld    (hl), a        ; 10-10-95, 0 showmem
	inc   hl
	ld    (hl), a        ; 10-10-95, 0 spare
	ld 	hl,stepRelay
	ld 	de,dkBreakBP
	ld 	(hl),0c9h      ; ret
	inc   hl
	ld 	(hl),e
	inc   hl
	ld 	(hl),d     		; relay vector

	ipset 0
	call	dkBreakBP		; enter the debugger
   jp 	dkLoop			

RunMode:
	ipset 3
	call dkSetIntVecTabR       ;  disable debug RSTs
	ipset 0

#ifdef _RAM_ 
	ld hl,OPMODE
	ld (hl),0x80
	jp StartUserCode	
#endif

#ifdef _FLASH_
	ld 	a,80h
	ld   	(OPMODE),a

	call	WaitSettle

	jp StartUserCode	

#endif

;; This code repeatedly measures the timing on the 32kHz oscillator until
;; it matches twice in a row.  The 32kHz oscillator circuit could take as
;; long as 1.5 seconds to rise to a full voltage and we want to wait until
;; that is true...

WaitSettle::
	ld		de, 0000h				// first measurement value
	push	de							// save it for later
startmeas:
	ld		bc, 0000h				// our counter
	ld		de, 07FFh				// mask for RTC bits
wait_for_zero:
	ioi	ld (RTC0R), a			// load RTC registers
	ioi	ld hl, (RTC0R)			// read 1st two RTC registers
	and	hl, de					// mask off bits
	jr		nz, wait_for_zero		// repeat until all zero
timing_loop:
	inc	bc							// increment counter
	push	bc							// save counter
	ld		b, 057h					// empirically-derived loop counter
	ld		hl, WDTCR
delay_loop:
	ioi	ld	(hl), 05Ah			// hit watchdog
	djnz	delay_loop
	pop	bc							// restore counter
	ioi	ld (RTC0R), a			// load RTC registers
	ioi	ld hl, (RTC0R)			// read 1st two RTC registers
	bit	2, h						// test bit for 0800h
	jr		z, timing_loop			// if nonzero, keep looping
	
	ld		h, b						// h = upper nibble of counter
	ld		a, c						
	add	a, 08h					// (effectively rounding up)
	ld		l, a						// l = lower nibble of counter + 8
	rr		hl
	rr		hl
	rr		hl							// divide by 16
	rr		hl
	ld		a, l						// lower nibble is divisor!
	dec	a
	pop	de							// get last count
	cp		a, e						// compare last and current counts
	jr		z, donemeas				// if alike, done	
	ld		e, a
	push	de							// save this count
	jr		startmeas
donemeas:
	ret
	
dkInitTC::
	call	dkcInit					;	initialize comm module
	call	dkInitFcTable			;	initialize the 3-table
	call	dkInitControlFlags	;	initalize the control flags used by do28
	ret
		
	;	repeat trying until we read a byte from the receive buffer
dkReadAgain:
	call  bioshitwd
	call	dkReadProgPort
	jr		z,dkReadAgain

	;	repeat trying until we unload the byte to the transmit buffer
	ld		c,a
dkWriteAgain:
	call  bioshitwd
	call	dkWriteProgPort
	jr		nz,dkWriteAgain
		
	;	parallel port D, bit 0 goes to 0

dkWriteMem::
	// if log adr < DATAORG, use log Flash adr = phys adr
	// if log adr >= E000,   use phys adr with XPCval
	// if  DATAORG <= log adr < E000, use logical RAM addr
	ld    a,xpc
	push  af
	call  bioshitwd
	ld		a,(curHeader+address+1)
#ifdef _FLASH_
	cp		DATAORG>>8
	jr		nc,CheckXmem		
	xor   a                  ; any XPCval is garbage
	ld		(curHeader+XPCval),a
	call  FSM_Flash
	pop   af
	ld    xpc,a
	ret
#endif


CheckXmem:
	cp		0xe0
	jr		c,ItsInRootRAM

#ifdef _FLASH_ 
ItsInXMem:	
	; determine if phys addr is below 80000h
	ld		hl,(curHeader+address)
	ld    a,h
	srl   a
	srl   a
	srl   a
	srl   a
	ld 	hl,curHeader+XPCval
	add	a,(hl)
#ifdef USE_2NDFLASH_CODE   
	ld    c,a      ; save for 2nd flash check
#endif   
	and   0x80		; check the upper bit for ram store 
#ifdef _FLASH_
	jr    nz,ItsInXRAM
#endif

ItsInXFlash:
#ifdef USE_2NDFLASH_CODE   
	ld    a,c
	and  	0x40			
	jr   	z,nochangexpc				; in second flash?
	ld    a,0x32
	ld 	(_FlashInfo+flashXPC),a ; fool flash driver
nochangexpc:
#endif
	call 	FSM_XFlash		
#ifdef USE_2NDFLASH_CODE   
	ld    hl,_FlashInfo+flashXPC
   ld 	(hl),0xf2					; restore for 1rst flash
#endif   
	pop   af
	ld    xpc,a
	ret
#endif	

ItsInXRAM:
	ld		a,(curHeader+XPCval)
	ld    xpc,a
ItsInRootRAM:
	push  ip
	ipset 1
	ld		hl,(curHeader+address)		;	destination
	ex		de,hl
	ld		hl,commBuffer					;	source
	ld		a,(curHeader+length)
	ld		b,0
	ld		c,a
moveByte:
	ld		a,(hl)
	ld		(de),a
	inc	hl
	inc	de
	dec	c
	jr		nz,moveByte
	pop ip
	pop   af
	ld    xpc,a
	ret

#endasm

#asm

dkSerialISR::
	;	serial interrupt handler
	push	af
	ex    af,af'
	push	af
	ld    a,xpc
	push	af
	push	bc
	push	de
	push	hl
	push  ix	
	
	call	dkcEntry				;	enter the FSM

	ioi 	ld a,(SASR)			;	check the status
	bit	SS_TPRG_BIT,a		;	transmit in progress bit
	jr		nz,.readyToExit	;	transmit in progress, don't disable it
	;	transmit is not in progress, clear the transmit buffer empty
	;	flag now

	ioi 	ld (SASR), a

.readyToExit:

	pop   ix		
	pop	hl
	pop	de
	pop	bc
	pop	af
	ld    xpc,a
	pop	af
	ex    af,af'
	pop	af
	ipres
	ret

dkReadProgPort::
	;	destroys A
	;	returns byte read (if any) in A
	;	returns with Z set if nothing is read
		
	;	check if there is anything available
	ioi 	ld a, (SASR)
	bit	SS_RRDY_BIT,a		;	if a received byte ready?
	ret	z						;	nope, return with z set
	;	otherwise, a byte *is* ready, read from data port
	ioi 	ld a, (SADR)
	ret							;	return with z *not* set

dkWriteProgPort::
	;	assumes byte to transmit is in C
	;	destroys A
	;	returns with Z reset if not transmitted
		
	;	check if the port is ready
	ioi 	ld a, (SASR)
	bit	SS_TFULL_BIT,a		;	can I transmit now?
	ret	nz						;	nope, return with nz set
	;	otherwise, the transmit buffer is ready, write to it!
	ld		a,c					;	move byte to transmit to a
	ioi 	ld (SADR), a
	ret							;	return with z *not* set

	nop
dkDCID:
	db "DynamiC"
dkProdName:
	db PRODUCT_NAME
dkInitFcTable::
	;	initialize the fctable here

;	zero out everything first
	ld		hl,fcTable
	ld		b,_fcTable+@LENGTH
	xor	a
dkInitFCClrByte:
	ld		(hl),a
	inc	hl
	djnz	dkInitFCClrByte
	
;struct _fcTable {
;	char DCID[7];			//	this field should contain "DynamiC"
	ld		hl,dkDCID				;	note that this DCID is name of the string
	ld		de,fcTable+DCID	;	note that this DCID is a field ID
	ld		bc,7
	ldir  
;	char majorRev;			//	major revision
	ld		a,0x02
	ld		(fcTable+majorRev),a
;	char minorRev;			//	minor revision
	ld		a,0x00
	ld		(fcTable+minorRev),a
;	char targetName[8];	//	name of target
	ld		hl,dkProdName			;	name of string
	ld		de,fcTable+targetName
	ld		bc,8
	ldir
;	void *symTable;		//	pointer to symbol table
	ld		hl,symTab			;	symbol table address
	ld		(fcTable+symTable),hl
;	unsigned checksum;	//	checksum for library
;	void *codeBase;		//	base of code area
	ld		hl,0x2000
	ld		(fcTable+codeBase),hl
;	void *dataTop;			//	top of code
	ld		hl,0xda00
	ld		(fcTable+dataTop),hl
;	void *dataBase;		//	base (bottom) of data
	ld		hl,0x2000
	ld		(fcTable+dataBase),hl
;	void *codeTop;			//	top of data
	ld		hl,0xd900
	ld		(fcTable+codeTop),hl
;### needs to be filed
;	void *dbgStack;		//	pointer to debug stack
	bool	hl					// set the stack from the current stack pointer
	ld		l,a
	add	hl,sp
	ld		(fcTable+dbgStack),hl	;	note that this is the field dkDbgStack
;	void *stepVector;		//	stepping breakpoint vector
	ld		hl,stepRelay ;INTVEC_BASE+RST28_OFS			;	stepRelay
	ld		(fcTable+stepVector),hl
;	char chDisStep;		//	character to stop stepping breakpoint
	ld		a,0xc9			;	code for return
	ld		(fcTable+chDisStep),a
;	char chEnbStep;		//	character to enable stepping breakpoint
	ld		a,0xc3			;	code for jp
	ld		(fcTable+chEnbStep),a
;	void *trapVector;		//	pointer to TRAP development vector
;	void *rst38Vector;	//	pointer to RST 38 development vector
;	void *PFVector;		//	pointer to powerfail vector
;	### requires changes, hard coded for now
	ld		hl,0x22f3
	ld		(fcTable+PFVector),hl
;	void *commTable;		//	pointer to communication table
	ld		hl,dkControlFlags+commPtr
	ld		(fcTable+commTable),hl
;	char commAttn;			//	communication attention flag
	ld		hl,dkControlFlags+commAttn
	ld		(hl),0
;	char ramSize;			//	size of ram in 4kbyte pages
;### requires changes, hard coded for now
//	call	CheckRamSize
	ld		a,RAM_SIZE ;			;	128kbyte RAM

	ld		(fcTable+ramSize),a
;	char memBreak;			//	CBAR value
;### requires changes, hard coded for now
	ld		a,HW_MEMBREAK			;	typical EPROM/RAM break
	ld		(fcTable+memBreak),a
;	void *nextBankV;		//	next bank vector
;	void *biosEnd;			//	end of BIOS
	ld		hl,dkEnd
	ld		(fcTable+biosEnd),a
;	char xcodeTop;			//	top of xmem code
;this field doesn't seem to be used?
;	char ramStart;			//	start address of RAM in 4kbyte pages
;### requires changes, hard coded for now
	ld		a,RAM_START			;	typical RAM mapping
	ld		(fcTable+ramStart),a
   ld 	hl, _xexit
   ld    (DCParam+errorExit), hl  ; initialize error exit
	ret
#define ERROR_EXIT DCParam+errorExit
bioshitwd::
	push  af
	ld    a, 0x5a
	ioi 	ld (WDTCR),a	
	pop  af
	ret
#endasm

#asm
dkDoMsg::
.waitFlagClear:
	ld		a,(dkControlFlags+commAttn)
	or		a
	jr		nz, .waitFlagClear

	push	ip
	ipset	1
	;	flag is now cleared
	ld		de, stdioCommBuff+4
	ld		bc,0

	; store the new print flag
	ld		a,(NewPrintConFlag)
	ld		(fcTable+PrintToCon),a	
	
.chkEOM:
	ld		a,(hl)
	or		a
	jr		z,.foundEOM

	ld		(de),a
	inc	hl
	inc	de
	inc	bc
	jr		.chkEOM

.foundEOM:
	ld		(stdioCommBuff),bc

	ld		a,1
	ld		(dkControlFlags+commAttn),a

	ld		hl,(dkControlFlags+commPtr) 
   pop   ip
	ret

#endasm

#asm
__bp_init::
dkBPInit::
	ld		hl, (fcTable+chDisStep) ; Get Enable/Disable Bytes
	ld 	(_dkdisable28),hl   ; disable byte and enable byte
	ld		hl,	stepRelay ;(fcTable+stepVector)
	ld 	a,	(_dkenable28)
	ld		(hl),	a							;	enable break point
	ld 	hl,	DCSrcDebug+fEntryCount      ; Pointer to Control
	ld 	(hl),	0      ; Disable Control Initially
	ld	 	de,	DCSrcDebug+nestCount		;	some convention used by do18?
	rst 18h
#endasm

#asm
_xexit2::
	rst	18h
	ipset 3
	jp		_xexit2

_xexit::
	rst	18h
	ipset 3
	ld    a,0x53
	ioi   ld (WDTCR),a
_xexitLoop:
	jp		_xexitLoop
#endasm

#asm
	
dkSetIntVecTabP::	 ; Program mode
	;	set up interrupt vector table
	ld		a,0xff & (INTVEC_BASE >> 8)	;
	ld		iir,a
	ld		a,0xff & (XINTVEC_BASE >> 8)	;
	ld		eir,a
	ld		a,0xc3		;	this is the jump instruction
	ld		(INTVEC_BASE+RST18_OFS),a		;	all are relays
	ld		(INTVEC_BASE+RST20_OFS),a
	ld		(INTVEC_BASE+RST28_OFS),a
	ld		hl,dkSoftBP
	ld		(INTVEC_BASE+RST18_OFS+1),hl
	ld		hl,dkHardBP
	ld		(INTVEC_BASE+RST20_OFS+1),hl
	ld		hl,stepRelay;dkBreakBP
	ld		(INTVEC_BASE+RST28_OFS+1),hl
	ld    hl,dkBreakBP 
	ld    (stepRelay+1),hl
	ld    a,0c3h
	ld    (stepRelay),a
	ret

dkSetIntVecTabR::   ; Runmode
	;	set up interrupt vector table
	ld		a,0xff & (INTVEC_BASE >> 8)	;
	ld		iir,a
	ld		a,0xff & (XINTVEC_BASE >> 8)	;
	ld		eir,a
	ld		a,0xc9		;	this is the ret instruction
	ld		(INTVEC_BASE+RST18_OFS),a		;	all are relays
	ld		(INTVEC_BASE+RST20_OFS),a
	ld		(INTVEC_BASE+RST28_OFS),a
	ret

; .startup/dkStartup
; code to run each time the program executes
; initializes the stack allocation 
;
dkStartup::	
	pop hl
   jp	(hl)					; jump to old return address
	
#endasm

//#flushlib

#asm

dkEnd::
__xexit2:: jp _xexit2
__xexit::  jp _xexit
#endasm

#flushlib

#asm
symTab::
	dw		symsize

	dw RAM_START
	db 0
	db "IOP_RAM_STAR",'T'+0x80

	dw DATASEGVAL
	db 0
	db "IOP_DATASEGVA",'L'+0x80
	
	dw RAM_SIZE
	db 0
	db "IOP_RAM_SIZ",'E'+0x80
	
	dw INTVEC_BASE
	db 0
	db "IOP_INTVEC_BAS",'E'+0x80
	
	dw FLASH_SIZE
	db 0
	db "IOP_FLASH_SIZ",'E'+0x80

	dw DATAORG
	db 0
	db "IOP_DATAOR",'G'+0x80

	dw STACKORG
	db 0
	db "IOP_STACKOR",'G'+0x80

	dw OPMODE
	db 0
	db "OPMOD",'E'+0x80

	dw		__xexit2
	db		0
	db		"..exit",'2'+0x80

	dw		_xexit
	db		0
	db		"exi",'t'+0x80

	dw		__xexit
	db		0
	db		".exi",'t'+0x80
	
	dw		_xexit
	db		0
	db		".exit",'2'+0x80

AUX_STACK_LIMIT:: EQU DCParam+auxStackLimit

AUX_STACK_PTR:: EQU DCParam+auxStackPtr

STACK_LIMIT::	EQU DCParam+stackLimit

	dw		DCParam+rst28Swt
	db		0
	db		"RST28SW",'T'+0x80

	dw		DCParam+rst28SwtOff
	db		0
	db		"RST28SWT_OF",'F'+0x80

	dw		dkStartup
	db		0
	db		".startu",'p'+0x80

	dw dkBPInit
	db	0
	db	"..bp_ini",'t'+0x80

_store_ID_Block_Size::
	dw 0xffff
	db	0
	db	"_ID_BLOCK_SIZE",'_'+0x80

#endasm

//#flushlib

//	we need to end the symbol table now
#asm
	dw	0		;	indicates end of symbol table
	db	0

symTabEnd::
symsize: equ symTabEnd-symTab-2
#endasm


// include bios C support libraries
#use default.h

//!!!Do NOT insert code between here and #pragma CompileProgram!!!
//#flushlib
#asm
BIOSCodeEnd:
StartUserCode::
#endasm
#pragma CompileProgram

