ref: 4b53b584263c8b7ea997d756e9712bf438bc348b
dir: /src/jedec.c/
/******************************************************************************
** JEDEC.c
*******************************************************************************
**
** description:
**
** This file contains some functions to save GAL data in JEDEC format.
**
******************************************************************************/
#include <u.h>
#include <libc.h>
#include <stdio.h>
#include "galasm.h"
/*
#include <stdlib.h>
#include <string.h>
*/
static usize WriteOutputWithCRLFLineEndings(void *buf, usize size, usize nmemb, FILE *out);
static usize WriteOutputWithNativeLineEndings(void *buf, usize size, usize nmemb, FILE *out);
/******************************************************************************
** FileChecksum()
*******************************************************************************
** input: filename Filename for which to calculate checksum
** pchecksum Pointer to receive the 16 bit checksum
**
** output: TRUE or FALSE to indicate success
**
** remarks: This function calculates the JEDEC file checksum. The start and
** the end of the area for which the checksum should be calculated
** must be marked by <STX> and <ETX>!.
******************************************************************************/
int FileChecksum(char *filename, unsigned *pchecksum)
{
FILE *fp;
int c;
*pchecksum = 0;
if ((fp = fopen(filename, "rb")))
{
while ((c = fgetc(fp)) != 0x2)
{
if (c == EOF)
{
fclose(fp);
return FALSE;
}
}
while (TRUE)
{
*pchecksum = (*pchecksum + (UBYTE) c) % 0x10000;
if (c == 0x3)
{
break;
}
c = fgetc(fp);
if (c == EOF)
{
fclose(fp);
return FALSE;
}
}
fclose(fp);
return TRUE;
}
else
{
return FALSE;
}
}
/******************************************************************************
** FuseChecksum()
*******************************************************************************
** input: galtype type of GAL
**
** output: 16 bit checksum of the JEDEC structure
**
** remarks: This function does calculate the fuse checksum of the JEDEC
** structure.
******************************************************************************/
unsigned FuseChecksum(int galtype)
{
int n;
unsigned checksum;
UBYTE byte;
BYTE *ptr, *ptrXOR, *ptrS1;
ptr = &Jedec.GALLogic[0] - 1L;
ptrXOR = &Jedec.GALXOR[0];
ptrS1 = &Jedec.GALS1[0];
n = 0;
checksum = 0;
byte = 0;
for (;;)
{
if (galtype == GAL16V8)
{
if (n == XOR16)
{
ptr = &Jedec.GALXOR[0];
}
else
{
if (n == XOR16+8)
{
ptr = &Jedec.GALSig[0];
}
else
{
if (n == NUMOFFUSES16)
break;
else
ptr++;
}
}
}
if (galtype == GAL20V8)
{
if (n == XOR20)
{
ptr = &Jedec.GALXOR[0];
}
else
{
if (n == XOR20+8)
{
ptr = &Jedec.GALSig[0];
}
else
{
if (n == NUMOFFUSES20)
break;
else
ptr++;
}
}
}
if (galtype == GAL22V10)
{
if (n >= XOR22V10 && n < XOR22V10 + 20)
{
if (!(n % 2))
ptr = ptrXOR++;
else
ptr = ptrS1++;
}
else
{
if (n == SIG22V10)
ptr = &Jedec.GALSig[0] - 1L;
if (n == SIG22V10 + SIG_SIZE)
break;
else
ptr++;
}
}
if (galtype == GAL20RA10)
{
if (n == XOR20RA10)
{
ptr = &Jedec.GALXOR[0];
}
else
{
if (n == SIG20RA10 + SIG_SIZE)
break;
else
ptr++;
}
}
byte |= (*ptr << (n+8) % 8);
if (!((n + 9)%8))
{
checksum = (checksum + byte) % 0x10000;
byte = 0;
}
n++;
}
checksum = (checksum + byte) % 0x10000;
return(checksum);
}
/******************************************************************************
** MakeJedecBuff()
*******************************************************************************
** input: buff ActBuffer structure for the ram buffer
** galtype type of GAL
** cfg pointer to the config structure
**
** output: 0: o.k.
** -1: not enough free memory
**
** remarks: generates the JEDEC file in a ram buffer
******************************************************************************/
int MakeJedecBuff(struct ActBuffer buff, int galtype, struct Config *cfg)
{
UBYTE mystrng[16];
int n, m, bitnum, bitnum2, flag;
int MaxFuseAdr = 0, RowSize = 0, XORSize = 0;
switch (galtype)
{
case GAL16V8:
MaxFuseAdr = MAX_FUSE_ADR16; /* This variables are defined */
RowSize = ROW_SIZE_16V8; /* both globally AND locally! */
XORSize = 8; /* All assignments concern to */
break; /* the locale variables!!!! */
case GAL20V8:
MaxFuseAdr = MAX_FUSE_ADR20;
RowSize = ROW_SIZE_20V8;
XORSize = 8;
break;
case GAL22V10:
MaxFuseAdr = MAX_FUSE_ADR22V10;
RowSize = ROW_SIZE_22V10;
XORSize = 10;
break;
case GAL20RA10:
MaxFuseAdr = MAX_FUSE_ADR20RA10;
RowSize = ROW_SIZE_20RA10;
XORSize = 10;
break;
}
if (!cfg->JedecFuseChk)
if (AddString(&buff, (UBYTE *)"\2\n")) /* <STX> */
return(-1);
/*** make header of JEDEC file ***/
if (AddString(&buff, (UBYTE *)"Used Program: GALasm 2.1\n"))
return(-1);
if (AddString(&buff, (UBYTE *)"GAL-Assembler: GALasm 2.1\n"))
return(-1);
if (galtype == GAL16V8)
{
if (AddString(&buff, (UBYTE *)"Device: GAL16V8\n\n"))
return(-1);
}
if (galtype == GAL20V8)
{
if (AddString(&buff, (UBYTE *)"Device: GAL20V8\n\n"))
return(-1);
}
if (galtype == GAL20RA10)
{
if (AddString(&buff, (UBYTE *)"Device: GAL20RA10\n\n"))
return(-1);
}
if (galtype == GAL22V10)
{
if (AddString(&buff, (UBYTE *)"Device: GAL22V10\n\n"))
return(-1);
}
if (AddString(&buff, (UBYTE *)"*F0\n")) /* default value of fuses */
return(-1);
if (cfg->JedecSecBit)
{ /* Security-Bit */
if (AddString(&buff, (UBYTE *)"*G1\n"))
return(-1);
}
else
if (AddString(&buff, (UBYTE *)"*G0\n"))
return(-1);
if (galtype == GAL16V8) /* number of fuses */
if (AddString(&buff, (UBYTE *)"*QF2194\n"))
return(-1);
if (galtype == GAL20V8)
if (AddString(&buff, (UBYTE *)"*QF2706\n"))
return(-1);
if (galtype == GAL20RA10)
if (AddString(&buff, (UBYTE *)"*QF3274\n"))
return(-1);
if (galtype == GAL22V10)
if (AddString(&buff, (UBYTE *)"*QF5892\n"))
return(-1);
/*** make fuse-matrix ***/
bitnum = bitnum2 = flag = 0;
for (m = 0; m < RowSize; m++)
{
flag = 0;
bitnum2 = bitnum;
for (n = 0; n <= MaxFuseAdr; n++)
{
if (Jedec.GALLogic[bitnum2])
{
flag = 1;
break;
}
bitnum2++;
}
if (flag)
{
sprintf((char *)&mystrng[0], "*L%04d ", bitnum);
if (AddString(&buff, (UBYTE *)&mystrng[0]))
return(-1);
for (n=0; n<=MaxFuseAdr; n++)
{
if (AddByte(&buff, (UBYTE)(Jedec.GALLogic[bitnum] + '0')))
return(-1);
bitnum++;
}
if (AddByte(&buff, (UBYTE)'\n'))
return(-1);
}
else
bitnum = bitnum2;
}
if (!flag)
bitnum = bitnum2;
/*** XOR-Bits ***/
sprintf((char *)&mystrng[0], "*L%04d ", bitnum); /* add fuse adr. */
if (AddString(&buff, (UBYTE *)&mystrng[0]))
return(-1);
for (n = 0; n < XORSize; n++)
{
if (AddByte(&buff, (UBYTE)(Jedec.GALXOR[n] + '0')))
return(-1);
bitnum++;
if (galtype == GAL22V10)
{ /*** S1 of 22V10 ***/
if (AddByte(&buff, (UBYTE)(Jedec.GALS1[n] + '0')))
return(-1);
bitnum++;
}
}
if (AddByte(&buff, (UBYTE)'\n'))
return(-1);
/*** Signature ***/
sprintf((char *)&mystrng[0], "*L%04d ", bitnum);
if (AddString(&buff, (UBYTE *)&mystrng[0]))
return(-1);
for (n = 0; n < SIG_SIZE; n++)
{
if (AddByte(&buff, (UBYTE)(Jedec.GALSig[n] + '0')))
return(-1);
bitnum++;
}
if (AddByte(&buff, (UBYTE)'\n'))
return(-1);
if ((galtype == GAL16V8) || (galtype == GAL20V8))
{
/*** AC1-Bits ***/
sprintf((char *)&mystrng[0], "*L%04d ", bitnum);
if (AddString(&buff, (UBYTE *)&mystrng[0]))
return(-1);
for (n = 0; n < AC1_SIZE; n++)
{
if (AddByte(&buff, (UBYTE)(Jedec.GALAC1[n] + '0')))
return(-1);
bitnum++;
}
if (AddByte(&buff, (UBYTE)'\n'))
return(-1);
/*** PT-Bits ***/
sprintf((char *)&mystrng[0], "*L%04d ", bitnum);
if (AddString(&buff, (UBYTE *)&mystrng[0]))
return(-1);
for (n = 0; n < PT_SIZE; n++)
{
if (AddByte(&buff, (UBYTE)(Jedec.GALPT[n] + '0')))
return(-1);
bitnum++;
}
if (AddByte(&buff, (UBYTE)'\n'))
return(-1);
/*** SYN-Bit ***/
sprintf((char *)&mystrng[0], "*L%04d ", bitnum);
if (AddString(&buff, (UBYTE *)&mystrng[0]))
return(-1);
if (AddByte(&buff, (UBYTE)(Jedec.GALSYN + '0')))
return(-1);
if (AddByte(&buff, (UBYTE)'\n'))
return(-1);
bitnum++;
/*** AC0-Bit ***/
sprintf((char *)&mystrng[0], "*L%04d ", bitnum);
if (AddString(&buff, (UBYTE *)&mystrng[0]))
return(-1);
if (AddByte(&buff, (UBYTE)(Jedec.GALAC0 + '0')))
return(-1);
if (AddByte(&buff, (UBYTE)'\n'))
return(-1);
}
/* if (cfg->JedecFuseChk)
{*/ /* add fuse-checksum */
sprintf((char *)&mystrng[0], "*C%04x\n", FuseChecksum(galtype));
if (AddString(&buff, (UBYTE *)&mystrng[0]))
return(-1);
/* }*/
if (AddString(&buff, (UBYTE *)"*\n")) /* closing '*' */
return(-1);
if(!cfg->JedecFuseChk)
{
if (AddByte(&buff, (UBYTE)0x3)) /* <ETX> */
return(-1);
}
return(0);
}
/******************************************************************************
** WriteJedecFile()
*******************************************************************************
** input: galtype type of GAL
** cfg configuration structure
**
** output: none
**
** remarks: generats the JEDEC file out of the JEDEC structure
******************************************************************************/
void WriteJedecFile(char *filename, int galtype, struct Config *cfg)
{
struct ActBuffer mybuff;
struct Buffer *first_buff;
UBYTE *filebuffer, *filebuffer2;
long result;
unsigned checksum;
FILE *fp;
char mystring[16];
usize (*write)(void *buf, usize size, usize nmemb, FILE *out);
char *write_mode;
char *append_mode;
if (cfg->ForceCRLF)
{
write = WriteOutputWithCRLFLineEndings;
write_mode = "wb";
append_mode = "ab";
}
else
{
write = WriteOutputWithNativeLineEndings;
write_mode = "w";
append_mode = "a";
}
if(!(first_buff = (struct Buffer *) calloc(sizeof(struct Buffer),1)))
{
ErrorReq(2); /* out of memory? */
return;
}
mybuff.ThisBuff = first_buff;
mybuff.Entry = (UBYTE *)(&first_buff->Entries[0]);
mybuff.BuffEnd = (UBYTE *)first_buff + (long)sizeof(struct Buffer);
if (MakeJedecBuff(mybuff, galtype, cfg))
{ /* put JEDEC in ram-buffer */
FreeBuffer(first_buff); /* error? */
ErrorReq(2);
return;
}
if ((fp = fopen(filename, write_mode)))
{
for (;;)
{
filebuffer = filebuffer2 = mybuff.Entry;
while (filebuffer2 < mybuff.BuffEnd)
{ /* get size of buffer */
if (!*filebuffer2)
break;
filebuffer2++;
}
/* save buffer */
/* DHH - 24-Oct-2012: ensure lines are terminated with CRLF */
result = write(filebuffer,(usize) 1, (usize) (filebuffer2 - filebuffer),fp);
if (result != (filebuffer2 - filebuffer))
{ /* write error? */
fclose(fp);
FreeBuffer(first_buff);
ErrorReq(13);
return;
}
if (!mybuff.ThisBuff->Next) /* more buffers here? */
break; /* no, then cancel */
mybuff.ThisBuff = mybuff.ThisBuff->Next;
mybuff.Entry = (UBYTE *)(&mybuff.ThisBuff->Entries[0]);
mybuff.BuffEnd = (UBYTE *)mybuff.ThisBuff + (long)sizeof(struct Buffer);
}
fclose(fp);
if (!cfg->JedecFuseChk)
{
if (FileChecksum(filename, &checksum))
{
if ((fp = fopen(filename, append_mode)))
{
sprintf(mystring, "%04x\n", checksum);
write(mystring, (usize) 1, strlen(mystring), fp);
fclose(fp);
}
else
{
FreeBuffer(first_buff);
ErrorReq(13);
return;
}
}
else
{
FreeBuffer(first_buff);
ErrorReq(13);
return;
}
}
}
else
{
FreeBuffer(first_buff); /* error?, then cancel*/
ErrorReq(13); /* can't open file */
return;
}
FreeBuffer(first_buff);
}
/*
* DHH - 24-Oct-2012
* This function works like fwrite, but outputs newlines as CRLF.
* My GAL programmer (Wellon VP-190) doesn't like JEDEC files
* with bare newlines in them.
*/
static usize WriteOutputWithCRLFLineEndings(void *buf_, usize size, usize nmemb, FILE *out)
{
unsigned char *buf = (unsigned char *) buf_;
usize i;
for (i = 0; i < size*nmemb; i++) {
unsigned char byte = buf[i];
if (byte == '\n') {
fwrite("\r\n", 1, 2, out);
} else {
fwrite(&byte, 1, 1, out);
}
}
return nmemb;
}
static usize WriteOutputWithNativeLineEndings(void *buf_, usize size, usize nmemb, FILE *out)
{
return fwrite(buf_, size, nmemb, out);
}