code:
/*	$OpenBSD: arcbios.c,v 1.20 2014/03/29 18:09:30 guenther 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 <lib/libkern/libkern.h>

#include <mips64/arcbios.h>
#include <mips64/archtype.h>
#include <machine/autoconf.h>
#include <machine/cpu.h>
#include <machine/mnode.h>

#include <stand.h>

#ifdef __LP64__
int	 bios_is_32bit;
#endif
void	*bios_base;
#ifdef __LP64__
u_int	 kl_n_shift = 32;
#endif

int	arcbios_init(void);
const char *boot_get_path_component(const char *, char *, int *);
const char *boot_getnr(const char *, int *);

static const struct systypes {
	char *sys_name;
	int  sys_ip;
} sys_types[] = {
    { "SGI-IP20", 20 },
    { "SGI-IP22", 22 },
    { "SGI-IP26", 26 },
    { "SGI-IP28", 28 },
    { "SGI-IP30", 30 },
    { "SGI-IP32", 32 }
};

#define KNOWNSYSTEMS (nitems(sys_types))

/*
 * ARCBios trampoline code.
 */
#ifdef __LP64__
#define ARC_Call(Name,Offset)	\
__asm__("\n"			\
"	.text\n"		\
"	.ent	" #Name "\n"	\
"	.align	3\n"		\
"	.set	noreorder\n"	\
"	.globl	" #Name "\n"	\
#Name":\n"			\
"	lw	$3, bios_is_32bit\n"\
"	ld	$2, bios_base\n"\
"	beqz	$3, 1f\n"	\
"	 nop\n"			\
"	lw	$3, 0x20($2)\n"	\
"	lw	$2," #Offset "($3)\n"\
"	jr	$2\n"		\
"	 nop\n"			\
"1:\n"				\
"	ld	$3, 2*0x20($2)\n"\
"	ld	$2, 2*" #Offset "($3)\n"\
"	jr	$2\n"		\
"	 nop\n"			\
"	.end	" #Name "\n"	);
#else
#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_base\n"\
"	lw	$3, 0x20($2)\n"	\
"	lw	$2," #Offset "($3)\n"\
"	jr	$2\n"		\
"	 nop\n"			\
"	.end	" #Name "\n"	);
#endif

#if 0
ARC_Call(Bios_Load,			0x00);
ARC_Call(Bios_Invoke,			0x04);
ARC_Call(Bios_Execute,			0x08);
#endif
ARC_Call(Bios_Halt,			0x0c);
#if 0
ARC_Call(Bios_PowerDown,		0x10);
ARC_Call(Bios_Restart,			0x14);
ARC_Call(Bios_Reboot,			0x18);
#endif
ARC_Call(Bios_EnterInteractiveMode,	0x1c);
#if 0
ARC_Call(Bios_Unused1,			0x20);
#endif
ARC_Call(Bios_GetPeer,			0x24);
ARC_Call(Bios_GetChild,			0x28);
#if 0
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);
#endif
ARC_Call(Bios_GetSystemId,		0x44);
ARC_Call(Bios_GetMemoryDescriptor,	0x48);
#if 0
ARC_Call(Bios_Unused2,			0x4c);
ARC_Call(Bios_GetTime,			0x50);
ARC_Call(Bios_GetRelativeTime,		0x54);
ARC_Call(Bios_GetDirectoryEntry,	0x58);
#endif
ARC_Call(Bios_Open,			0x5c);
ARC_Call(Bios_Close,			0x60);
ARC_Call(Bios_Read,			0x64);
#if 0
ARC_Call(Bios_GetReadStatus,		0x68);
#endif
ARC_Call(Bios_Write,			0x6c);
ARC_Call(Bios_Seek,			0x70);
#if 0
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);
#endif

/*
 * Simple getchar/putchar interface.
 */

#if 0
int
getchar()
{
	char buf[4];
	long cnt;

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

	return (buf[0] & 255);
}
#endif

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

	if (c == '\n') {
		buf[0] = '\r';
		buf[1] = c;
		cnt = 2;
	} else {
		buf[0] = c;
		cnt = 1;
	}

	Bios_Write(1, &buf[0], cnt, &cnt);
}

/*
 * Identify ARCBios type.
 */
int
arcbios_init()
{
	arc_config_t *cf;
	arc_sid_t *sid;
#ifdef __LP64__
	register_t prid;
#endif
	char *sysid = NULL;
	int sysid_len;
	int i;

	/*
	 * Figure out where ARCBios can be addressed. On R8000, we can not
	 * use compatibility space, but on IP27/IP35, we can not blindly
	 * use XKPHYS due to subspacing, while compatibility space works.
	 * Fortunately we can get the processor ID to tell these apart, even
	 * though 32-bit coprocessor 0 instructions are not supposed to be
	 * supported on the R8000 (they probably misbehave somehow if the
	 * register has bits sets in the upper 32 bits, which is not the
	 * case of the R8000 PrId register).
	 */
#ifdef __LP64__
	__asm__ volatile ("mfc0 %0, $15" /* COP_0_PRID */ : "=r" (prid));
	if ((prid & 0xff00) == (MIPS_R8000 << 8))
		bios_base = (void *)PHYS_TO_XKPHYS(ARCBIOS_BASE, CCA_CACHED);
	else
		bios_base = (void *)PHYS_TO_CKSEG0(ARCBIOS_BASE);
#else
	bios_base = (void *)(int32_t)PHYS_TO_CKSEG0(ARCBIOS_BASE);
#endif

	/*
	 * Figure out if this is an ARCBios machine and if it is, see if we're
	 * dealing with a 32 or 64 bit version.
	 */
#ifdef __LP64__
	if ((ArcBiosBase32->magic == ARC_PARAM_BLK_MAGIC) ||
	    (ArcBiosBase32->magic == ARC_PARAM_BLK_MAGIC_BUG)) {
		bios_is_32bit = 1;
	} else if ((ArcBiosBase64->magic == ARC_PARAM_BLK_MAGIC) ||
	    (ArcBiosBase64->magic == ARC_PARAM_BLK_MAGIC_BUG)) {
		bios_is_32bit = 0;
	}
#endif

	/*
	 * Minimal system identification.
	 */
	sid = (arc_sid_t *)Bios_GetSystemId();
	cf = (arc_config_t *)Bios_GetChild(NULL);
	if (cf != NULL) {
#ifdef __LP64__
		if (bios_is_32bit) {
			sysid = (char *)(long)cf->id;
			sysid_len = cf->id_len;
		} else {
			sysid = (char *)((arc_config64_t *)cf)->id;
			sysid_len = ((arc_config64_t *)cf)->id_len;
		}
#else
		sysid = (char *)(long)cf->id;
		sysid_len = cf->id_len;
#endif

		if (sysid_len > 0 && sysid != NULL) {
			sysid_len--;
			for (i = 0; i < KNOWNSYSTEMS; i++) {
				if (strlen(sys_types[i].sys_name) != sysid_len)
					continue;
				if (strncmp(sys_types[i].sys_name, sysid,
				    sysid_len) != 0)
					continue;
				return sys_types[i].sys_ip;	/* Found it. */
			}
		}
	} else {
#ifdef __LP64__
		if (IP27_KLD_KLCONFIG(0)->magic == IP27_KLDIR_MAGIC) {
			/*
			 * If we find a kldir assume IP27. Boot blocks
			 * do not need to tell IP27 and IP35 apart.
			 */
			return 27;
		}
#endif
	}

	printf("UNRECOGNIZED SYSTEM '%s' VENDOR '%s' PRODUCT '%s'\n",
	    cf == NULL || sysid == NULL ? "(null)" : sysid,
	    sid->vendor, sid->prodid);
	printf("Halting system!\n");
	Bios_Halt();
	printf("Halting failed, use manual reset!\n");
	for (;;) ;
}

/*
 *  Decompose the device pathname and find driver.
 *  Returns pointer to remaining filename path in file.
 */
int
devopen(struct open_file *f, const char *fname, char **file)
{
	const char *cp, *ncp, *ecp;
	struct devsw *dp;
	int partition = 0;
	char namebuf[256];
	char devname[32];
	int rc, i, n, noopen = 0;

	ecp = cp = fname;
	namebuf[0] = '\0';

	/*
	 * Scan the component list and find device and partition.
	 */
	if (strncmp(cp, "bootp()", 7) == 0) {
		strlcpy(devname, "bootp", sizeof(devname));
		strlcpy(namebuf, cp, sizeof(namebuf));
		noopen = 1;
	} else if (strncmp(cp, "dksc(", 5) == 0) {
		strncpy(devname, "scsi", sizeof(devname));
		cp += 5;
		cp = boot_getnr(cp, &i);
		/* i = controller number */
		if (*cp++ == ',') {
			cp = boot_getnr(cp, &i);
			/* i = target id */
			if (*cp++ == ',') {
				memcpy(namebuf, fname, cp - fname);
				namebuf[cp - fname] = '\0';
				strlcat(namebuf, "0)", sizeof namebuf);

				cp = boot_getnr(cp, &i);
				partition = i;
				cp++;	/* skip final ) */
			}
		}
	} else {
		ncp = boot_get_path_component(cp, namebuf, &i);
		while (ncp != NULL) {
			if (strcmp(namebuf, "partition") == 0)
				partition = i;
			ecp = ncp;

			/* XXX Do this with a table if more devs are added. */
			if (strcmp(namebuf, "scsi") == 0)
				strncpy(devname, namebuf, sizeof(devname));

			cp = ncp;
			ncp = boot_get_path_component(cp, namebuf, &i);
		}

		memcpy(namebuf, fname, ecp - fname);
		namebuf[ecp - fname] = '\0';
	}

	/*
	 * Dig out the driver.
	 */
	dp = devsw;
	n = ndevs;
	while (n--) {
		if (strcmp(devname, dp->dv_name) == 0) {
			if (noopen)
				rc = 0;
			else
				rc = (dp->dv_open)(f, namebuf, partition, 0);
			if (rc == 0) {
				f->f_dev = dp;
				if (file && *cp != '\0')
					*file = (char *)cp;
			}
			return (rc);
		}
		dp++;
	}
	return (ENXIO);
}

const char *
boot_get_path_component(const char *p, char *comp, int *no)
{
	while (*p && *p != '(')
		*comp++ = *p++;
	*comp = '\0';

	if (*p == '\0')
		return (NULL);

	*no = 0;
	p++;
	while (*p && *p != ')') {
		if (*p >= '0' && *p <= '9')
			*no = *no * 10 + *p++ - '0';
		else
			return (NULL);
	}
	return (++p);
}

const char *
boot_getnr(const char *p, int *no)
{
	*no = 0;
	while (*p >= '0' && *p <= '9')
		*no = *no * 10 + *p++ - '0';
	return p;
}


