

/*==============================================================*/
/*			DIRNET Utility				*/
/*==============================================================*/

#define	NODEBUG		1

#include "dirnet.os"
#include "c:switch.os"

#define BOOLEAN	int


/*======================================================================*/
/*	Change History							*/
/*======================================================================*/
/*	3.0	03/14/84 Change wording of MAP options		  - jjc */
/*	1.0b    03/12/84 Change wording of MAP options		  - jjc */
/*	1.0a	02/28/84 Upgrade for cpm 80 version		  - jjc */
/*	1.0	02/15/84 Add MAP option for full unsorted output  - jjc */
/*	0.0e	02/10/84 Ignore deleted partitions in display	  - jjc */
/*      0.0d    01/31/84 Check value returned by hdstat		  - jjc */ 
/*	0.0c	01/30/84 Add hdstat call for volume info          - jjc */
/*	0.0b	12/28/83 Bios86 calls updated			  - jjc	*/
/*	0.0a	11/18/83 Utility written in C based on Pascal code- jjc	*/
/*======================================================================*/
/*page*/
#define BANNER "DirNet Version 3.0 For Separated Boot\n\n"

#define DirnetAborted	"\nDirnet aborted due to error\n"
#define NoNetMsg	"Your network is not operational.\nPlease check your HiNet master station\n"
#define DirNet1Msg	"                     Current HiNet Partitions\n"
#define DirNet2Msg	"                     ------------------------\n"
#define DirNet3Msg	"\nPartitions on Volume %d %-10.10s\n\n"
#define NoHD		"The hard disk is not operative\n"

#define	NoParam		"Sorry, the only valid DIRNET parameter is MAP, or M for short.\n"

#define	MAXSizeMsg	7
CHAR	*SizeMsgTab [MAXSizeMsg] =  {
	"256K",
	"512K",
	"  1M",
	"  2M",
	"  4M",
	"  8M",
	"????", 
	};
/*page*/
#define		MAXvol		4	/* Only 4 volumes allowed.	     */
#define		UNUSED22_31size	10	/* Unused bytes in vol_info struct.  */
#define		VOLlabelSIZE	10	/* 10 chars in volume label.	     */

/* DMS hard disk information returned by hard disk controller call 
    "get volume information" = 18h = 24 decimal after hd_stat_info
    for every volume. Only sent if hd_stat_info.status = 0.		*/

struct vol_info
{
	CHAR	vol_present;
	CHAR	cur_track;
	CHAR	tracks;
	CHAR	sect_per_track;
	CHAR	head_mask;
	int	addr_part_offset_table;
	int	addr_bad_sector_table;
	int	addr_dirty_bad_sector_flag;
	CHAR	open_error;
	char	vol_label[VOLlabelSIZE];
	char	unused22_31[UNUSED22_31size];
};

/*page*/
/* DMS hard disk information returned by hard disk controller call 
    "get volume information" = 18h = 24 decimal.			*/

struct hd_stat_info
{
	CHAR	command_echo;
	CHAR	vers_rom;
	CHAR	rev_rom;
	CHAR	vers_firmware;
	CHAR	rev_firmware;
	CHAR	Xebec;
	CHAR	unused6;
	CHAR	status;
	struct vol_info		volume[MAXvol];
} stat;


#define MAXpartitions	64
#define NAMELTH		8
#define PartDeleted(p) ((p)->name [0] == 'd')

struct PARTITION {
	CHAR	size;
	CHAR	name [NAMELTH];
	CHAR	password [6];
	CHAR	control;
	} DiskParts [MAXpartitions];

struct PARTITION	*PartTab [MAXpartitions];
int	Npartitions;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* DAT control byte mappings:

	bit	use
	---	---
	0,1	00 = CPM		01 = MSDOS
		10 = unused		11 = unused
	2,3	unused
	4,5	00 = Read/Write		01 = Read/Only
		10 = First/Write	11 = unused
	6	HiDos shared	(Separate from bits 4,5 for speed of
				 checking, i.e only one bit test.)
	7	Tape backup
*/
/* Macros for testing control byte */	
#define DAT_r_w(n) ((n & 0x30) == 0x00)
#define DAT_r_o(n) ((n & 0x30) == 0x10)
#define DAT_f_w(n) ((n & 0x30) == 0x20)
#define DAT_HiDos(n) (n & 0x40)
#define DAT_MSDos(n) ((n & 0x03) == 0x01)
#define DAT_CPM(n) ((n & 0x03) == 0x00)
#define DAT_tape(n) (n & 0x80)



int	DoMap	= FALSE;

