static char rcsid[] = "$Header: sky.c,v 820.1 86/12/04 19:56:28 root Exp $";
static char sccsid[]="%W% %Y% %Q% %G%";

/************************************************************************
 *									*
 *				Copyright 1984				*
 *			VALID LOGIC SYSTEMS INCORPORATED		*
 *									*
 *	This listing contains confidential proprietary information	*
 *	which is not to be disclosed to unauthorized persons without	*
 *	written consent of an officer of Valid Logic Systems 		*
 *	Incoroporated.							*
 *									*
 *	The copyright notice appearing above is included to provide	*
 *	statutory protection in the event of unauthorized or 		*
 *	unintentional public disclosure.				*
 *									*
 ************************************************************************/

#include "sky.h"
#include "../h/types.h"
#include "../s32dev/skyreg.h"
#include "../s32dev/mbvar.h"
#include "../machine/cpu.h"



int skyprobe();
int skyintr();
int skyattach();

struct mb_device *skyinfo[NSKY];
u_short skystd[] = {0x1282, 0};
struct mb_driver skydriver = 
	{ 0, skyprobe, 0, skyattach, skystd, "sky", skyinfo};

u_long skysvs = 0;

/*
 * skyprobe --
 *	Probe the SKY device to see if it is there.  We don't expect
 *	to cause an interrupt.
 */
skyprobe(reg, intr, unit)
	register char *reg;
	register int (*intr)();
	register int unit;
{
	register char c;
	
	if (unit >= NSKY) {
		printf("%s%d: illegal unit number.\n", 
			skydriver.mdr_dname, unit);
		return(0);
	}
	if (intr != skyintr) {
		printf("%s%d: illegal interrupt vector 0x%x\n",
			skydriver.mdr_dname, unit, intr);
		return(0);
	}
	c = *reg;
	skysvs = (SKYVIRTADDR >> pageshift) << pageshift;
	return(1);
}

/*
 * skyintr --
 *	Dummy routine for autoconf
 */
skyintr()
{
}


/*
 * skyattach --
 *	Dummy routine for autoconf
 */
skyattach()
{
}


/*
 * skysave --
 *	This is the code that gets executed from resume() (in ../s32/locore.s)
 *	to save our current operation during a context switch.
 */
skysave(p, q, apc)
	register struct skyffp *p;	/* address of the SKY regs */
	register unsigned long *q;	/* address of u.u_fpsave */
	unsigned short *apc;		/* address of u.u_fppc */
{
	register int j;

	/*
	 * We initialize the command register to SKYNOP with the
	 * knowledge that if it isn't in this state, we can read
	 * it from the command register. (see below)
	 */
	*apc = SKYNOP;

	/*
	 * If we're in an idle state, we can directly send the save command
	 * (see below), otherwise we have to send some commands to the
	 * board...
	 */
	for (;!(SKYIDLE&p->sky_stcreg);) 
		/*
		 * Loop until the board is idle or is ready to accept input
		 * as determined from the I/O RDY flag in the status
		 * register.
		 */
		if (SKYIORDY&p->sky_stcreg) {
			p->sky_stcreg = SKYSNGRUN;	/* single step mode */

			/*
			 * If the I/O DIR flag is set, read the
			 * data register and discard, otherwise write dummy
			 * data to DTREG1 (16 bits).
			 */
			if (SKYIODIR&p->sky_stcreg) 
				j = p->sky_dt1reg;
			else 
				p->sky_dt1reg = 0;

			/*
			 * If I/O RDY is set then if I/O DIR is set
			 * read (16 bits) Data Register 1 (DTREG1)
			 * else if I/O DIR is not set, write dummy data
			 * to DTREG1.
			 */
			if (SKYIORDY&p->sky_stcreg) {
				if (SKYIODIR&p->sky_stcreg) 
					j = p->sky_dt1reg;
				else 
					p->sky_dt1reg = 0;
			}
			/*
			 * Save the contents of the command register.
			 * We decrement the register by 1 so that we
			 * can restart at the correct place in the
			 * interrupted I/O routine.
			 */
			*apc = p->sky_comreg - 1;

			/*
			 * Reset and restart the board...
			 */
			p->sky_stcreg=SKYRESET;
			p->sky_comreg=SKYSTART0;
			p->sky_comreg=SKYSTART0; /* dumb H/W needs it twice! */
			p->sky_comreg=SKYSTART1;
			p->sky_stcreg=SKYRUNENB;
			break;
		}

	p->sky_comreg = SKYNOP;
	p->sky_comreg = SKYSAVE;	/* Execute the context save function */

	/*
	 * Read the 32-bit internal registers from the board and save
	 * them in the process's u-page.
	 */
	 for (j=8; --j>=0; ) 
		*q++ = p->sky_dtreg;
}

/*
 * skyrestor
 *	This is the code that restores the SKY registers that were saved
 *	during a previous context switch by skysave().  We are called
 *	from resume() (in ../s32/locore.s).
 */
skyrestor(p, q, apc)
	register struct skyffp *p;	/* Address of the SKY I/O registers */
	register unsigned long *q;	/* Address of u.u_fpsave */
	unsigned short *apc;		/* Address of u.u_fppc */
{
	register int j;

	p->sky_comreg = SKYRESTOR;	/* Execute SKY context restore */

	/*
	 * Feed the board the contents of the registers that were
	 * cached in the u-page during the previous save.
	 */
	for (j=8; --j>=0; ) 
		p->sky_dtreg= *q++;

	/*
	 * Restore the previous command register
	 */
	p->sky_comreg= *apc;
}
