
/****************************************************************
*								*
*	Test code to run the KIWI on the 360 (mag tape)		*
*								*
*	20Mar85....original.........................J.Middleton *
*	02May85....added prompts....................J.Middleton *
*	06May85....removed sbch sets,byte cnt.......J.Middleton *
*	17Sep85....add external memory option.......J.Middleton *
*	17Dec85....add command retry test...........J.Middleton *
*	12Feb86....lbx memory hooks.................J.Middleton *
*								*
*****************************************************************
*/
#include "kiwi.h"
#include "diag.h"
#include "diagdat.h"
#include "rabits.h"
#include "msgs.h"

#define CIOPORT	(unsigned char *) 0xFEF601
#define CIOCTRL	(unsigned char *) 0xFEF607
#define CIOPB (unsigned char * ) 0xfef603

#define WRITE 1
#define READ  2
#define SENSE 4
#define DAER  014
#define NOP  033

#define WRLEN 8196
#define MB_IRQ	0x40

#define MB_IRQ0	0x40
#define MB_IRQ1	0x42
#define MB_IRQ2	0x44
#define MB_IRQ3	0x46
#define MB_IRQ4	0x48
#define MB_IRQ5	0x4a
#define MB_IRQ6	0x4c
#define MB_IRQ7	0x4e

#define CE 8
#define DE 4

#define BASEADDR 0xffff00
#define WARM	0xfe0008
#define HK_BCL  0xfec000
#define	MEMSTART 0x100000

#define DEFSBC  0xb3
#define TSTSBC 0x01
#define DEFWCNT 0x10

#define set 0
#define clear 1

unsigned char subch;
unsigned char intlev;
unsigned char brstFlg;
unsigned char mbFlg;
unsigned char spcFlg;
unsigned char wcount;

unsigned char buffer[MAXLN];

unsigned char e38cmt[] = { 01, 02, 04, 07, 014, 033, 
		0303, 0313, 0323, 0213,
		0013, 0023, 0043, 0053,
		0063, 0073, 0123, 0143,
		0153, 0163, 0173, 0003,
		0027, 0047, 0057, 0067,
		0077, 0017, 0037, 0263,
		0223, 0273, 0243, 0253,
		0373, 0103, 0133, 
		0203, 0233, 0333, 0343,
		0353, 0373, 0363,
		0 };

unsigned char e38ict[] = { 0303, 0313, 0323, 0213, 0013, 0023, 0043, 0053,
		0063, 0073, 0123, 0143, 0153, 0163, 0173, 0003,
		0017, 0027, 0037, 0047, 0057, 0067, 0077, 0223,
		0243, 0253, 0263, 0273, 0373, 0103, 0133, 0007,
		0203, 0233, 0333, 0343, 0353, 0373, 0363, 
		0 };

unsigned char e38bbt[] = { DEFSBC, 0 };

unsigned char e38nrt[] = { DEFSBC, 0 };

unsigned char e38spct[] = { 014, 0 };	/* 0x0c */

unsigned char e38spat[] = { DEFSBC, 0 };

struct kiwidev * kiwi1;
unsigned char vTable[256];
unsigned char chstTable[256];

extern short csBuff[];		/* this stuff is the 8x305 microcode */
extern unsigned buffSize;

unsigned char xbuff[WRLEN];
unsigned xlen = WRLEN;
unsigned char xodd = FALSE;
unsigned char* xpnt;