code:
/*	$OpenBSD: boot.c,v 1.24 2014/02/22 20:27:21 miod Exp $ */

/*
 * Copyright (c) 2004 Opsycon AB, www.opsycon.se.
 *
 * 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 AUTHOR ``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 AUTHOR 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/stat.h>
#define _KERNEL
#include <sys/fcntl.h>
#undef _KERNEL

#include <lib/libkern/libkern.h>
#include <stand.h>

#include <mips64/arcbios.h>
#include <mips64/cpu.h>

#include <sys/exec_elf.h>
#undef ELFSIZE
#include "loadfile.h"

void	 dobootopts(int, char **);
void	 loadrandom(const char *, const char *, void *, size_t);
char	*strstr(char *, const char *);	/* strstr.c */

enum {
	AUTO_NONE,
	AUTO_YES,
	AUTO_NO,
	AUTO_MINI,
	AUTO_DEBUG
} bootauto = AUTO_NONE;
char *OSLoadPartition = NULL;
char *OSLoadFilename = NULL;

int	IP;

char   rnddata[BOOTRANDOM_MAX];

#include "version"

/*
 * OpenBSD/sgi Boot Loader.
 */
void
boot_main(int argc, char *argv[])
{
	u_long marks[MARK_MAX];
	u_int64_t *esym;
	char line[1024];
	u_long entry;
	int fd;
	extern int arcbios_init(void);

	IP = arcbios_init();
	printf("\nOpenBSD/sgi-IP%d ARCBios boot version %s\n", IP, version);
	/* we want to print IP20 but load IP22 */
	if (IP == 20)
		IP = 22;

	for (entry = 0; entry < argc; entry++)
		printf("arg %d: %s\n", entry, argv[entry]);

	dobootopts(argc, argv);
	if (OSLoadPartition == NULL) {
		/*
		 * Things are probably horribly wrong, or user has no idea
		 * what's he's doing.  Be nice lads and try to provide
		 * working defaults, which ought to work on all systems.
		 */
		OSLoadPartition = "disk(0)part(0)";
	}
	strlcpy(line, OSLoadPartition, sizeof(line));
	if (OSLoadFilename != NULL)
		strlcat(line, OSLoadFilename, sizeof(line));

	printf("Boot: %s\n", line);

	/*
	 * Try and load randomness if booting from a disk.
	 */

	if (bootauto != AUTO_MINI &&
	    strstr(OSLoadPartition, "bootp(") == NULL &&
	    strstr(OSLoadPartition, "cdrom(") == NULL) {
		loadrandom(OSLoadPartition, BOOTRANDOM, rnddata,
		    sizeof(rnddata));
	}

	/*
	 * Load the kernel and symbol table.
	 */

	marks[MARK_START] = 0;
	if ((fd = loadfile(line, marks, LOAD_KERNEL | COUNT_KERNEL)) != -1) {
		(void)close(fd);

		entry = marks[MARK_ENTRY];
#ifdef __LP64__
		esym = (u_int64_t *)marks[MARK_END];
#else
#undef  CKSEG0_BASE
#define CKSEG0_BASE	0xffffffff80000000ULL
		esym = (u_int64_t *)(uint32_t)PHYS_TO_CKSEG0(marks[MARK_END]);
#endif

		if (entry != 0)
			((void (*)())entry)(argc, argv, esym);
	}

	/* We failed to load the kernel. */
	panic("Boot FAILED!");
	/* NOTREACHED */
}

__dead void
_rtt()
{
	Bios_EnterInteractiveMode();
	for (;;) ;
}

/*
 * Decode boot options.
 */
void
dobootopts(int argc, char **argv)
{
	static char filenamebuf[1 + 32];
	char *SystemPartition = NULL;
	char *cp, *sep;
	int i;
	char *writein = NULL;

	for (i = 1; i < argc; i++) {
		cp = argv[i];
		if (cp == NULL)
			continue;
		if (strncmp(cp, "OSLoadOptions=", 14) == 0) {
			if (strcmp(&cp[14], "auto") == 0)
				bootauto = AUTO_YES;
			else if (strcmp(&cp[14], "single") == 0)
				bootauto = AUTO_NO;
			else if (strcmp(&cp[14], "mini") == 0)
				bootauto = AUTO_MINI;
			else if (strcmp(&cp[14], "debug") == 0)
				bootauto = AUTO_DEBUG;
		} else if (strncmp(cp, "OSLoadPartition=", 16) == 0)
			OSLoadPartition = &cp[16];
		else if (strncmp(cp, "OSLoadFilename=", 15) == 0)
			OSLoadFilename = &cp[15];
		else if (strncmp(cp, "SystemPartition=", 16) == 0)
			SystemPartition = &cp[16];
		else {
			/*
			 * Either a boot-related environment variable, or
			 * a boot write-in (boot path or options to the
			 * program being loaded).
			 */
			if (*cp == '-')
				continue;	/* options */
			if (strchr(cp, '=') != NULL)
				continue;	/* variable (or bad choice */
						/* of filename) */
			if (writein == NULL)
				writein = cp;
		}
	}

	switch (bootauto) {
	case AUTO_NONE:
		/* If "OSLoadOptions=" is missing, use boot path if given. */
		if (writein != NULL) {
			/* check for a possible path component */
			sep = strchr(writein, '(');
			if (sep != NULL && strchr(sep, ')') != NULL) {
				/* looks like this is a full path */
				OSLoadPartition = "";
			} else {
				/* relative path, keep OSLoadPartition */
			}
			OSLoadFilename = writein;
		}
		break;
	case AUTO_MINI:
	    {
		static char loadpart[64];
		char *p;

		strlcpy(loadpart, argv[0], sizeof loadpart);
		if ((p = strstr(loadpart, "partition(8)")) != NULL) {
			p += strlen("partition(");
		} else if (strncmp(loadpart, "dksc(", 5) == 0) {
			p = strstr(loadpart, ",8)");
			if (p != NULL)
				p++;
		} else
			p = NULL;

		if (p != NULL) {
			p[0] = '0';
			p[2] = '\0';
			snprintf(filenamebuf, sizeof filenamebuf,
			    "/bsd.rd.IP%d", IP);
			OSLoadPartition = loadpart;
			OSLoadFilename = filenamebuf;
		}
	    }
		break;
	default:
		break;
	}
}

/*
 * Prevent loading a wrong kernel.
 */
int
check_phdr(void *v)
{
	Elf64_Phdr *phdr = (Elf64_Phdr *)v;
	uint64_t addr;

	switch (IP) {
	case 22:
		addr = 0xffffffff88000000ULL >> 24;
		break;
	case 26:
		addr = 0xa800000008000000ULL >> 24;
		break;
	case 27:
		addr = 0xa800000000000000ULL >> 24;
		break;
	case 28:
	case 30:
		addr = 0xa800000020000000ULL >> 24;
		break;
	case 32:
		addr = 0xffffffff80000000ULL >> 24;
		break;
	default:
		/*
		 * If the system could not be identified, accept any
		 * address and hope the user knows what's he's doing.
		 */
		return 0;
	}

	if ((phdr->p_vaddr >> 24) != addr) {
		/* I'm sorry Dave, I can't let you do that. */
		printf("This kernel does not seem to be compiled for this"
		    " machine type.\nYou need to boot an IP%d kernel.\n", IP);
		return 1;
	}

	return 0;
}

/*
 * Load the saved randomness file.
 */
void
loadrandom(const char *partition, const char *name, void *buf, size_t buflen)
{
	char path[MAXPATHLEN];
	struct stat sb;
	int fd;

	strlcpy(path, partition, sizeof path);
	strlcat(path, name, sizeof path);

	fd = open(path, O_RDONLY);
	if (fd == -1) {
		if (errno != EPERM)
			printf("cannot open %s: %s\n", path, strerror(errno));
		return;
	}
	if (fstat(fd, &sb) == -1 || sb.st_uid != 0 || !S_ISREG(sb.st_mode) ||
	    (sb.st_mode & (S_IWOTH|S_IROTH)))
		goto fail;
	(void) read(fd, buf, buflen);
fail:
	close(fd);
}

license: unknown


code:
/*	$OpenBSD: conf.c,v 1.5 2012/03/19 17:38:31 miod Exp $ */

/*
 * Copyright (c) 1997 Per Fogelstrom
 *
 * 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 AUTHOR ``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 AUTHOR 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 <stand.h>

extern void	nullsys();
extern int	nodev();
extern int	noioctl();

int	diostrategy(void *, int, daddr32_t, size_t, void *, size_t *);
int	dioopen(struct open_file *, ...);
int	dioclose(struct open_file *);
#define	dioioctl	noioctl

int	netstrategy(void *, int, daddr32_t, size_t, void *, size_t *);
int	netopen(struct open_file *, ...);
int	netclose(struct open_file *);
#define	netioctl	noioctl

struct devsw devsw[] = {
	{ "scsi",	diostrategy, dioopen, dioclose,	dioioctl },
	{ "bootp",	netstrategy, netopen, netclose,	netioctl }
};

int	ndevs = (sizeof(devsw)/sizeof(devsw[0]));


code:
/*	$OpenBSD: diskio.c,v 1.9 2014/07/12 21:03:38 tedu Exp $ */

/*
 * Copyright (c) 2000 Opsycon AB  (www.opsycon.se)
 * Copyright (c) 2000 Rtmx, Inc   (www.rtmx.com)
 *
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed for Rtmx, Inc by
 *	Opsycon Open System Consulting AB, Sweden.
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <stand.h>
#include <sys/param.h>
#include <sys/disklabel.h>
#include <mips64/arcbios.h>

struct	dio_softc {
	int	sc_fd;			/* PROM file ID */
	int	sc_part;		/* Disk partition number. */
	struct	disklabel sc_label;	/* Disk label for this disk. */
};

int
diostrategy(void *devdata, int rw, daddr32_t bn, size_t reqcnt, void *addr,
    size_t *cnt)
{
	struct dio_softc *sc = (struct dio_softc *)devdata;
	struct partition *pp = &sc->sc_label.d_partitions[sc->sc_part];
	arc_quad_t offset;
	long result;

	offset.hi = 0;
	offset.lo = (pp->p_offset + bn) * DEV_BSIZE;

	if ((Bios_Seek(sc->sc_fd, &offset, 0) < 0) ||
	    (Bios_Read(sc->sc_fd, addr, reqcnt, &result) < 0))
		return (EIO);

	*cnt = result;
	return (0);
}

