
/* epart.c */

/*
 * Partition edit and pick for MS-DOS
 *
 * 08-Oct-1988	jye.  change and add this codes to do the partition 
 * 					  editing and picking for MS-DOS
 * 18-NOV-1988  jye.  change and add codes in the partition editing and
 *					  picking for the user interface.
 */

#include "obdefs.h"
#include "gemdefs.h"
#include "osbind.h"
#include "mydefs.h"
#include "part.h"
#include "ipart.h"
#include "bsl.h"
#include "hdxpch.h"
#include "addr.h"
#include "myerror.h"
#include "obdefs.h" 

extern int typedev;
extern int typedrv;
extern char sbuf[];
extern int npart;				/* number of partitions */
extern int ext;				/* the index of extended partition */

/*
 * Global variables these routines communicate with
 *
 */
static PART *pinfo;		/* -> partition block */
static int totcyl;		/* total # of cylinder */
static long sizleft;	/* size of unused disk in blocks */
static long extleft;	/* size of unused extended partition in blocks */
static int formw, formh;
static int lx, ly, sx, sy;
static int ok2draw;		/* 0: don't draw PARTPNL boxes */
static int pnlflg;		/* 1: partition scheme comes from panel */
static int along;		/* 1: will not redraw and clean the box */
static int lowlim;		/* index of dialog box */
static int first;		/* flag for add bad and good sectors only one time */
long disksiz;			/* size of disk in blocks */
long sumsiz;			/* the sum of bytes of root sectors */
long spcyl;				/* sector per cylinder */
long sptrk;				/* sector per track */
int yesscan;			/* the flag for the func. IBMGPART use */
int tolpart;			/* the total of number partitions */
int epty;				/* the y-coordinate of the moving bar */
int restept;			/* 1: rest the moving bar to initial place */



#define MFM 17			/* sectors per track of MFM */
#define RLL 26			/* sectors per track of RLL */


/* 
 * get ST partition information for ST structure
 */

stgpart(xdev, bs, rpinfo)

int xdev;
char *bs;
PART **rpinfo;

{
	int i, j, linkst, ret;
	long sect;
	register PART *ipart;
	PART *xpinfo;

	if ((npart = countpart(xdev)) == ERROR)	{
		return ERROR;
	}
	if ((*rpinfo = (PART *)Malloc((long)sizeof(PART)*npart)) <= 0)	{
		err(nomemory);
		if (rpinfo > 0)		Mfree(rpinfo);
		return ERROR;
	}
	xpinfo = *rpinfo;
	inipart(xpinfo, npart);
   	ipart = &((RSECT *)(bs + 0x200 - sizeof(RSECT)))->hd_p[0];
	for (i = 0; i < NPARTS; i++, ipart++)	{
		xpinfo[i].p_flg = ipart->p_flg;
		xpinfo[i].p_st = ipart->p_st;
		xpinfo[i].p_siz = ipart->p_siz;
		if (ipart->p_flg & P_EXISTS)	{
			if (i == ext)		{
				xpinfo[i].p_id[0] = 'X';
				xpinfo[i].p_id[1]  ='G';
				xpinfo[i].p_id[2] = 'M';
			} else if (xpinfo[i].p_siz < MB16)	{
				xpinfo[i].p_id[0] = 'G';
				xpinfo[i].p_id[1]  ='E';
				xpinfo[i].p_id[2] = 'M';
			} else {
				xpinfo[i].p_id[0] = 'B';
				xpinfo[i].p_id[1]  ='G';
				xpinfo[i].p_id[2] = 'M';
			}
		}
	}
	if (ext != NO_EXT)	{ /* there are extended partition */
		sect = xpinfo[ext].p_st;
		do	{
    		if ((ret = getroot(xdev, bs, sect)) != 0) {
  			  	if (tsterr(ret) != OK)
				    err(rootread);
				return ERROR;
    		}
   			ipart = &((RSECT *)(bs + 0x200 - sizeof(RSECT)))->hd_p[0];
			xpinfo[i].p_flg = ipart->p_flg;
			xpinfo[i].p_st = sect;
			xpinfo[i].p_siz = ipart->p_siz + ROOTSECT;
			if (xpinfo[i].p_siz < MB16)	{
				xpinfo[i].p_id[0] = 'G';
				xpinfo[i].p_id[1]  ='E';
				xpinfo[i].p_id[2] = 'M';
			} else {
				xpinfo[i].p_id[0] = 'B';
				xpinfo[i].p_id[1]  ='G';
				xpinfo[i].p_id[2] = 'M';
			}
			ipart++;				
			i++;
			sect = ipart->p_st + xpinfo[ext].p_st;
		} while ((ipart->p_id[0] == 'X') && (ipart->p_id[1] == 'G') &&
				(ipart->p_id[2] == 'M'));  /* more partition */
	} 
	return OK;
}





inipart(xpart, npart)
PART *xpart;
int npart;
{
	int i;

	for (i = 0; i < npart; i++)	{
		xpart[i].p_siz = 0L;
		xpart[i].p_flg = 0;
		xpart[i].p_st = 0L;
		xpart[i].p_id[0] = 0;
		xpart[i].p_id[1] = 0;
		xpart[i].p_id[2] = 0;
	}
}