/*page*/
/*==============================================================*/
/*	get_params	- get parameters and set flags		*/
/*==============================================================*/
get_params (argc, argv)
	int	argc;
	CHAR	*argv [];
{
	while (--argc)
	{	
#ifndef NODEBUG
		printf ("%d, %s\n", argc, *(argv+1));
#endif
		switch (**(++argv))
		{
		case 'M':
		case 'm':
			DoMap = TRUE;
			break;
		default :
			printf (NoParam);
			break;
		}
	} /* while */
}

/*page*/
/*==============================================================*/
/*	MapPartition	- print partition info, in MAP form.	*/
/*==============================================================*/
MapPartition (i, p)
int			i;
struct PARTITION	*p;
{
	printf (" %02x  %-8.8s         ",i, p->name); 
	PrintSize (p->size);

	if (DAT_HiDos (p->control))		printf ("    HiDos Shared ");
	else if (DAT_MSDos (p->control))	printf ("    MS-DOS       ");
	else if (DAT_CPM (p->control))		printf ("    CPM/HiDos    ");
	else	printf ("    %02x         ", p->control);

	if (DAT_r_w (p->control))		printf (" Read/Write ");
	else if (DAT_r_o (p->control))		printf (" Read/Only  ");
	else if (DAT_f_w (p->control))		printf (" Ownable    ");
	else	printf (" %02x  ", p->control);

	if (DAT_tape (p->control))		printf (" Flagged backup");


	printf ("\n");
	}


/*page*/
/*==============================================================*/
/*	PrintSize	- Prints the size of a file		*/
/*==============================================================*/

PrintSize (size)
CHAR	size;
{
	if (size >= 0 && size < MAXSizeMsg)
		printf (SizeMsgTab [size-1]);
	else
		printf (SizeMsgTab [7]);
	}

/*page*/
/*==============================================================*/
/*	PrintPartition	- print partition info			*/
/*==============================================================*/

PrintPartition (p)
struct PARTITION	*p;
{
	printf (" : %-8.8s ", p->name); 
	PrintSize (p->size);
	}

/*page*/
/*==============================================================*/
/*	SortPartitions	- sort partition names			*/
/*==============================================================*/
SortPartitions ()
{
int			gap, i, j;
struct PARTITION	*ptmp;

#ifndef NODEBUG
	printf ("Starting sort of partition names...");
#endif 

	for (i = 1, j = 0; i < MAXpartitions; i++) {
		if (DiskParts [i].size == 0) break; /* last partition */
		if (!PartDeleted (&DiskParts [i])) 
			PartTab [j++] = &DiskParts [i];
		}

	Npartitions = j;

	for (gap = Npartitions/2; gap > 0; gap /= 2)
		for (i = gap; i < Npartitions; i++)
			for (j = i-gap; j >= 0; j -= gap) {
				if (strncmp (PartTab [j]->name, 
					PartTab [j + gap]->name, NAMELTH) <= 0)
					break;

				ptmp = PartTab [j];
				PartTab [j] = PartTab [j + gap];
				PartTab [j + gap] = ptmp;
				}

#ifndef NODEBUG
	printf ("sort finished\n");
#endif
	}

#ifdef cpm80
zabort () {
	printf (DirnetAborted);
	exit (1);
	}
#endif


/*page*/
#define NCOLS	(4)
main (argc, argv)
int	argc;
CHAR	*argv [];
{
int	i, r, c, v;
int	Nprinted = 0;
int	NROWS;

	Npartitions = MAXpartitions;
	printf (BANNER);
	hdstat (&stat);
	if (stat.status != 0) {
		printf (NoHD);
		return (1);
		}

	get_params (argc, argv);

	printf (DirNet1Msg);
	printf (DirNet2Msg);

	for (v = 0; v < MAXvol; v++) {
		*((CHAR *) &stat) = v;
		if ((stat . volume [v] . vol_present != 0)
			&& (GetDirNet (v, DiskParts)) == 0) {
			printf (DirNet3Msg, v, stat.volume [v].vol_label);
			if (DoMap) {
				for (i = 0; i < MAXpartitions 
					&& DiskParts [i].size != 0 ; ++i)
					MapPartition (i, &DiskParts [i]);
				}
			else {
				SortPartitions ();
				NROWS = ((Npartitions + NCOLS - 1) / NCOLS);
				for (r = 0; r < NROWS; r++) {
					for (c = 0; c < NCOLS; c++)
						if ((i = r + c*NROWS) < Npartitions)
							PrintPartition (PartTab [i]);
						printf (" :\n");
						}
					}
				}
		}
	return (0);
	}


