Files
sicspsi/utils/ecb_load_new/ecbdriv_els.c
cvs 2a93216346 - New batch file management module
- New oscillator module
- Bug fixes
2004-11-17 10:50:17 +00:00

726 lines
21 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*******************************************************************************
* This file contains the TASCOM ECB driver functions.
*
*
* Project: TASCOM
* File name: ecbdriv_els.c
*
* Author: J. Bundgaard Nov. 1991.
*
*
*
* Copyright (C) Risoe National Laboratory, 1991-1994, All rights reserved
*******************************************************************************/
/*******************************************************************************
*& modified by:
*&
*&
*& V003.101 P.S. 26-APR-2004
*& For the ecb_load program only.
*&
*&
*&*****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include "ecb_load.h"
#include GPIB_H
/*******************************************************************************
* Static variables
*******************************************************************************/
static repete = 1;
static int look_up[] = {10, 11, 12, 13, 14 ,15};
/*******************************************************************************
* External variables defined in this file.
*******************************************************************************/
int x_ecb1 = -1; /* Unit descriptor of ECB system #1 */
Z80_reg x_inreg; /* Z80 registers b,c,d and e before call */
Z80_reg x_outreg; /* Z80 registers b,c,d and e after call */
unsigned char x_ecb_data[ECB_BYTES]; /* Array to hold data blocks for ECB */
int x_ecb_error_count = 0; /* Counter for ECB call errors */
int x_cpu_typ = 0; /* =0: WP-CPU, =1: P2701, =2: P2701 + P2501 */
Ecb_data x_ecba; /* DMA data from P2701a ECB-CPU */
/*******************************************************************************
* Prototypes for functions defined in this file.
*******************************************************************************/
extern void Ecb_init(void);
extern int Ecb_error(void);
extern void Ecb_unit (void); /* Establish unit No. for ECB */
extern int Ecb_func (int , unsigned char); /* Call ECB function */
extern void Ecb_read (int, unsigned short, unsigned short); /* Read n bytes */
extern void Ecb_write (int, unsigned short, unsigned short); /* Write n bytes */
static int Ecb_prepare (int, unsigned char, unsigned short, unsigned short);
static int Ecb_send_func (int, unsigned char); /* Send function code */
static void Ecb_error_func (char *, unsigned char, int);
static void Restart_ecb_func (int unit, unsigned char function);
static int Restart_ecb_prepare(int,unsigned char,unsigned short,unsigned short);
static void Do_reset (void);
extern void Ecb_down_load (FILE *stream);
static unsigned long Hex_to_bin(char c);
static char Bin_to_hex (int i);
extern int Ecb_type (int);
/*******************************************************************************
* ECB system initialisation
*******************************************************************************/
extern void
Ecb_init(void)
{
x_cpu_typ = 1; /* New CPU module, P2701 */
x_ecb1 = -1;
if (x_gpib0 >= 0)
{
x_ecb1 = ibfind (ECB1); /* Now see if the ECB system is avaiable */
if (x_ecb1 <= 0)
{
x_ecb1 = -1;
x_error_text =(char *) ECB1;
x_tas_error = GPIB_FIND_ERROR;
Ecb_load_error();
}
else
{
ibsic (x_gpib0); /* Send interface clear */
usleep (300000); /* Wait 0.3 sec. */
ibtmo (x_ecb1, T10s); /* Time out 10 sec. */
}
}
x_tas_error = FALSE;
return;
}
/*******************************************************************************
* Function to call a Z80 function (subroutine) without interrupt.
* This means that the function No. must be greater than or equal to
* 128 (function 0) and less than or equal to 191 (function 63).
* 'Unit' is the address of the ECB system on the GPIB bus. Four Z80 regs.
* are transferred upon the call from the host to the ECB system, and
* again read back to the host upon exit from the ECB function. This
* mechanismen is used to tranfer of arguments and results. Two global
* structures are used for the purpose, x_inreg and x_outreg.
*******************************************************************************/
extern int
Ecb_func (int unit, unsigned char function)
{
int byte_cnt;
short status;
char *ecb_error_text;
void TC_FAR *point_input = &x_inreg;
void TC_FAR *point_output = &x_outreg;
if (Ecb_send_func (unit, function) == FALSE)
{
if (repete == 1)
Restart_ecb_func (unit, function); /* GPIB error: recall Ecb_func() once */
return (FALSE);
}
/* Function accepted. Send the 4 Z80 register values */
byte_cnt = 4;
status = ibwrt (unit, point_input, byte_cnt);
if (status < 0)
{
if (repete ==1)
{
Restart_ecb_func (unit, function); /* GPIB error: recall Ecb_func() once */
return;
}
if (status | TIMO)
x_error_text = "Timeout";
else
x_error_text = '\0';
x_tas_error = GPIB_WRITE_ERROR;
ecb_error_text = "during write of data bytes at ECB function";
Ecb_error_func(ecb_error_text, function, unit);
return(FALSE);
}
/* Wait for the function to complete and then receive the 4 Z80 regs. values */
status = ibrd (unit, point_output, byte_cnt);
if (status < 0)
{
if (repete ==1)
{
Restart_ecb_func (unit, function); /* GPIB error: recall Ecb_func() once */
return(FALSE);
}
if (status | TIMO)
x_error_text = "Timeout";
else
x_error_text = '\0';
x_tas_error = GPIB_READ_ERROR;
ecb_error_text = "during read of data bytes at ECB function";
Ecb_error_func(ecb_error_text, function, unit);
return(FALSE);
}
return(TRUE);
}
/*******************************************************************************
* Function to re-call Ecb_func() in case of a GPIB bus error.
*******************************************************************************/
static void
Restart_ecb_func (int unit, unsigned char function)
{
Do_reset();
Ecb_func (unit, function);
repete = 1; /* Reset repete to allow re-calls */
return;
}
/*******************************************************************************
* Function to re-call Ecb_send_func() in case of a GPIB bus error.
*******************************************************************************/
static int
Restart_ecb_prepare (int unit, unsigned char function,
unsigned short address, unsigned short byte_count)
{
short status;
Do_reset();
status = Ecb_prepare (unit, function, address, byte_count);
repete = 1; /* Reset repete to allow re-calls */
return(status);
}
/*******************************************************************************
* Send Interface clear and print a message.
*******************************************************************************/
static void
Do_reset (void)
{
ibsic (x_gpib0); /* Send interface clear */
usleep (300000); /* Wait 0.3 sec. */
ibsic (x_gpib0); /* Send interface clear */
usleep (300000); /* Wait 0.3 sec. */
repete = 0; /* No more re-calls */
return;
}
/*******************************************************************************
* Function that transfers 'byte_count' bytes from the ECB system to
* the host. 'Address' specifies source start address in the Z80 me-
* mory space. Destination is the global unsigned character array
* x_ecb_data.
*******************************************************************************/
extern void
Ecb_read (int unit, unsigned short address, unsigned short byte_count)
{
short status;
void TC_FAR *point_data = &x_ecb_data;
if (Ecb_prepare (unit, READ_N_BYTES, address, byte_count) == FALSE)
return;
/* Read the requested No. of bytes */
status = ibrd (unit, point_data, (int) byte_count);
if (status < 0)
{
if (status | TIMO)
x_error_text = "Timeout";
else
x_error_text = '\0';
x_tas_error = GPIB_READ_ERROR;
return;
}
return;
}
/*******************************************************************************
* Function that transfers 'byte_count' bytes from the host to the ECB
* system. 'Address' specifies destination start address in the Z80 me-
* mory space. Source is the global unsigned character array x_ecb_data.
*******************************************************************************/
extern void
Ecb_write (int unit, unsigned short address, unsigned short byte_count)
{
short status;
char *ecb_error_text;
void TC_FAR *point_data = &x_ecb_data;
if (Ecb_prepare (unit, WRITE_N_BYTES, address, byte_count) == FALSE)
return;
/* Write the requested No. of bytes */
status = ibwrt (unit, point_data, (int) byte_count);
if (status < 0)
{
if (status | TIMO)
x_error_text = "Timeout";
else
x_error_text = '\0';
x_tas_error = GPIB_WRITE_ERROR;
ecb_error_text = "";
Ecb_error_func(ecb_error_text, 0, unit);
return;
}
/* Receive a dummy byte */
byte_count = 1;
status = ibrd (unit, point_data, (int) byte_count);
if (status < 0)
{
if (status | TIMO)
x_error_text = "Timeout";
else
x_error_text = '\0';
x_tas_error = GPIB_READ_ERROR;
return;
}
return;
}
/*******************************************************************************
* Prepare an ECB read or write n bytes. See Ecb_read() and Ecb_write().
*******************************************************************************/
static int
Ecb_prepare (int unit, unsigned char function,
unsigned short address, unsigned short byte_count)
{
int byte_cnt;
short status;
Swap save, adr, count;
char *ecb_error_text;
void TC_FAR *point_adress = (Swap *) &adr.word;
void TC_FAR *point_count = (Swap *) &count.word;
if (byte_count > ECB_BYTES)
{
x_error_int = byte_count;
x_tas_error = ECB_OVERFLOW;
ecb_error_text = "";
Ecb_error_func(ecb_error_text, 0, unit);
return (FALSE);
}
save.word = address; /* Swap address bytes */
adr.b.lsb = save.b.msb;
adr.b.msb = save.b.lsb;
save.word = byte_count; /* Swap byte count bytes */
count.b.lsb = save.b.msb;
count.b.msb = save.b.lsb;
if (Ecb_send_func (unit, function) == FALSE)
{
if (repete ==1)
{ /* GPIB error, Restart Ecb_prepare() once */
status = Restart_ecb_prepare (unit, function, address, byte_count);
return(status);
}
ecb_error_text = "during write of ECB function code ";
Ecb_error_func(ecb_error_text, function, unit);
return (FALSE);
}
byte_cnt = 2; /* Function accepted, send the two byte address value */
status = ibwrt (unit, point_adress, byte_cnt);
if (status < 0)
{
if (repete ==1)
{ /* GPIB error, Restart Ecb_prepare() once */
Restart_ecb_prepare (unit, function, address, byte_count);
return(status);
}
if (status | TIMO)
x_error_text = "Timeout";
else
x_error_text = '\0';
x_tas_error = GPIB_WRITE_ERROR;
ecb_error_text = "";
Ecb_error_func(ecb_error_text, 0, unit);
return (FALSE);
}
/* Send the two byte byte_count value */
status = ibwrt (unit, point_count, byte_cnt);
if (status < 0)
{
if (repete ==1)
{ /* GPIB error, Restart Ecb_prepare() once */
Restart_ecb_prepare (unit, function, address, byte_count);
return(status);
}
if (status | TIMO)
x_error_text = "Timeout";
else
x_error_text = '\0';
x_tas_error = GPIB_WRITE_ERROR;
ecb_error_text = "";
Ecb_error_func(ecb_error_text, 0, unit);
return (FALSE);
}
return (TRUE);
}
/*******************************************************************************
* Function to send ECB function code and receive an acknowledge
* character as response.
*******************************************************************************/
static int
Ecb_send_func (int unit, unsigned char function)
{
unsigned char response;
unsigned long byte_cnt;
int error_type;
short status;
char *ecb_error_text;
void TC_FAR *point_func = &function;
void TC_FAR *point_resp = &response;
byte_cnt = 1; /* Send function code */
status = ibwrt (unit, point_func, byte_cnt);
error_type = iberr;
if (status < 0)
{
if (repete == 1)
return(FALSE);
if (status | TIMO)
{
if ((error_type == ENOL) || (error_type == EBUS))
{
x_error_text = ECBTEXT;
x_tas_error = GPIB_NO_LISNER_ERROR;
Ecb_load_error();
return (FALSE);
}
x_error_text = "Timeout";
}
else
x_error_text = '\0';
x_tas_error = GPIB_WRITE_ERROR;
Ecb_load_error();
return (FALSE);
}
/* Get acknowledge byte back */
status = ibrd (unit, point_resp, byte_cnt);
if (status < 0)
{
if (repete == 1)
return(FALSE);
if (status | TIMO)
x_error_text = "Timeout";
else
x_error_text = '\0';
x_tas_error = GPIB_READ_ERROR;
ecb_error_text = "during read of ack-byte at ECB function ";
Ecb_error_func(ecb_error_text, function, unit);
return (FALSE);
}
if (response != ACKN) /* Acknowledge ? */
{
x_error_int = function;
x_tas_error = ECB_ILLEGAL_FUNC;
ecb_error_text = " ECB function code ";
Ecb_error_func(ecb_error_text, function, unit);
return (FALSE);
}
return (TRUE);
}
/*******************************************************************************
* Errors at calls to the ECB system. After two ECB errors TASCOM
* returns to DOS.
*******************************************************************************/
static void
Ecb_error_func (char *ecb_error_text, unsigned char function, int unit)
{
Ecb_load_error();
if (function != 0)
{
printf ("%s %d\n",ecb_error_text, function);
fflush (stdout);
exit(0);
}
return;
}
/*******************************************************************************
* Errors at calls to the ECB system. After two ECB errors TASCOM
* returns to DOS.
*******************************************************************************/
static void
Ecb_error_func1 (char *ecb_error_text, unsigned char function, int unit)
{
Ecb_load_error();
if (function != 0)
{
printf ("%s %d\n",ecb_error_text, function);
fflush (stdout);
exit(0);
}
return;
}
/******************************************************************************
* Down load the ECB program.
* Reads lines from the HEX file and add up to 20 data lines together before
* sending them to the ECB system.
******************************************************************************/
extern void
Ecb_down_load (FILE *stream)
{
int ecb_type, unit, function, load_count = -1;
char *point;
unsigned short byte_count, address;
char line[F_BUFSIZ];
unsigned long type, no_bytes, adrs, total_bytes, old_adrs, total1, total0, total2;
int line_no = 0;
void TC_FAR *point_func = &function;
int line_not_output = 0; /* if =1: data waiting in line[] */
void TC_FAR *line9 = &line[9];
/* Stop_display(); */
for (;;)
{
if (line_not_output == 1)
line_not_output = 0; /* Start with old line */
else
{ /* Read a line from file */
point = fgets (line, F_BUFSIZ, stream);
if (point != NULL)
{
byte_count = strlen(line);
byte_count -= 4; /* Remove checksum and \n in the */
line[byte_count+1] = NUL; /* line, i.e. the four last characters */
line[0] = '0'; /* Replace : in line[0] with 0 */
}
else
{
if (!ferror(stream))
byte_count = 0;
else
{
fclose (stream);
stream = NULL;
x_tas_error = FILE_READ;
Ecb_load_error ();
printf (" during download of the ECB program\n");
/* Start_display(); */
return;
}
}
}
line_no += 1;
if (byte_count != 0)
{
if (line_no == 1)
strcpy (x_ecb_data, line);
type = (Hex_to_bin(line[7]) << 4) + Hex_to_bin(line[8]);
if (type != 0)
{
if (line_no > 1) /* Output buffer and mark that */
line_not_output = 1; /* last input line has not been output */
}
else
{
no_bytes = (Hex_to_bin(line[1]) << 4) + Hex_to_bin(line[2]);
adrs = (Hex_to_bin(line[3]) << 12) + (Hex_to_bin(line[4]) << 8) +
(Hex_to_bin(line[5]) << 4) + Hex_to_bin(line[6]);
if (line_no == 1)
{
total_bytes = no_bytes;
old_adrs = adrs;
continue; /* Get next input line */
}
else
{
if (old_adrs + no_bytes == adrs)
{ /* Contigious addresses */
total_bytes += no_bytes;
old_adrs = adrs;
strcat (x_ecb_data, line9); /* Add the new bytes to buffer */
total0 = total_bytes/256; /* and adjust number of bytes */
x_ecb_data[0] = Bin_to_hex(total0);
total1 = total_bytes - 256*total0;
total2 = total1/16;
x_ecb_data[1] = Bin_to_hex(total2);
x_ecb_data[2] = Bin_to_hex(total1 - 16*total2);
if (line_no < 20) /* Max 20 lines together */
continue; /* Get next input line */
}
}
line_not_output = 0; /* Output buffer, nothing waiting in line[] */
}
unit = x_ecb1;
address = 1;
byte_count = strlen (x_ecb_data);
Ecb_write (unit, address, byte_count); /* Write a line to ECB */
line_no = 0;
/* if (Test_ctrl_c())
/* {
/* Start_display();
/* return; /* Control(c) hit */
/* }
*/
if (load_count == -1) /* Type Loading followed by dots while */
{ /* down loading the file */
printf ("\nLoading");
fflush (stdout);
load_count = 0;
}
load_count += 1;
if (load_count > 15)
{
printf (".");
fflush (stdout);
load_count = 0;
}
function = ECB_DOWN_LOAD;
Ecb_func (unit, function); /* Call ECB download function */
if (x_outreg.b != LOAD_NEXT) /* Wait for reply from ECB */
break; /* If LOAD_NEXT, get next line, else finished */
}
}
printf ("\nLoading complete\n");
fflush (stdout);
/* Start_display(); */
return;
}
/*******************************************************************************
* Convert HEX to bin
*******************************************************************************/
static unsigned long
Hex_to_bin(char c)
{
if(isdigit((int) c))
return (c - '0');
else
return look_up[c - 'A'];
}
/*******************************************************************************
* Convert Bin to HEX
*******************************************************************************/
static char
Bin_to_hex (int i)
{
if(i <= 9)
return ( (char)(i + (int)('0')) );
else
return ( (char)( (i - 10) + (int)('A')) );
}
/******************************************************************************
* Get type and version of the ECB program. If return_value is TYPE_OUT, the
* type is returned as 1 for RAM and 0 for ROM. If return_value is VERS_OUT,
* the version number * 100 is returned.
* If return_value = 0, type and version are printed.
******************************************************************************/
extern int
Ecb_type (int return_value)
{
int unit, function;
int version, status;
/* P2701a CPU: Get ROM/RAM type */
unit = x_ecb1;
function = ECB_TYPE;
status = Ecb_func (unit, function);
if (status == 0)
exit(0);
version = 100*(int)x_outreg.b + 10*(int)x_outreg.c + (int)x_outreg.e;
if (return_value == TYPE_OUT)
return((int) x_outreg.d);
if (return_value == VERS_OUT)
return(version);
printf ("ECB program: ");
if (x_outreg.d == 1)
printf ("RAM");
else if (x_outreg.d == 0)
printf ("ROM");
printf (" mode, version %4.2f\n", ((float) version)/100);
fflush (stdout);
return((int) x_outreg.d);
}
/*******************************************************************************
* Ecb option error routine.
*******************************************************************************/
extern int
Ecb_error(void)
{
switch (x_tas_error)
{
case ECB_OVERFLOW:
printf (" Byte count %d overflows ECB data buffer.", x_error_int);
break;
case ECB_ILLEGAL_FUNC:
printf (" No such ECB function: %d", x_error_int);
break;
default:
return(NOT_FOUND);
}
printf ("\n");
fflush (stdout);
return(FOUND);
}