/* $Id: hty_load.c,v 1.3 91/09/16 16:09:15 leynette Exp $ */
/****************************************************************/
/* 						hty_load.c								*/
/****************************************************************/
/*																*/
/*                 Confidential Information                     */
/*      Limited Distribution to Authorized Persons Only         */
/*     Created 1987 and Protected as an Unpublished Work        */
/*          Under the U.S. Copyright Act of 1976.               */
/*         Copyright (c) 1987, Systech Corporation          	*/
/*                  All Rights Reserved                         */
/*																*/
/*	THIS SOFTWARE IS LICENSED BY AND IS THE	CONFIDENTIAL AND 	*/
/*	PROPRIETARY PROPERTY OF SYSTECH COMPUTER CORPORATION AND 	*/
/*	MAY NOT, WITHOUT THE PRIOR WRITTEN CONSENT OF SYSTECH 		*/
/*	COMPUTER CORPORATION, BE REPRODUCED, USED OR DISCLOSED 		*/
/*	EXCEPT IN ACCORDANCE WITH A SYSTECH COMPUTER CORPORATION 	*/
/*	SOFTWARE LICENSE AGREEMENT.									*/
/****************************************************************/
/*																*/
/* This file reads from a "hty_config" file and sends the		*/
/* network configuration to the raw driver.						*/
/*																*/
/*	hty_load d /dev/rhp0 /etc/hty_config						*/
/*																*/
/*	See routine usage() for usage information.					*/
/*																*/
/****************************************************************/

#include <stdio.h>
#include <ctype.h>
#include <string.h>

#include <fcntl.h>
#include "hps.types.h"
#include "hps.iocb.h"
#include "hps.ioctl.h"
#include "hps.onb.h"
#include "hps.net.h"
#include "hps.asynch.h"
#include "hpsdrconf.h"


#define MAX_LINE	256
#define MAX_PORTS	17			/* maximum ports on a cluster (e.g. 7088) */

DNL_CONF		buf[MAX_LINE+1];
int				fd;				/* file descriptor */
int				ret;			/* stores ret val from getmsg */
int				n, gap, i, j;
int				buf_index = 0;	/* first element contains len */
int				lastbrd;
int				brdcnt;
long			temp;
	
extern int			errno;


/* port types defines */
#define TERMINAL	'T'			/* terminal */
#define PLP			'P'			/* parallel line printer */
#define SLP			'S'			/* serial line printer	*/
#define SERIAL		0x01		/* A serial printer is special			*/ 
#define PARALLEL	0x02		/* Indicates a parallel printer			*/

/* max and min defines */
#define MAX_ADDR	0xFF		/* cluster and host adapter address */
#define MIN_ADDR	0x01		/* cluster and host adapter address */
#define INVALID_ADDR(addr)	((addr)< MIN_ADDR || (addr) > MAX_ADDR)

