/* --------------------------------------------------------------- */
/*                                                                 */
/*  Copyright 1988-1996, Rigel Corporation, Gainesville, Florida   */
/*                                                                 */
/*  phone: (352) 373-4629                                          */
/*  fax:   (352) 373-4629                                          */
/*                                                                 */
/*  http://www.rigelcorp.com                                       */
/*                                                                 */
/*  RIGEL confidential - for internal use only                     */
/*                                                                 */
/*  COMPILE WITH <TURBO C> OR <BORLAND C>                          */
/*  may require minor changes for compilation with <Microsoft C>   */
/*                                                                 */
/* --------------------------------------------------------------- */


#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>

#include <bios.h>
#include <conio.h>
#include <ctype.h>
#include <dos.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define PlainKeys          1
#define AltKeys            2
#define BufferSize    0x4000           /* 16k bytes.           */
#define BufferSize_1  0x3fff           /* BufferSize - 1       */


typedef  unsigned int  BOOL;
typedef  unsigned char BYTE;
typedef  unsigned int  UINT;

#define   TRUE        1
#define   FALSE       0
#define   ESC        27

/*--- global goodies --------------------------------------- */
BYTE  Com_ID     = 1;    // port COMM2
BYTE  nComPort   = 2;    // port COMM2

UINT  com_params = 0xe3; // 9600 Baud
/*------------------------------------------------------------------*\
| $00e3 for default 9600 baud, 8 data bits, 1 stop bit, no parity.  |
| com_params=bbbppsll where                                         |
|	  bbb: baud rate 110,150,300,600,1200,2400,4800,9600        |
|          pp: parity 0:no, 1: odd, 3:even                          |
|           s: stop bit: 0 (1 stop bit) or 1 (2 stop bits)          |
|          ll: word length: 2 (7-bit) or 3 (8-bit)                  |
\*------------------------------------------------------------------*/

unsigned int  tailptr, headptr;
int           overflow;
unsigned char buffer[BufferSize];

unsigned int  com_dataport,
	      com_interruptenableport,
	      com_interruptidport,
	      com_linecontrolport,
	      com_modemcontrolport,
	      com_linestatusport,
	      com_modemstatusport;

/* ---- interrupt function vectors ---------------------------------------- */
void interrupt far (*oldhandler)(...);
/* ------------------------------------------------------------------------ */

/* ------------------------------------------------------------------------- */
/* :::::::::::::: interrupt service routine :::::::::::::::::::::::::::::::: */
/* ------------------------------------------------------------------------- */
void interrupt far inthandler(...){ /* interrupt0bh handling routine */

 while(!(inportb(com_interruptidport) & 1))
  {
   if((inportb(com_interruptidport) & 0x06)==4)
    {
     if(tailptr<BufferSize_1) tailptr++; else tailptr=0;
     if(tailptr!=headptr) buffer[tailptr] = inportb(com_dataport);
       else
	{
	 if(tailptr>0) tailptr--; else tailptr=BufferSize_1;
	 overflow=1;
	 inportb(com_dataport);
	 }
     }
   }
 outportb(0x20, 0x20);
}
/* ------------------------------------------------------------------------ */
/* :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: */
/* ------------------------------------------------------------------------ */
void send(unsigned char b){
/* waits for transfer hold register empty */
 while(!(inportb(com_linestatusport) & 0x20)); /* until thre */
 outportb(com_dataport, b);
}
/* ------------------------------------------------------------------------ */
unsigned char receive(void){

 if(headptr != BufferSize) headptr++; else headptr = 0;
 return(buffer[headptr]);
}
/* ------------------------------------------------------------------------ */
void send_str(char *s){
int i;

 if(*s) for(i=0;i<strlen(s);i++)send((unsigned char)s[i]);
 send(13); /* send a <cr>. */
}
/* ------------------------------------------------------------------------ */
int CharReady(void){return(headptr!=tailptr);}
/* ------------------------------------------------------------------------- */
void beep(void){ sound(880); delay(200); nosound(); }
/* ------------------------------------------------------------------------- */
void kbdw(void){
 while(bioskey(1)) bioskey(0);
 bioskey(0);
}
/* ------------------------------------------------------------------------ */
void Help(void){
 printf("\n\nCommands:\n");
 printf("--------------------------\n");
 printf("ALT-Q         Quit\n");
 printf("F1 or ESC     Help\n");
 printf("F2            Bootstrap\n");
 printf("ALT-Q         Quit\n\n");
 printf("Press any key to continue...\n\n");
 kbdw();
 printf("In terminal mode...\n\n");
}
/* ------------------------------------------------------------------------ */
void OptionsSetup(int argc, char **argv){

 clrscr();
 printf("XHost V2.2 (c) Rigel Corp. 1988-1996\n");
 printf("Skeletal code for bootstrapping C16x microcontrollers\n");

 if(argc>1)
  {
   if(*argv[2]=='C')
    {
     switch(*(argv[2]+1))
      {
       case '1' : nComPort = 1;
                  break;
       case '2' : nComPort = 2;
                  break;
       default  : printf("Unrecognized Parameter: %s\n",argv[2]);
       }
     }
   }

 printf("\nCurrently Selected Options: \n ");
 switch(nComPort)
  {
   case 1 : printf("Serial Port 1 "); break;
   case 2 : printf("Serial Port 2 "); break;
   default: printf("Error: Serial Port Must be 1 or 2 - default 1 will be used\n");
   }

 printf("\n\n");
 printf("For COMM1, Run XHost with the command line option\n\n");
 printf("   XHost c=1\n\n");

 Help();
}

