[BACK]Return to arcbios.c CVS log [TXT][DIR] Up to [local] / sys / arch / mips64 / mips64

File: [local] / sys / arch / mips64 / mips64 / arcbios.c (download)

Revision 1.1, Tue Mar 4 16:07:32 2008 UTC (16 years, 2 months ago) by nbrk
Branch point for: MAIN

Initial revision

/*	$OpenBSD: arcbios.c,v 1.9 2007/04/26 17:02:40 miod Exp $	*/
/*-
 * Copyright (c) 1996 M. Warner Losh.  All rights reserved.
 * Copyright (c) 1996-2004 Opsycon AB.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <machine/pte.h>
#include <machine/cpu.h>
#include <machine/memconf.h>
#include <machine/param.h>
#include <machine/autoconf.h>
#include <mips64/arcbios.h>
#include <mips64/archtype.h>

#if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000)
#include <machine/mnode.h>
#endif

int bios_is_32bit = 1;
/*
 * If we can not get the onboard ethernet address to override this bogus
 * value, ether_ifattach() will pick a valid address.
 */
char bios_enaddr[20] = "ff:ff:ff:ff:ff:ff";

extern int	physmem;		/* Total physical memory size */
extern int	rsvdmem;		/* Total reserved memory size */

void bios_configure_memory(void);
int bios_get_system_type(void);

arc_dsp_stat_t	displayinfo;		/* Save area for display status info. */

static struct systypes {
	char *sys_vend;		/* Vendor ID if name is ambigous */
	char *sys_name;		/* May be left NULL if name is sufficient */
	int  sys_type;
} sys_types[] = {
    { NULL,		"PICA-61",			ACER_PICA_61 },
    { NULL,		"NEC-R94",			ACER_PICA_61 },
    { NULL,		"DESKTECH-TYNE",		DESKSTATION_TYNE },
    { NULL,		"DESKTECH-ARCStation I",	DESKSTATION_RPC44 },
    { NULL,		"Microsoft-Jazz",		MAGNUM },
    { NULL,		"RM200PCI",			SNI_RM200 },
    { NULL,		"SGI-IP17",			SGI_CRIMSON },
    { NULL,		"SGI-IP19",			SGI_ONYX },
    { NULL,		"SGI-IP20",			SGI_INDIGO },
    { NULL,		"SGI-IP21",			SGI_POWER },
    { NULL,		"SGI-IP22",			SGI_INDY },
    { NULL,		"SGI-IP25",			SGI_POWER10 },
    { NULL,		"SGI-IP26",			SGI_POWERI },
    { NULL,		"SGI-IP27",			SGI_O200 },
    { NULL,		"SGI-IP32",			SGI_O2 },
};

#define KNOWNSYSTEMS (sizeof(sys_types) / sizeof(struct systypes))

/*
 *	ARC Bios trampoline code.
 */
