Commit bae74907 authored by Thanassis Tsiodras's avatar Thanassis Tsiodras

Compile ZestSC1 USB-based communication library.

parent 0f499d65
/*******************
* Hardware details *
*******************/
#define VENDOR_ID 0x165d
#define PRODUCT_ID 0x0001
#define ANCHOR_LOAD_INTERNAL 0xA0
#define VR_SET_REG 0xD0
#define VR_GET_REG 0xD1
#define VR_START_CONFIG 0xD2
#define VR_CONFIG_STATUS 0xD3
#define VR_SET_SIGNAL_DIR 0xD4
#define VR_SET_SIGNALS 0xD5
#define VR_GET_SIGNALS 0xD6
#define VR_WRITE_EEPROM 0xD7
#define VR_READ_EEPROM 0xD8
#define VR_READBACK_READ 0xD9
#define VR_READBACK_WRITE 0xDA
#define VR_READBACK_DONE 0xDB
#define VR_GET_FIRMWARE_VER 0xDC
#define EEPROM_SERIAL_ADDRESS 0xfffc
#define EEPROM_CARDID_ADDRESS 0xfffb
#define EEPROM_FPGA_ADDRESS 0xfffa
#define EEPROM_MEMORY_SIZE_ADDRESS 0xfff6
#define CPUCS_REG_FX2 0xE600
#define EP_CTRL_WRITE (USB_ENDPOINT_OUT | USB_TYPE_VENDOR)
#define EP_CTRL_READ (USB_ENDPOINT_IN | USB_TYPE_VENDOR)
#define EP_INT_READ (USB_ENDPOINT_IN | 1)
#define EP_DATA_WRITE (USB_ENDPOINT_OUT | 2)
#define EP_CONFIG_WRITE (USB_ENDPOINT_OUT | 2)
#define EP_DATA_READ (USB_ENDPOINT_IN | 6)
#define EP_CONFIG_READ (USB_ENDPOINT_IN | 6)
#define ZESTSC1_MAX_TRANSFER_LENGTH (16*1024) // Maximum transfer in one URB under Linux
/**************
* Error macro *
**************/
extern ZESTSC1_ERROR_FUNC ZestSC1_ErrorHandler;
#define ZESTSC1_ERROR(f, x) \
{ \
if (ZestSC1_ErrorHandler!=NULL) \
ZestSC1_ErrorHandler(f, Handle, x, ZESTSC1_ERROR_STRING(x)); \
return (x); \
}
#define ZESTSC1_ERROR_GENERAL(f, x) \
{ \
if (ZestSC1_ErrorHandler!=NULL) \
ZestSC1_ErrorHandler(f, NULL, x, ZESTSC1_ERROR_STRING(x)); \
return (x); \
}
#define ZESTSC1_ERROR_STRING(x) \
ZestSC1_ErrorStrings[(x)>=ZESTSC1_ERROR_BASE ? \
(x)-ZESTSC1_ERROR_BASE+(ZESTSC1_MAX_INFO-ZESTSC1_INFO_BASE)+(ZESTSC1_MAX_WARNING-ZESTSC1_WARNING_BASE) : \
((x)>=ZESTSC1_WARNING_BASE ? (x)-ZESTSC1_WARNING_BASE+(ZESTSC1_MAX_INFO-ZESTSC1_INFO_BASE) : (x)-ZESTSC1_INFO_BASE)]
extern char *ZestSC1_ErrorStrings[];
/************************
* Card handle structure *
************************/
#define ZESTSC1_HANDLE_MAGIC 0xfeedfac0
typedef struct
{
unsigned long Magic;
usb_dev_handle *DeviceHandle;
unsigned long TimeOut;
int Interface;
} ZESTSC1_HANDLE_STRUCT;
#define ZESTSC1_CHECK_HANDLE(f, x) \
ZESTSC1_HANDLE_STRUCT *Struct = (ZESTSC1_HANDLE_STRUCT *)Handle; \
if (Struct==NULL || \
Struct->Magic!=ZESTSC1_HANDLE_MAGIC) \
ZESTSC1_ERROR(f, ZESTSC1_ILLEGAL_HANDLE);
/*************************************
* FPGA configuration image structure *
*************************************/
#define ZESTSC1_IMAGE_HANDLE_MAGIC 0xdeadbee0
typedef struct
{
unsigned long Magic;
void *Buffer;
unsigned long BufferSize;
ZESTSC1_FPGA_TYPE PartType;
} ZESTSC1_IMAGE_HANDLE_STRUCT;
#define ZESTSC1_BITFILE_NAME 0x61
#define ZESTSC1_BITFILE_PART 0x62
#define ZESTSC1_BITFILE_DATE 0x63
#define ZESTSC1_BITFILE_TIME 0x64
#define ZESTSC1_BITFILE_IMAGE 0x65
/************
* Constants *
************/
#define ZESTSC1_DEFAULT_TIMEOUT 10000
/************
* Functions *
************/
ZESTSC1_STATUS ZestSC1_Reset8051(ZESTSC1_HANDLE Handle);
ZESTSC1_STATUS ZestSC1_Transfer(ZESTSC1_HANDLE Handle, int EP, void *Buffer, int Length);
/**********************************************************
* *
* (c) 2004 Orange Tree Technologies Ltd *
* *
* ZestSC1.h *
* Version 1.0 *
* *
* Header file for ZestSC1 USB FPGA card *
* *
**********************************************************/
#ifndef __ZESTSC1_H__
#define __ZESTSC1_H__
#ifdef __cplusplus
extern "C"
{
#endif
/**********************************************************
* Handles for referencing boards and configuration images *
**********************************************************/
typedef void *ZESTSC1_HANDLE;
typedef void *ZESTSC1_IMAGE;
/************************
* Function return codes *
************************/
#define ZESTSC1_INFO_BASE 0
#define ZESTSC1_WARNING_BASE 0x4000
#define ZESTSC1_ERROR_BASE 0x8000
typedef enum
{
ZESTSC1_SUCCESS = ZESTSC1_INFO_BASE,
ZESTSC1_MAX_INFO,
ZESTSC1_MAX_WARNING = ZESTSC1_WARNING_BASE,
ZESTSC1_ILLEGAL_HANDLE = ZESTSC1_ERROR_BASE,
ZESTSC1_ILLEGAL_STATUS_CODE,
ZESTSC1_NULL_PARAMETER,
ZESTSC1_DEVICE_IN_USE,
ZESTSC1_ILLEGAL_CARD_ID,
ZESTSC1_INTERNAL_ERROR,
ZESTSC1_OUT_OF_MEMORY,
ZESTSC1_FILE_NOT_FOUND,
ZESTSC1_FILE_ERROR,
ZESTSC1_ILLEGAL_FILE,
ZESTSC1_TIMEOUT,
ZESTSC1_DRIVER_MISSING,
ZESTSC1_SIGNAL_IS_INPUT,
ZESTSC1_SIGNAL_IS_OUTPUT,
ZESTSC1_ILLEGAL_IMAGE_HANDLE,
ZESTSC1_INVALID_PART_TYPE,
ZESTSC1_MAX_ERROR
} ZESTSC1_STATUS;
typedef void (*ZESTSC1_ERROR_FUNC)(const char *Function,
ZESTSC1_HANDLE Handle,
ZESTSC1_STATUS Status,
const char *Msg);
/*******************
* Valid FPGA types *
*******************/
typedef enum
{
ZESTSC1_FPGA_UNKNOWN,
ZESTSC1_XC3S400,
ZESTSC1_XC3S1000,
} ZESTSC1_FPGA_TYPE;
/*****************************
* Card information structure *
*****************************/
typedef struct
{
unsigned long CardID;
unsigned long SerialNumber;
ZESTSC1_FPGA_TYPE FPGAType;
unsigned long MemorySize;
unsigned long TimeOut;
unsigned long FirmwareVersion;
} ZESTSC1_CARD_INFO;
/**********************
* Function prototypes *
**********************/
ZESTSC1_STATUS ZestSC1CountCards(unsigned long *NumCards,
unsigned long *CardIDs,
unsigned long *SerialNumbers,
ZESTSC1_FPGA_TYPE *FPGATypes);
ZESTSC1_STATUS ZestSC1OpenCard(unsigned long CardId,
ZESTSC1_HANDLE *Handle);
ZESTSC1_STATUS ZestSC1SetTimeOut(ZESTSC1_HANDLE Handle,
unsigned long MilliSeconds);
ZESTSC1_STATUS ZestSC1SetCardID(ZESTSC1_HANDLE Handle,
unsigned long CardID);
ZESTSC1_STATUS ZestSC1GetCardInfo(ZESTSC1_HANDLE Handle,
ZESTSC1_CARD_INFO *Info);
ZESTSC1_STATUS ZestSC1CloseCard(ZESTSC1_HANDLE Handle);
ZESTSC1_STATUS ZestSC1RegisterErrorHandler(ZESTSC1_ERROR_FUNC Function);
ZESTSC1_STATUS ZestSC1GetErrorMessage(ZESTSC1_STATUS Status,
char **Buffer);
ZESTSC1_STATUS ZestSC1ConfigureFromFile(ZESTSC1_HANDLE Handle,
char *FileName);
ZESTSC1_STATUS ZestSC1LoadFile(char *FileName,
ZESTSC1_IMAGE *Image);
ZESTSC1_STATUS ZestSC1Configure(ZESTSC1_HANDLE Handle,
ZESTSC1_IMAGE Image);
ZESTSC1_STATUS ZestSC1RegisterImage(void *Buffer,
unsigned long BufferLength,
ZESTSC1_IMAGE *Image);
ZESTSC1_STATUS ZestSC1FreeImage(ZESTSC1_IMAGE Image);
ZESTSC1_STATUS ZestSC1WriteRegister(ZESTSC1_HANDLE Handle,
unsigned long Offset,
unsigned char Value);
ZESTSC1_STATUS ZestSC1ReadRegister(ZESTSC1_HANDLE Handle,
unsigned long Offset,
unsigned char *Value);
ZESTSC1_STATUS ZestSC1ReadData(ZESTSC1_HANDLE Handle,
void *Buffer,
unsigned long Length);
ZESTSC1_STATUS ZestSC1WriteData(ZESTSC1_HANDLE Handle,
void *Buffer,
unsigned long Length);
ZESTSC1_STATUS ZestSC1SetSignalDirection(ZESTSC1_HANDLE Handle,
unsigned char Direction);
ZESTSC1_STATUS ZestSC1SetSignals(ZESTSC1_HANDLE Handle,
unsigned char Value);
ZESTSC1_STATUS ZestSC1ReadSignals(ZESTSC1_HANDLE Handle,
unsigned char *Value);
ZESTSC1_STATUS ZestSC1WaitForInterrupt(ZESTSC1_HANDLE Handle);
#ifdef __cplusplus
}
#endif
#endif // __ZESTSC1_H__
#include <string.h>
#include <sys/stat.h>
#include <stdio.h>
#include <usb.h>
#include <errno.h>
#include "ZestSC1.h"
#include "Local.h"
/*
* Table of part type data
*/
static struct _ZESTSC1_PART_TYPE_MAP
{
char *Name;
ZESTSC1_FPGA_TYPE PartType;
long MinLength;
long MaxLength;
}
ZestSC1_PartTypes[] =
{
{ "3s400", ZESTSC1_XC3S400, 211000, 213000 },
{ "3s1000", ZESTSC1_XC3S1000, 401000, 404000 },
};
#define ZESTSC1_NUM_PART_TYPES (sizeof(ZestSC1_PartTypes)/sizeof(struct _ZESTSC1_PART_TYPE_MAP))
/*
* Local function prototypes
*/
static ZESTSC1_STATUS ZestSC1_LoadFile(char *FileName,
ZESTSC1_IMAGE *Image);
static ZESTSC1_STATUS ZestSC1_Configure(ZESTSC1_HANDLE Handle,
ZESTSC1_IMAGE Image);
static ZESTSC1_STATUS ZestSC1_FreeImage(ZESTSC1_IMAGE Image);
/******************************************************************************
* Configure the FPGA on a board directly from a file *
******************************************************************************/
ZESTSC1_STATUS ZestSC1ConfigureFromFile(ZESTSC1_HANDLE Handle,
char *FileName)
{
ZESTSC1_IMAGE Image;
ZESTSC1_STATUS Status;
/*
* Load image from disk
*/
Status = ZestSC1_LoadFile(FileName, &Image);
if (Status!=ZESTSC1_SUCCESS)
{
ZESTSC1_ERROR("ZestSC1ConfigureFromFile", Status);
}
/*
* Configure FPGA
*/
Status = ZestSC1_Configure(Handle, Image);
if (Status!=ZESTSC1_SUCCESS)
{
ZestSC1_FreeImage(Image);
ZESTSC1_ERROR("ZestSC1ConfigureFromFile", Status);
}
/*
* Free image
*/
Status = ZestSC1_FreeImage(Image);
if (Status!=ZESTSC1_SUCCESS)
{
ZESTSC1_ERROR("ZestSC1ConfigureFromFile", Status);
}
return ZESTSC1_SUCCESS;
}
/******************************************************************************
* Load an FPGA configuration from a file into memory *
******************************************************************************/
ZESTSC1_STATUS ZestSC1LoadFile(char *FileName,
ZESTSC1_IMAGE *Image)
{
ZESTSC1_STATUS Status;
Status = ZestSC1_LoadFile(FileName, Image);
if (Status!=ZESTSC1_SUCCESS)
{
ZESTSC1_ERROR_GENERAL("ZestSC1LoadFile", Status);
}
return ZESTSC1_SUCCESS;
}
/******************************************************************************
* Load an FPGA configuration from a file into memory *
* Internal version that always returns errors (i.e. no error callback) *
******************************************************************************/
static ZESTSC1_STATUS ZestSC1_LoadFile(char *FileName,
ZESTSC1_IMAGE *Image)
{
int ImageDone = 0;
int PartDone = 0;
int Char[5];
char *PartString = 0;
unsigned long Count;
unsigned long BufferLength;
char *Buffer = 0;
#ifdef MSVC
struct _stat FileStat;
#else
struct stat FileStat;
#endif
int Length;
FILE *FileHandle;
ZESTSC1_IMAGE_HANDLE_STRUCT *NewHandle;
ZESTSC1_STATUS RetVal = ZESTSC1_SUCCESS;
/*
* Open file
*/
if (FileName==NULL || Image==NULL)
{
return ZESTSC1_NULL_PARAMETER;
}
FileHandle = fopen(FileName, "rb");
if (FileHandle==NULL)
{
return ZESTSC1_FILE_NOT_FOUND;
}
/*
* Get the file length
*/
if (stat(FileName, &FileStat)!=0)
{
/*
* Could not get file status
*/
fclose(FileHandle);
return ZESTSC1_FILE_ERROR;
}
/*
* Allocate a new handle and initialise
*/
NewHandle = (ZESTSC1_IMAGE_HANDLE_STRUCT *)malloc(sizeof(ZESTSC1_IMAGE_HANDLE_STRUCT));
if (NewHandle==NULL)
{
return ZESTSC1_OUT_OF_MEMORY;
}
NewHandle->Magic = ZESTSC1_IMAGE_HANDLE_MAGIC;
NewHandle->Buffer = NULL;
/*
* Need to search for part type and image fields in the file
*/
while (ImageDone==0 || PartDone==0)
{
Char[0] = fgetc(FileHandle);
if (Char[0]==EOF)
{
/*
* Not expecting an end of file
*/
RetVal = ZESTSC1_ILLEGAL_FILE;
goto fail;
}
switch (Char[0])
{
case ZESTSC1_BITFILE_NAME:
case ZESTSC1_BITFILE_DATE:
case ZESTSC1_BITFILE_TIME:
/*
* String field encountered - ignore
*/
Char[1] = fgetc(FileHandle);
Char[2] = fgetc(FileHandle);
if (Char[1]==EOF || Char[2]==EOF)
{
/*
* Not expecting an end of file
*/
RetVal = ZESTSC1_ILLEGAL_FILE;
goto fail;
}
Length = (((unsigned long)Char[1])<<8) | (unsigned long)Char[2];
if (Length>FileStat.st_size)
{
/*
* Illegal value - assume its a bad format file
*/
RetVal = ZESTSC1_ILLEGAL_FILE;
goto fail;
}
/*
* Drop the string but check it is a valid string
*/
for (Count=Length; Count>0; Count--)
{
Char[0]=fgetc(FileHandle);
if (Char[0]==EOF)
{
RetVal = ZESTSC1_ILLEGAL_FILE;
goto fail;
}
if (Char[0]==0 && Count!=1)
{
RetVal = ZESTSC1_ILLEGAL_FILE;
goto fail;
}
}
break;
case ZESTSC1_BITFILE_PART:
/*
* Field containing the part type
*/
Char[1] = fgetc(FileHandle);
Char[2] = fgetc(FileHandle);
if (Char[1]==EOF || Char[2]==EOF)
{
/*
* Not expecting an end of file
*/
RetVal = ZESTSC1_ILLEGAL_FILE;
goto fail;
}
Length = (((unsigned long)Char[1])<<8) | (unsigned long)Char[2];
/*
* Read the string
*/
if (Length>16)
{
/*
* This is not a part type
*/
RetVal = ZESTSC1_ILLEGAL_FILE;
goto fail;
}
PartString=malloc(Length);
if (PartString==NULL)
{
/*
* Could not allocate buffer for string
*/
RetVal = ZESTSC1_OUT_OF_MEMORY;
goto fail;
}
if (fgets(PartString, Length, FileHandle)==NULL)
{
/*
* File error while reading string
*/
RetVal = ZESTSC1_ILLEGAL_FILE;
goto fail;
}
PartDone=1;
break;
case ZESTSC1_BITFILE_IMAGE:
/*
* Field containing the image data
*/
Char[1] = fgetc(FileHandle);
Char[2] = fgetc(FileHandle);
Char[3] = fgetc(FileHandle);
Char[4] = fgetc(FileHandle);
if (Char[1]==EOF || Char[2]==EOF || Char[3]==EOF || Char[4]==EOF)
{
/*
* Not expecting an end of file
*/
RetVal = ZESTSC1_ILLEGAL_FILE;
goto fail;
}
BufferLength = (((unsigned long)Char[1])<<24) |
(((unsigned long)Char[2])<<16) |
(((unsigned long)Char[3])<<8) |
((unsigned long)Char[4]);
if (BufferLength>(unsigned long)FileStat.st_size)
{
/*
* Illegal value - assume its a bad format file
*/
RetVal = ZESTSC1_ILLEGAL_FILE;
goto fail;
}
Buffer = malloc((BufferLength+511+512)&~511);
if (Buffer==NULL)
{
/*
* Could not allocate buffer for image
*/
RetVal = ZESTSC1_ILLEGAL_FILE;
goto fail;
}
ImageDone=1;
if (fread(Buffer, sizeof(char), BufferLength, FileHandle)!=BufferLength*sizeof(char))
{
/*
* Error while reading data
*/
RetVal = ZESTSC1_ILLEGAL_FILE;
goto fail;
}
memset(Buffer+BufferLength, 0, ((BufferLength+511+512)&~511)-BufferLength);
NewHandle->Buffer = Buffer;
NewHandle->BufferSize = BufferLength;
break;
}
}
/*
* Try to find part type
*/
NewHandle->PartType = ZESTSC1_FPGA_UNKNOWN;
for (Count=0; Count<ZESTSC1_NUM_PART_TYPES; Count++)
{
if (PartString && strstr(PartString, ZestSC1_PartTypes[Count].Name)!=NULL)
{
NewHandle->PartType = ZestSC1_PartTypes[Count].PartType;
break;
}
}
fclose(FileHandle);
free(PartString);
if (NewHandle->PartType==ZESTSC1_FPGA_UNKNOWN)
{
free(Buffer);
return ZESTSC1_INVALID_PART_TYPE;
}
else
{
*Image = NewHandle;
return ZESTSC1_SUCCESS;
}
fail:
/*
* Failure while reading file
*/
if (FileHandle!=NULL)
{
fclose(FileHandle);
}
if (PartDone==1)
{
free(PartString);
}
if (ImageDone==1)
{
free(Buffer);
}
free(NewHandle);
return RetVal;
}
/******************************************************************************
* Configure the FPGA on a board from a configuration image in memory *
******************************************************************************/
ZESTSC1_STATUS ZestSC1Configure(ZESTSC1_HANDLE Handle,
ZESTSC1_IMAGE Image)
{
ZESTSC1_STATUS Status;
Status = ZestSC1_Configure(Handle, Image);
if (Status!=ZESTSC1_SUCCESS)
{
ZESTSC1_ERROR("ZestSC1Configure", Status);
}
return ZESTSC1_SUCCESS;
}
/******************************************************************************
* Configure the FPGA on a board from a configuration image in memory *
* Internal version that always returns errors (i.e. no error callback) *
******************************************************************************/
static ZESTSC1_STATUS ZestSC1_Configure(ZESTSC1_HANDLE Handle,
ZESTSC1_IMAGE Image)
{
char Buffer[3] = {0,0,0};
ZESTSC1_HANDLE_STRUCT *Struct = (ZESTSC1_HANDLE_STRUCT *)Handle;
ZESTSC1_IMAGE_HANDLE_STRUCT *ImageStruct = (ZESTSC1_IMAGE_HANDLE_STRUCT *)Image;
int RetVal = 0;
unsigned long Length = 0;
ZESTSC1_STATUS Status;
/*
* Check the card handle is OK
*/
if (Struct==NULL ||
Struct->Magic!=ZESTSC1_HANDLE_MAGIC)
{
return ZESTSC1_ILLEGAL_HANDLE;
}
/*
* Check the image handle is OK
*/
if (ImageStruct==NULL ||
ImageStruct->Magic!=ZESTSC1_IMAGE_HANDLE_MAGIC)
{
return ZESTSC1_ILLEGAL_IMAGE_HANDLE;
}
/*
* Abort all current transfers
*/
// FIXME: There is no Linux equivalent of AbortPipe
/*
* Reset 8051
*/
Status = ZestSC1_Reset8051(Handle);
if (Status!=ZESTSC1_SUCCESS)
{
return Status;
}
/*
* Send data to the card
*/
Length = (ImageStruct->BufferSize+511+512)&~511;
RetVal = usb_control_msg(Struct->DeviceHandle, EP_CTRL_READ, VR_START_CONFIG,
(Length>>16)&0xffff, Length&0xffff,
Buffer, 2, Struct->TimeOut);
if (RetVal<=0)
{
return ZESTSC1_INTERNAL_ERROR;
}
if (Buffer[1]!=0)
{
return ZESTSC1_TIMEOUT;
}
if (usb_bulk_write(Struct->DeviceHandle, EP_CONFIG_WRITE,
ImageStruct->Buffer, Length, Struct->TimeOut)!=(long)Length)
{
return ZESTSC1_INTERNAL_ERROR;
}