/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header $ */
/* $Source $ */
/* 
 * Copyright University of Southern California, 1988
 */

#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <dos.h>
#include <fcntl.h>
#include <io.h>
#include "pctype.h"
#include "pcparam.h"
#include "rb.h"
#include "bios.h"
#include "dio.h"
#include "os2data.h"

/* structures for hard disk info */
struct	drvparm	hdparm[NHD];
struct	rb_part	rb_part[NHD];

/*
 * This routine is used to write certain configuration paramaters to
 * a control block in the coprocessor memory that are required to
 * boot the system. Since the coprocessor addresses the PCIF
 * as the next 1MB after the end of it's own physical storage
 * we need to tell it how much memory it has. The other values
 * passed up are done so to make the boot process a little easier.
 */
void write_config()
{
	register int    i;
	u_short         pstart, pend, lastdrive, drive, j, sysid, plen;
	u_long          addr;
	struct postconfig   config;

	struct hdinfo  *hdinfoptr;
	struct drvparm *hd;
	char            tmpbuf[2 * SECSIZE];
	struct ptable  *ptable = (struct ptable *) (tmpbuf + PTOFFSET);
	struct rb_part *hdpart;
	struct miscconfig {
		long	nvram;
		long	ipl_device;
		long	keyboard_id;
		long	machine_type;
		} miscconfig;
	extern long	boot_dev;		/* the boot device */
	extern u_short	dst_flag;		/* if dst in effect */
	u_short pc_mem_size = 0;		/* no memory available */
	extern char     version[];		/* the version string */

	/*
	 * Initialize the conf structure. 
	 */

	bzero((char *) &config, sizeof (struct postconfig));

	/*
	 * Now fill it in. 
	 */

	config.mem_size = exchw(physmem_reg);

	/*
	 * Note: Do NOT exchange these values. Unix expects to see them in
	 * INTEL byte order. 
	 */

	switch (physmem_reg)
	{
	case 2:
		/* change long to u_long and declare exchl as u_long */
		config.memconfig = exchl((u_long) CONFIG2MB);
		break;

	case 4:
		config.memconfig = exchl((u_long) CONFIG4MB);
/*		printf("memconfig = %lx configdata %x\n",config.memconfig,
				CONFIG4MB);
*/
		break;

	case 8:
		config.memconfig = exchl((u_long) CONFIG8MB);
		break;

	default:
		printf("(%d) ", physmem_reg);
		pcpanic("Unknown Memory Size For ROMP Coprocessor");
		break;
	}

	config.pcif_base = exchw(r_base);	/* Port address of PCIF	 */
	config.cpu = cpu_number;		/* this cpu number */
	config.maxcpu = ncpu;			/* total cpu's */

	/* changed for moving cbcb up to the user process */

	config.cbcb_addr = exchl(physaddr((char far *) cbcbptr));
#ifdef CONFIG_DEBUG
	printf("cbcb_addr = %lx size=%d ",config.cbcb_addr,sizeof (struct cbcb));
	printf("cbcb_addr (os2) = %lx\n",physaddr((char far *) cbcbptr));

	printf("cbcbptr = 0x%x(in write_config)\n",cbcbptr);
#endif
	config.dst_flag = exchw(dst_flag);
	config.pc_mem_size = exchw(pc_mem_size);

	strncpy(config.version, version, (sizeof config.version) - 1);	/* copy version msg */

	config.os_type = OS_2_TYPE;

	/*
	 * Get all the Disk Info 
	 *
	 * Note: Bios drive numbers for the fixed disks start at 0x80; 
	 *
	 */

	lastdrive = 0x80 + (NHD - 1);
	for (drive = 0x80; drive <= lastdrive; drive++)
	{
		j = drive - 0x80;
		hd = &hdparm[j];
		hdinfoptr = &config.hdinfo[j];
		hdpart = &rb_part[j];
		if (hd->maxcyl)
		{
			hdinfoptr->ncpd = exchw(hd->maxcyl);
			hdinfoptr->ntpc = exchw(hd->maxhd);
			hdinfoptr->nspt = exchw(hd->maxsec);
			hdinfoptr->flag |= HDINFO_PRESENT;

			/*
			 * Check to see if there is a 4.2 Partition present.
			 * If there is then see if there is a bad block table 
			 */

			if (hdio(DISKOP_READ,drive,0,0,1,1,
					(char far *)tmpbuf) >= 0)
			{
				if (ptable->signature == VALID_SIG)
				{
					for (i = 0; i < 4; i++)
					{
						sysid = ptable->pt[i].sysid & 0x00ff;
						pstart = XTRACTCYL(ptable->pt[i].scyl, ptable->pt[i].ssec);
						pend = XTRACTCYL(ptable->pt[i].ecyl, ptable->pt[i].esec);
						plen = pend - pstart + 1;
						if (sysid == ACIS42)
						{
							/*
							 * Save it for rb to
							 * use 
							 */

							hdpart->pstart = pstart;
							hdpart->plen = plen;

							/*
							 * Now put it into
							 * the config record 
							 */

							hdinfoptr->pstart = exchw(pstart);
							hdinfoptr->plen = exchw(plen);
							hdinfoptr->flag |= HDINFO_42PART;

						}

					}
				} else
				{
				printf("Invalid Signature %#x\n", ptable->signature);
				printf("No Partition Table Present for drive %#x\n", drive);
				hdinfoptr->flag |= HDINFO_NOBRPT;
				}
			} else
				pcpanic("Can't Read Partition Record");

			hdinfoptr->flag = exchw(hdinfoptr->flag);
		}
	}

/*	prconfig(&config); */

	addr = UNIXPOST;	/* This is where the stuff goes */

	if (moveout(addr, (caddr_t) &config, sizeof(config)) < 0)
		pcpanic("Can't write config data to coprocessor");

	addr = UNIXPOSTMISC;	/* where misc stuff goes */

	bzero((char *) &miscconfig, sizeof (struct miscconfig));

	miscconfig.ipl_device = exchl((long) boot_dev);

	if (moveout(addr, (caddr_t) & miscconfig, sizeof(miscconfig)) < 0)
		pcpanic("Can't write misc config data to coprocessor");
}