countpart(dev)
int dev;
{
	char bs[512];
	PART *ipart;
	int ret, count, i; 
	long sect, start;
	if ((ret = getroot(dev, bs, (SECTOR)0)) != 0)	{
		if (tsterr(ret) != OK)
			err(rootread);
		return ERROR;
	}
	ipart = &((RSECT *)(bs + 0x200 - sizeof(RSECT)))->hd_p[0];
	ext = NO_EXT;
	for (i=0; i < NPARTS; i++, ipart++)	{
		if ((ipart->p_flg & P_EXISTS) && 
				(ipart->p_id[0] == 'X') && 
				(ipart->p_id[1] == 'G') && 
				(ipart->p_id[2] == 'M'))	{
			ext = i;
			start = ipart->p_st;
		}
	}
	count = 4;
	if (ext != NO_EXT)	{
		sect = start;
		do	{
			if ((ret = getroot(dev, bs, sect)) != 0)	{
				if (tsterr(ret) != OK)
					err(rootread);
				return ERROR;
			}
   			ipart = &((RSECT *)(bs + 0x200 - sizeof(RSECT)))->hd_p[0];
			count++;
			ipart++;				
			sect = ipart->p_st + start;
		} while ((ipart->p_id[0] == 'X') && (ipart->p_id[1] == 'G') &&
				(ipart->p_id[2] == 'M'));  /* more partition */
	} 
	return (count);
}



/*
 * Force checksum of sector image to a value
 */
forcesum(image, sum)
UWORD *image;
UWORD sum;
{
    register int i;
    register UWORD w;

    w = 0;
	/* up limit is half of buffer size - 2 */
    for (i = 0; i < ((UWORD)BPS/2 - 1); ++i)
	w += *image++;
    *image++ = sum - w;
}


/*
 * Put word in memory in 8086 byte-reversed format.
 *
 */
iw(wp, w)
UWORD *wp;
UWORD w;
{
    char *p;

    p = (char *)wp;
    p[0] = (w & 0xff);
    p[1] = ((w >> 8) & 0xff);
}

/*
 * Put long word in memory in 8086 word-reversed format.
 *
 */
ilong(lp, l)
long *lp;
long l;
{
    UWORD *p;

    p = (UWORD *)lp;
    iw(&p[0],(UWORD)(l & 0xffff));
    iw(&p[1],(UWORD)((l >> 16) & 0xffff));
}

/*
 * Get long word in memory, from 8086 word-reversed format.
 *
 */
glong(al, lp)   /* al is a swaped return long word,*/
				/* lp is a to be swaped long word */
long *al;
long *lp;

{
   char *p, *q;

    p = (char *)al;
    q = (char *)lp;
	p[0] = q[3];
	p[1] = q[2];
	p[2] = q[1];
	p[3] = q[0];
}

/*
 * Get word in memory, from 8086 byte-reversed format.
 *
 */
UWORD gw(wp, aw)
UWORD *wp;
UWORD *aw;
{
    char *p, *q;

    p = (char *)wp;
    q = (char *)aw;
    q[0] = p[1];
    q[1] = p[0];
    return *aw;
}


/*
 * Stupid delay between writes (.01 second);
 * called in supervisor mode on the ST.
 *
 * The hard disk controller cannot keep up with
 * full-tilt accesses for some reason.
 *
 */
delay()
{
    register long hz200v, *p;

    p = (long *)0x4ba;
    hz200v = *p + 2L;		/* compute future value */
    while (*p < hz200v)		/* wait for it to reach that */
	;
}


/*
 * Throw up an alert box
 * with the given text.
 *
 */
err(s)
char *s;
{
    ARROW_MOUSE;
    form_alert(1, s);
    BEE_MOUSE;
    return ERROR;
}


/*
 * Error, concatenate the three strings
 * and throw up an alert box.
 *
 */
errs(s1, s2, s3)
char *s1, *s2, *s3;
{
    strcpy(sbuf, s1);
    strcat(sbuf, s2);
    strcat(sbuf, s3);
    return err(sbuf);
}


/*
 *  Errcode()
 *	Find error code for previous instruction which returned Check
 *  Condition Status.
 *
 *  Input:
 *	pdev - the physical device number (0 -> 7).
 *  Return:
 *	errnum - the error code.
 */
errcode(pdev)
int pdev;
{
    char data[128];
    extern long rqsense(), ostack;
    UWORD errnum;
	int mask = 0x0001;
	int set, scsidrv;
   
    if (pdev > 15) return ERROR;
    ostack = Super(NULL);
	/* check #pdev device is set or not */
	set = typedev & (mask << pdev);
	scsidrv = typedrv & (mask << pdev);
	if ((set)||(scsidrv)) {	/* if set, it is a removable driver */
		errnum = rqsense(pdev, 16, data);
	} else {	/* if not set, it is a not removable driver */
   		errnum = rqsense(pdev, 4, data);
	}
    delay();
    Super(ostack);
    
    if (errnum != 0)
        return err("[1][Fatal error][OK]");
        
	if ((set)||(scsidrv))	{ /* if set, it is a removable driver */
    	errnum = (UWORD)data[12];
	} else { /* if not set, it is a not removable driver */
    	data[0] &= 0x7f;		/* mask out advalid bit */
    	errnum = (UWORD)data[0];
	}
    return errnum;		/* return it */
}


/*
 *  Tsterr()
 *	Given an error code, test if it is a medium change error
 *  or a write protection error.  Put up the appropiate box if
 *  it is either one of those, and return OK.  
 *	If it is not either of those, return ERROR.
 *
 */
tsterr(errnum)
UWORD errnum;
{
    switch(errnum) {
    	case MDMCHGD:
    	    err(mdmchng);
    	    break;
    	
    	case WRTPRTD:
    	    err(wrprotct);
    	    break;
    	    
    	case DEVNRDY:
    	    err(drvnrdy);
    	    break;
    	    
    	default:
    	    return ERROR;
    }
    return OK;
}
