#if 0
#
# ADIDRV V1.00
# Driver for configuring VL-Bus IDE-Card with Appian ADI2 and Acer 5105 Chip.
# For help call ADIDRV without parameters.
#
# Copyright (C) 1993, by Karsten Ball\"uder, Germany
#			
#		For any comments, questions, etc, send e-mail to:
#				kballued@jupiter.rz.uni-osnabrueck.de
#
# This software is in the public domain. Permission is granted to modify and 
# distribute it free of charge as long as it is accompanied with a note naming
# the original author.
#
# See README for details.
#
# For compiling adidrv.c simply call it as a shell command!
# Shell script for compiling adidrv.c:
gcc -O6 -o adidrv adidrv.c
exit
#endif
/***************** here starts the C-part of it... ***********************/

#define USAGE \
		"\nADI2 configuration program (C) 1993 by Karsten Ballueder\n"\
		"----------------------------------------------------------\n"\
		"                     kballued@jupiter.rz.uni-osnabrueck.de\n\n"\
		"USAGE:	%s  -dapwsl [filename] [register:value] [address]\n\n"\
		"\td - detect base adress\t\ta - set base address\n"\
		"\tp - print all registers\t\tw - write register with value\n"\
		"\ts - save all registers to file\tl - load all registers from file\n\n"

#include "main.h"

#include 	<sys/stat.h>
#include 	<stdlib.h>
#include	<fcntl.h>
#include	<unistd.h>
#include 	<stdio.h>

#define 	ID	0x004
#define 	IDX     0x008
#define 	DATA	0x00c
#define 	BASE_A	0x0030
#define 	BASE_B	0x00b0

#define 	CHIP_ID	0x33

unsigned int 	base[] = {BASE_A, BASE_B};
unsigned int 	BASE = BASE_B;
int 		portfd = -1;


int access_ports(void)
{
	return open("/dev/port",O_RDWR);
}

unsigned int read_adi_port(unsigned idx)
{
	unsigned char 	data;

	if(idx > 0x0f)
	{	printf("\aError: Cannot access register %02u.\n",idx);
		return;
	}	
	lseek(portfd,BASE+IDX,SEEK_SET);
	data = idx, write(portfd,&data,1);
	
	lseek(portfd,BASE+DATA,SEEK_SET);
	read(portfd,&data,1);	

	return data;
}

void write_adi_port(unsigned idx, unsigned value)
{
	unsigned char 	data;


	if(idx > 0x0f)
	{	printf("\aError: Cannot access register %02u.\n",idx);
		return;
	}	
	lseek(portfd,BASE+IDX,SEEK_SET);
	data = idx, write(portfd,&data,1);
	
	lseek(portfd,BASE+DATA,SEEK_SET);
	data = value, write(portfd,&data,1);	
	printf("wrote %u to %u\n", value, idx);
}

unsigned char get_id(void)
{
	unsigned char data;
	
	lseek(portfd,BASE+ID,SEEK_SET);
	read(portfd,&data,1);
	return data;
}

void save_conf(char *file)
{
	int fd = open(file,O_CREAT|O_WRONLY|O_TRUNC,S_IRUSR|S_IWUSR);
	unsigned int i;
	unsigned char data;

	if(fd < 1)
	{	printf("\aCannot open file %s for write!\n", file);
		return;
	}

	for(i = 1; i <=	0x0F; i++)
	{	data = read_adi_port(i);
		write(fd, &data, sizeof data);
	}
	close(fd);
}
	
void load_conf(char *file)
{
	int fd = open(file,O_RDONLY);
	unsigned int i;
	unsigned char data;

	if(fd < 1)
	{	printf("\aCannot open file %s for read!\n", file);
		return;
	}

	for(i = 1; i <=	0x0F; i++)
	{	read(fd, &data, sizeof data);
		write_adi_port(i, data);
	}
	close(fd);
}

void detect_adi2(void)
{	
	unsigned int 	i, flag;

	flag = 255;
	for(i = 0; i < 2; i++)
	{	BASE = base[i];
		if(get_id()==0x33)
			printf("ADI2 detected at 0x%02x.\n",
				BASE), flag = i;
			
	}
	if(flag == 255)
		printf("\aALERT! No ADI2 detected.\n");
	else
		BASE = base[flag];
}


MAIN
{
	unsigned i, flag;
	char *pname = *argv;

	if((portfd = access_ports()) < 0)
		printf("\aFatal error: Cannot open \\dev\\port!\n"),
		exit(1);

	if(argc < 2)
		printf(USAGE,pname), exit(EXIT_FAILURE);

	write_adi_port(ID,CHIP_ID);

	OPT
	ARG 'd':
		detect_adi2();		
	ARG 'a':
		PARM
		if(sscanf(*argv,"%x", &BASE))
			printf("ADI2 base port set to 0x%02x.\n", BASE);
		else
			printf("\aERROR: option -a must be followed by hexadecimal base address!\n");
	NEXTOPT	
	ARG 'p':
		printf("Reg.\tValue\n");		
		for(i=0; i <= 0x0F; i++)
			printf("0x%02x\t0x%02x\n",(unsigned) i, read_adi_port(i));

	ARG 's':
		PARM
		if(*argv)
			save_conf(*argv);
		else
			printf("\aERROR: option -s must be followed by filename!\n");
	NEXTOPT
	ARG 'l':
		PARM
		if(*argv)
			load_conf(*argv);
		else
			printf("\aERROR: option -l must be followed by filename!\n");
	NEXTOPT
	ARG 'w':
		PARM
		if(sscanf(*argv,"%u:%u", &i, &flag)==2)
			write_adi_port(i,flag);
		else
			printf("\aError: option -w must be followed by register:value.\n");
	NEXTOPT
	ARG 'h':
		printf(USAGE,pname);
	OTHER 
		printf("\aError: unknown option.\n");
		printf(USAGE,pname);
	ENDOPT

	close(portfd);
	return EXIT_SUCCESS;
}
