/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:rbinit.c 12.0$ */
/* $ACIS:rbinit.c 12.0$ */
/* $Source: /ibm/acis/usr/sys/os2code/RCS/rbinit.c,v $ */

/*
 * Copyright University of Southern California, 1988
 */

#include    	<subcalls.h>
#include    	<doscalls.h>
#include	"pctype.h"
#include	"pcparam.h"
#include	"rb.h"
#include	"os2ioctl.h"
#include	"vga.h"
#include	"os2data.h"

void rompstart(addr)
	u_long          addr;
{

	u_long          raddr = exchl(addr);	/* Back to IBM format from
						 * Intel Format */
	printf("Start Coprocessor at %#lx\n", addr);

	/*
	 * Write the IAR address to 0  and tell coprocessor to start running 
	 */
	if (moveout(0L, (char far *) &raddr, 4) < 0)
		fatal("Faild write of ipl address",0);
	else
		SETBIT(r_base+R_CTRL, R_IPLC);
}

void init_wind()			/* initialize ROMP windows */
{
	register int    j;

	for (j = 0; j <= 3; j++)
		IOOUT((r_base + j), j);

	pc_wind1 = pcif_map(pc_base,0);
	pc_wind2 = pcif_map(pc_base + 0x10000,0);
	pc_wind3 = pcif_map(pc_base + 0x20000,0);
	pc_wind4 = pcif_map(pc_base + 0x30000,0);
#ifdef INIT_DEBUG
	printf("pcif window 1 = %lx, (%lx)\n",pc_wind1,physaddr(pc_wind1));
	printf("pcif window 2 = %lx, (%lx)\n",pc_wind2,physaddr(pc_wind2));
	printf("pcif window 3 = %lx, (%lx)\n",pc_wind3,physaddr(pc_wind3));
	printf("pcif window 4 = %lx, (%lx)\n",pc_wind4,physaddr(pc_wind4));
#endif INIT_DEBUG
}

/* 
 * initialize the ROMP per the manual
 */
int rompinit()			
{

	u_short         j;

	RSETALL(r_base+P_CTRL);	/* reset all the PCIF registers */
	RSETALL(r_base+P_STAT);
	RSETALL(r_base+R_CLOCK);
	RSETALL(r_base+R_CTRL);
	RSETALL(r_base+R_INTR);

	SETBIT(r_base+R_CTRL, R_MM);	/* turn on master mode in PCIF */

	if (intlv_flag)
		SETBIT(r_base+R_CTRL, R_INTL);	/* turn on interleaved mode */

	IOOUT(r_base+P_BASE, (pc_base >> 18));	/* set the PC base address */
	SETBIT(r_base+P_CTRL, P_ECCON);/* enable ecc correction */

	SETBIT(r_base+P_CTRL, P_2WIND);/* enable first two windows */
	SETBIT(r_base+P_CTRL, P_4WIND);/* enable next two windows */

	SETBIT(r_base+R_CLOCK, R_CPOR);/* POR the ROMP */
	DELAY(10);
	RSETBIT(r_base+R_CLOCK, R_CPOR);	/* turn off POR */
	DELAY(10);
	SETBIT(r_base+R_CLOCK, R_RSET);
	DELAY(10);
	RSETBIT(r_base+R_CLOCK, R_RSET);
	DELAY(10);

	j = IOIN(r_base+R_STAT) & 0x00ff;

	if (j != 0x7f)		/* if ROMP status is bad */
		return (j);	/* return with error */
	else
		return (0);
}


/*
 * Initialize memory on the coprocessor.
 *
 * This routine enables num_win PC to Unix windows, then
 * it writes all zeros to all of coprocessor memmory.
 */