int
dioopen(struct open_file *f, ...)
{
	char *ctlr;
	int partition;

	struct dio_softc *sc;
	struct disklabel *lp;
	long fd;
	daddr32_t labelsector;
	va_list ap;

	va_start(ap, f);
	ctlr = va_arg(ap, char *);
	partition = va_arg(ap, int);
	va_end(ap);

	if (partition >= MAXPARTITIONS)
		return (ENXIO);

	if (Bios_Open(ctlr, 0, &fd) < 0)
		return (ENXIO);

	sc = alloc(sizeof(struct dio_softc));
	bzero(sc, sizeof(struct dio_softc));
	f->f_devdata = (void *)sc;

	sc->sc_fd = fd;
	sc->sc_part = partition;

	lp = &sc->sc_label;
	lp->d_secsize = DEV_BSIZE;
	lp->d_secpercyl = 1;
	lp->d_npartitions = MAXPARTITIONS;
	lp->d_partitions[partition].p_offset = 0;
	lp->d_partitions[0].p_size = 0x7fff0000;

	labelsector = LABELSECTOR;

#if 0
	/* Try to read disk label and partition table information. */
	i = diostrategy(sc, F_READ, (daddr32_t)labelsector, DEV_BSIZE, buf, &cnt);

	if (i == 0 && cnt == DEV_BSIZE)
		msg = getdisklabel(buf, lp);
	else
		msg = "rd err";

	if (msg) {
		printf("%s: %s\n", ctlr, msg);
		return (ENXIO);
	}
#endif

	return (0);
}

int
dioclose(struct open_file *f)
{
	Bios_Close(((struct dio_softc *)f->f_devdata)->sc_fd);
	free(f->f_devdata, sizeof(struct dio_softc));
	f->f_devdata = NULL;
	return (0);
}


code:
/*	$NetBSD: filesystem.c,v 1.2 1995/02/16 02:33:05 cgd Exp $	*/

/*
 * Copyright (c) 1993 Philip A. Nelson.
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Philip A. Nelson.
 * 4. The name of Philip A. Nelson may not be used to endorse or promote
 *    products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY PHILIP NELSON ``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 PHILIP NELSON 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.
 *
 *	filesystem.c
 */

#include <stand.h>
#include <ufs.h>
#include "netfs.h"

struct fs_ops file_system[] = {
	{ netfs_open, netfs_close, netfs_read, netfs_write, netfs_seek, netfs_stat },
	{ ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, ufs_stat },
};

int nfsys = sizeof(file_system)/sizeof(struct fs_ops);


code:
/*	$OpenBSD: netfs.c,v 1.1 2012/03/19 17:38:31 miod Exp $	*/

/*-
 * Copyright (c) 2001 Steve Murphree, Jr.
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by TooLs GmbH.
 * 4. The name of TooLs GmbH may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
 */

/*
 *	TFTP file system.
 */

#include <sys/param.h>
#include <lib/libkern/libkern.h>
#include <stand.h>

#include <sys/stat.h>

#include "netfs.h"

/*
 * In-core open file.
 */
struct tftp_file {
	char 		filename[128];
	off_t		f_seekp;	/* seek pointer */
	char		*f_buf;		/* buffer for data block */
	off_t		f_off;		/* index into buffer for data block */
	daddr32_t	f_buf_blkno;	/* block number of data block */
	size_t		f_buf_size;
};

#define TFTP_BLOCK_SHIFT	9
#define TFTP_BLOCK_SIZE		(1<<TFTP_BLOCK_SHIFT) /* 512 by tftp convention */
#define TFTP_BLOCK_NO(x)	((x >> TFTP_BLOCK_SHIFT) + 1)
#define TFTP_BLOCK_OFF(x)	(x % TFTP_BLOCK_SIZE)

static int	tftp_read_file(struct open_file *, char **, size_t *);

/*
 * Read a portion of a file into an internal buffer.  Return
 * the location in the buffer and the amount in the buffer.
 */

char	tftp_buf[TFTP_BLOCK_SIZE];	/* static */
struct	tftp_file tftp_ctrl;

static int
tftp_read_file(f, buf_p, size_p)
	struct open_file *f;
	char **buf_p;		/* out */
	size_t *size_p;		/* out */
{
	struct tftp_file *fp = (struct tftp_file *)f->f_fsdata;
	long off;
	daddr32_t file_block;
	size_t block_size;
	int i, rc;

	off = TFTP_BLOCK_OFF(fp->f_seekp);
	file_block = TFTP_BLOCK_NO(fp->f_seekp);
	block_size = TFTP_BLOCK_SIZE;

	if (file_block == fp->f_buf_blkno + 1) {
		/*
		 * Normal, incremental block transfer.
		 */
		rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
			file_block, block_size, fp->f_buf, &fp->f_buf_size);
		if (rc)
			return (rc);
		if (!(file_block % 4)) /* twiddle every 4 blocks */
			twiddle();
		fp->f_buf_blkno = file_block;
	} else if (file_block > fp->f_buf_blkno + 1) {
		/*
		 * Read ahead to the requested block;  If we need
		 * those we skipped, see below.
		 */
		for (i = (fp->f_buf_blkno + 1); i <= file_block; i++) {
			rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
				i, block_size, fp->f_buf, &fp->f_buf_size);
			if (rc)
				return (rc);
		}
		fp->f_buf_blkno = file_block;
	} else if (file_block < fp->f_buf_blkno) {
		/*
		 * Uh oh...  We can't rewind.  Reopen the file
		 * and start again.
		 */
		char filename[128];

		strlcpy(filename, fp->filename, sizeof filename);
                netfs_close(f);
                netfs_open(filename, f);

		/* restore f_seekp reset by netfs_open() */
		fp->f_seekp = (file_block - 1) * TFTP_BLOCK_SIZE + off;
		for (i = 1; i <= file_block; i++) {
			rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
				i, block_size, fp->f_buf, &fp->f_buf_size);
			if (rc)
				return (rc);
		}
		fp->f_buf_blkno = file_block;
	}

	/*
	 * Return address of byte in buffer corresponding to
	 * offset, and size of remainder of buffer after that
	 * byte.
	 */
	*buf_p = fp->f_buf + off;
	*size_p = fp->f_buf_size - off;

	/*
	 * But truncate buffer at end of file.
	 */
	if (fp->f_buf_size > block_size){
		twiddle();
		return(EIO);
	}

	return (0);
}

/*
 * Open a file.
 */
int
netfs_open(path, f)
	char *path;
	struct open_file *f;
{
	struct tftp_file *fp;
	int rc = 0;
extern int netstrategy(void *, int, daddr32_t, size_t, void *, size_t *);

	if (f->f_dev->dv_strategy != netstrategy)
		return EINVAL;

	/* locate file system specific data structure and zero it.*/
	fp = &tftp_ctrl;
	bzero(fp, sizeof(struct tftp_file));
	f->f_fsdata = (void *)fp;
	fp->f_seekp = 0;
	fp->f_buf = tftp_buf;
	bzero(fp->f_buf, TFTP_BLOCK_SIZE);
	fp->f_buf_size = 0;

        strlcpy(fp->filename, path, sizeof fp->filename);

	twiddle();
        rc = (f->f_dev->dv_open)(f, path);
	return (rc);
}

int
netfs_close(f)
	struct open_file *f;
{
	struct tftp_file *fp = (struct tftp_file *)f->f_fsdata;

	fp->f_buf = (void *)0;
	f->f_fsdata = (void *)0;
        (f->f_dev->dv_close)(f);
	return (0);
}

/*
 * Copy a portion of a file into kernel memory.
 * Cross block boundaries when necessary.
 */
int
netfs_read(f, start, size, resid)
	struct open_file *f;
	void *start;
	size_t size;
	size_t *resid;	/* out */
{
	struct tftp_file *fp = (struct tftp_file *)f->f_fsdata;
	size_t csize;
	char *buf;
	size_t buf_size;
	int rc = 0;
	char *addr = start;

	while (size != 0) {
		rc = tftp_read_file(f, &buf, &buf_size);
		if (rc)
			break;

		csize = size;
		if (csize > buf_size)
			csize = buf_size;

		bcopy(buf, addr, csize);

		fp->f_seekp += csize;
		addr += csize;
		size -= csize;
	}
	if (resid)
		*resid = size;
	return (rc);
}

/*
 * Not implemented.
 */
int
netfs_write(f, start, size, resid)
	struct open_file *f;
	void *start;
	size_t size;
	size_t *resid;	/* out */
{

	return (EROFS);
}

/*
 * We only see forward.  We can't rewind.
 */
off_t
netfs_seek(f, offset, where)
	struct open_file *f;
	off_t offset;
	int where;
{
	struct tftp_file *fp = (struct tftp_file *)f->f_fsdata;

	switch (where) {
	case SEEK_SET:
		fp->f_seekp = offset;
		break;
	case SEEK_CUR:
		fp->f_seekp += offset;
		break;
	case SEEK_END:
		errno = EIO;
		return (-1);
		break;
	default:
		return (-1);
	}
	return (fp->f_seekp);
}

int
netfs_stat(f, sb)
	struct open_file *f;
	struct stat *sb;
{
	return EIO;
}

#ifndef NO_READDIR
int
netfs_readdir (struct open_file *f, char *name)
{
	return EIO;
}
#endif


code:
/*	$OpenBSD: netfs.h,v 1.1 2012/03/19 17:38:31 miod Exp $	*/

/*-
 * Copyright (c) 2001 Steve Murphree, Jr.
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by TooLs GmbH.
 * 4. The name of TooLs GmbH may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
 */

int	netfs_open(char *path, struct open_file *f);
int	netfs_close(struct open_file *f);
int	netfs_read(struct open_file *f, void *buf,
			size_t size, size_t *resid);
int	netfs_write(struct open_file *f, void *buf,
			size_t size, size_t *resid);
off_t	netfs_seek(struct open_file *f, off_t offset, int where);
int	netfs_stat(struct open_file *f, struct stat *sb);
#ifndef NO_READDIR
int	netfs_readdir(struct open_file *f, char *name);
#endif


code:
/*	$OpenBSD: netio.c,v 1.1 2012/03/19 17:38:31 miod Exp $	*/

/*
 * Copyright (c) 2012 Miodrag Vallat.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/param.h>
#include <lib/libkern/libkern.h>
#include <stand.h>

#include <mips64/arcbios.h>

int
netstrategy(void *devdata, int rw, daddr32_t bn, size_t reqcnt, void *addr,
    size_t *cnt)
{
	long fd = (long)devdata;
	long result;
	int rc;

	rc = Bios_Read(fd, addr, reqcnt, &result);
	if (rc != 0)
		return (EIO);

	*cnt = result;
	return 0;
}

int
netopen(struct open_file *f, ...)
{
	char *path;
	long fd;
	int rc;
	va_list ap;

	va_start(ap, f);
	path = va_arg(ap, char *);
	va_end(ap);

	/* to match netfs.c filename buffers... */
	if (strlen(path) > 128 - 1)
		return ENAMETOOLONG;

	rc = Bios_Open(path, 0, &fd);
	if (rc != 0) {
		switch (rc) {
		case arc_EACCES:
			return EACCES;
		case arc_EISDIR:
			return EISDIR;
		case arc_ENOENT:
			return ENOENT;
		default:
			return ENXIO;
		}
	}

	f->f_devdata = (void *)fd;

	return 0;
}

