/*

    Copyright (C) Corollary, Inc., 1993, 1994.
    All Rights Reserved.
    This Module contains Proprietary Information of
    Corollary, Inc., and should be treated as Confidential.

Module Name:

    cbusmem.c

Abstract:

    This module implements the handling of additional memory
    ranges to be freed to the OS/2 kernel for the Corollary MP
    architectures.

Author:

    Landy Wang (landy@corollary.com) 11-Jan-1994
 */

#include <psd.h>
#include "cbustype.h"

#define SIXTEEN_MB		(16 * 1024 * 1024)

VOID
CbusMemoryFree(
IN ULONG Address,
IN ULONG Size
)
{
}

#if 0

struct memlist *		CbusExtraMemory;

/*

Routine Description:

    Add the specified memory range to our list of memory ranges to
    give to MM later.  Called each time we find a memory card during startup,
    also called on Cbus1 systems when we add a jumpered range (between 8 and
    16MB).  ranges are jumpered via EISA config when the user has added a
    dual-ported RAM card and wants to configure it into the middle of memory
    (not including 640K-1MB, which is jumpered for free) somewhere.

Arguments:

    Address - Supplies a start physical address in bytes of memory to free

    Size - Supplies a length in bytes spanned by this range

 */

VOID
CbusMemoryFree(
IN ULONG Address,
IN ULONG Size
)
{
	struct memlist *p;
	struct memlist *q;
	struct memlist *qprev;

	/*
	 * note that Cbus1 "hole" memory is always reclaimed at the
	 * doubly-mapped address in high memory, never in low memory.
	 */

	/*
	 * add the card provided we can alloc space below...
	 */
	p = (struct memlist *)kmem_alloc( sizeof(struct memlist), KM_NOSLEEP);
	if (!p)
		return;

	/*
	 * insert this descriptor into the chain - the chain must be
	 * sorted in numerically ascending addresses for the kernel.
	 */
	if (!CbusExtraMemory) {
		CbusExtraMemory = p;
		p->next = (struct memlist *)0;
	}
	else {
		qprev = (struct memlist *)0;
		p->next = (struct memlist *)0;
		for (q = CbusExtraMemory; q; qprev = q, q = q->next) {
			if (Address < q->address) {
				if (qprev) {
					/*
					 * sort it into the middle
					 */
					qprev->next = p;
					p->next = q;
				}
				else {
					/*
					 * it must go at the beginning
					 */
					p->next = CbusExtraMemory;
					CbusExtraMemory = p;
				}
				break;
			}
		}
		if (!p->next) {
			/*
			 * it needs to be added at the very end
			 */
			qprev->next = p;
			p->next = q;
		}
	}

	p->address = Address;
	p->size = Size;
}

/*
 * will only be called once - to get all memory above the specified address
 */
struct memlist *
CBUS_ReportMem(
paddr_t	mem_base
)
{
	struct memlist *p = CbusExtraMemory;
	struct memlist *prev = CbusExtraMemory;
	struct memlist *chunk;

	while (p && (p->address + p->size <= mem_base)) {
		/*
		 * we are responsible for freeing the chunks that we don't
		 * give to the kernel.  do this now.
		 */
		chunk = p;
		p = p->next;
		kmem_free(chunk, (sizeof(struct memlist)));
	}

	if (p) {
		ASSERT (mem_base >= p->address);
		/*
		 * hack down the memory if it's not already aligned with
		 * the kernel's request.
		 */
		if (p->address != mem_base) {
			p->size -= (mem_base - p->address);
			p->address = mem_base;
		}
	}

	return p;
}
#endif
