/* $Id: hpsver.c,v 2.5 91/09/03 17:39:07 annette Exp $ */
/****************************************************************/
/* hpsver.c - get version information for                   	*/
/*            the TCS and the raw, tty and vtio drivers         */
/****************************************************************/
/*																*/
/*                 Confidential Information                     */
/*      Limited Distribution to Authorized Persons Only         */
/*     Created 1988 and Protected as an Unpublished Work        */
/*          Under the U.S. Copyright Act of 1976.               */
/*         Copyright (c) 1988, 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 program will return version information for the TCS    */
/*	and the raw, tty and vtio drivers if they are installed     */
/*	and initialized.  The information provided contains the     */
/*	following:                                                  */
/*	         Title: Component title                             */
/*            Version: Software version number                  */
/*            Part Number: Systech part number                  */
/*            Creation Date: Date compiled                      */
/*            Description: Product this component is part of    */
/*																*/
/****************************************************************/

#include <stdio.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"

#ifdef HPS_STREAMS
#include <sys/types.h>
#include <sys/stream.h>
#include <sys/stropts.h>
#include "hps_svcintf.h" 
#endif

#define SUCCESS			0		/* success for ioctl() */
#define IOCB_DATA_LEN  	512		/* maximum iocb data length */

#define RAW_DEVNAME_S  "/dev/rhp%s"

typedef struct
{
	A_IOCB iocb;
	char data[IOCB_DATA_LEN];
} IOCB_DATA;

/* macro for initializing iocb data to ZERO */
#define INIT_DATA(data) 	{\
			int i;\
			for (i=0; i<IOCB_DATA_LEN; i++)\
				(data)[i] = 0;\
		}

/* macro for printing error messages */
#define VER_ERR(s1,s2) 	fprintf(stderr,"\n\n%s: %s\n\t%s\n", pname, (s1), (s2))

/* macro for printing version information */
#define PRINTSTR(verptr) printf("\t%s\n",verptr); \
			verptr += strlen(verptr) + 1
#define PRINTINFO(title)	{\
			verptr = ri.data; \
			printf("\n\n\t==%s==\n",title); \
			PRINTSTR(verptr);\
			PRINTSTR(verptr);\
			PRINTSTR(verptr);\
			PRINTSTR(verptr);\
			PRINTSTR(verptr);\
			printf("\n");\
		}
 
#define RAW_TYPE	0
#define TTY_TYPE	1
#define DEBUG_TYPE	2

char  hps_intel    = 0;			/* host byte ordering	*/
IOCB_DATA ri;  			/* the IOCB */