int
netclose(struct open_file *f)
{
	long fd = (long)f->f_devdata;

	(void)Bios_Close(fd);
	return 0;
}


code:
/*	$OpenBSD: start.S,v 1.4 2012/09/29 21:40:48 miod Exp $ */

/*
 * Copyright (c) 2001 Opsycon AB (www.opsycon.se)
 *
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed under OpenBSD by
 *	Opsycon AB, Sweden (www.opsycon.com).
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 *
 */

#define ABICALLS

#include <machine/regdef.h>
#include <machine/asm.h>

/*
 * Frame required for the debugger (if we have any).
 */
#define START_FRAME	((4 * 4) + 4 + 4)

	.globl	__start
__start:
#ifndef __LP64__	/* LP64 code is compiled without gp support */
	LA	gp, _gp
#endif

	jal	boot_main

1:
	b	1b


code:
/*-
 * Copyright (c) 1990 The Regents of the University of California.
 * All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Chris Torek.
 *
 * 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.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * 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 <lib/libkern/libkern.h>

/*
 * Find the first occurrence of find in s.
 */
char *
strstr(char *s, const char *find)
{
        char c, sc;
        size_t len;

        if ((c = *find++) != 0) {
                len = strlen(find);
                do {
                        do {
                                if ((sc = *s++) == 0)
                                        return (NULL);
                        } while (sc != c);
                } while (strncmp(s, find, len) != 0);
                s--;
        }
        return s;
}


code:
/*	$OpenBSD: version,v 1.6 2014/02/22 20:27:21 miod Exp $	*/
/* Public domain. Come on, it can hardly be considered as code. */

#if 0

No version strings up to 2012
	many changes, but nothing to tell bootblocks about, except perhaps
	their size (har, har)

1.1
	smarter argv[] analysis: the first argument which does neither look
	like an environment variable nor dash-prefixed options, is assumed
	to be a file path. If there are no signs of it being a full ARC
	path, OSLoadPartition is prepended to it.
	The old behaviour was to only accept filenames starting with "/", and
	thus always relative to OSLoadPartition.

1.2
	IP28 support. Also, no longer refuse to run on IP26 systems, they
	will hopefully run at some point in the future.

1.3
	IP26 support, for real.

1.4
	Unbreak IP27 support, broken by accident in 1.3

1.5
	Loadfile support for .openbsd.randomdata section

1.6
	/etc/random.seed support

#endif

static const char version[] = "1.6";

path: sys/arch/sgi/stand/boot/version


code:
#	$OpenBSD: Makefile,v 1.2 2011/07/09 10:44:09 miod Exp $

.include "${.CURDIR}/../Makefile32.inc"
LDSCRIPT=	${.CURDIR}/ld.script
LDFLAGS+=	${SALDFLAGS} -T ${LDSCRIPT} -e __start -s
PROG=		boot32
.PATH:	${.CURDIR}/../boot
.include "${.CURDIR}/../boot/Makefile"

SRCS+=	ashrdi3.c moddi3.c udivdi3.c umoddi3.c qdivrem.c

${PROG}: $(OBJS) $(LDADD)
	$(LD) $(LDFLAGS) -o ${PROG} $(OBJS) -L${LIBSADIR} ${LIBSA} \
	    -L${LIBZDIR} ${LIBZ}

LINKS=		${BINDIR}/${PROG} ${BINDIR}/boot-IP32

.include <bsd.prog.mk>


code:
OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips",
	      "elf32-tradlittlemips")
OUTPUT_ARCH(mips)
ENTRY(_start)
SECTIONS
{
  /* Read-only sections, merged into text segment: */
  . = 0x80010000 + SIZEOF_HEADERS;
  .text      :
  {
    _ftext = . ;
    *(.text)
    *(.rodata)
    *(.rodata1)
    *(.rodata.str1.4)
    *(.reginfo)
    *(.init)
    *(.stub)
    /* .gnu.warning sections are handled specially by elf32.em.  */
    *(.gnu.warning)
  } =0
  _etext = .;
  PROVIDE (etext = .);
  .fini      : { *(.fini)    } =0
  .data    :
  {
    _fdata = . ;
    *(.data)
    CONSTRUCTORS
  }
  .data1   : { *(.data1) }
  .ctors         : { *(.ctors)   }
  .dtors         : { *(.dtors)   }
  _gp = ALIGN(16) + 0x7ff0;
  .got           :
  {
    *(.got.plt) *(.got)
   }
  /* We want the small data sections together, so single-instruction offsets
     can access them all, and initialized data all before uninitialized, so
     we can shorten the on-disk segment size.  */
  .sdata     : { *(.sdata) }
  .lit8 : { *(.lit8) }
  .lit4 : { *(.lit4) }
  _edata  =  .;
  PROVIDE (edata = .);
  __bss_start = .;
  _fbss = .;
  .sbss      : { *(.sbss) *(.scommon) }
  .bss       :
  {
   *(.dynbss)
   *(.bss)
   *(COMMON)
  }
  _end = . ;
  PROVIDE (end = .);
  /* These are needed for ELF backends which have not yet been
     converted to the new style linker.  */
  .stab 0 : { *(.stab) }
  .stabstr 0 : { *(.stabstr) }
  /* DWARF debug sections.
     Symbols in the .debug DWARF section are relative to the beginning of the
     section so we begin .debug at 0.  It's not clear yet what needs to happen
     for the others.   */
  .debug          0 : { *(.debug) }
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  .line           0 : { *(.line) }
  /* These must appear regardless of  .  */
  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
}


code:
/Makefile/1.3/Sun Dec  8 14:42:21 2013//TOPENBSD_5_8_BASE
D


code:
#	$OpenBSD: Makefile,v 1.3 2013/12/08 14:42:21 miod Exp $

LDFLAGS+=	${SALDFLAGS} --oformat=elf64-tradbigmips -e __start
STRIP=		strip
INSTALL_STRIP=

PROG=		boot64
.PATH:	${.CURDIR}/../boot
.include "${.CURDIR}/../boot/Makefile"

${PROG}: $(OBJS) $(LDADD)
	@# Link first as self-contained binary to enforce there are no
	@# unresolved symbols
	$(LD) $(LDFLAGS) -o ${PROG} $(OBJS) -L${LIBSADIR} ${LIBSA} \
	    -L${LIBZDIR} ${LIBZ}
	@# then link as a relocatable binary
	$(LD) $(LDFLAGS) -r -o ${PROG} $(OBJS) -L${LIBSADIR} ${LIBSA} \
	    -L${LIBZDIR} ${LIBZ}
	$(STRIP) --strip-unneeded ${PROG}

LINKS=		${BINDIR}/${PROG} ${BINDIR}/boot-IP27
LINKS+=		${BINDIR}/${PROG} ${BINDIR}/boot-IP28
LINKS+=		${BINDIR}/${PROG} ${BINDIR}/boot-IP30

.include <bsd.prog.mk>


path: sys/arch/sgi/stand/bootecoff/CVS/Tag


code:
#	$OpenBSD: Makefile,v 1.1 2012/03/19 17:38:31 miod Exp $

.include "${.CURDIR}/../Makefile32.inc"
STRIP?=		strip
LDSCRIPT=	${.CURDIR}/ld.script
LDFLAGS+=	${SALDFLAGS} -T ${LDSCRIPT} -e __start -N -s
PROG=		bootecoff
.PATH:	${.CURDIR}/../boot
.include "${.CURDIR}/../boot/Makefile"

SRCS+=	ashrdi3.c moddi3.c udivdi3.c umoddi3.c qdivrem.c

${PROG}: $(OBJS) $(LDADD)
	$(LD) $(LDFLAGS) -o ${PROG} $(OBJS) -L${LIBSADIR} ${LIBSA} \
	    -L${LIBZDIR} ${LIBZ}

LINKS=		${BINDIR}/${PROG} ${BINDIR}/boot-IP22

.include <bsd.prog.mk>

path: sys/arch/sgi/stand/bootecoff/Makefile


code:
OUTPUT_FORMAT("ecoff-bigmips", "ecoff-bigmips",
	      "ecoff-littlemips")
OUTPUT_ARCH(mips)
ENTRY(_start)
SECTIONS
{
  /* Read-only sections, merged into text segment: */
  . = 0x88002000 + SIZEOF_HEADERS;
  .text      :
  {
    _ftext = . ;
    *(.text)
    *(.rodata)
    *(.rodata1)
    *(.rodata.str1.4)
    *(.reginfo)
    *(.init)
    *(.stub)
    /* .gnu.warning sections are handled specially by elf32.em.  */
    *(.gnu.warning)
  } =0
  _etext = .;
  PROVIDE (etext = .);
  .fini      : { *(.fini)    } =0
  .data    :
  {
    _fdata = . ;
    *(.data)
    CONSTRUCTORS
  }
  .data1   : { *(.data1) }
  .ctors         : { *(.ctors)   }
  .dtors         : { *(.dtors)   }
  _gp = ALIGN(16) + 0x7ff0;
  .got           :
  {
    *(.got.plt) *(.got)
   }
  /* We want the small data sections together, so single-instruction offsets
     can access them all, and initialized data all before uninitialized, so
     we can shorten the on-disk segment size.  */
  .sdata     : { *(.sdata) }
  .lit8 : { *(.lit8) }
  .lit4 : { *(.lit4) }
  _edata  =  .;
  PROVIDE (edata = .);
  __bss_start = .;
  _fbss = .;
  .sbss      : { *(.sbss) *(.scommon) }
  .bss       :
  {
   *(.dynbss)
   *(.bss)
   *(COMMON)
  }
  _end = . ;
  PROVIDE (end = .);
  /DISCARD/ : {
    *(.pdr)
    *(.mdebug.abi32)
    *(.comment)
    *(.stab)
    *(.stabstr)
    *(.debug)
    *(.debug_srcinfo)
    *(.debug_aranges)
    *(.debug_pubnames)
    *(.debug_sfnames)
    *(.line)
  }
}


path: sys/arch/sgi/stand/libsa/CVS/Entries


code: src/sys/arch/sgi/stand/libsa

