/*
 *	
 *	User space firmware loader utility for ISI Cards. 
 *	This assumes the firmware files (bin)s to be in the 
 *	"/usr/local/ISICOM/ directory" - sameer
 *
 */
 
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include "isicom.h"

#define	FIRMWARE_PATH	"/usr/local/ISICOM/" 

main(int argc, char ** argv)
{
	unsigned int fd, signature, fwd, records=0,i,card;
	bin_frame frame,file_frame;
	unsigned short r;
	char firmware[50];
	
	if ((fd=open("/dev/isictl", O_RDWR))==-1) {
		printf("Open failed on /dev/isictl.\n");
		exit(0);
	}
	for (card = 0; card < 4; card++) {
		signature = card;
		/*
		 * ioctl failure may be due to either non-existent card  or 
		 * bad I/O port, in the latter case the firmware loader will
		 * spit out the error message.
		 */
		if (ioctl(fd,MIOCTL_RESET_CARD,&signature)) 
			continue;
	
		switch(signature){
			case 0xa5: sprintf(firmware, FIRMWARE_PATH"isi608.bin"); break;
			case 0xbb: sprintf(firmware, FIRMWARE_PATH"isi608em.bin"); break;
			case 0xcc: sprintf(firmware, FIRMWARE_PATH"isi616em.bin"); break;
			case 0xdd: sprintf(firmware, FIRMWARE_PATH"isi4608.bin"); break;
			case 0xee: sprintf(firmware, FIRMWARE_PATH"isi4616.bin"); break;
			default  : printf("Unknown signature.\n"); exit(0);
		}
	
		
		if ((fwd=open(firmware, O_RDONLY))==-1) { 
			printf("Couldn't find firmware file %s.\n", firmware);
			continue;
		}
		while(read(fwd, &frame.addr, 2*sizeof(unsigned short))==(2*sizeof(unsigned short))) {
		/* 
		 *  first read the addr and count values from the firmware file 
		 */ 
			if (read(fwd, frame.bin_data, frame.count)==frame.count) {
				frame.board = card;			
				if (ioctl(fd, MIOCTL_LOAD_FIRMWARE, &frame)) {
					printf("ioctl failed to load record.\n");
					exit(0);
				}
				else	 
					records++;		
			}
			else {
				printf("Failed to read required amount of data from the .bin file.\n");
				exit(0);
			}
		}
		
	
		if (close(fwd))
			printf("couldn't close firmware file.\n");
		
		
		if ((fwd=open(firmware, O_RDONLY))==-1) { 
			printf("Couldn't find firmware file %s.\n", firmware);
			continue;
		}
		records=0;
		while(read(fwd, &frame.addr,2*sizeof(unsigned short)) == (2*sizeof(unsigned short))) {
		/* 
		 *  first read the addr and count values from the firmware file 
		 */
			if ((r=read(fwd, file_frame.bin_data, frame.count)) == frame.count)	{
				frame.board = card;		
				if (ioctl(fd, MIOCTL_READ_FIRMWARE, &frame)) {
					printf("ioctl failed to read record.\n");
					exit(0);
				}
				records++;
		
			}
			else {
				printf("Failed to read required amount of data from the .bin file.\n");
				exit(0);
			}
			for(i=0;i<r;i++) 
				if (file_frame.bin_data[i] != frame.bin_data[i]) {
					printf("Firmware load verification failure.\n");
					exit(0);
				}	
	
		}
			
		printf("Firmware %s loaded and verified.\n", firmware);
		if (close(fwd))
			printf("couldn't close firmware file.\n");	
		signature = card;		
		if (ioctl(fd, MIOCTL_XFER_CTRL, &signature)) {
			printf("ioctl failed to xfer ctrl.\n");
			continue;
		}
	}	
	if (close(fd))
		printf("Close failed on /dev/isictl.\n");
	exit(0);	
}
	
	
	