main(argc, argv)
int argc;
char **argv;
{
	extern int errno;
	char choice[128];		/* user's choice */ 
	int  hpsfd;  			/* file descriptor for raw the device */
	int  tmp_hpsfd;
	char hps_mindev[128];	/* minor device for the host adapter */
	char *verptr;
	int debug_driver = 0;
	int raw_driver = 0;
	int hty_driver = 0;
	int tcs = 0;
	char c;
	char *key;
	char *devname;

#ifdef HPS_STREAMS
	struct strbuf	ctlbuf;
	struct strbuf	datbuf;
	long			ctlcmd;
	int				gflags;
#endif
	static short tmp;

	register i;

	tmp = 0;
	hps_intel = *(char *)&tmp;

	/* format the iocb for TCS VERSION */
	ri.iocb.hdr.len 		= sizeof(A_IOCB);
	ri.iocb.hdr.maj_dev		= ASYNCH_DEV;
	ri.iocb.hdr.min_dev		= 0;					/* must always be 0 */
	ri.iocb.hdr.int_enab	= ENABLED;
	ri.iocb.hdr.data.hps_addr= (bit32)ri.data;
	ri.iocb.hdr.data_len	= IOCB_DATA_LEN;
	ri.iocb.hdr.mail.hps_addr= 0xFFFFFFFF; 
	ri.iocb.hdr.mode		= 0;					/* non DPRAM */
	ri.iocb.hdr.data_dir	= FROM_HPS;  			/* data comes FROM HPS */
	ri.iocb.link			= NULL;
	ri.iocb.cmd_param 		= 0;
	if (hps_intel)
		ri.iocb.command			= (IOCTL<<8)|(IOCTL>>8);
	else
		ri.iocb.command			= IOCTL;

	/* initialize host adapter */
	strcpy(hps_mindev, "0");
	if (argc >= 3)
		devname = argv[2];
	else
		devname = RAW_DEVNAME;
	if ((hpsfd = open(devname, 2)) < 0) 
	{
		fprintf(stderr, "%s: Cannot open device %s\n", 
			argv[0], devname);
		if (argc > 1)
			exit(2);
		else	/* If no parameters then menu driven */
		do
		{
			fprintf(stderr, 
				"\tDo you wish to try another host adapter (y/n/default=y)?  ");
			gets(choice);
			if (choice[0] == 'n' || choice[0] == 'N')
			{
				printf("%s: exiting...\n", argv[0]);
				exit(errno);
			}
			else
			{
				hpsfd = hps_get_new(hpsfd, hps_mindev);
			}
		} while (!hpsfd);
	}

	/* Scan the command line */
	if (argc >= 2)
	{
		key = argv[1];
		i = argc - 2;
		while (*key)
		{
			switch (c = *key++) /* Possible values: d, h, r, t */
			{
				case 'd':	/* Get version of debug driver */
					debug_driver = 1;
					break;
					
				case 'h':	/* Get version of hty driver */
					hty_driver = 1;
					break;

				case 'r':	/* Get version of raw driver */
					raw_driver = 1;
					break;

				case 't':	/* Get version of TCS */
					tcs = 1;
					break;

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

		if (tcs)
			hps_get_TCS_version(hpsfd, argv[0]);
		if (raw_driver)
			hps_get_driver_version(hpsfd, RAW_TYPE, argv[0]);
		if (hty_driver)
			hps_get_driver_version(hpsfd, TTY_TYPE, argv[0]);
		if (debug_driver)
			hps_get_driver_version(hpsfd, DEBUG_TYPE, argv[0]);
	}
	else
	do
	{
		printf("\n\nWhich version information do you want to display?\n");
		printf("\t0  - Quit\n");
		printf("\t1  - TCS\n");
		printf("\t2  - Driver - raw\n");
		printf("\t3  - Driver - tty\n");

#ifdef HPS_STREAMS
		printf("\t4  - Driver - hdb\n");
#else
		printf("\t4  - Driver - vtio\n");
#endif
		
		printf("\t5  - Change host adapter (currently %s)\n", hps_mindev);
		printf("Your choice (enter a number): ");
		gets(choice);

		switch (choice[0]) 
		{
			case '0':  /* Time to quit */
				close(hpsfd);  /* close raw device */
				exit(0);
				break;

			case '1':  /* get TCS version information */
				hps_get_TCS_version(hpsfd, argv[0]);
				break;

			case '2':  /* get raw driver version information */
				hps_get_driver_version(hpsfd, RAW_TYPE, argv[0]);
				break;

			case '3':  /* get tty driver version information */
				hps_get_driver_version(hpsfd, TTY_TYPE, argv[0]);
				break;

			case '4':  /* get vtio driver version information */
				hps_get_driver_version(hpsfd, DEBUG_TYPE, argv[0]);
				break;

			case '5':
				if ((tmp_hpsfd = hps_get_new(hpsfd, hps_mindev)) > 0)
					hpsfd = tmp_hpsfd;
				break;

			default:
				fprintf(stderr, "%s: Invalid choice, enter something valid.\n", argv[0]); 
				break;	
		}  /* end switch */
	}
	while (choice[0] != '0');
}


int hps_get_new(hpsfd, hps_mindev)
int hpsfd;
char *hps_mindev;
{
	char hps_devname[128];
	char hps_new[128];
	int  tmp_hpsfd;

	printf("\nEnter new host adapter (currently %s): ",hps_mindev);
	gets(hps_new);
	if (!hps_new[0] || !strcmp(hps_new, hps_mindev))
	{
		printf("host adapter remains %s\n", hps_mindev);
		return (hpsfd);
	}

	sprintf(hps_devname, RAW_DEVNAME_S, hps_new);
	/* Open HPS interface */
	if ((tmp_hpsfd = open(hps_devname, 2)) < 0)
	{
		fprintf(stderr, "Open failed on host adapter %s\n", hps_new);
		printf("Still using host adapter %s\n", hps_mindev);
		return (-1);
	}
	else
	{
		strcpy(hps_mindev, hps_new);
		close(hpsfd);
		return (tmp_hpsfd);
	}
}

hps_get_TCS_version(hpsfd, pname)
int hpsfd;
char *pname;
{
#ifdef HPS_STREAMS
	struct strbuf	ctlbuf;
	struct strbuf	datbuf;
	long			ctlcmd;
	int				gflags;
#endif
	char *verptr;

	INIT_DATA(ri.data);

	if (hps_intel)
		ri.iocb.cmd_modifier = (AIOC_GETV<<8)|(AIOC_GETV>>8);
	else
		ri.iocb.cmd_modifier = AIOC_GETV;

	/* send iocb on its way to the hps */
#ifdef HPS_STREAMS
	ctlbuf.maxlen = 0;
	ctlbuf.len    = sizeof(long);
	ctlbuf.buf    = (char *)&ctlcmd;
	ctlcmd        = HPS_DOIOCB;
	datbuf.maxlen = 0;
	datbuf.len    = sizeof(ri);
	datbuf.buf    = (char *)&ri;   /* data to be sent to TCS */

	if (putmsg(hpsfd,&ctlbuf,&datbuf,0) < 0)
	{
		printf("hpsver: putmsg failed\n");
		return(-1);
	}

	ctlbuf.len    = 0;
	ctlbuf.maxlen = sizeof(long);
	ctlbuf.buf    = (char *)&ctlcmd;
	datbuf.len    = 0;
	datbuf.maxlen = sizeof(ri);
	datbuf.buf    = (char *)&ri;
	gflags        = 0;
	ctlcmd        = 0;
	bzero((char *)&ri,sizeof(ri));

	if (getmsg(hpsfd,&ctlbuf,&datbuf,&gflags) == 0)
#else
	if (ioctl(hpsfd, DO_IOCB, &ri) == SUCCESS)  
#endif
	{
		verptr = ri.data;
		if (*verptr != 0)
			PRINTINFO("TCS VERSION INFORMATION")
		else
			VER_ERR("No version information for the TCS.", 
					"Has the TCS been downloaded???");
	}
	else
		VER_ERR("Cannot get TCS version information.",
				"AIOC_GETV failed.");
}

hps_get_driver_version(hpsfd, driver_type, pname)
int hpsfd;
int driver_type;
char *pname;
{
#ifdef HPS_STREAMS
	struct strbuf	ctlbuf;
	struct strbuf	datbuf;
	long			ctlcmd;
	int				gflags;
#endif
	int cmd;
	int status;
	char *verptr;
	char success1[80];
	char error1[80];
	char error2[80];

	INIT_DATA(ri.data);
#ifdef HPS_STREAMS
	ctlbuf.maxlen = 0;
	ctlbuf.len    = sizeof(long);
	ctlbuf.buf    = (char *)&ctlcmd;
	strcpy(error1, "Version information not available");
	switch(driver_type)
	{
	case RAW_TYPE:
		ctlcmd        = HPS_GETRVER;
		strcpy(success1, "RAW DRIVER VERSION INFORMATION");
		strcpy(error2, "for the HPS/Streams RAW driver.");
		break;
	case TTY_TYPE:
		ctlcmd        = HPS_GETTVER;
		strcpy(success1, "TTY DRIVER VERSION INFORMATION");
		strcpy(error2, "for the HPS/Streams TTY driver.");
		break;
	case DEBUG_TYPE:
		ctlcmd        = HPS_GETDVER;
		strcpy(success1, "HDB DRIVER VERSION INFORMATION");
		strcpy(error2, "for the HPS/Streams HDB driver.");
		break;
	}
	datbuf.maxlen = 0;
	datbuf.len    = sizeof(ri);
	datbuf.buf    = (char *)&ri;

	if (putmsg(hpsfd,&ctlbuf,&datbuf,0) < 0)
	{
		printf("hpsver: putmsg failed\n");
		return(-1);
	}

	ctlbuf.len    = 0;
	ctlbuf.maxlen = sizeof(long);
	ctlbuf.buf    = (char *)&ctlcmd;
	datbuf.len    = 0;
	datbuf.maxlen = sizeof(ri);
	datbuf.buf    = (char *)&ri;
	gflags        = 0;
	ctlcmd        = 0;
	bzero((char *)&ri,sizeof(ri));

	status = getmsg(hpsfd,&ctlbuf,&datbuf,&gflags);
#else
	switch(driver_type)
	{
	case RAW_TYPE:
		cmd = GET_RVER;
		strcpy(success1, "RAW DRIVER VERSION INFORMATION");
		strcpy(error1, "No version information for the RAW driver.");
		strcpy(error2, "Has version info been entered???");
		break;
	case TTY_TYPE:
		cmd = GET_TVER;
		strcpy(success1, "TTY DRIVER VERSION INFORMATION");
		strcpy(error1, "No version information for the TTY driver.");
		strcpy(error2, "Has a port been opened???\n\tThis will initialize the tty driver.");
		break;
	case DEBUG_TYPE:
		cmd = GET_VVER;
		strcpy(success1, "VTIO DRIVER VERSION INFORMATION");
		strcpy(error1, "No version information for the VTIO driver.");
		strcpy(error2, "Has vtioinit been executed???");
		break;
	}
	status = ioctl(hpsfd, cmd, ri.data);
#endif
	if (status == SUCCESS)
	{
		verptr = ri.data;
		if (*verptr != 0)
			PRINTINFO(success1)
		else
			VER_ERR(error1, error2);
	}
	else
		VER_ERR("Cannot get driver version information.",
				"IOCTL failed.");
}

usage(name)
char *name;
{
	fprintf (stderr, "%s: usage: %s [dhrt] [devname]\n", name, name);
}


/*
 * MODIFICATION HISTORY:
 *
 * $Log:	hpsver.c,v $
 * Revision 1.1.2.1  92/06/24  13:53:40  marker
 * Branch RISCOS_5_01_2_FIXES off of trunk.
 * 
 * Revision 2.5  91/09/03  17:39:07  annette
 * Changed error message handling.
 * INTERNAL
 * 
 * Revision 2.4  91/08/21  13:09:06  don
 * Added command line options "dhrt" and an optional device name.
 * If command line options are specified then the program just checks
 * the debug (d), hty (h), raw (r) or TCS (t) versions and does not
 * bother with the menu interface.  The optional device name may only
 * be entered when one of the command line options is entered.
 * ENHANCEMENT
 * 
 * Revision 2.3  91/01/10  17:23:19  dave
 * Modify header; add footer.
 * COSMETIC
 * 
 */