#define ARC_Call(Name,Offset)	\
__asm__("\n"			\
"	.text\n"		\
"	.ent	" #Name "\n"	\
"	.align	3\n"		\
"	.set	noreorder\n"	\
"	.globl	" #Name "\n"	\
#Name":\n"			\
"	lw	$2, bios_is_32bit\n"\
"	beqz	$2, 1f\n"	\
"	nop\n"			\
"       lw      $2, 0xffffffff80001020\n"\
"       lw      $2," #Offset "($2)\n"\
"	jr	$2\n"		\
"	nop\n"			\
"1:\n"				\
"       ld      $2, 0xffffffff80001040\n"\
"	ld	$2, 2*" #Offset "($2)\n"\
"	jr	$2\n"		\
"	nop\n"			\
"	.end	" #Name "\n"	);

ARC_Call(Bios_Load,			0x00);
ARC_Call(Bios_Invoke,			0x04);
ARC_Call(Bios_Execute,			0x08);
ARC_Call(Bios_Halt,			0x0c);
ARC_Call(Bios_PowerDown,		0x10);
ARC_Call(Bios_Restart,			0x14);
ARC_Call(Bios_Reboot,			0x18);
ARC_Call(Bios_EnterInteractiveMode,	0x1c);
ARC_Call(Bios_Unused1,			0x20);
ARC_Call(Bios_GetPeer,			0x24);
ARC_Call(Bios_GetChild,			0x28);
ARC_Call(Bios_GetParent,		0x2c);
ARC_Call(Bios_GetConfigurationData,	0x30);
ARC_Call(Bios_AddChild,			0x34);
ARC_Call(Bios_DeleteComponent,		0x38);
ARC_Call(Bios_GetComponent,		0x3c);
ARC_Call(Bios_SaveConfiguration,	0x40);
ARC_Call(Bios_GetSystemId,		0x44);
ARC_Call(Bios_GetMemoryDescriptor,	0x48);
ARC_Call(Bios_Unused2,			0x4c);
ARC_Call(Bios_GetTime,			0x50);
ARC_Call(Bios_GetRelativeTime,		0x54);
ARC_Call(Bios_GetDirectoryEntry,	0x58);
ARC_Call(Bios_Open,			0x5c);
ARC_Call(Bios_Close,			0x60);
ARC_Call(Bios_Read,			0x64);
ARC_Call(Bios_GetReadStatus,		0x68);
ARC_Call(Bios_Write,			0x6c);
ARC_Call(Bios_Seek,			0x70);
ARC_Call(Bios_Mount,			0x74);
ARC_Call(Bios_GetEnvironmentVariable,	0x78);
ARC_Call(Bios_SetEnvironmentVariable,	0x7c);
ARC_Call(Bios_GetFileInformation,	0x80);
ARC_Call(Bios_SetFileInformation,	0x84);
ARC_Call(Bios_FlushAllCaches,		0x88);
ARC_Call(Bios_TestUnicodeCharacter,	0x8c);
ARC_Call(Bios_GetDisplayStatus,		0x90);

/*
 *	Simple getchar/putchar interface.
 */

int
bios_getchar()
{
	char buf[4];
	int  cnt;

	if (Bios_Read(0, &buf[0], 1, &cnt) != 0)
		return(-1);
	return(buf[0] & 255);
}

void
bios_putchar(c)
char c;
{
	char buf[4];
	int  cnt;

	if (c == '\n') {
		buf[0] = '\r';
		buf[1] = c;
		cnt = 2;
		if (displayinfo.CursorYPosition < displayinfo.CursorMaxYPosition)
			displayinfo.CursorYPosition++;
	}
	else {
		buf[0] = c;
		cnt = 1;
	}
	Bios_Write(1, &buf[0], cnt, &cnt);
}

void
bios_putstring(s)
char *s;
{
	while (*s) {
		bios_putchar(*s++);
	}
}

void
bios_printf(const char *fmt, ...)
{
	va_list ap;
	char buf[1024];

	va_start(ap, fmt);
	vsnprintf(buf, sizeof(buf), fmt, ap);
	bios_putstring(buf);
}

/*
 * Get memory descriptor for the memory configuration and
 * create a layout database used by pmap init to set up
 * the memory system. Note that kernel option "MACHINE_NONCONTIG"
 * must be set for systems with non contigous physical memory.
 *
 * Concatenate obvious adjecent segments.
 */
void
bios_configure_memory()
{
	arc_mem_t *descr = 0;
	struct phys_mem_desc *m;
	vaddr_t seg_start, seg_end;
	int	i;

	descr = (arc_mem_t *)Bios_GetMemoryDescriptor(descr);
	while(descr != 0) {

		seg_start = descr->BasePage;
		seg_end = seg_start + descr->PageCount;

		switch (descr->Type) {
		case BadMemory:		/* Have no use for theese */
			break;

		case FreeMemory:
		case FreeContigous:
			physmem += descr->PageCount;
			m = 0;
			for (i = 0; i < MAXMEMSEGS; i++) {
				if (mem_layout[i].mem_last_page == 0) {
					if (m == 0)
						m = &mem_layout[i]; /* free */
				}
				else if (seg_end == mem_layout[i].mem_first_page) {
					m = &mem_layout[i];
					m->mem_first_page = seg_start;
				}
				else if (mem_layout[i].mem_last_page == seg_start) {
					m = &mem_layout[i];
					m->mem_last_page = seg_end;
				}
			}
			if (m && m->mem_first_page == 0) {
				m->mem_first_page = seg_start;
				m->mem_last_page = seg_end;
			}
			break;

		case ExeceptionBlock:
		case SystemParameterBlock:
		case FirmwareTemporary:
		case FirmwarePermanent:
			rsvdmem += descr->PageCount;
			physmem += descr->PageCount;
			break;

		case LoadedProgram:	/* Count this into total memory */
			physmem += descr->PageCount;
			break;

		default:		/* Unknown type, leave it alone... */
			break;
		}
		descr = (arc_mem_t *)Bios_GetMemoryDescriptor(descr);
	}

#ifdef DEBUG_MEM_LAYOUT
	for ( i = 0; i < MAXMEMSEGS; i++) {
		if (mem_layout[i].mem_first_page) {
			bios_printf("MEM %d, 0x%x to  0x%x\n",i,
				mem_layout[i].mem_first_page * 4096,
				mem_layout[i].mem_last_page * 4096);
	    }
	}
#endif
}

/*
 * Find out system type.
 */
int
bios_get_system_type()
{
	arc_config_t	*cf;
	arc_sid_t	*sid;
	int		i;

	/*
	 *  Figure out if this is an ARC Bios machine and if its 32 or 64 bits.
	 */
	if ((ArcBiosBase32->magic == ARC_PARAM_BLK_MAGIC) ||
	    (ArcBiosBase32->magic == ARC_PARAM_BLK_MAGIC_BUG)) {
		bios_is_32bit = 1;
		bios_printf("ARCS32 Firmware Version %d.%d\n",
		    ArcBiosBase32->version, ArcBiosBase32->revision);
	} else if ((ArcBiosBase64->magic == ARC_PARAM_BLK_MAGIC) ||
	    (ArcBiosBase64->magic == ARC_PARAM_BLK_MAGIC_BUG)) {
		bios_is_32bit = 0;
		bios_printf("ARCS64 Firmware Version %d.%d\n",
		    ArcBiosBase64->version, ArcBiosBase64->revision);
	} else {
		return -1;	/* XXX BAD BAD BAD!!! */
	}

	sid = (arc_sid_t *)Bios_GetSystemId();

	cf = (arc_config_t *)Bios_GetChild(NULL);
	if (cf) {
		for (i = 0; i < KNOWNSYSTEMS; i++) {
			if (strcmp(sys_types[i].sys_name, (char *)(long)cf->id) != 0)
				continue;
			if (sys_types[i].sys_vend &&
			    strncmp(sys_types[i].sys_vend, sid->vendor, 8) != 0)
				continue;
			return (sys_types[i].sys_type);	/* Found it. */
		}
#if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000)
	} else if (IP27_KLD_KLCONFIG(0)->magic == IP27_KLDIR_MAGIC) {
		/* If we find a kldir assume IP27 */
		return SGI_O200;
#endif
	}

	sid->vendor[8] = 0;
	sid->prodid[8] = 0;
	bios_printf("UNRECOGNIZED SYSTEM '%s' VENDOR '%s' PRODUCT '%s'\n",
		cf ? (char *)(long)cf->id : "??", sid->vendor, sid->prodid);
	bios_printf("See the www.openbsd.org for further information.\n");
	bios_printf("Halting system!\n");
	Bios_Halt();
	bios_printf("Halting failed, use manual reset!\n");
	while(1);
}

/*
 * Incomplete version of bios_ident
 */
void
bios_ident()
{
	sys_config.system_type = bios_get_system_type();
	if (sys_config.system_type < 0 || sys_config.system_type == SGI_O200) {
		return;
	}
	/* If not an IP27 platform, get memory configuration from bios */
	bios_configure_memory();
#ifdef __arc__
	displayinfo = *(arc_dsp_stat_t *)Bios_GetDisplayStatus(1);
#endif
}

/*
 * Return geometry of the display. Used by pccons.c to set up the
 * display configuration.
 */
void
bios_display_info(xpos, ypos, xsize, ysize)
    int	*xpos;
    int	*ypos;
    int *xsize;
    int *ysize;
{
#ifdef __arc__
	*xpos = displayinfo.CursorXPosition;
	*ypos = displayinfo.CursorYPosition;
	*xsize = displayinfo.CursorMaxXPosition;
	*ysize = displayinfo.CursorMaxYPosition;
#endif
}