path: sys/arch/sgi/stand/libsa/CVS/Repository


code:
#	$OpenBSD: Makefile,v 1.8 2013/01/01 18:49:33 miod Exp $

LIB=	sa

.PATH:	${.CURDIR}/../../../../lib/libsa

CLEANFILES += machine mips64

CFLAGS+= ${CEXTRAFLAGS} ${SAABI} -nostdinc -mno-abicalls -D_NO_ABICALLS \
	-fno-pie \
	-I${.CURDIR} -I${.CURDIR}/../include -I${.CURDIR}/../.. \
	-I${.CURDIR}/../../.. -I${.CURDIR}/../../../.. \
	-I${.CURDIR}/../../../../lib/libsa \
	-I${.OBJDIR}

CPPFLAGS+= -D__INTERNAL_LIBSA_CREAD ${STANDALONE}
CPPFLAGS+= ${LIBSA_CPPFLAGS}

# stand routines
SRCS=	alloc.c exit.c getfile.c gets.c globals.c \
	memcmp.c memcpy.c memset.c printf.c snprintf.c strerror.c strncpy.c

# io routines
SRCS+=	close.c closeall.c dev.c disklabel.c dkcksum.c fstat.c ioctl.c lseek.c \
	open.c read.c stat.c write.c cread.c

# boot filesystems
SRCS+=	ufs.c nfs.c cd9660.c

${OBJS}:	${.CURDIR}/../Makefile.inc

NOPROFILE=
NOPIC=

.if !make(libdep) && !make(sadep) && !make(salibdir) && !make(obj)
.BEGIN:
	@([ -h machine ] || ln -s ${.CURDIR}/../../include machine)
	@([ -h mips64 ] || ln -s ${.CURDIR}/../../../mips64/include mips64)
.endif

install:

.include <bsd.lib.mk>

path: sys/arch/sgi/stand/libsa/Makefile


code:
/*	$OpenBSD: heap.h,v 1.1 2009/05/14 18:57:43 miod Exp $	*/
/* public domain */

/*
 * Declarations for the libsa heap allocator.
 *
 * Relocatable 64 bit bootblocks use memory below the load address and
 * can not use the `end' symbol.
 */

#ifdef __LP64__
#define	NEEDS_HEAP_INIT

#define	HEAP_LIMIT	heap_limit
#define	HEAP_SIZE	(1UL << 20)	/* 1MB */
#define	HEAP_START	heap_start

static unsigned long heap_start;
static unsigned long heap_limit;
static char *top;			/* no longer declared in alloc.c */

static inline void heap_init(void);
static inline void
heap_init()
{
	extern char __start[];

	if (top == NULL) {
		heap_limit = (unsigned long)&__start;
		heap_start = heap_limit - HEAP_SIZE;
		top = (char *)heap_start;
	}
}

#endif


code:
/Makefile/1.1/Thu May 14 18:57:43 2009//TOPENBSD_5_8_BASE
D


code:
#	$OpenBSD: Makefile,v 1.1 2009/05/14 18:57:43 miod Exp $

.include "${.CURDIR}/../Makefile32.inc"
.include "${.CURDIR}/../libsa/Makefile"


code:
/Makefile/1.5/Fri Aug 31 08:14:08 2012//TOPENBSD_5_8_BASE
D

path: sys/arch/sgi/stand/libz/CVS/Entries


code: src/sys/arch/sgi/stand/libz

path: sys/arch/sgi/stand/libz/CVS/Repository


code:
#	$OpenBSD: Makefile,v 1.5 2012/08/31 08:14:08 pascal Exp $

S=${.CURDIR}/../../../..
ZDST=${.OBJDIR}

.PATH: ${S}/lib/libz

.include "${S}/lib/libz/Makefile"
CFLAGS+= ${CEXTRAFLAGS} ${SAABI} -mno-abicalls -D_NO_ABICALLS \
	${AFLAGS} -fno-pie -I${S}

path: sys/arch/sgi/stand/libz/Makefile


code:
#	$OpenBSD: Makefile,v 1.1 2009/05/14 18:57:43 miod Exp $

.include "${.CURDIR}/../Makefile32.inc"
.include "${.CURDIR}/../libz/Makefile"


path: sys/arch/sgi/stand/sgivol/CVS/Entries


path: sys/arch/sgi/stand/sgivol/CVS/Tag


code:
#	$OpenBSD: Makefile,v 1.3 2005/04/27 18:02:16 deraadt Exp $
#	$NetBSD: Makefile,v 1.5 2002/12/13 02:36:37 lukem Exp $

MAN=	sgivol.8
MANSUBDIR=sgi

.if ${MACHINE} == "sgi"
PROG=	sgivol
LDADD+=	-lutil
LDSTATIC=-static

.else
NOPROG=
.endif

.include <bsd.prog.mk>

path: sys/arch/sgi/stand/sgivol/Makefile


code:
/*	$OpenBSD: sgivol.c,v 1.23 2014/07/12 19:01:49 tedu Exp $	*/
/*	$NetBSD: sgivol.c,v 1.8 2003/11/08 04:59:00 sekiya Exp $	*/

/*-
 * Copyright (c) 2001 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Michael Hitch and Hubert Feyrer.
 *
 * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 <unistd.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <util.h>

#include <sys/disklabel.h>
#include <sys/endian.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/dkio.h>

/*
 * Some IRIX man pages refer to the size being a multiple of whole cylinders.
 * Later ones only refer to the size being "typically" 2MB.  IRIX fx(1)
 * uses a default drive geometry if one can't be determined, suggesting
 * that "whole cylinder" multiples are not required.
 */

#define SGI_SIZE_VOLHDR	3135	/* Can be overridden via -h parameter. */

/*
 * Mode of operation can be one of:
 * -i	Initialise volume header.
 * -r	Read a file from volume header.
 * -w	Write a file to volume header.
 * -l	Link a file into the volume header.
 * -d	Delete a file from the volume header.
 * -p	Modify a partition.
 */

char	mode;
int	quiet;
int	fd;
int	partno, partfirst, partblocks, parttype;
struct	sgilabel *volhdr;
int32_t	checksum;

/* Volume header size in sectors. */
u_int32_t volhdr_size = SGI_SIZE_VOLHDR;

const char *vfilename = "";
const char *ufilename = "";

struct disklabel lbl;

unsigned char *buf;
unsigned int bufsize;

const char *sgi_types[] = {
	"Volume Header",
	"Repl Trks",
	"Repl Secs",
	"Raw",
	"BSD4.2",
	"SysV",
	"Volume",
	"EFS",
	"LVol",
	"RLVol",
	"XFS",
	"XSFLog",
	"XLV",
	"XVM"
};

void	display_vol(void);
void	init_volhdr(void);
void	read_file(void);
void	write_file(void);
void	link_file(void);
void	delete_file(void);
void	modify_partition(void);
void	write_volhdr(void);
int	allocate_space(int);
void	checksum_vol(void);
void	usage(void);