unsigned char sbuff[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
			 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
unsigned slen = 12;
unsigned char sodd = FALSE;
unsigned char pswitch;
unsigned char as_de;

main()
{
	unsigned i;
	char * p;
	unsigned char pint;
start:
	p = (char *) HK_BCL;
	*p = 0x82;		/* set hk68 for intel bytes */
	kiwi1 = (struct kiwidev *)BASEADDR;
	kiwi1->mc = 0;			/* stop 8x305 */
	for (i=7; i<=0; i--)
		kiwi1->ra.w[i] = 0;	/* clear register array */

	/* set up default optins */
	setDef();

	xprintf("\nEnter 'y' to present DE on power up");
	if (getchar() == 'y') 
		as_de = 1;	/* set async device end flag */
	else
		as_de = 0;	/* clear async device end flag */

	xprintf("\nPrint interrupt messages? [no print]: ");
	if (getchar() == 'y') 
		pswitch = 1;
	else
		pswitch = 0;

	/* prompt for option set */
	xprintf("\nEnter 'y' to set options: ");
	if (getchar() == 'y') 
		setOpt();

	/* zero the tables */
	for (i=0; i<256; i++) {
		vTable[i] = INVALID;
		chstTable[i] = 0;
	}
	
	init8259();
	kiwi1->pic2 = 0xff;	/* mask off all 8259 interrupts */
	initvec();
	initcio();


	xprintf("\nLoading KIWI control store");
	if (!kload2(csBuff, buffSize)) {
		xprintf("\nDownload Error, Goodbye");
		hkwarm();
	}

	xprintf("\nEnter 'y' to start the microcode: ");
	if (getchar() != 'y') 
		hkwarm();

	kiwi1->mc |= run;
	wait(1000);
	xprintf("\n8x305 executing");
	
	/* make sure we are offline by issuing an offline command */
	K$COM |= I$GO | I$OFL;
	wait(5000);

	xprintf("\nInitializing valid address RAM");
	vTable[subch] = VALID;
/*	vTable[TSTSBC] = VALID;		*/
	initVaddr(vTable);

	xprintf("\nZero 256x1 and Status RAM");
	zRAMs();

	xprintf("\nInitializing 256x1 status RAM");
	init256(e38cmt, VLCM, set);
	init256(e38ict, IMMC, set);
	if (set == brstFlg)
		init256(e38bbt, BBR, set);
	else
		init256(e38bbt, BBR, clear);
	init256(e38nrt, NTRD, clear);
	if (1 == spcFlg) {
		init256(e38spct, SPCM, set);
		init256(e38spat, SPAD, set);
	}

	xprintf("\nInitialization complete. ");

	goOn();

	kiwi1->pic2 = 0;	/* clear interrupt mask */
	kiwi1->pic1 = 0x0a;
	while (kiwi1->pic1 != 0)
		kiwi1->pic1 = 0x10;	/* issue eoi */
	
	/* put the 8600 in the idle loop */
	if (as_de == 1) {
		K$COMSTA = DE;
		K$CHADD = subch;
		K$MULCOM |= I$ENDG;
	}
	K$MULCOM |= I$GO;
	
	/* for now, poll the CIO (port B) to see if there is an interrupt */
	xprintf("\nEntering interrupt poll loop.");
	repeat {
		if (kbhit() == TRUE) {
			xprintf("\nRestart program ? [y or n]: ");
			if (getchar() == 'y')
				goto start;
			else 
				hkwarm();
		}

		if (*CIOPB != 0xff) {
			if (*CIOPB == 0xfe) {
				/* 8x305 int request, call kiwi int handler */
				kih();	
			}
			else {	 	/* unrecognized interrupt */
				xprintf("\n\07Illegal Interrupt");
				xprintf("\n\CIO port b = %2x", *CIOPB);
				hkwarm();
			}
		}
	}
	
}

/*---------------------------------------------------------------------*/
/* KIWI Interrupt handler */

kih()
{
	unsigned char pint;

	/* see what kind of interrupt is requested */
	kiwi1->pic1 = 0x0c;	/* set poll bit */
	pint = kiwi1->pic1;
	while ((pint & 0x80) == 0x80) {
		switch (pint & 0x7) {
			case 0:
				kiwi1->pic1 = 0x0a;
				kiwi1->pic1 = 0x10;	/* issue eoi */
				chint();
				break;
			case 1:
				xprintf("\nReset switch\n");
				kiwi1->pic1 = 0x0a;
				kiwi1->pic1 = 0x10;	/* issue eoi */
				hkwarm();
				break;
			case 2:
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
				kiwi1->pic1 = 0x20;
				xprintf("\n\07Unrecognized int from 8600.");
				kiwi1->pic1 = 0x0a;
				xprintf("\nPic IR = %2x", kiwi1->pic1);
				break;
		}
		kiwi1->pic1 = 0x0c;	/* set poll bit */
		pint = kiwi1->pic1;
	}
}


chint()
{
	unsigned i;

	/* this is the real thing, find out what caused the irq */
	if (!I$REDY) {
		xprintf("\nReady bit not set after interrupt occurred.");
		hkwarm();
	}

	if (I$ERRB)
		eproc();

	if (I$CRTY) {
		if (pswitch)
			xprintf("\nCommand retry command = %x",K$COMSTA);
	
		init256(e38spct, SPCM, clear);
				kiwi1->pic1 = 0x0a;
				kiwi1->pic1 = 0x10;	/* issue eoi */
		init256(e38spat, SPAD, clear);
				kiwi1->pic1 = 0x0a;
				kiwi1->pic1 = 0x10;	/* issue eoi */

		/* set up DE status */
		K$COMSTA = DE;
		K$CHADD = subch;
		K$MULCOM |= I$GO | I$ENDG;
		return;
	}		
		
	if (I$WRCP) {
		if (pswitch)
			xprintf("\nWrite complete");
		/* get buffer size,  odd/even */
		xlen = WRLEN - K$BFSZ;
		if (I$ODBY) {
			xodd = TRUE;
			if (pswitch)
				xprintf("  len = %4x bytes", ((xlen << 1)-1) );
			}
		else {
			xodd = FALSE;
			if (pswitch)
				xprintf("  len = %4x bytes", (xlen << 1) );
			}
		/* set up DE status */
		K$COMSTA = DE;
		K$CHADD = subch;
		K$MULCOM |= I$GO | I$ENDG;
		return;
	}

	if (I$RDCP) {
		if (I$ENDP)
			if (pswitch) 
				xprintf("\nRead complete and ending presented");
		else
			if (pswitch) {
				xprintf("\nRead complete");
				xprintf("  len = %4x bytes", (K$BFSZ << 1) );
			}
		/* CE, DE already presented on read, just issue GO */
		K$MULCOM |= I$GO;
		return;
	}

	if (I$ENDP) {
		if (I$CRCV) {
			if (pswitch) 
				xprintf("\nEnding presented and command received");
			pCom();
		}
		else {
			if (pswitch) 
				xprintf("\nEnding presented");
			/* just issue GO */
			K$MULCOM |= I$GO;
		}
		return;
	}

	if (I$CRCV) {
		/* command received, */
		pCom();
		return;
	}


	/* Command not valid or immediate, error */
	xprintf("\nNot a valid or immediate command.");
	pra();

	K$MULCOM |= I$GO;

	return;
}
/*---------------------------------------------------------------------*/
eproc()
{
	/* process a few errors */
	xprintf("\nERROR - ");
	if (I$INVC)
		xprintf("Invalid command");
	if (I$CPAR)
		xprintf("Command Parity Error");
	if (I$STKS)
		if (pswitch)
			xprintf("Stacked status");
	if (I$ODBY)
		if (pswitch)
			xprintf("Odd byte write");
	if (I$STRD)
		xprintf("Stop on read");
	if (I$STWR)
		if (pswitch)
			xprintf("Stop on write");
	if (I$CTBD)
		xprintf("Command to busy device");
	if (I$HALT)
		xprintf("Halt I/O");
	if (I$CHRE) {
		xprintf("Channel Reset");
		goOn();
		kiwi1->pic1 = 0x0a;
		kiwi1->pic1 = 0x10;	/* issue eoi */
		return;
	}
	if (I$SERE)
		xprintf("Selective Reset");
	if (I$BPER)
		xprintf("Bus out parity error");
	if (I$DVNR)
		xprintf("Device not ready");
	if (I$ZFWA)
		xprintf("Zero function while active");
	if (I$NEXM)
		xprintf("Non-existant memory");
	if (I$OFFL) {
		xprintf("8600 switched offline");
		goOn();
		kiwi1->pic1 = 0x0a;
		kiwi1->pic1 = 0x10;	/* issue eoi */
	}

	return;
}
/*---------------------------------------------------------------------*/
goOn()
{
	K$COM |= I$ONL | I$GO;
	wait(8000);
	if (I$ON)
		xprintf("\n8600 online");
	else {
		xprintf("\n8600 failed to go online");
		xprintf("\nRTNREG = %2x", K$RTNREG);
		hkwarm();
	}
}
/*---------------------------------------------------------------------*/


/* process a received command */
pCom()
{
	unsigned char * table;
	unsigned i;

	if (K$COMSTA == WRITE) {
		if (pswitch) 
			xprintf("\nWrite command received");
		/* set up for a channel write */
		xlen = WRLEN;
		xodd = FALSE;
		sDma(xpnt, xlen, xodd);
		/* issue GO,WRITE plus ending=CE */
		K$WDCNT = wcount;
		K$COMSTA = CE;
		K$MULCOM |= I$GO | I$WRIT | I$ENDG;
		return;
	}

	if (K$COMSTA == READ) {
		if (pswitch) 
			xprintf("\nRead command received");
		chRead();
		return;
	}

	if (K$COMSTA == SENSE) {
		if (pswitch) 
			xprintf("\nSense command received");
		/* set up for channel read, 24 bytes = 0 */
		sDma(sbuff, slen, sodd);
		/* issue GO,READ plus ending=CE,DE */
		K$WDCNT = wcount;
		K$COMSTA = DE | CE;
		K$MULCOM |= I$GO | I$READ | I$ENDG;
		return;
	}

	if (K$COMSTA == DAER) {
		if (pswitch) 
			xprintf("\nRead Backward command received");
		/* do the same as a read */
		chRead();
		return;
		}

	if (K$COMSTA == NOP) {
		/* shouldn't be here */
		xprintf("\nFarmer and Cam said we wouldn't get a NOP command, but we did");
		return;
	}

	/* look up command in immediate command table */
	table = e38ict;
	while (*table != 0) {
		if (K$COMSTA == *table++) {
			if (pswitch) 
				xprintf("\nImmediate command received %2x", K$COMSTA);
			/* found immediate command */
			/* issue GO plus ending=DE */
			K$COMSTA = DE;
			K$MULCOM |= I$GO | I$ENDG;
			return;
		}
	}
}
/*---------------------------------------------------------------------*/
udcTemp()
{
	K$COMSTA = 0;
	K$CHADD = 0x38;
	K$COM = 0x820;
	wait(300);
	xprintf("  udcmmr = %2x", K$CHADD);
}
/*---------------------------------------------------------------------*/
pra()
{
	unsigned char i, ad;

	xprintf("\nRegister Array contents.");

	i = 0;
	ad = 0;
	while (i < 8) {
		xprintf("\n %2x  %4x", ad, kiwi1->ra.w[i]);
		ad += 2;
		i++;
	}
}
/*---------------------------------------------------------------------*/
	
sDma(buff, len, odd)
unsigned char * buff;
unsigned len;
unsigned char odd;
{
	long temp;

	if (odd == TRUE)
		K$MINIT |= I$ODD;	/* odd byte transsfer */
	else 
		K$MINIT &= ~I$ODD;	/* even byte transsfer */
	K$BFSZ = len;
	K$BFAD = (short)buff;
	temp = (long)buff >> 16;
	K$BFADU = (unsigned char)temp;
}
/*---------------------------------------------------------------------*/
chRead()
{
	/* set up for a channel read */
	sDma(xpnt, xlen, xodd);
	/* issue GO,READ plus ending = CD,DE */
	K$WDCNT = wcount;
	K$COMSTA = DE | CE;
	K$MULCOM |= I$GO | I$READ | I$ENDG;
}
/*---------------------------------------------------------------------*/

init256(table, mask, flip)
unsigned char * table;
unsigned char mask, flip;
{
	while (*table != 0) {
		K$CHADD = *table;
		K$COM = I$A256 | I$GO;	 /*read 256 ram */
		wait(100);

		if (flip == set)
			K$COMSTA |= mask;
		else
			K$COMSTA &= ~mask;
		K$MULCOM |= I$GO | I$C256;	/*write 256 ram */
		wait(100);
		table++;
	}
}	
/*---------------------------------------------------------------------*/
zRAMs()
{
	unsigned char addr;
	unsigned count;
	
	addr = count = K$COMSTA = 0;
	while (count++ < 256) {
		K$CHADD = addr++;
		K$COM = I$C256 | I$GO;	 /*write 256 ram */
		wait(100);
		K$COM = I$CSTA | I$GO;	/* write Status RAM */
		wait(100);
	}
}
/*---------------------------------------------------------------------*/
setOpt()
{
	unsigned char aok;
	unsigned char * p;
	unsigned i;

	xprintf("\n\n   Enter 'y' to set option.  Default is in brackets.");

	xprintf("\nMultibus memory? [HK68 memory]: ");
	if (getchar() == 'y') {
		mbFlg = set;		/* mb memory mode */
		xpnt = (unsigned char*)MEMSTART;
		initMem((unsigned char*)MEMSTART);	/* init parity memory */
		xprintf("  MB memory selected");
		}
	
	
	xprintf("\nByte mode? [burst]: ");
	if (getchar() == 'y') {
		brstFlg = clear;		/* byte mode */
		xprintf("  Byte Mode selected");
		}
	else
		xprintf("  Burst Mode selected");

		aok = FALSE;
		do {
			xprintf("\nEnter word count [0x10]: ");
			gets(buffer);
			if (argp.argcount != 0) {
				if (isnumeric(argp.argv[0]))   {
					wcount = atoh(argp.argv[0]);
					aok = TRUE;
				}
				else 
					xprintf("    Non-numeric, try again");
			}
			else {
				wcount = DEFWCNT;	/* default word count */
				aok = TRUE;
				xprintf("  Default word count selected.");
			}
		} while (aok == FALSE);

		aok = FALSE;
		do {
			xprintf("\nEnter subchannel address [0xB3]: ");
			gets(buffer);
			if (argp.argcount != 0) {
				if (isnumeric(argp.argv[0]))   {
					subch = atoh(argp.argv[0]);
					aok = TRUE;
				}
				else 
					xprintf("    Non-numeric, try again");
			}
			else {
				subch = DEFSBC;	/* default addr */
				aok = TRUE;
				xprintf("  Default addr selected.");
			}
		} while (aok == FALSE);

	xprintf("\nHigh speed transfers? [no High speed]: ");
	if (getchar() == 'y') {
		K$MINIT |= I$HSP;
		xprintf("  High Speed selected");
	}
	else 
		xprintf("  Normal Speed selected");


	xprintf("\nSingle DMA transfers? [multiple transfers]: ");
	if (getchar() == 'y') {
		K$MINIT |= I$SNGL;
		xprintf("  Single transfers selected");
	}
	else
		xprintf("  Multiple transfers selected");

	xprintf("\nSwap data bytes? [no swap]: ");
	if (getchar() == 'y') {
		K$MINIT |= I$SWP;
		xprintf("  Swap selected");
	}
	else
		xprintf("  No swaps selected");

	xprintf("\nCommand retry? [no command retry]: ");
	if (getchar() == 'y') {
		spcFlg = 1;
		xprintf("  Command Retry selected");
	}
	else
		xprintf("  No swaps selected");

	xprintf("\nLBX memory present? [no LBX]: ");
	if (getchar() == 'y') {
		xprintf("  LBX sense buffer initialized");
		p = sbuff;
 		p += 0x100000;
		for (i=0; i<=24; i++) {
			*p = 0;	/* clear LBX sense buffer */
			p++;
		}
	}

}

/*---------------------------------------------------------------------*/
initMem()
{
}
/*---------------------------------------------------------------------*/
setDef()
{
	mbFlg = clear;		/* set default for HK68 memory */
	xpnt = xbuff;
	brstFlg = set;		/* burst mode */
	wcount = DEFWCNT;	/* word count (byte mux) */

	subch = DEFSBC;	/* default subchannel */
	e38bbt[0] = subch;	/* set subchannel in burst/byte table */
	e38nrt[0] = subch;	/* set subchannel in not ready table */
	e38spat[0] = subch;	/* set subchannel in special addr table */

	K$MINIT &= ~I$HSP;	/* no high speed mode */

	K$MINIT &= ~I$SNGL;	/* multiple dma transfers */

	K$MINIT &= ~I$SWP;	/* no swap */

	pswitch = 0;		/* no print */
	spcFlg = 0;		/* no command retry */
}
/*---------------------------------------------------------------------*/
wait(time)
unsigned time;
{
	unsigned i;
	
	i=time;
	while (!I$REDY) {
		i--;
		i++;
		i--;
		if (i==0) {
			xprintf("\nTimed out waiting for 8x305 acknowledge");
			hkwarm();
		}
	}
}

/*---------------------------------------------------------------------*/
hkwarm()
{
	((int(*)())WARM)();
}
/*---------------------------------------------------------------------*/

initChst(table)
unsigned char * table;
{
	unsigned count;

	count = 0;
	while (*table != 0) {
		K$CHADD = count;
		K$COMSTA = *table;
		K$MULCOM |= I$GO | I$CSTA;
		count++;
		table++;
		wait(100);
	}
}

/*---------------------------------------------------------------------*/
init8259()
{

	/* icw1 */
	kiwi1->pic1 = 0x13;	/* edge trig, intvl=8, single, icw4 */
	/* icw2 */
	kiwi1->pic2 = 0x00;	/* 5 bit int vector, bit0-2 don't care */
	/* icw4 */
	kiwi1->pic2 = 0x0d;	/* 8086 set */

}

/*---------------------------------------------------------------------*/

/* init interrupt vectors */
initvec()
{
	int inter0();
	int inter1();
	int inter2();
	int inter3();
	int inter4();
	int inter5();
	int inter6();
	int inter7();

	*(int (**)()) (MB_IRQ0 << 2) = inter0;
	*(int (**)()) (MB_IRQ1 << 2) = inter1;
	*(int (**)()) (MB_IRQ2 << 2) = inter2;
	*(int (**)()) (MB_IRQ3 << 2) = inter3;
	*(int (**)()) (MB_IRQ4 << 2) = inter4;
	*(int (**)()) (MB_IRQ5 << 2) = inter5;
	*(int (**)()) (MB_IRQ6 << 2) = inter6;
	*(int (**)()) (MB_IRQ7 << 2) = inter7;
}
/*---------------------------------------------------------------------*/
/* initialize the CIO for Multibus interrupts */
initcio()
{
	register int cnt;
	register unsigned char c, zero;
	static unsigned char ciotable[] = {
		0x00,	0x8c,		/* clear reset, right jus, vis port b */
		0x28,	0x00,		/* port b, bit control mode */
		0x2a,	0x00,		/* port b, all paths non-inverting */
		0x2b,	0xff,		/* port b, all inputs */
		0x2c,	0x01,		/* port b, normal inputs (bus ints) */
		0x03,	MB_IRQ,		/* port b interrupt vector */
	};

	zero = 0;
	c = *CIOCTRL;
	*CIOCTRL = zero;
	c = *CIOCTRL;
	*CIOCTRL = zero;
	*CIOCTRL = 1;
	*CIOCTRL = zero;
	for (cnt = 0; cnt < sizeof(ciotable); cnt++)
		*CIOCTRL = ciotable[cnt];

	initasm();	
}
/*---------------------------------------------------------------------*/
ciointr()
{
	xprintf("\nHey, we got an interrupt, level %2x", intlev);
}
/*---------------------------------------------------------------------*/

/*  */