You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
782 lines
18 KiB
782 lines
18 KiB
/*--------------------------------------------------------------------------
|
|
*
|
|
* Copyright (C) Cyclades Corporation, 1997-2001.
|
|
* All rights reserved.
|
|
*
|
|
* Cyclades-Z Enumerator Driver
|
|
*
|
|
* This file: cyzload.c
|
|
*
|
|
* Description: This is the firmware loader for the Cyclades-Z series
|
|
* of multiport serial cards.
|
|
*
|
|
* Notes: This code supports Windows 2000 and Windows XP,
|
|
* x86 and ia64 processors.
|
|
*
|
|
* Complies with Cyclades SW Coding Standard rev 1.3.
|
|
*
|
|
*--------------------------------------------------------------------------
|
|
*/
|
|
|
|
/*-------------------------------------------------------------------------
|
|
*
|
|
* Change History
|
|
*
|
|
*--------------------------------------------------------------------------
|
|
*
|
|
*
|
|
*--------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "pch.h"
|
|
|
|
|
|
/*-------------------------------
|
|
*
|
|
* Prototypes
|
|
*
|
|
*--------------------------------
|
|
*/
|
|
|
|
ULONG
|
|
z_ident( Z_BOARD_IDENT board );
|
|
|
|
VOID
|
|
z_block_copy( Z_BOARD_IDENT board, PVOID ptr, ULONG offset, ULONG size );
|
|
|
|
VOID
|
|
z_fpga_copy( Z_BOARD_IDENT board, PVOID ptr, ULONG size );
|
|
|
|
VOID
|
|
z_start_cpu( Z_BOARD_IDENT board );
|
|
|
|
//VOID
|
|
//z_stop_cpu(
|
|
// Z_BOARD_IDENT board
|
|
//);
|
|
//
|
|
//int
|
|
//z_fpga_check(
|
|
// Z_BOARD_IDENT board
|
|
//);
|
|
//
|
|
//VOID
|
|
//z_reset_board( Z_BOARD_IDENT board );
|
|
|
|
|
|
HANDLE
|
|
zl_fopen( PCWSTR file_name );
|
|
|
|
VOID
|
|
zl_fclose( IN Z_STREAM NtFileHandle );
|
|
|
|
ULONG
|
|
zl_fread( IN PVOID ptr,
|
|
IN ULONG size,
|
|
IN ULONG count,
|
|
IN Z_STREAM stream,
|
|
IN ULONG Uoffset );
|
|
|
|
VOID
|
|
zl_delay( LONG number_of_ms );
|
|
|
|
|
|
#ifdef CHANGE_FOR_Z
|
|
//#ifdef ALLOC_PRAGMA
|
|
//#pragma alloc_text(INIT,z_load)
|
|
//#pragma alloc_text(INIT,z_ident)
|
|
//#pragma alloc_text(INIT,z_block_copy)
|
|
//#pragma alloc_text(INIT,z_fpga_copy)
|
|
//#pragma alloc_text(INIT,z_start_cpu)
|
|
//#pragma alloc_text(INIT,zl_fopen)
|
|
//#pragma alloc_text(INIT,zl_fclose)
|
|
//#pragma alloc_text(INIT,zl_fread)
|
|
//#pragma alloc_text(INIT,zl_delay)
|
|
//#ifdef RESET_BOARD
|
|
//#pragma alloc_text(PAGESER,z_reset_board)
|
|
//#else
|
|
//#pragma alloc_text(INIT,z_reset_board)
|
|
//#endif
|
|
//#pragma alloc_text(PAGESER,z_fpga_check)
|
|
//#pragma alloc_text(PAGESER,z_stop_cpu)
|
|
//#endif
|
|
#endif
|
|
|
|
#ifndef ZBUF_STACK
|
|
static struct ZFILE_HEADER header;
|
|
static struct ZFILE_CONFIG config;
|
|
static struct ZFILE_BLOCK block;
|
|
static char data[ZBUF_SIZE];
|
|
#endif
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------
|
|
*
|
|
* z_load( IN Z_BOARD_IDENT board,
|
|
* IN UINT32 function,
|
|
* IN PCWSTR filename )
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*
|
|
* Description: Loads the Cyclades-Z Firmware. Returns a non-zero on error.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
int
|
|
z_load (
|
|
Z_BOARD_IDENT board, UINT32 function, PCWSTR filename)
|
|
{
|
|
|
|
unsigned long i;
|
|
unsigned long dpmem;
|
|
unsigned long count;
|
|
Z_STREAM file;
|
|
//*********************
|
|
//size_t s, s2;
|
|
//*********************
|
|
unsigned long s,s2;
|
|
unsigned long mailbox;
|
|
unsigned long load_fpga_flag = TRUE;
|
|
unsigned long first_time = TRUE;
|
|
|
|
|
|
#ifdef ZBUF_STACK
|
|
struct ZFILE_HEADER header;
|
|
struct ZFILE_CONFIG config;
|
|
struct ZFILE_BLOCK block;
|
|
char data[ZBUF_SIZE];
|
|
#endif
|
|
|
|
mailbox = z_ident(board);
|
|
|
|
file = zl_fopen (filename);
|
|
|
|
if (file!=NULL)
|
|
{
|
|
/* Read the header */
|
|
zl_fread (&header, sizeof(header), 1, file, 0);
|
|
|
|
/* Find the correct configuration */
|
|
for (i=0; i<header.n_config; i++)
|
|
{
|
|
zl_fread (&config, sizeof(config), 1, file,
|
|
header.config_offset + (sizeof(config)*i));
|
|
|
|
if (config.mailbox==mailbox && config.function==function)
|
|
break;
|
|
}
|
|
|
|
/* Return error: No matching configuration */
|
|
if (i>=header.n_config)
|
|
{
|
|
zl_fclose (file);
|
|
return (ZL_RET_NO_MATCHING_FW_CONFIG);
|
|
}
|
|
|
|
#ifndef DEBUG_LOAD
|
|
if ((mailbox == 0) || (z_fpga_check(board))) {
|
|
load_fpga_flag = FALSE;
|
|
z_stop_cpu(board);
|
|
}
|
|
#endif
|
|
|
|
#ifdef RESET_BOARD
|
|
load_fpga_flag = TRUE;
|
|
/* Reset the board */
|
|
z_reset_board (board);
|
|
#endif
|
|
|
|
/* Load each block */
|
|
for (i=0; i<config.n_blocks; i++)
|
|
{
|
|
|
|
/* Load block struct */
|
|
zl_fread (&block, sizeof(block), 1, file,
|
|
header.block_offset+(sizeof(block)*config.block_list[i]));
|
|
|
|
/* Load and Copy the data block */
|
|
count=0;
|
|
s = block.size;
|
|
while (s>0)
|
|
{
|
|
s2 = zl_min(ZBUF_SIZE,s);
|
|
if (zl_fread (data, 1, s2, file, block.file_offset + count)!=0) {
|
|
|
|
/* Call the copy function */
|
|
if (block.type==ZBLOCK_FPGA) {
|
|
if (load_fpga_flag) {
|
|
z_fpga_copy (board, data, s2);
|
|
}
|
|
} else {
|
|
if (first_time) {
|
|
CYZ_WRITE_ULONG(&((board->Runtime)->loc_addr_base),
|
|
WIN_RAM);
|
|
//Code added to debug pentium II
|
|
//RtlFillMemory( (PUCHAR)board->BoardMemory,
|
|
// board->DPMemSize, 0x00 );
|
|
|
|
for (dpmem=0; dpmem<board->BoardMemoryLength; dpmem++) {
|
|
CYZ_WRITE_UCHAR(board->BoardMemory+dpmem,0x00);
|
|
}
|
|
first_time = FALSE;
|
|
}
|
|
z_block_copy (board, data, block.ram_offset + count, s2);
|
|
}
|
|
count += s2;
|
|
s -= s2;
|
|
} else {
|
|
zl_fclose (file);
|
|
return (ZL_RET_FILE_READ_ERROR);
|
|
}
|
|
} // end for (reading every ZBUF_SIZE)
|
|
|
|
if (block.type==ZBLOCK_FPGA) {
|
|
/* Delay for around for 1ms */
|
|
zl_delay(1); /* Is this needed? */
|
|
|
|
if (!z_fpga_check(board)) {
|
|
zl_fclose(file);
|
|
return(ZL_RET_FPGA_ERROR);
|
|
}
|
|
}
|
|
} // end for (reading every block)
|
|
zl_fclose (file);
|
|
|
|
z_start_cpu(board);
|
|
|
|
return (ZL_RET_SUCCESS);
|
|
|
|
} else {
|
|
|
|
/* Return error: Error opening file */
|
|
return (ZL_RET_FILE_OPEN_ERROR);
|
|
}
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------
|
|
*
|
|
* z_ident( IN Z_BOARD_IDENT board )
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*
|
|
* Description: Returns the ID number (the mailbox reg)
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
ULONG
|
|
z_ident( Z_BOARD_IDENT board )
|
|
{
|
|
ULONG mailbox;
|
|
|
|
mailbox = CYZ_READ_ULONG(&(board->Runtime)->mail_box_0);
|
|
|
|
return (mailbox);
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------
|
|
*
|
|
* z_reset_board( IN Z_BOARD_IDENT board )
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*
|
|
* Description: Resets the board using the PLX registers.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
VOID
|
|
z_reset_board( Z_BOARD_IDENT board )
|
|
{
|
|
|
|
ULONG sav_buf[12];
|
|
PULONG loc_reg;
|
|
ULONG j;
|
|
ULONG init_ctrl;
|
|
LARGE_INTEGER d100ms = RtlConvertLongToLargeInteger(-100*10000);
|
|
|
|
// Prepare board for reset.
|
|
// The PLX9060 seems to destroy the local registers
|
|
// when there is a hard reset. So, we save all
|
|
// important registers before resetting the board.
|
|
|
|
loc_reg = (ULONG *) board->Runtime;
|
|
for (j=0; j<12; j++) {
|
|
sav_buf[j] = CYZ_READ_ULONG(&loc_reg[j]);
|
|
}
|
|
|
|
// Reset board
|
|
|
|
init_ctrl = CYZ_READ_ULONG(&(board->Runtime)->init_ctrl);
|
|
init_ctrl |= 0x40000000;
|
|
CYZ_WRITE_ULONG(&(board->Runtime)->init_ctrl,init_ctrl);
|
|
KeDelayExecutionThread(KernelMode,FALSE,&d100ms);
|
|
init_ctrl &= ~(0x40000000);
|
|
CYZ_WRITE_ULONG(&(board->Runtime)->init_ctrl,init_ctrl);
|
|
KeDelayExecutionThread(KernelMode,FALSE,&d100ms);
|
|
|
|
// Restore loc conf registers
|
|
|
|
for (j=0; j<12; j++) {
|
|
CYZ_WRITE_ULONG(&loc_reg[j],sav_buf[j]);
|
|
}
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------
|
|
*
|
|
* z_block_copy( IN Z_BOARD_IDENT board,
|
|
* IN PVOID ptr,
|
|
* IN ULONG offset,
|
|
* IN ULONG size )
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*
|
|
* Description: This function should copy size bytes of data from the
|
|
* buffer pointed to by ptr into the Cyclades-Z's memory starting at
|
|
* offset.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
VOID
|
|
z_block_copy (Z_BOARD_IDENT board, PVOID ptr, ULONG offset, ULONG size)
|
|
{
|
|
//Code added to debug Pentium II
|
|
// RtlCopyMemory( (PUCHAR)board->BoardMemory + offset, ptr, size );
|
|
|
|
|
|
ULONG numOfLongs;
|
|
ULONG numOfBytes;
|
|
|
|
numOfLongs = size/sizeof(ULONG);
|
|
numOfBytes = size%sizeof(ULONG);
|
|
|
|
while (numOfLongs--) {
|
|
|
|
CYZ_WRITE_ULONG((PULONG)(board->BoardMemory + offset), *((PULONG)ptr));
|
|
//offset++;
|
|
offset += sizeof(ULONG);
|
|
((PULONG)ptr)++;
|
|
}
|
|
|
|
while (numOfBytes--) {
|
|
|
|
CYZ_WRITE_UCHAR((PUCHAR)board->BoardMemory + offset, *((PUCHAR)ptr));
|
|
offset++;
|
|
((PUCHAR)ptr)++;
|
|
}
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------
|
|
*
|
|
* z_fpga_copy( IN Z_BOARD_IDENT board,
|
|
* IN PVOID ptr,
|
|
* IN ULONG size )
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*
|
|
* Description: This function is the same as z_block_copy, except the
|
|
* offset is assumed to always be zero (and not increment) and the copy
|
|
* is done one byte at a time. Essentially, this is the same as writing
|
|
* a buffer to a byte-wide FIFO.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
VOID
|
|
z_fpga_copy (Z_BOARD_IDENT board, PVOID ptr, ULONG size)
|
|
{
|
|
int i;
|
|
char *data;
|
|
char *fpga;
|
|
|
|
fpga = board->BoardMemory;
|
|
data = (char *)ptr;
|
|
|
|
while (size>0)
|
|
{
|
|
CYZ_WRITE_UCHAR(fpga,*data);
|
|
|
|
KeStallExecutionProcessor(10); // wait 10 microseconds
|
|
|
|
size--;
|
|
data++;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------
|
|
*
|
|
* z_fpga_check( IN Z_BOARD_IDENT board )
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*
|
|
* Description: Returns 1 if FPGA is configured.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
int
|
|
z_fpga_check( Z_BOARD_IDENT board )
|
|
{
|
|
if (CYZ_READ_ULONG(&(board->Runtime)->init_ctrl) & 0x00020000) {
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------
|
|
*
|
|
* z_start_cpu( IN Z_BOARD_IDENT board )
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*
|
|
* Description: Starts CPU.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
VOID
|
|
z_start_cpu( Z_BOARD_IDENT board )
|
|
{
|
|
|
|
CYZ_WRITE_ULONG(&(board->Runtime)->loc_addr_base,WIN_CREG);
|
|
|
|
CYZ_WRITE_ULONG(&((struct CUSTOM_REG *) board->BoardMemory)->cpu_start,
|
|
0x00000000);
|
|
|
|
CYZ_WRITE_ULONG(&(board->Runtime)->loc_addr_base,WIN_RAM);
|
|
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------
|
|
*
|
|
* z_stop_cpu( IN Z_BOARD_IDENT board )
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*
|
|
* Description: Stops CPU.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
VOID
|
|
z_stop_cpu( Z_BOARD_IDENT board )
|
|
{
|
|
|
|
CYZ_WRITE_ULONG(&(board->Runtime)->loc_addr_base,WIN_CREG);
|
|
|
|
CYZ_WRITE_ULONG(&((struct CUSTOM_REG *) board->BoardMemory)->cpu_stop,
|
|
0x00000000);
|
|
|
|
CYZ_WRITE_ULONG(&(board->Runtime)->loc_addr_base,WIN_RAM);
|
|
|
|
}
|
|
|
|
|
|
/****************************************************************
|
|
*
|
|
* In David's code, the below functions were macros.
|
|
*
|
|
*****************************************************************/
|
|
|
|
/*------------------------------------------------------------------------
|
|
*
|
|
* zl_fopen(PCWSTR file_name)
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*
|
|
* Description: This routine opens a file, and returns the file handle
|
|
* if successful. Otherwise, it returns NULL.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
HANDLE zl_fopen( PCWSTR file_name )
|
|
{
|
|
UNICODE_STRING fileName;
|
|
NTSTATUS ntStatus;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
HANDLE NtFileHandle;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
ULONG LengthOfFile;
|
|
//WCHAR PathPrefix[] = L"\\SystemRoot\\system32\\drivers\\";
|
|
WCHAR PathPrefix[] = L"\\SystemRoot\\system32\\cyclad-z\\";
|
|
UNICODE_STRING FullFileName;
|
|
ULONG FullFileNameLength;
|
|
FILE_STANDARD_INFORMATION StandardInfo;
|
|
|
|
|
|
RtlInitUnicodeString( &fileName, file_name );
|
|
|
|
FullFileNameLength = sizeof(PathPrefix) + fileName.MaximumLength;
|
|
|
|
FullFileName.Buffer = ExAllocatePool (NonPagedPool,FullFileNameLength);
|
|
|
|
if (FullFileName.Buffer == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
FullFileName.Length = sizeof(PathPrefix) - sizeof(WCHAR);
|
|
FullFileName.MaximumLength = (USHORT)FullFileNameLength;
|
|
RtlMoveMemory (FullFileName.Buffer, PathPrefix, sizeof(PathPrefix));
|
|
RtlAppendUnicodeStringToString (&FullFileName, &fileName);
|
|
|
|
InitializeObjectAttributes ( &ObjectAttributes,
|
|
&FullFileName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL );
|
|
|
|
ntStatus = ZwCreateFile( &NtFileHandle,
|
|
SYNCHRONIZE | FILE_READ_DATA,
|
|
&ObjectAttributes,
|
|
&IoStatus,
|
|
NULL, // alloc size = none
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ,
|
|
FILE_OPEN,
|
|
FILE_SYNCHRONOUS_IO_NONALERT,
|
|
NULL, // eabuffer
|
|
0 ); // ealength
|
|
|
|
if ( !NT_SUCCESS( ntStatus ) )
|
|
{
|
|
ExFreePool(FullFileName.Buffer);
|
|
return NULL;
|
|
}
|
|
|
|
ExFreePool(FullFileName.Buffer);
|
|
|
|
//
|
|
// Query the object to determine its length.
|
|
//
|
|
|
|
ntStatus = ZwQueryInformationFile( NtFileHandle,
|
|
&IoStatus,
|
|
&StandardInfo,
|
|
sizeof(FILE_STANDARD_INFORMATION),
|
|
FileStandardInformation );
|
|
|
|
if (!NT_SUCCESS(ntStatus)) {
|
|
|
|
ZwClose( NtFileHandle );
|
|
return NULL;
|
|
}
|
|
|
|
LengthOfFile = StandardInfo.EndOfFile.LowPart;
|
|
|
|
//
|
|
// Might be corrupted.
|
|
//
|
|
|
|
if( LengthOfFile < 1 )
|
|
{
|
|
ZwClose( NtFileHandle );
|
|
return NULL;
|
|
}
|
|
|
|
return NtFileHandle;
|
|
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------
|
|
*
|
|
* zl_fclose(IN Z_STREAM NtFileHandle)
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*
|
|
* Description: This routine closes a file.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
VOID zl_fclose(IN Z_STREAM NtFileHandle)
|
|
{
|
|
ZwClose(NtFileHandle);
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------
|
|
*
|
|
* zl_fread( IN PVOID ptr,
|
|
* IN ULONG size,
|
|
* IN ULONG count,
|
|
* IN Z_STREAM stream,
|
|
* IN ULONG Uoffset
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*
|
|
* Description: This routine opens a file, and returns the file handle
|
|
* if successful. Otherwise, it returns NULL.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
ULONG zl_fread( IN PVOID ptr,
|
|
IN ULONG size,
|
|
IN ULONG count,
|
|
IN Z_STREAM stream,
|
|
IN ULONG Uoffset)
|
|
{
|
|
IO_STATUS_BLOCK IoStatus;
|
|
LARGE_INTEGER Loffset;
|
|
NTSTATUS ntStatus;
|
|
ULONG readsize;
|
|
|
|
readsize = size*count;
|
|
Loffset = RtlConvertUlongToLargeInteger(Uoffset);
|
|
|
|
ntStatus = ZwReadFile (stream, NULL, NULL, NULL, &IoStatus,
|
|
ptr, readsize, &Loffset, NULL);
|
|
|
|
if( (!NT_SUCCESS(ntStatus)) || (IoStatus.Information != readsize) )
|
|
{
|
|
return 0;
|
|
}
|
|
return readsize;
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------
|
|
*
|
|
* zl_delay( number_of_ms )
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*
|
|
* Description: Delay of milliseconds.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
VOID
|
|
zl_delay(
|
|
LONG number_of_ms
|
|
)
|
|
{
|
|
LARGE_INTEGER delaytime;
|
|
|
|
delaytime = RtlConvertLongToLargeInteger(-number_of_ms*10000);
|
|
|
|
KeDelayExecutionThread(KernelMode,FALSE,&delaytime);
|
|
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/****************************************************************************/
|
|
/****************************************************************************/
|
|
/****************************************************************************/
|
|
|
|
|
|
#if 0
|
|
//*******************************************************************
|
|
//
|
|
// Added for debug
|
|
//
|
|
//*******************************************************************
|
|
int
|
|
z_verify (
|
|
Z_BOARD_IDENT board, UINT32 function, PCWSTR filename)
|
|
{
|
|
|
|
unsigned long i;
|
|
unsigned long count;
|
|
Z_STREAM file;
|
|
//*********************
|
|
//size_t s, s2;
|
|
//*********************
|
|
long s,s2;
|
|
unsigned long mailbox;
|
|
|
|
|
|
#ifdef ZBUF_STACK
|
|
struct ZFILE_HEADER header;
|
|
struct ZFILE_CONFIG config;
|
|
struct ZFILE_BLOCK block;
|
|
char data[ZBUF_SIZE];
|
|
#endif
|
|
|
|
maibox = z_ident(board);
|
|
|
|
file = zl_fopen (filename);
|
|
|
|
if (file!=NULL)
|
|
{
|
|
/* Read the header */
|
|
zl_fread (&header, sizeof(header), 1, file, 0);
|
|
|
|
/* Find the correct configuration */
|
|
for (i=0; i<header.n_config; i++)
|
|
{
|
|
zl_fread (&config, sizeof(config), 1, file,
|
|
header.config_offset + (sizeof(config)*i));
|
|
|
|
if (config.mailbox==mailbox && config.function==function)
|
|
break;
|
|
}
|
|
|
|
/* Return error: No matching configuration */
|
|
if (i>=header.n_config)
|
|
{
|
|
zl_fclose (file);
|
|
return (ZL_RET_NO_MATCHING_FW_CONFIG);
|
|
}
|
|
|
|
/* Load each block */
|
|
for (i=0; i<config.n_blocks; i++)
|
|
{
|
|
/* Load block struct */
|
|
zl_fread (&block, sizeof(block), 1, file,
|
|
header.block_offset+(sizeof(block)*config.block_list[i]));
|
|
|
|
/* Load and Copy the data block */
|
|
count=0;
|
|
|
|
for (s=block.size; s>0; s-=ZBUF_SIZE)
|
|
{
|
|
s2 = zl_min(ZBUF_SIZE,s);
|
|
if (zl_fread (data, 1, s2, file, block.file_offset + count)!=0) {
|
|
|
|
/* Call the copy function */
|
|
if (block.type==ZBLOCK_FPGA)
|
|
z_fpga_copy (board, data, s2);
|
|
else {
|
|
if (z_block_comp (board, data, block.ram_offset + count,
|
|
s2)==0){
|
|
zl_fclose(file);
|
|
return (3);
|
|
}
|
|
}
|
|
count += s2;
|
|
} else {
|
|
zl_fclose (file);
|
|
return (3);
|
|
}
|
|
} // end for
|
|
} // end for
|
|
|
|
zl_fclose (file);
|
|
return (0);
|
|
|
|
} else {
|
|
/* Return error: Error opening file */
|
|
return (2);
|
|
}
|
|
}
|
|
|
|
ULONG
|
|
z_block_comp (Z_BOARD_IDENT board, PVOID ptr, UINT32 offset, long size)
|
|
{
|
|
return (RtlCompareMemory( (PUCHAR)board->BoardMemory + offset, ptr, size ));
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|