int
main(int argc, char *argv[])
{
	int ch, oflags;
	char fname[FILENAME_MAX];
	char *endp;

	quiet = 0;
	mode = ' ';

	while ((ch = getopt(argc, argv, "irwlpdqfh:")) != -1) {
		switch (ch) {
		case 'q':
			quiet = 1;
			break;
		case 'f':
			/* Legacy. Do nothing. */
			break;
		case 'i':
			mode = 'i';
			break;
		case 'h':
			volhdr_size = strtol(optarg, &endp, 0);
			if (*endp != '\0' || errno != 0)
				errx(1, "incorrect volume header size: %s",
				    optarg);
			break;
		case 'r':
			mode = 'r';
			break;
		case 'w':
			mode = 'w';
			break;
		case 'l':
			mode = 'l';
			break;
		case 'd':
			mode = 'd';
			break;
		case 'p':
			mode = 'p';
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	if (mode == 'r' || mode == 'w' || mode == 'l') {
		if (argc != 3)
			usage();
		vfilename = argv[0];
		ufilename = argv[1];
		argc -= 2;
		argv += 2;
	} else if (mode == 'd') {
		if (argc != 2)
			usage();
		vfilename = argv[0];
		argc--;
		argv++;
	} else if (mode == 'p') {
		if (argc != 5)
			usage();
		partno = strtol(argv[0], &endp, 0);
		if (*endp != '\0' || errno != 0 ||
		    partno < 0 || partno > SGI_SIZE_VOLDIR)
			errx(1, "invalid partition number: %s", argv[0]);
		partfirst = strtol(argv[1], &endp, 0);
		if (*endp != '\0' || errno != 0)
			errx(1, "invalid partition start: %s", argv[1]);
		partblocks = strtol(argv[2], &endp, 0);
		if (*endp != '\0' || errno != 0)
			errx(1, "invalid partition size: %s", argv[2]);
		parttype = strtol(argv[3], &endp, 0);
		if (*endp != '\0' || errno != 0)
			errx(1, "invalid partition type: %s", argv[3]);
		argc -= 4;
		argv += 4;
	}
	if (argc != 1)
		usage();

	oflags = ((mode == 'i' || mode == 'w' || mode == 'l' || mode == 'd'
	    || mode == 'p') ? O_RDWR : O_RDONLY);

	/* Open raw device. */
	if ((fd = open(argv[0], oflags)) < 0) {
		snprintf(fname, sizeof(fname), "/dev/r%s%c",
		    argv[0], 'a' + getrawpartition());
		if ((fd = open(fname, oflags)) < 0)
			err(1, "open %s", fname);
	}

	/* Get disklabel for device. */
	if (ioctl(fd, DIOCGDINFO, &lbl) == -1)
		err(1, "ioctl DIOCGDINFO");

	/* Allocate a buffer that matches the device sector size. */
	bufsize = lbl.d_secsize;
	if (bufsize < sizeof(struct sgilabel))
		errx(1, "sector size is smaller than SGI volume header!\n");
	if ((buf = malloc(bufsize)) == NULL)
		err(1, "failed to allocate buffer");

	/* Read SGI volume header. */
	if (read(fd, buf, bufsize) != bufsize)
		err(1, "read volhdr");
	volhdr = (struct sgilabel *)buf;

	if (mode == 'i') {
		init_volhdr();
		exit(0);
	}

	if (betoh32(volhdr->magic) != SGILABEL_MAGIC)
		errx(2, "no Volume Header found, magic=%x.  Use -i first.",
		    betoh32(volhdr->magic));

	if (mode == 'r')
		read_file();
	else if (mode == 'w')
		write_file();
	else if (mode == 'l')
		link_file();
	else if (mode == 'd')
		delete_file();
	else if (mode == 'p')
		modify_partition();
	else if (!quiet)
		display_vol();

	exit (0);
}

void
display_vol(void)
{
	int32_t *l;
	int i;

	l = (int32_t *)buf;
	checksum = 0;
	for (i = 0; i < sizeof(struct sgilabel) / sizeof(int32_t); ++i)
		checksum += betoh32(l[i]);

	printf("disklabel shows %llu sectors with %u bytes per sector\n",
	    DL_GETDSIZE(&lbl), lbl.d_secsize);
	printf("checksum: %08x%s\n", checksum, checksum == 0 ? "" : " *ERROR*");
	printf("root part: %d\n", betoh32(volhdr->root));
	printf("swap part: %d\n", betoh32(volhdr->swap));
	printf("bootfile: %s\n", volhdr->bootfile);

	/* volhdr->devparams[0..47] */
	printf("\nVolume header files:\n");
	for (i = 0; i < SGI_SIZE_VOLDIR; ++i) {
		if (volhdr->voldir[i].name[0] != '\0') {
			printf("%-8s offset %4d blocks, "
			    "length %8d bytes (%d blocks)\n",
			    volhdr->voldir[i].name,
			    betoh32(volhdr->voldir[i].block),
			    betoh32(volhdr->voldir[i].bytes),
			    howmany(betoh32(volhdr->voldir[i].bytes),
			    DEV_BSIZE));
		}
	}

	printf("\nSGI partitions:\n");
	for (i = 0; i < MAXPARTITIONS; ++i) {
		if (betoh32(volhdr->partitions[i].blocks) != 0) {
			printf("%2d:%c blocks %8d first %8d type %2d (%s)\n",
			    i, i + 'a', betoh32(volhdr->partitions[i].blocks),
			    betoh32(volhdr->partitions[i].first),
			    betoh32(volhdr->partitions[i].type),
			    betoh32(volhdr->partitions[i].type) >
			    (sizeof(sgi_types) / sizeof(sgi_types[0])) ?
			    "???" :
			    sgi_types[betoh32(volhdr->partitions[i].type)]);
		}
	}
}

void
init_volhdr(void)
{
	memset(volhdr, 0, sizeof(struct sgilabel));
	volhdr->magic = htobe32(SGILABEL_MAGIC);
	volhdr->root = htobe16(0);
	volhdr->swap = htobe16(1);
	strlcpy(volhdr->bootfile, "/bsd", sizeof(volhdr->bootfile));
	volhdr->dp.dp_skew = 1; /* XXX */
	volhdr->dp.dp_gap1 = 1; /* XXX */
	volhdr->dp.dp_gap2 = 1; /* XXX */
	volhdr->dp.dp_cyls = htobe16(lbl.d_ncylinders);
	volhdr->dp.dp_shd0 = 0;
	volhdr->dp.dp_trks0 = htobe16(lbl.d_ntracks);
	volhdr->dp.dp_secs = htobe16(lbl.d_nsectors);
	volhdr->dp.dp_secbytes = htobe16(lbl.d_secsize);
	volhdr->dp.dp_interleave = 1;
	volhdr->dp.dp_nretries = htobe32(22);
	volhdr->partitions[10].blocks =
	    htobe32(DL_SECTOBLK(&lbl, DL_GETDSIZE(&lbl)));
	volhdr->partitions[10].first = 0;
	volhdr->partitions[10].type = htobe32(SGI_PTYPE_VOLUME);
	volhdr->partitions[8].blocks = htobe32(DL_SECTOBLK(&lbl, volhdr_size));
	volhdr->partitions[8].first = 0;
	volhdr->partitions[8].type = htobe32(SGI_PTYPE_VOLHDR);
	volhdr->partitions[0].blocks =
	    htobe32(DL_SECTOBLK(&lbl, DL_GETDSIZE(&lbl) - volhdr_size));
	volhdr->partitions[0].first = htobe32(DL_SECTOBLK(&lbl, volhdr_size));
	volhdr->partitions[0].type = htobe32(SGI_PTYPE_BSD);
	write_volhdr();
}

void
read_file(void)
{
	FILE *fp;
	int i;

	if (!quiet)
		printf("Reading file %s\n", vfilename);
	for (i = 0; i < SGI_SIZE_VOLDIR; ++i) {
		if (strncmp(vfilename, volhdr->voldir[i].name,
		    strlen(volhdr->voldir[i].name)) == 0)
			break;
	}
	if (i >= SGI_SIZE_VOLDIR)
		errx(1, "%s: file not found", vfilename);
	/* XXX assumes volume header starts at 0? */
	lseek(fd, betoh32(volhdr->voldir[i].block) * DEV_BSIZE, SEEK_SET);
	if ((fp = fopen(ufilename, "w")) == NULL)
		err(1, "open %s", ufilename);
	i = betoh32(volhdr->voldir[i].bytes);
	while (i > 0) {
		if (read(fd, buf, bufsize) != bufsize)
			err(1, "read file");
		fwrite(buf, 1, i > bufsize ? bufsize : i, fp);
		i -= i > bufsize ? bufsize : i;
	}
	fclose(fp);
}

void
write_file(void)
{
	FILE *fp;
	int slot;
	int block, i, fsize, fbufsize;
	struct stat st;
	char *fbuf;

	if (!quiet)
		printf("Writing file %s\n", ufilename);

	if (stat(ufilename, &st) != 0)
		err(1, "stat %s", ufilename);
	if (st.st_size == 0)
		errx(1, "%s: file is empty", vfilename);

	if (!quiet)
		printf("File %s has %lld bytes\n", ufilename, st.st_size);
	slot = -1;
	for (i = 0; i < SGI_SIZE_VOLDIR; ++i) {
		if (volhdr->voldir[i].name[0] == '\0' && slot < 0)
			slot = i;
		if (strcmp(vfilename, volhdr->voldir[i].name) == 0) {
			slot = i;
			break;
		}
	}
	if (slot == -1)
		errx(1, "no more directory entries available");
	if (betoh32(volhdr->voldir[slot].block) > 0) {
		if (!quiet)
			printf("File %s exists, removing old file\n",
			    vfilename);
		volhdr->voldir[slot].name[0] = 0;
		volhdr->voldir[slot].block = volhdr->voldir[slot].bytes = 0;
	}
	/* XXX assumes volume header starts at 0? */
	block = allocate_space((int)st.st_size);
	if (block < 0)
		errx(1, "no more space available");

	/*
	 * Make sure the name in the volume header is max. 8 chars,
	 * NOT including NUL.
	 */
	if (strlen(vfilename) > sizeof(volhdr->voldir[slot].name))
		warnx("%s: filename is too long and will be truncated",
		    vfilename);
	strncpy(volhdr->voldir[slot].name, vfilename,
	    sizeof(volhdr->voldir[slot].name));

	volhdr->voldir[slot].block = htobe32(block);
	volhdr->voldir[slot].bytes = htobe32(st.st_size);

	write_volhdr();

	/* Write the file itself. */
	if (lseek(fd, block * DEV_BSIZE, SEEK_SET) == -1)
		err(1, "lseek write");
	fbufsize = volhdr->dp.dp_secbytes;
	if ((fbuf = malloc(fbufsize)) == NULL)
		err(1, "failed to allocate buffer");
	i = st.st_size;
	fp = fopen(ufilename, "r");
	while (i > 0) {
		bzero(fbuf, fbufsize);
		fsize = i > fbufsize ? fbufsize : i;
		if (fread(fbuf, 1, fsize, fp) != fsize)
			err(1, "reading file from disk");
		if (write(fd, fbuf, fbufsize) != fbufsize)
			err(1, "writing file to SGI volume header");
		i -= fsize;
	}
	fclose(fp);
	free(fbuf);
}

void
link_file(void)
{
	int slot, i;
	int32_t block, bytes;

	if (!quiet)
		printf("Linking file %s to %s\n", vfilename, ufilename);
	for (i = 0; i < SGI_SIZE_VOLDIR; ++i) {
		if (strncmp(vfilename, volhdr->voldir[i].name,
		    strlen(volhdr->voldir[i].name)) == 0)
			break;
	}
	if (i >= SGI_SIZE_VOLDIR)
		errx(1, "%s: file not found", vfilename);

	block = volhdr->voldir[i].block;
	bytes = volhdr->voldir[i].bytes;

	slot = -1;
	for (i = 0; i < SGI_SIZE_VOLDIR; ++i) {
		if (volhdr->voldir[i].name[0] == '\0' && slot < 0)
			slot = i;
		if (strcmp(ufilename, volhdr->voldir[i].name) == 0) {
			slot = i;
			break;
		}
	}
	if (slot == -1)
		errx(1, "no more directory entries available");

	/*
	 * Make sure the name in the volume header is max. 8 chars,
	 * NOT including NUL.
	 */
	if (strlen(ufilename) > sizeof(volhdr->voldir[slot].name))
		warnx("%s: filename is too long and will be truncated",
		    ufilename);
	strncpy(volhdr->voldir[slot].name, ufilename,
	    sizeof(volhdr->voldir[slot].name));

	volhdr->voldir[slot].block = block;
	volhdr->voldir[slot].bytes = bytes;
	write_volhdr();
}

void
delete_file(void)
{
	int i;

	for (i = 0; i < SGI_SIZE_VOLDIR; ++i) {
		if (strcmp(vfilename, volhdr->voldir[i].name) == 0) {
			break;
		}
	}
	if (i >= SGI_SIZE_VOLDIR)
		errx(1, "%s: file not found", vfilename);

	/* XXX: we don't compact the file space, so get fragmentation */
	volhdr->voldir[i].name[0] = '\0';
	volhdr->voldir[i].block = volhdr->voldir[i].bytes = 0;
	write_volhdr();
}

void
modify_partition(void)
{
	if (!quiet)
		printf("Modify partition %d start %d length %d\n",
		    partno, partfirst, partblocks);
	volhdr->partitions[partno].blocks = htobe32(partblocks);
	volhdr->partitions[partno].first = htobe32(partfirst);
	volhdr->partitions[partno].type = htobe32(parttype);
	write_volhdr();
}

void
write_volhdr(void)
{
	checksum_vol();

	if (!quiet)
		display_vol();
	if (lseek(fd, 0, SEEK_SET) == -1)
		err(1, "lseek 0");
	if (write(fd, buf, bufsize) != bufsize)
		err(1, "write volhdr");
}

int
allocate_space(int size)
{
	int n, blocks;
	int first;

	blocks = howmany(size, DEV_BSIZE);
	first = roundup(2 * DEV_BSIZE, volhdr->dp.dp_secbytes) / DEV_BSIZE;

	for (n = 0; n < SGI_SIZE_VOLDIR;) {
		if (volhdr->voldir[n].name[0]) {
			if (first < (betoh32(volhdr->voldir[n].block) +
			    howmany(betoh32(volhdr->voldir[n].bytes),
			        DEV_BSIZE)) &&
			    (first + blocks) >
			        betoh32(volhdr->voldir[n].block)) {

				first = roundup(
				    betoh32(volhdr->voldir[n].block) +
				    howmany(betoh32(volhdr->voldir[n].bytes),
				        DEV_BSIZE),
				    volhdr->dp.dp_secbytes / DEV_BSIZE);
#if DEBUG
				printf("allocate: "
				    "n=%d first=%d blocks=%d size=%d\n",
				    n, first, blocks, size);
				printf("%s %d %d\n", volhdr->voldir[n].name,
				    volhdr->voldir[n].block,
				    volhdr->voldir[n].bytes);
				printf("first=%d block=%d last=%d end=%d\n",
				    first, volhdr->voldir[n].block,
				    first + blocks - 1,
				    volhdr->voldir[n].block +
				    howmany(volhdr->voldir[n].bytes,
				        DEV_BSIZE));
#endif
				n = 0;
				continue;
			}
		}
		++n;
	}
	if (first + blocks > DL_GETDSIZE(&lbl))
		first = -1;
	/* XXX assumes volume header is partition 8 */
	/* XXX assumes volume header starts at 0? */
	if (first + blocks >= betoh32(volhdr->partitions[8].blocks))
		first = -1;
	return (first);
}

void
checksum_vol(void)
{
	int32_t *l;
	int i;

	volhdr->checksum = checksum = 0;
	l = (int32_t *)buf;
	for (i = 0; i < sizeof(struct sgilabel) / sizeof(int32_t); ++i)
		checksum += betoh32(l[i]);
	volhdr->checksum = htobe32(-checksum);
}

void
usage(void)
{
	extern char *__progname;

	fprintf(stderr,
	    "usage: %s [-q] disk\n"
	    "       %s [-q] -d vhfilename disk\n"
	    "       %s [-q] -i [-h vhsize] disk\n"
	    "       %s [-q] -l vhfilename1 vhfilename2 disk\n"
	    "       %s [-q] -r vhfilename diskfilename disk\n"
	    "       %s [-q] -w vhfilename diskfilename disk\n",
	    __progname, __progname, __progname, __progname, __progname,
	    __progname);

	exit(1);
}


code: src/sys/arch/sgi/xbow

path: sys/arch/sgi/xbow/CVS/Repository


code:
#	$OpenBSD: Makefile,v 1.1 2008/04/07 22:47:40 miod Exp $

AWK=	awk

xbowdevs.h xbowdevs_data.h: xbowdevs devlist2h.awk
	/bin/rm -f xbowdevs.h xbowdevs_data.h
	${AWK} -f devlist2h.awk xbowdevs

path: sys/arch/sgi/xbow/Makefile


code:
#! /usr/bin/awk -f
#	$OpenBSD: devlist2h.awk,v 1.2 2008/07/28 18:50:59 miod Exp $
#	$NetBSD: devlist2h.awk,v 1.2 1996/01/22 21:08:09 cgd Exp $
#
# Copyright (c) 1995, 1996 Christopher G. Demetriou
# 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.
# 3. All advertising materials mentioning features or use of this software
#    must display the following acknowledgement:
#      This product includes software developed by Christopher G. Demetriou.
# 4. The name of the author may not be used to endorse or promote products
#    derived from this software without specific prior written permission
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
#
BEGIN {
	nproducts = nvendor_dup = nvendors = 0
	dfile="xbowdevs_data.h"
	hfile="xbowdevs.h"
}
NR == 1 {
	VERSION = $0
	gsub("\\$", "", VERSION)

	printf("/*\n") > dfile
	printf(" * THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.\n") \
	    > dfile
	printf(" *\n") > dfile
	printf(" * generated from:\n") > dfile
	printf(" *\t%s\n", VERSION) > dfile
	printf(" */\n\n") > dfile

	printf("/*\n") > hfile
	printf(" * THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.\n") \
	    > hfile
	printf(" *\n") > hfile
	printf(" * generated from:\n") > hfile
	printf(" *\t%s\n", VERSION) > hfile
	printf(" */\n") > hfile

	next
}
$1 == "vendor" {
	nvendors++

	if ($2 in vendorindex) {
		printf("duplicate vendor name %s\n", $2);
		nvendor_dup++;
	}

	vendorindex[$2] = nvendors;		# record index for this name, for later.
	vendors[nvendors, 1] = $2;		# name
	vendors[nvendors, 2] = $3;		# id
	printf("#define\tXBOW_VENDOR_%s\t%s\n", vendors[nvendors, 1],
	    vendors[nvendors, 2]) > hfile

	next
}
$1 == "product" {
	nproducts++

	products[nproducts, 1] = $2;		# vendor name
	products[nproducts, 2] = $3;		# product id
	products[nproducts, 3] = $4;		# id
	printf("#define\tXBOW_PRODUCT_%s_%s\t%s\t", products[nproducts, 1],
	    products[nproducts, 2], products[nproducts, 3]) > hfile

	i=4; f = 5;

	# comments
	ocomment = oparen = 0
	if (f <= NF) {
		printf("\t/* ") > hfile
		ocomment = 1;
	}
	while (f <= NF) {
		if ($f == "#") {
			printf("(") > hfile
			oparen = 1
			f++
			continue
		}
		if (oparen) {
			printf("%s", $f) > hfile
			if (f < NF)
				printf(" ") > hfile
			f++
			continue
		}
		products[nproducts, i] = $f
		printf("%s", products[nproducts, i]) > hfile
		if (f < NF)
			printf(" ") > hfile
		i++; f++;
	}
	if (oparen)
		printf(")") > hfile
	if (ocomment)
		printf(" */") > hfile
	printf("\n") > hfile

	next
}
{
	if ($0 == "")
		blanklines++
	print $0 > hfile
	if (blanklines < 2)
		print $0 > dfile
}
END {
	# print out the match tables

	printf("\n") > dfile

	if (nvendor_dup > 0)
		exit(1);

	printf("/* Descriptions of known devices. */\n") > dfile

	printf("struct xbow_product {\n") > dfile
	printf("\tuint32_t vendor;\n") > dfile
	printf("\tuint32_t product;\n") > dfile
	printf("\tconst char *productname;\n") > dfile
	printf("};\n\n") > dfile

	printf("static const struct xbow_product xbow_products[] = {\n") \
	    > dfile
	for (i = 1; i <= nproducts; i++) {
		printf("\t{\n") > dfile
		printf("\t    XBOW_VENDOR_%s, XBOW_PRODUCT_%s_%s,\n",
		    products[i, 1], products[i, 1], products[i, 2]) \
		    > dfile

		printf("\t    \"") > dfile
		j = 4;
		needspace = 0;
		while (products[i, j] != "") {
			if (needspace)
				printf(" ") > dfile
			printf("%s", products[i, j]) > dfile
			needspace = 1
			j++
		}
		printf("\",\n") > dfile
		printf("\t},\n") > dfile
	}
	printf("\t{ 0, 0, NULL, }\n") > dfile
	printf("};\n\n") > dfile
}


code:
#	$OpenBSD: files.xbow,v 1.9 2012/05/10 21:30:09 miod Exp $

# IP30 and IP27 planar XBow bus
define	xbow {[widget = -1], [vendor = -1], [product = -1]}
device	xbow
attach	xbow at mainbus
file	arch/sgi/xbow/xbow.c			xbow

# IP30 Heart
device	xheart {} : onewirebus
attach	xheart at xbow
file	arch/sgi/xbow/xheart.c			xheart

# PCI Bridge
device	xbridge {}
attach	xbridge at xbow
device	xbpci {[bus = -1]} : pcibus
attach	xbpci at xbridge
file	arch/sgi/xbow/xbridge.c			xbridge

# Odyssey graphics
device	odyssey: wsemuldisplaydev, rasops32
attach	odyssey at xbow
file	arch/sgi/xbow/odyssey.c			odyssey		needs-flag

# ImpactSR graphics
attach	impact at xbow with impact_xbow
file	arch/sgi/xbow/impact_xbow.c		impact_xbow


code:
/*	$OpenBSD: hub.h,v 1.7 2009/11/08 22:44:16 miod Exp $	*/

/*
 * Copyright (c) 2009 Miodrag Vallat.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 *  HUB access macros.
 */
#define	LWIN_SIZE_BITS		24
#define	LWIN_SIZE		(1ULL << LWIN_SIZE_BITS)

#define	NODE_LWIN_BASE(nasid, widget)                               \
        (IP27_NODE_IO_BASE(nasid) + ((uint64_t)(widget) << LWIN_SIZE_BITS))

#define	IP27_LHUB_ADDR(_x) \
	((volatile uint64_t *)(NODE_LWIN_BASE(0, 1) + (_x)))
#define	IP27_RHUB_ADDR(_n, _x) \
	((volatile uint64_t *)(NODE_LWIN_BASE(_n, 1) + 0x800000 + (_x)))
#define	IP27_RHUB_PI_ADDR(_n, _sn, _x) \
	((volatile uint64_t *)(NODE_LWIN_BASE(_n, 1) + 0x800000 + \
	    ((_sn) ? HUBPI_OFFSET : 0) + (_x)))

#define	IP27_LHUB_L(r)			*(IP27_LHUB_ADDR(r))
#define	IP27_LHUB_S(r, d)		*(IP27_LHUB_ADDR(r)) = (d)
#define	IP27_RHUB_L(n, r)		*(IP27_RHUB_ADDR((n), (r)))
#define	IP27_RHUB_S(n, r, d)		*(IP27_RHUB_ADDR((n), (r))) = (d)
#define IP27_RHUB_PI_L(n, s, r)		*(IP27_RHUB_PI_ADDR((n), (s), (r)))
#define	IP27_RHUB_PI_S(n, s, r, d)	*(IP27_RHUB_PI_ADDR((n), (s), (r))) = (d)

#define	NODE_HSPEC_BASE(nasid) \
        (IP27_NODE_HSPEC_BASE(nasid))

#define	IP27_LHSPEC_ADDR(_x) \
	((volatile uint64_t *)(NODE_HSPEC_BASE(0) + (_x)))
#define	IP27_RHSPEC_ADDR(_n, _x) \
	((volatile uint64_t *)(NODE_HSPEC_BASE(_n) + 0x20000000 + (_x)))

#define	IP27_LHSPEC_L(r)		*(IP27_LHSPEC_ADDR(r))
#define	IP27_LHSPEC_S(r, d)		*(IP27_LHSPEC_ADDR(r)) = (d)
#define	IP27_RHSPEC_L(n, r)		*(IP27_RHSPEC_ADDR((n), (r)))
#define	IP27_RHSPEC_S(n, r, d)		*(IP27_RHSPEC_ADDR((n), (r))) = (d)

/*
 * HUB SPECIAL space (very incomplete)
 */

#define	LBOOTBASE_IP27		0x10000000
#define	LBOOTSIZE_IP27		0x10000000

#define	LREGBASE_IP35		0x10000000
#define	LREGSIZE_IP35		0x08000000
#define	LBOOTBASE_IP35		0x18000000
#define	LBOOTSIZE_IP35		0x08000000

#define	HSPEC_L1_UARTBASE	0x00000080
#define	HSPEC_SYNERGY0		0x04000000	/* synergy #0 base */
#define	HSPEC_SYNERGY1		0x05000000	/* synergy #1 base */

#define	HSPEC_L1_UART(r) \
	(LREGBASE_IP35 + HSPEC_L1_UARTBASE + ((r) << 3))
#define	HSPEC_SYNERGY(s,r) \
	(LREGBASE_IP35 + ((s) ? HSPEC_SYNERGY1 : HSPEC_SYNERGY0) + ((r) << 3))

/*
 * HUB IO space (very incomplete)
 */

/*
 * HUB PI - Processor Interface
 */

#define	HUBPIBASE			0x00000000

#define	HUBPI_REGION_PRESENT		0x00000018
#define	HUBPI_CPU_NUMBER		0x00000020
#define	HUBPI_CALIAS_SIZE		0x00000028
#define PI_CALIAS_SIZE_0			0

#define	HUBPI_CPU0_PRESENT		0x00000040
#define	HUBPI_CPU1_PRESENT		0x00000048
#define	HUBPI_CPU0_ENABLED		0x00000050
#define	HUBPI_CPU1_ENABLED		0x00000058

#define	HUBPI_IR_CHANGE			0x00000090
#define	PI_IR_SET				0x100
#define	PI_IR_CLR				0x000
#define	HUBPI_IR0			0x00000098
#define	HUBPI_IR1			0x000000a0
#define	HUBPI_CPU0_IMR0			0x000000a8
#define	HUBPI_CPU0_IMR1			0x000000b0
#define	HUBPI_CPU1_IMR0			0x000000b8
#define	HUBPI_CPU1_IMR1			0x000000c0

/*
 * Offset to use to access the second PI over the remote hub interface
 * on IP35.
 */
#define	HUBPI_OFFSET			0x00200000

/*
 * ISR bit assignments.
 */

/** Level 1 interrupt */
/* ?? MSC panic */
#define	HUBPI_ISR1_MSC_ERROR		63
/* NI interface error */
#define	HUBPI_ISR1_NI_ERROR		62
/* MD correctable error */
#define	HUBPI_ISR1_MD_COR_ERROR		61
/* cpu correctable error B */
#define	HUBPI_ISR1_COR_ERROR_B		60
/* cpu correctable error A */
#define	HUBPI_ISR1_COR_ERROR_A		59
/* clock error */
#define	HUBPI_ISR1_CLOCK_ERROR		58
/* IP35 NACK interrupts */
#define	HUBPI_ISR1_NACK_B		57
#define	HUBPI_ISR1_NACK_A		56
/* IP35 LB error */
#define	HUBPI_ISR1_LB			55
/* IP35 XB error */
#define	HUBPI_ISR1_XB			54
/* 53-45 used by PROM */
/* 44-43 available */
/* 42-41 LLP errors */
/* NI broadcast errors */
#define	HUBPI_ISR1_NI_ERROR_B		40
#define	HUBPI_ISR1_NI_ERROR_A		39
/* 38-36 used by IP35 PROM */
/* 35-0 available */

/** Level 0 interrupt */
/* 63-7 available */
/* IPI interrupts */
#define	HUBPI_ISR0_IPI_B		6
#define	HUBPI_ISR0_IPI_A		5
/* ? */
#define	HUBPI_ISR0_UART			4
/* page migration interrupt */
#define	HUBPI_ISR0_PAGE_MIGRATION	3
/* graphics->cpu interrupts */
#define	HUBPI_ISR0_GFX_B		2
#define	HUBPI_ISR0_GFX_A		1
/* 0 reserved */

#define	HUBPI_INTR1_WIDGET_MAX		35
#define	HUBPI_INTR1_WIDGET_MIN		0
#define	HUBPI_INTR0_WIDGET_MAX		63
#define	HUBPI_INTR0_WIDGET_MIN		7

#define	HUBPI_NINTS			64	/* per register */

/*
 * HUB MD - Memory/Directory
 */

#define	HUBMDBASE_IP27			0x00200000
#define	HUBMDBASE_IP35			0x00780000

/*
 * HUB IO - Widget I/O
 */

#define	HUBIOBASE			0x00400000

#define	HUBIO_IOTTE(x)			(0x00000160 + (x) * 8)
#define	IOTTE_MAX				7
#define	IOTTE_SWIN0				(IOTTE_MAX - 1)

#define	IOTTE(space,widget,offset) \
	(((space) << 12) | ((widget) << 8) | (offset))
#define	IOTTE_SPACE_DEVICE		1
#define	IOTTE_SPACE_MEMORY		0
#define	IOTTE_SPACE(iotte)		(((iotte) >> 12) & 0x01)
#define	IOTTE_WIDGET(iotte)		(((iotte) >> 8) & 0x0f)
#define	IOTTE_OFFSET(iotte)		((iotte) & 0xff)

/*
 * HUB LB - Local Bedrock
 */

#define	HUBLBBASE_IP35			0x00600000

/*
 * HUB NI - Network Interface
 */

#define	HUBNIBASE_IP27			0x00600000
#define	HUBNIBASE_IP35			0x00680000

#define	HUBNI_STATUS			0x00000000
#define	NI_MORENODES				0x0000000000040000
#define	HUBNI_RESET			0x00000008
#define	NI_RESET_ACTION_IP27			0x02
#define	NI_RESET_PORT_IP27			0x80
#define	NI_RESET_LOCAL_IP27			0x01
#define	NI_RESET_ACTION_IP35			0x01
#define	NI_RESET_PORT_IP35			0x02
#define	NI_RESET_LOCAL_IP35			0x04
#define	HUBNI_RESET_ENABLE		0x00000010
#define	NI_RESET_ENABLE				0x01

/*
 * HUB XB - Crossbar interface
 */

#define	HUBXBBASE_IP35			0x00700000


code:
/*	$OpenBSD: impact_xbow.c,v 1.1 2012/04/18 17:28:24 miod Exp $	*/

/*
 * Copyright (c) 2010, 2012 Miodrag Vallat.
 * Copyright (c) 2009, 2010 Joel Sing <jsing@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * Driver for the SGI ImpactSR graphics board (XBow attachment).
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/types.h>

#include <machine/autoconf.h>

#include <mips64/arcbios.h>

#include <sgi/dev/impactvar.h>
#include <sgi/xbow/widget.h>
#include <sgi/xbow/xbow.h>
#include <sgi/xbow/xbowdevs.h>

#define	IMPACTSR_REG_OFFSET		0x00000000
#define	IMPACTSR_REG_SIZE		0x00200000

struct impact_xbow_softc {
	struct impact_softc	sc_base;

	struct mips_bus_space	iot_store;
};

int	impact_xbow_match(struct device *, void *, void *);
void	impact_xbow_attach(struct device *, struct device *, void *);

const struct cfattach impact_xbow_ca = {
	sizeof(struct impact_xbow_softc), impact_xbow_match, impact_xbow_attach
};

int	impact_xbow_is_console(struct xbow_attach_args *);

int
impact_xbow_match(struct device *parent, void *match, void *aux)
{
	struct xbow_attach_args *xaa = aux;

	if (xaa->xaa_vendor == XBOW_VENDOR_SGI5 &&
	    xaa->xaa_product == XBOW_PRODUCT_SGI5_IMPACT)
		return 1;

	return 0;
}

void
impact_xbow_attach(struct device *parent, struct device *self, void *aux)
{
	struct xbow_attach_args *xaa = aux;
	struct impact_xbow_softc *sc = (struct impact_xbow_softc *)self;
	bus_space_tag_t iot;
	bus_space_handle_t ioh;
	int console;

	if (strncmp(bios_graphics, "alive", 5) != 0) {
		printf(" device has not been setup by firmware!\n");
		return;
	}

	printf(" revision %d\n", xaa->xaa_revision);

	console = impact_xbow_is_console(xaa);

	if (console != 0) {
		iot = NULL;
		ioh = 0;
	} else {
		/*
		 * Create a copy of the bus space tag.
		 */
		bcopy(xaa->xaa_iot, &sc->iot_store,
		    sizeof(struct mips_bus_space));
		iot = &sc->iot_store;

		/* Setup bus space mappings. */
		if (bus_space_map(iot, IMPACTSR_REG_OFFSET,
		    IMPACTSR_REG_SIZE, 0, &ioh)) {
			printf("failed to map registers\n");
			return;
		}
	}

	if (impact_attach_common(&sc->sc_base, iot, ioh, console, 1) != 0) {
		if (console == 0)
			bus_space_unmap(iot, ioh, IMPACTSR_REG_SIZE);
	}
}