main(argc,argv)
int  argc;
char *argv[];
{
	FILE *cfgfp;
	int  chan;
	int  ha_num, clus_addr, num_chan;
	int  min_dev = 0, i;
	int	 result;
	char line[MAX_LINE];
	char port_type[MAX_PORTS];
	char slps[MAX_LINE];
	char *dldev = RAW_DEVNAME;	/* Default HPS node name */
	char *key;
	char *conf_file = "/etc/hty_config"; /* Set a default */
	char c;
	extern int rmtblanks();

	/* Scan the command line */
	if (argc >= 2)
	{
		key = argv[1];
		i = argc - 2;
		while (*key)
		{
			switch (c = *key++) /* Possible values: fd */
			{
				case 'f':				/* Set the config file name */
					if (i <= 0)
					{
						fprintf(stderr,
							"%s: Need configuration file name\n", argv[0]);
						usage(argv[0]);
						exit(1);
					}
					else 
					{
						conf_file = argv[argc - i];
						i--;
					}
					break;

				case 'd':	/* Set the device name */
					if (i <= 0)
					{
						fprintf(stderr, "%s: Need device name\n",argv[0]);
						usage(argv[0]);
						exit(1);
					}
					else 
					{
						dldev = argv[argc - i];
						i--;
					}
					break;

				default:
					fprintf(stderr,
						"%s: \"%c\" bad keyletter\n", argv[0], c);
					usage(argv[0]);
					exit(1);
			}
		}
	}

	if ((cfgfp = fopen(conf_file, "r")) == 0)
	{
		fprintf(stderr, "%s: Unable to open file %s\n", argv[0], conf_file);
		if (errno)
			perror(argv[0]);
		exit(1);
	}

	while (fgets(line, MAX_LINE, cfgfp) != 0)
	{
		/* Initialize to no serial line printers */
		*slps = 0;			

		rmtblanks(line);
		if (strlen(line) == 0) continue;
		sscanf(line, "%d %d %d %s", &ha_num, &clus_addr, &num_chan, slps);

		/* Check for valid host adapter number */
		if (ha_num < 0 || ha_num > NHPSCTRL)
			fprintf(stderr,"%s: Host Adapter %d is out of range (%d to %d)\n",
					argv[0], ha_num, 0, NHPSCTRL);

		/* Check for valid cluster address */
		if (INVALID_ADDR(clus_addr))
			fprintf(stderr,"%s: Cluster Address %d is out of range (%d to %d)\n",
					argv[0], clus_addr, MIN_ADDR, MAX_ADDR);

		/* Check for valid number of channels */
		if (num_chan != 8 && num_chan != 9 && num_chan != 16 && num_chan != 17)
			fprintf(stderr,"%s: Cluster type %d is invalid.  Valid cluster types are 8, 9, 16, or 17.\n", 
					argv[0], num_chan);
			
		/* Make terminal ports the default */
		for (chan=0; chan<num_chan; chan++)
			port_type[chan] = TERMINAL;

		/* Search for serial ports */
		if (*slps)
			result = look4serial(slps, num_chan, port_type, argv[0]);

		if (result)
		{
			fprintf(stderr,"%s: Error on %s line %s\n",argv[0],conf_file,line);
			continue;
		}

		/* The 8th port of 9 chan clusters are always parallel ports */
		/* The 16th channel is a parallel printer for the HPS6237  */
		if (num_chan == 9)
			port_type[8] = PLP;
		else if (num_chan == 17)
			port_type[16] = PLP;

		/* Write info in buffer */
#if 1
		buf_index++;
		buf[buf_index].c_cboard = ha_num; 
		buf[buf_index].c_cstation = clus_addr;
		buf[buf_index].c_cnumber  = num_chan;
#else
		for (n=0; n<num_chan; n++)
		{
			buf[buf_index+n].c_cboard = ha_num; 
			buf[buf_index+n].c_cstation = clus_addr;
			buf[buf_index+n].c_cnumber  = n;
			if (port_type[n] == TERMINAL)
				buf[buf_index+n].c_cflags = 0;
			else if (port_type[n] == PLP)
				buf[buf_index+n].c_cflags = PARALLEL;
			else
				buf[buf_index+n].c_cflags = SERIAL;
			min_dev++;
		}
		buf_index = buf_index + n;
#endif
	}

	/*
	 *	Compute the total number of channels in the config file.
	 */
	buf[0].d1.data_len = buf_index;

	/*
	 *	Open up the respective device (hps).
	 *
	 *	IF open returns an error, then print an appropriate
	 *	message, and exit.
	 */
	if ((fd = open(dldev,O_RDWR)) < 0)
	{
		fprintf(stderr, "%s: Cannot open device %s\n", argv[0], dldev);
		if (errno)
			perror(argv[0]);
		exit(3);
	}

	/*
	 *  Send system configuration info to the Board.	
	 */
	if ((ret = ioctl(fd, DO_CONFIG, buf)) != 0)
	{
		fprintf(stderr, "%s: Error setting network configuration.\n", argv[0]);
		if (errno)
			perror(argv[0]);
	}

	/*
	 *	Close the raw device
	 */
	close(fd);
	
	fclose(cfgfp);
	exit(0);
}


int  look4serial(line, num_chan, port_type, pname)
char *line;				/* string containing serial ports for cluster */
int  num_chan;			/* number of channels for this cluster 		*/
char *port_type;		/* array of port types 						*/
char *pname;
{
	char *port = line;
	char *pos  = line;
	int  serial;
	int  error=0;

	line[strlen(line)] = ' ';
	while (*pos)
	{
		if (*pos == ',' || *pos == ' ')
		{
			*pos = 0;
			if (*port)
			{
				serial = atoi(port);
				/* serial port must be in port range 0 to num_chan-1 */
				if (serial < 0 || serial > num_chan-1)
				{
					fprintf(stderr,
							"%s\tSerial port %d out of range (0 to %d)\n",
							pname, serial, num_chan-1);
					error = 1;
				}
				else if (num_chan == 9 && serial == num_chan-1)
				{
					fprintf(stderr, 
							"%s\tParallel port %d cannot be a serial port\n",
							pname, serial);
					error = 1;
				}
				else
					port_type[serial] = SLP;
			}
			port = pos + 1;
		}
		pos++;
	}
	return (error);
}

/*
 * rmtblanks():  remove trailing blanks and comments from string <line>
 */
rmtblanks(line)
char *line;
{
	int i;
	char *holdptr;

	if ((holdptr = strchr(line,'#')) != 0)
		*holdptr = 0;
	for (i=strlen(line)-1; i>=0; i--)
	{
		if (isspace(line[i]))
			line[i] = 0;
		else
			break;
	}
}

usage(prog)
char *prog;
{ 
#define DISPLAY_HELP \
"%s [d <device name>] [f <hty_config>]\n\
	%s reads from file <hty_config> and builds a table which is in turn\n\
	sent to the driver to dynamically set the network configuration.\n"

	fprintf(stderr, "%s: usage: ", prog);
	fprintf(stderr, DISPLAY_HELP, prog, prog);
	exit(1);
}

/*
 * MODIFICATION HISTORY:
 *
 * $Log:	hty_load.c,v $
 * Revision 1.1.2.1  92/06/24  13:53:42  marker
 * Branch RISCOS_5_01_2_FIXES off of trunk.
 * 
 * Revision 1.3  91/09/16  16:09:15  leynette
 * Modified the options for this program by adding the 'f' option for an alternate
 * filename.  The default config file is now /etc/hty_config.  Removed #define for
 * CONFIGFILE.
 * ENHANCEMENT
 * 
 * Revision 1.2  91/09/03  17:58:03  annette
 * Changed usage statement to be more accurate.
 * INTERNAL
 * 
 * Revision 1.1  91/09/03  17:49:17  annette
 * Initial revision
 * 
 */
