/*	Subttl	Includes*/
#include "stdio.h"
#include "ctype.h"
#include "pindrivr.h"
#include "window.h"
#include "tic.h"

/*	Subttl	Equates*/
#define TRUE				1
#define FALSE				0

extern unsigned int UdiSegment;

FILE *fp, *fopen();

static unsigned int eof_flag;
static unsigned int checksum;

download_lib (fname)
char *fname;
{
    unsigned char hex_field_char;
    unsigned int char_count;
    unsigned int char_counter;
    unsigned int start_addr;
    unsigned int rec_type;
    unsigned rec_checksum;
    unsigned cksum;
    unsigned int load_address;
    int line_cnt;
    unsigned get_one_byte ();
    unsigned get_two_bytes ();

    int err_code=0;
    eof_flag = FALSE;
    line_cnt = 1;

    fp = fopen(fname,"r");
    if(fp == NULL) return(2);

    for (hex_field_char = get_fchar(); !err_code && eof_flag != TRUE; hex_field_char = get_fchar ())
    {
	if (hex_field_char == ':')
	{
	    checksum = 0;

	    char_count = get_one_byte ();
	    load_address = get_two_bytes ();
	    if(line_cnt == 1) start_addr = load_address;

	    rec_type = get_one_byte ();
	    switch (rec_type)
	    {
		case 0:
		{
		    outportb(FifoCmdPort,0x80);
		    outportb(FifoCmdPort,0x80);
		    outportb(FifoDataPort,LOAD_CODE);
		    outportb(FifoDataPort,char_count);
		    outportb(FifoDataPort,load_address>>8);
		    outportb(FifoDataPort,load_address);
		    cksum = 0;
		    for (char_counter = 0; char_counter < char_count; char_counter++)
		    {
			hex_field_char = get_one_byte();
			cksum += hex_field_char;
			outportb(FifoDataPort,hex_field_char);
		    }
		    rec_checksum = get_one_byte ();
		    outportb(FifoDataPort,~cksum+1);
		    if (checksum & 0xff)
		    {
			err_code = 1;
		    }
		    break;
		}

		case 1:
		{
		    get_one_byte ();
		    eof_flag = TRUE;
		    break;
		}

		default:
		{
		    for (char_counter = 0; char_counter < char_count; char_counter++)
		    {
			get_one_byte ();
		    }
		    get_one_byte ();
		}
	    }
	}
	line_cnt++;
    }

    fclose(fp);
    return (err_code);
}


unsigned get_one_byte ()
{
    unsigned int first_byte;
    unsigned char ch;

    ch = get_fchar();
    if(ch >= 'A' && ch <= 'F') ch = ch - 'A' + 10;
    else if(ch >= '0' && ch <= '9') ch = ch - '0';
    first_byte = ch;
    ch = get_fchar();
    if(ch >= 'A' && ch <= 'F') ch = ch - 'A' + 10;
    else if(ch >= '0' && ch <= '9') ch = ch - '0';
    first_byte = (first_byte << 4) + ch;
    checksum += first_byte;
    return (first_byte);
}

unsigned get_two_bytes ()
{
    return (get_one_byte () * 256 + get_one_byte ());
}

int get_fchar()
{
    unsigned int ch;
    while(1)
    {
	ch = getc(fp);
	if(ch == EOF) eof_flag = TRUE;
	if(!isspace(ch)) break;
    }
    return(ch);
}

wrfifocmnd(cmnd)
int cmnd;
{
    outportb(FifoCmdPort,0x01);
    outportb(FifoCmdPort,cmnd);
}

rdfifostat()
{
    outportb(FifoCmdPort,0x00);
    return inportb(FifoCmdPort) & 0x00ff;
}


old_execute (address)
unsigned int address;
{
#asm
	FifoCmdPort  Equ  313h
	FifoDataPort Equ  312h

	Mov	AL,80h		    ;frame the code
	Mov	DX,FifoCmdPort
	Out	DX,AL
	Out	DX,AL
	Mov	DX,FifoDataPort
	Mov	AL,4		    ;execute command
	Out	DX,AL
	Mov	AL,[BP+5]	    ;pass address
	Out	DX,AL
	Mov	AL,[BP+4]
	Out	DX,AL
#endasm
}


execute_function (function)
unsigned char function;
{
    while (rdfifostat () & AF_FLAG){}	     /* loop until AF flag is reset */
    outportb (FifoCmdPort, 0x80);	     /* frame the command */
    outportb (FifoCmdPort, 0x80);
    outportb (FifoDataPort, EXEC_FUNC);
    outportb (FifoDataPort, function);
}