void init_rmem(num_win)
	int             num_win;
{
	int             i;
	u_long          lval1, addr;
	char far       *buff = buff_dio;

	/* Enable buffer mode for windows */
	for (i = 0; i < num_win; i++) SETBIT(r_base+P_CTRL, i);

	printf("Clear Coprocessor Memory (%#lx):\n", physmem_bytes);

	addr = 0;
	while (addr < physmem_bytes)
	{
		lval1 = physmem_bytes - addr;
		if (lval1 > MEMBLOCK)
			lval1 = MEMBLOCK;

		if ((i = moveout(addr,(u_long) buff,LOWORD(lval1))) < 0)
		{
			i = LOBYTE(i);
			printf("(%d) Error Clearing Memory\n", i);
			fatal("Can't clear memory",0);
		}
		addr += lval1;
		printf("%#lx\r", addr);
	}
	
	/* Reset the buffer mode for windows */
	for (i = 0; i < num_win; i++)
		RSETBIT(r_base+P_CTRL, i);

}


/*
 * reset the romp when we are about to go back to DOS
 */
romp_reset()
{
	SETBIT(r_base+R_CLOCK, R_CPOR);	/* POR the ROMP */
	DELAY(10);
	RSETBIT(r_base+R_CLOCK, R_CPOR);	/* turn off POR */
	DELAY(10);
	SETBIT(r_base+R_CLOCK, R_RSET);
	DELAY(10);
	RSETBIT(r_base+R_CLOCK, R_RSET);
	DELAY(10);
}

/*
 * init_cbcb - Initialize the cbcb
 *
 *   Zero it out, then fill in the addresses of the PC control blocks that
 *   we know about.
 */

void init_cbcb()
{
	register int    i;
	register char  *cptr;
	char far       *farptr;

	cptr = (char *) cbcbptr;

	for(i=0;i++ < sizeof(struct cbcb);cptr++) 
		*cptr = 0;

	cbcbptr->cpu = cpu_number;
	farptr = (char far *) vec_map;
	cbcbptr->cbcb_ent[SVENT].pc_cb = exchl(physaddr(farptr));

	farptr = (char far *) &kbdata;
	cbcbptr->cbcb_ent[KBENT].pc_cb = exchl(physaddr(farptr));

	farptr = (char far *) &xclock;
	cbcbptr->cbcb_ent[CLENT].pc_cb = exchl(physaddr(farptr));

	farptr = (char far *) hd_return_code;
	if ((i = LOWORD(farptr) & 0x3) != 0)
	{
		hd_return_code = (struct dio_rtn_codes *) 
					(LOWORD(farptr) + (4 - i));
		farptr = (char far *) hd_return_code;
	}
	cbcbptr->cbcb_ent[HDENT].pc_cb = exchl(physaddr(farptr));

	farptr = (char far *) fd_return_code;
	if ((i = LOWORD(farptr) & 0x3) != 0)
	{
		fd_return_code = (struct dio_rtn_codes *) 
					(LOWORD(farptr) + (4 - i));
		farptr = (char far *) fd_return_code;
	}
	cbcbptr->cbcb_ent[FDENT].pc_cb = exchl(physaddr(farptr));

	farptr = (char far *) vga;
	cbcbptr->cbcb_ent[BIOSENT].pc_cb = exchl(physaddr(farptr));

	farptr = (char far *)ubp;
	cbcbptr->cbcb_ent[AFIENT].pc_cb = exchl(physaddr(farptr));

	farptr = (char far *)ub_pc;
	cbcbptr->cbcb_ent[UBENT].pc_cb = exchl(physaddr(farptr));


	farptr = (char far *) &msdata;
	cbcbptr->cbcb_ent[MSENT].pc_cb = exchl(physaddr(farptr));

	farptr = (char far *) &spkdata;
	cbcbptr->cbcb_ent[SPKENT].pc_cb = exchl(physaddr(farptr));

	farptr = (char far *) &old_mask;
	cbcbptr->cbcb_ent[MASKENT].pc_cb = exchl(physaddr(farptr));

	cbcbptr->dummy2 = '>';
	cbcbptr->dummy3 = '<';
	cbcbptr->debug = debug;
}