/* ------------------------------------------------------------------------ */
void SetComPorts(void){
 switch(nComPort)
  {
   case 1 : Com_ID = 0;
	    com_dataport            = 0x3f8;
	    com_interruptenableport = 0x3f9;
	    com_interruptidport     = 0x3fa;
	    com_linecontrolport     = 0x3fb;
	    com_modemcontrolport    = 0x3fc;
	    com_linestatusport      = 0x3fd;
	    com_modemstatusport     = 0x3fe;
	    break;

  case 2 :  Com_ID = 1;
	    com_dataport            = 0x2f8;
	    com_interruptenableport = 0x2f9;
	    com_interruptidport     = 0x2fa;
	    com_linecontrolport     = 0x2fb;
	    com_modemcontrolport    = 0x2fc;
	    com_linestatusport      = 0x2fd;
	    com_modemstatusport     = 0x2fe;
	    break;
  default:  printf("Error : Serial Port ID be 1 or 2\n");
	    exit(1);
    }
}

/* ------------------------------------------------------------------------ */
void com_setup(void){
struct REGPACK reg;

 SetComPorts();
 switch(Com_ID)
  {
   case 0 :   /* com1 */
	    oldhandler = getvect(0x0c);	 /* save the old interrupt vector */
	    setvect(0x0c, inthandler);   /* install interrupt 0ch vector     */
	    outportb(0x21, inportb(0x21) & 0xef); /* 8259 mask - enable int 0ch/ir 4  */
	    break;

   case 1 :  /* com2 */
	    oldhandler = getvect(0x0b);	 /* save the old interrupt vector */
	    setvect(0x0b, inthandler);   /* install interrupt 0ch vector     */
	    outportb(0x21, inportb(0x21) & 0xf7); /* 8259 mask - enable int 0bh/ir 3  */
   }

 reg.r_dx = Com_ID;
 reg.r_ax = com_params;
 intr(0x14, &reg);

 outportb(com_linecontrolport,3);    /* dlab = 0                            */
 outportb(com_modemcontrolport,8);   /* force aux2 control low              */
 outportb(com_interruptenableport,1);/* 8250 interrupts upon data available */
 tailptr  = 0;
 headptr  = 0;
 overflow = 0;

 switch(Com_ID)
  {
   case 0 : outportb(0x21, inportb(0x21) & 0xef); /* 8259 mask - enable int 0ch/ir 4  */
	    break;
   case 1 : outportb(0x21, inportb(0x21) & 0xf7); /* 8259 mask - enable int 0bh/ir 3  */
   }
}
/* ------------------------------------------------------------------------ */
void com_wrapup(void){

 outportb(com_interruptenableport, 0); /* 8250 interrupts disabled          */
 outportb(com_modemcontrolport, 0);    /* reset modem control register      */

 switch(Com_ID)
  {
   case 0 : /* com1  */
	    setvect(0x0c, oldhandler);            /* restore interrupt 0ch vector       */
	    outportb(0x21, inportb(0x21) | 0x10); /* 8259 mask - disable int 0ch - ir 4 */
	    break;
   case 1 : /* com2  */
	    setvect(0x0b, oldhandler);            /* restore interrupt 0bh vector       */
	    outportb(0x21, inportb(0x21) | 0x08); /* 8259 mask - disable int 0bh - ir 3 */
   }

 outportb(com_linecontrolport, inportb(com_linecontrolport) & 0x7f); /* dlab = 0                           */
 if( (inportb(com_linestatusport) & 1) ) inportb(com_dataport);    /* flush input port                   */
}
/* ------------------------------------------------------------------------ */
void SendBinFile(char *sFileName){
int    hBinFile;
UINT   nCount, nScriptLength;
BYTE   ucBuffer[0x800];  // 2K buffer

 hBinFile=open(sFileName, O_BINARY | O_RDONLY, S_IREAD);
 if(hBinFile==-1)
  {
   printf("cannot open %s\n",sFileName);
   return;
   }

 nCount = (UINT) filelength(hBinFile);
 lseek(hBinFile, 0L, SEEK_SET);
 nScriptLength=read(hBinFile, (void *)ucBuffer, nCount);
 if(nCount!=nScriptLength)
  {
   printf("error : %d of %d bytes read\n", nCount, nScriptLength);
   close(hBinFile);
   return;
   }

 for(nCount=0; nCount<nScriptLength; nCount++)
  {
   send(ucBuffer[nCount]);
   delay(1);
   }

 close(hBinFile);
}
/* ------------------------------------------------------------------------ */
void Boot(void){
BYTE bCh;
BOOL bGotAck;

 while(CharReady()) printf("%c",(char)receive());

 printf("\n========== Boot =====================================================\n");

 printf("\nPlease Verify Jumper Settings\n\n");

 printf("    Task        Label  Jumper  Setting (+ : present    - : absent)     \n");
 printf("-------------- ------ -------- --------------------------------------  \n");
 printf("Memory Decode    ROM    SW2     Hi (towards the serial ports)          \n");
 printf("Memory Decode    RAM    SW3     Lo (towards the serial ports)          \n");

 printf("Reset Options  RSTOPT  JP21     15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0  \n");
 printf("                                 -  -  -  -  +  + - + - + - + - - - -  \n");

 printf("\nPress Reset On the Board...  Then Press Any Key to Continue...\n");
 while(bioskey(1)) bioskey(0);
 bioskey(0);

// --- handshake code ---
 printf("\n\rInitiating Handshake... ");
 send(0);
 delay(250);
 bGotAck=FALSE;
 while(CharReady())
  {
   bCh=receive();
   if(bCh==0xc5) bGotAck=TRUE;
   printf("[0x%02X]\n",bCh);
   }
 if(!bGotAck)
  {
   printf("\n\rHandshake Failed...\n");
   printf("Press Reset On the Board and Check the Jumpers...\n");
   printf("\n\r========== Boot aborted =============================================\n");
   return;
   }
  else printf("Successful Handshake...\n");

// --- send script ---
 printf("\nSending bootstrap script (X67CR.bin)...Please Wait...\n");
 SendBinFile("x67cr.bin");
 delay(100);
 printf("\n");
 while(CharReady()) printf("%c",(char)receive());

// --- send minmon ---
 printf("\nSending the minumum monitor (XMM67CR.bin)...Please Wait...\n");
 SendBinFile("xmm67cr.bin");
 delay(10);
 send('\r');
 delay(100);
 printf("\n");
 while(CharReady()) printf("%c",(char)receive());

 printf("\n\n========== Boot ends ================================================\n");
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------- */
/*            main                                                           */
/* ------------------------------------------------------------------------- */
void main(int argc, char **argv){
unsigned char scan_code;
int           iC;
BOOL          bQuit;
char          C;

 nosound();
 OptionsSetup(argc, argv);
 com_setup();
 bQuit = 0;
 setcbrk(0);

 while(bioskey(1))bioskey(0);
 send_str("h");

 do
  {
  textcolor(15);
  while(CharReady()) printf("%c",(char)receive());
  if(overflow)
   {
    printf("ERROR - Communications Port Buffer Overflow\n");
    printf("        Incoming Data May Be Lost\n");
    overflow=0;
    }

  if(bioskey(1))
   {
    C=(char)(iC = bioskey(0));
    switch(C)
     {
      case (char) 8   : send(127);  /*backspace*/
		        break;
      case (char) ESC : Help();     /*escape*/
		        break;
      case (char) 0   : scan_code = (unsigned char)(iC>>8);
		        switch(scan_code)
		         {
			  case  59     /*F1    */ : Help();
                                                    break;
			  case  60     /*F2    */ : Boot();
                                                    break;
			  case  105    /*Alt-F2*/ : break;
			  case  16     /*Alt-Q */ : bQuit = 1;
			  }
		        break;

	    default   : send((int)(C));
      }
    }
   } while(!bQuit);

 com_wrapup();
}
/* -------------------------------------------------------------------------- */