execute_code (address)
unsigned int address;
{
    while (rdfifostat () & AF_FLAG){}	   /* loop until AF flag is reset */
    outportb (FifoCmdPort, 0x80);	     /* frame the command */
    outportb (FifoCmdPort, 0x80);
    outportb (FifoDataPort, EXECUTE);
    outportb (FifoDataPort, address >> 8);   /* pass the address */
    outportb (FifoDataPort, address);
}


/* This function will be used to move the data from the code bank
     to the data bank. */

move_data_block (start_address, dest_address, count)
unsigned int start_address;
unsigned int count;
{
    while (rdfifostat () & AF_FLAG){}	   /* loop until AF flag is reset */
    outportb (FifoCmdPort, 0x80);	     /* frame the command */
    outportb (FifoCmdPort, 0x80);
    outportb (FifoDataPort, MOVE_BLOCK);
    outportb (FifoDataPort, start_address >> 8);   /* pass source the address */
    outportb (FifoDataPort, start_address);
    outportb (FifoDataPort, dest_address >> 8);   /* pass destination the address */
    outportb (FifoDataPort, dest_address);
    outportb (FifoDataPort, count >> 8);
    outportb (FifoDataPort, count);
}


/* This function will be used to load the 196 processor's internal
    registers (in words). The register no. and the data must
    be specified. */

load_196_reg (reg_no, data)
unsigned int reg_no;
unsigned int data;
{
    while (rdfifostat () & AF_FLAG){}	   /* loop until AF flag is reset */
    outportb (FifoCmdPort, 0x80);	   /* frame the command */
    outportb (FifoCmdPort, 0x80);
    outportb (FifoDataPort, LOAD_REG);
    outportb (FifoDataPort, reg_no);
    outportb (FifoDataPort, data >> 8);
    outportb (FifoDataPort, data);
}


/* This function will return the version number on the turbo interface card. */

unsigned char get_tic_version ()
{
    unsigned char data;
    unsigned char exit_flag;

    while (rdfifostat () & AF_FLAG){}	   /* loop until AF flag is reset */
    outportb(FifoCmdPort,0x80); 	   /* frame the command */
    outportb(FifoCmdPort,0x80);
    outportb(FifoDataPort,GET_VERS);

    /*load_196_reg (07, 0x8642);*/
    /*execute_function (2);*/
    /*execute_code (0x8329);*/
    return (tic_wait ());
}


/* This function will be used to wait for the execution of a tic function.
    This will exit if a framed bit is detected. It will return the last
    byte read from the FIFO. */

tic_wait ()
{
    unsigned char data;
    unsigned char exit_flag;

    while (1)
    {
	data = inportb (FifoDataPort);
	if (rdfifostat () & FD_FLAG)
	{
	    break;
	}
    }

    return (data);
}

/* This function will be used to load a word into the tic data RAM.
    Enter with address and data. */

load_data_word (data, address)
unsigned int data;
unsigned int address;
{
    int chksum;
    /* download address */
    while (rdfifostat () & AF_FLAG){}	   /* loop until AF flag is reset */
    outportb (FifoCmdPort, 0x80);	   /* frame the command */
    outportb (FifoCmdPort, 0x80);
    outportb (FifoDataPort, LOAD_DATA);
    outportb (FifoDataPort, 2); 	   /* no of byte(s) */
    outportb (FifoDataPort, address >> 8);
    outportb (FifoDataPort, address);
    outportb (FifoDataPort, data);   /* low byte first */
    outportb (FifoDataPort, data >> 8);

    chksum = 0;
    chksum = (data & 0x00ff) + (data >> 8);
    outportb (FifoDataPort, ~chksum + 1);
}


/* This function will be used to load a string of data into the data bank
    of the interface card. Enter with a pointer to the string, size of
    string element (1 - byte, 2 - word size), no of elements to process,
    and the data target address. */
/* If count == 0, string is null terminated. */

dnld_string (ptr, size, count, address)
void *ptr;
unsigned int size;
int count;
unsigned int address;