prconfig(config)
struct	postconfig	*config;
{
	printf("Config:\n");
	printf("\tmem_size\t%x\n",exchw(config->mem_size));
	printf("\tpcif_base\t%x\n",exchw(config->pcif_base));
	printf("\tcbcb_addr\t%lx\n",exchl((u_long)config->cbcb_addr));
	printf("\tequip\t\t%x\n",(u_short)config->equip);
	printf("\tega_info\t%x\n",(u_short)config->ega_info);
	printf("\tmemconfig\t%lx\n",exchl((u_long)config->memconfig));
	printf("\tmemconfig\t%lx\n",((u_long)config->memconfig));

	printf("\thdinfo 1\n");
	printf("\t\tncpd = %d\n",exchw(config->hdinfo[0].ncpd));
	printf("\t\tntpc = %d\n",exchw(config->hdinfo[0].ntpc));
	printf("\t\tnspt = %d\n",exchw(config->hdinfo[0].nspt));
	printf("\t\tpstart= %d\n",exchw(config->hdinfo[0].pstart));
	printf("\t\tplen = %d\n",exchw(config->hdinfo[0].plen));
	printf("\t\tflag = %d\n",exchw(config->hdinfo[0].flag));

	printf("\thdinfo 2\n");
	printf("\t\tncpd = %d\n",exchw(config->hdinfo[1].ncpd));
	printf("\t\tntpc = %d\n",exchw(config->hdinfo[1].ntpc));
	printf("\t\tnspt = %d\n",exchw(config->hdinfo[1].nspt));
	printf("\t\tpstart= %d\n",exchw(config->hdinfo[1].pstart));
	printf("\t\tplen = %d\n",exchw(config->hdinfo[1].plen));
	printf("\t\tflag = %d\n",exchw(config->hdinfo[1].flag));
}

/*
 * zero a chunk of memory
 */
bzero(cp1,length)
	char	       *cp1;
	int		length;
{
	while (--length >= 0)
		*cp1++ = 0;
}