/*
 * Console support.
 */

int
impact_xbow_cnprobe()
{
	u_int32_t wid, vendor, product;

	if (xbow_widget_id(console_output.nasid, console_output.widget,
	    &wid) != 0)
		return 0;

	vendor = WIDGET_ID_VENDOR(wid);
	product = WIDGET_ID_PRODUCT(wid);

	if (vendor != XBOW_VENDOR_SGI5 || product != XBOW_PRODUCT_SGI5_IMPACT)
		return 0;

	if (strncmp(bios_graphics, "alive", 5) != 0)
		return 0;

	return 1;
}

int
impact_xbow_cnattach()
{
	static struct mips_bus_space impact_iot_store;
	bus_space_tag_t iot;
	bus_space_handle_t ioh;
	int rc;

	/* Build bus space accessor. */
	xbow_build_bus_space(&impact_iot_store, console_output.nasid,
	    console_output.widget);
	iot = &impact_iot_store;

	rc = bus_space_map(iot, IMPACTSR_REG_OFFSET, IMPACTSR_REG_SIZE,
	    0, &ioh);
	if (rc != 0)
		return rc;

	rc = impact_cnattach_common(iot, ioh, 1);
	if (rc != 0) {
		bus_space_unmap(iot, ioh, IMPACTSR_REG_SIZE);
		return rc;
	}

	return 0;
}

int
impact_xbow_is_console(struct xbow_attach_args *xaa)
{
	return xaa->xaa_nasid == console_output.nasid &&
	    xaa->xaa_widget == console_output.widget;
}