{
    int chksum;

    /* download address */
    outportb (FifoCmdPort,0x80);
    outportb (FifoCmdPort,0x80);
    outportb (FifoDataPort,LOAD_DATA);
    outportb (FifoDataPort,strlen (ptr));   /* no of bytes */
    outportb (FifoDataPort,address >> 8);
    outportb (FifoDataPort,address);

    outportb (FifoDataPort,0x29);   /* low byte first */
    outportb (FifoDataPort,0x83);

    chksum = 0;
    chksum = 0x29 + 0x83;
    outportb (FifoDataPort,(~chksum + 1));

    /* download address */
    outportb (FifoCmdPort,0x80);
    outportb (FifoCmdPort,0x80);
    outportb (FifoDataPort,LOAD_DATA);
    outportb (FifoDataPort,2);	 /* no of bytes */
    outportb (FifoDataPort,0x90);
    outportb (FifoDataPort,0x02);

    outportb (FifoDataPort,0x53);   /* low byte first */
    outportb (FifoDataPort,0x82);

    chksum = 0;
    chksum = 0x53 + 0x82;
    outportb (FifoDataPort,(~chksum + 1));

    /* download address */
    outportb (FifoCmdPort,0x80);
    outportb (FifoCmdPort,0x80);
    outportb (FifoDataPort,LOAD_DATA);
    outportb (FifoDataPort,2);	 /* no of bytes */
    outportb (FifoDataPort,0x90);
    outportb (FifoDataPort,0x00);

    outportb (FifoDataPort,0x00);   /* low byte first */
    outportb (FifoDataPort,0x82);

    chksum = 0;
    chksum = 0x82;
    outportb (FifoDataPort,(~chksum + 1));
}


/* This function will be used to test the basic pc-cpu communication.
    It will return a TRUE if the test is successful, FALSE, otherwise. */

cpu_test ()
{
    int ctr;
    int status;
    int data;
    int tmp_data;

    status = TRUE;

    /* flush fifo */
    for (ctr = 0; ctr < FIFO_SIZE; ctr++)
    {
	inportb (FifoDataPort);
    }

    /* send data, wait, then retrieve sent data */
    for (ctr = 0; (status == TRUE) && (ctr <= 0xff); ctr++)
    {
	/*while (rdfifostat () & AF_FLAG){}	 /* loop until AF flag is reset */
	outportb (FifoCmdPort, 0x80);	       /* frame the command */
	outportb (FifoCmdPort, 0x80);
	outportb (FifoDataPort, CARDTEST);
	outportb (FifoDataPort, 0x00);	       /* subtest 0 */
	outportb (FifoDataPort, ctr);
	delay_us (250);
	data = inportb (FifoDataPort);
	if (data != ctr)
	{
	    status = FALSE;
	}
    }

    /* send data, wait, then retrieve sent data from the mailbox */
    for (ctr = 0; (status == TRUE) && (ctr <= 0xff); ctr++)
    {
	/*while (rdfifostat () & AF_FLAG){}	 /* loop until AF flag is reset */
	outportb (FifoCmdPort, 0x80);	       /* frame the command */
	outportb (FifoCmdPort, 0x80);
	outportb (FifoDataPort, CARDTEST);
	outportb (FifoDataPort, 0x01);	       /* subtest 1 */
	outportb (FifoDataPort, ctr);
	delay_us (250);

	if(rdfifostat () & MB_FLAG)
	{
	    /* read mailbox */
	    outportb (FifoCmdPort, 0x06);
	    data = inportb (FifoCmdPort);
	    if (data != ctr)
	    {
		status = FALSE;
	    }
	}
	else	/* mailbox bit is not working */
	{
	    status = FALSE;
	}
    }

    /* send data, wait, then retrieve a framed data */
    for (ctr = 0; (status == TRUE) && (ctr <= 0xff); ctr++)
    {
	/*while (rdfifostat () & AF_FLAG){}	 /* loop until AF flag is reset */
	outportb (FifoCmdPort, 0x80);	       /* frame the command */
	outportb (FifoCmdPort, 0x80);
	outportb (FifoDataPort, CARDTEST);
	outportb (FifoDataPort, 0x02);	       /* subtest 2 */
	outportb (FifoDataPort, ctr);
	delay_us (250);

	data = inportb (FifoDataPort);
	tmp_data = rdfifostat ();

	if(((tmp_data & FD_FLAG) == 0) || (data != ctr))
	{
	    status = FALSE;
	}
    }

    return (status);
}


/* This function will be used to detect if the turbo interface card is
     present. It will return a TRUE if it is present, FALSE otherwise. */

detect_tic ()
{
    int status = TRUE;
    unsigned char data;

    status = cpu_test ();

    if (status == TRUE)
    {
	/* send an unframed command */
	outportb (FifoDataPort, 0x00);
	delay_ms (1);

	if(rdfifostat () & MB_FLAG)
	{
	    /* read mailbox */
	    outportb (FifoCmdPort, 0x06);
	    data = inportb (FifoCmdPort);
	    if (data != ERROR_FRAMING)
	    {
		status = FALSE;
	    }
	}
	else	/* tic is not in command mode  */
	{
	    status = FALSE;
	}
    }

    return (status);
}


half_pump ()
{
    outportb (UdiMemMapPort, UdiSegment >> 8);
    outportb (UdiLockPort0, 0x00);
    outportb (UdiLockPort0, 0xaa);
}
