code:
/*	$OpenBSD: devopen.c,v 1.12 2014/07/13 09:26:08 jasper Exp $	*/

/*
 * Copyright (c) 1996-1999 Michael Shalayeff
 * 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 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 OR HIS RELATIVES 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 MIND, 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/disklabel.h>
#include <dev/cons.h>
#include "libsa.h"
#include <stand/boot/cmd.h>

/* XXX use slot for 'rd' for 'hd' pseudo-device */
const char bdevs[][4] = {
	"wd", "", "fd", "", "sd", "st", "cd", "",
	"", "", "", "", "", "", "", "", "", "hd", ""

};
const int nbdevs = nitems(bdevs);

const char cdevs[][4] = {
	"cn", "", "", "", "", "", "", "",
	"", "", "", "", "com"
};
const int ncdevs = nitems(cdevs);

/* pass dev_t to the open routines */
int
devopen(struct open_file *f, const char *fname, char **file)
{
	struct devsw *dp = devsw;
	register int i, rc = 1;

	*file = (char *)fname;

#ifdef DEBUG
	if (debug)
		printf("devopen:");
#endif

	for (i = 0; i < ndevs && rc != 0; dp++, i++) {
#ifdef DEBUG
		if (debug)
			printf(" %s: ", dp->dv_name);
#endif
		if ((rc = (*dp->dv_open)(f, file)) == 0) {
			f->f_dev = dp;
			return 0;
		}
#ifdef DEBUG
		else if (debug)
			printf("%d", rc);
#endif

	}
#ifdef DEBUG
	if (debug)
		putchar('\n');
#endif

	if ((f->f_flags & F_NODEV) == 0)
		f->f_dev = dp;

	return rc;
}

void
devboot(dev_t bootdev, char *p)
{
	dev_t unit = 0;		/* XXX */

	*p++ = 'h';
	*p++ = 'd';
	*p++ = '0' + unit;
	*p++ = 'a';
	*p = '\0';
}

char ttyname_buf[8];

char *
ttyname(int fd)
{
	snprintf(ttyname_buf, sizeof ttyname_buf, "%s%d",
	    cdevs[major(cn_tab->cn_dev)], minor(cn_tab->cn_dev));

	return ttyname_buf;
}

dev_t
ttydev(char *name)
{
	int i, unit = -1;
	char *no = name + strlen(name) - 1;

	while (no >= name && *no >= '0' && *no <= '9')
		unit = (unit < 0 ? 0 : (unit * 10)) + *no-- - '0';
	if (no < name || unit < 0)
		return NODEV;
	for (i = 0; i < ncdevs; i++)
		if (strncmp(name, cdevs[i], no - name + 1) == 0)
			return (makedev(i, unit));
	return NODEV;
}


code:
/*	$OpenBSD: disk.h,v 1.1 2005/05/24 20:38:20 uwe Exp $	*/

/*
 * Copyright (c) 1997 Tobias Weingartner
 * 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 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 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.
 *
 */

#ifndef _DISKPROBE_H
#define _DISKPROBE_H

#include <sys/queue.h>

/* XXX snatched from <i386/biosdev.h> */
#if 1
/* Info about disk from the bios, plus the mapping from
 * BIOS numbers to BSD major (driver?) number.
 *
 * Also, do not bother with BIOSN*() macros, just parcel
 * the info out, and use it like this.  This makes for less
 * of a dependance on BIOSN*() macros having to be the same
 * across /boot, /bsd, and userland.
 */
#define	BOOTARG_DISKINFO 1
typedef struct _bios_diskinfo {
	/* BIOS section */
	int bios_number;	/* BIOS number of drive (or -1) */
	u_int bios_cylinders;	/* BIOS cylinders */
	u_int bios_heads;	/* BIOS heads */
	u_int bios_sectors;	/* BIOS sectors */
	int bios_edd;		/* EDD support */

	/* BSD section */
	dev_t bsd_dev;		/* BSD device */

	/* Checksum section */
	u_int32_t checksum;	/* Checksum for drive */

	/* Misc. flags */
	u_int32_t flags;
#define BDI_INVALID	0x00000001	/* I/O error during checksumming */
#define BDI_GOODLABEL	0x00000002	/* Had SCSI or ST506/ESDI disklabel */
#define BDI_BADLABEL	0x00000004	/* Had another disklabel */
#define BDI_EL_TORITO	0x00000008	/* 2,048-byte sectors */
#define BDI_PICKED	0x80000000	/* kernel-only: cksum matched */

} bios_diskinfo_t;

#define	BOOTARG_CKSUMLEN 3		/* u_int32_t */
#endif /* 1 */

/* All the info on a disk we've found */
struct diskinfo {
	bios_diskinfo_t bios_info;
	struct disklabel disklabel;

	dev_t bsddev, bootdev;

	TAILQ_ENTRY(diskinfo) list;
};
TAILQ_HEAD(disklist_lh, diskinfo);

/* diskprobe.c */
struct diskinfo *dkdevice(dev_t, dev_t);
void		 bios_devpath(int, int, char *);
char		*bios_getdiskinfo(int, bios_diskinfo_t *);
int		 bios_getdospart(bios_diskinfo_t *);
char		*bios_getdisklabel(bios_diskinfo_t *, struct disklabel *);
void		 dump_diskinfo(void);

#endif /* _DISKPROBE_H */

license: unknown


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

/*
 * Copyright (c) 1997 Tobias Weingartner
 * 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 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 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.
 *
 */

/* We want the disk type names from disklabel.h */
#undef DKTYPENAMES

#include <sys/param.h>
#include <sys/queue.h>
#include <sys/reboot.h>
#include <sys/disklabel.h>
#include <stand/boot/bootarg.h>
#if 0
#include <machine/biosvar.h>
#endif
#include <lib/libz/zlib.h>
#include "disk.h"
#if 0
#include "biosdev.h"
#endif
#include "libsa.h"

#define MAX_CKSUMLEN MAXBSIZE / DEV_BSIZE	/* Max # of blks to cksum */

/* Disk spin-up wait timeout. */
static u_int timeout = 10;

/* Local Prototypes */
static void hardprobe(void);

/* List of disk devices we found/probed */
struct disklist_lh disklist;

/*
 * Probe for all hard disks.
 */
static void
hardprobe(void)
{
	struct diskinfo *dip;
	int i, order[] = { 0x80, 0x82 }; /* XXX probe disks in this order */
	u_int bsdunit, type;
	u_int scsi = 0, ide = 0;
	u_int disk = 0;

	/* Hard disks */
	for (i = 0; i < sizeof(order) / sizeof(order[0]); i++) {
		dip = alloc(sizeof(struct diskinfo));
		bzero(dip, sizeof(*dip));

		if (bios_getdiskinfo(order[i], &dip->bios_info) != NULL) {
			free(dip, 0);
			continue;
		}

		printf("hd%u", disk++);

		/* Try to find the label, to figure out device type. */
		if (bios_getdisklabel(&dip->bios_info, &dip->disklabel)
		    == NULL) {
			printf("*");
			bsdunit = ide++;
			type = 0;	/* XXX let it be IDE */
		} else {
			/* Best guess */
			switch (dip->disklabel.d_type) {
			case DTYPE_SCSI:
				type = 4;
				bsdunit = scsi++;
				dip->bios_info.flags |= BDI_GOODLABEL;
				break;

			case DTYPE_ESDI:
			case DTYPE_ST506:
				type = 0;
				bsdunit = ide++;
				dip->bios_info.flags |= BDI_GOODLABEL;
				break;

			default:
				dip->bios_info.flags |= BDI_BADLABEL;
				type = 0;	/* XXX Suggest IDE */
				bsdunit = ide++;
			}
		}

		dip->bios_info.checksum = 0; /* just in case */
		/* Fill out best we can. */
		dip->bios_info.bsd_dev =
		    MAKEBOOTDEV(type, 0, 0, bsdunit, RAW_PART);

		/* Add to queue of disks. */
		TAILQ_INSERT_TAIL(&disklist, dip, list);

		printf(" ");
	}
}

/* Probe for all BIOS supported disks */
u_int32_t bios_cksumlen;
void
diskprobe(void)
{
	struct diskinfo *dip;
	int i;

	/* These get passed to kernel */
	bios_diskinfo_t *bios_diskinfo;

	/* Init stuff */
	TAILQ_INIT(&disklist);

	/* Do probes */
	hardprobe();

#if 0
	/* Checksumming of hard disks */
	for (i = 0; disksum(i++) && i < MAX_CKSUMLEN; )
		;
	bios_cksumlen = i;

	/* Get space for passing bios_diskinfo stuff to kernel */
	for (i = 0, dip = TAILQ_FIRST(&disklist); dip;
	    dip = TAILQ_NEXT(dip, list))
		i++;
	bios_diskinfo = alloc(++i * sizeof(bios_diskinfo_t));

	/* Copy out the bios_diskinfo stuff */
	for (i = 0, dip = TAILQ_FIRST(&disklist); dip;
	    dip = TAILQ_NEXT(dip, list))
		bios_diskinfo[i++] = dip->bios_info;

	bios_diskinfo[i++].bios_number = -1;
	/* Register for kernel use */
	addbootarg(BOOTARG_CKSUMLEN, sizeof(u_int32_t), &bios_cksumlen);
	addbootarg(BOOTARG_DISKINFO, i * sizeof(bios_diskinfo_t),
	    bios_diskinfo);
#endif
}

/*
 * Find info on the disk given by major + unit number.
 */
struct diskinfo *
dkdevice(dev_t maj, dev_t unit)
{
	struct diskinfo *dip;

	for (dip = TAILQ_FIRST(&disklist); dip;
	     dip = TAILQ_NEXT(dip, list)) {
		/* XXX skip non-matching entries according to maj. */

		if (unit-- == 0)
			return dip;
	}

	return NULL;
}

/*
 * Find the Linux device path that corresponds to the given "BIOS" disk,
 * where 0x80 corresponds to /dev/hda, 0x81 to /dev/hdb, and so on.
 */
void
bios_devpath(int dev, int part, char *p)
{
	*p++ = '/';
	*p++ = 'd';
	*p++ = 'e';
	*p++ = 'v';
	*p++ = '/';
	if ((dev & 0x80) != 0)
		*p++ = 'h';
	else
		*p++ = 'f';
	*p++ = 'd';
	*p++ = 'a' + (dev & 0x7f);
	if (part != -1)
		*p++ = '1' + part;
	*p = '\0';
}

/*
 * Fill out a bios_diskinfo_t for this device.
 */
char *
bios_getdiskinfo(int dev, bios_diskinfo_t *bdi)
{
	static char path[PATH_MAX];
	struct linux_stat sb;
	char *p;

	bzero(bdi, sizeof *bdi);
	bdi->bios_number = -1;

	bios_devpath(dev, -1, path);

	if (ustat(path, &sb) != 0)
		return "no device node";

	bdi->bios_number = dev;

	if (bios_getdospart(bdi) < 0)
		return "no OpenBSD partition";

	return 0;
}

int
bios_getdospart(bios_diskinfo_t *bdi)
{
	char path[PATH_MAX];
	char buf[DEV_BSIZE];
	struct dos_partition *dp;
	int fd;
	u_int part;
	size_t rsize;

	bios_devpath(bdi->bios_number, -1, path);

	/*
	 * Give disk devices some time to become ready when the first open
	 * fails.  Even when open succeeds the disk is sometimes not ready.
	 */
	if ((fd = uopen(path, O_RDONLY)) == -1 && errno == ENXIO) {
		int t;

		while (fd == -1 && timeout > 0) {
			timeout--;
			sleep(1);
			fd = uopen(path, O_RDONLY);
		}
		if (fd != -1)
			sleep(2);
	}
	if (fd == -1)
		return -1;

	/* Read the disk's MBR. */
	if (unixstrategy((void *)fd, F_READ, DOSBBSECTOR,
	    DEV_BSIZE, buf, &rsize) != 0 || rsize != DEV_BSIZE) {
		uclose(fd);
		errno = EIO;
		return -1;
	}

	/* Find OpenBSD primary partition in the disk's MBR. */
	dp = (struct dos_partition *)&buf[DOSPARTOFF];
	for (part = 0; part < NDOSPART; part++)
		if (dp[part].dp_typ == DOSPTYP_OPENBSD)
			break;
	if (part == NDOSPART) {
		uclose(fd);
		errno = ERDLAB;
		return -1;
	}
	uclose(fd);

	return part;
}

char *
bios_getdisklabel(bios_diskinfo_t *bdi, struct disklabel *label)
{
	char path[PATH_MAX];
	char buf[DEV_BSIZE];
	int part;
	int fd;
	size_t rsize;

	part = bios_getdospart(bdi);
	if (part < 0)
		return "no OpenBSD partition";

	bios_devpath(bdi->bios_number, part, path);

	/* Test if the OpenBSD partition has a valid disklabel. */
	if ((fd = uopen(path, O_RDONLY)) != -1) {
		char *msg = "failed to read disklabel";

		if (unixstrategy((void *)fd, F_READ, LABELSECTOR,
		    DEV_BSIZE, buf, &rsize) == 0 && rsize == DEV_BSIZE)
			msg = getdisklabel(buf, label);
		uclose(fd);
		/* Don't wait for other disks if this label is ok. */
		if (msg == NULL)
			timeout = 0;
		return (msg);
	}

	return "failed to open partition";
}


code:
/*	$OpenBSD: exec.c,v 1.2 2005/01/10 21:10:57 uwe Exp $	*/

/*
 * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
 *
 * 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 "libsa.h"
#include <lib/libsa/loadfile.h>

void
run_loadfile(u_long *marks, int howto)
{
	panic("run_loadfile");
}


code:
/*	$OpenBSD: exit.c,v 1.5 2011/04/07 15:12:03 drahn Exp $	*/
/*	$NetBSD: exit.c,v 1.11 1996/12/01 20:22:19 pk Exp $	*/

/*-
 *  Copyright (c) 1993 John Brezak
 *  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. 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 <sys/stdarg.h>

#include "libsa.h"

/* unixcons.c */
extern struct termios tioc;
extern int            tioc_valid;
extern __dead void uexit(int);

__dead void
panic(const char *fmt, ...)
{
	extern void closeall(void);
	va_list ap;
	static int paniced;

	if (!paniced) {
		paniced = 1;
		closeall();
	}

	va_start(ap, fmt);
	vprintf(fmt, ap);
	printf("\n");
	va_end(ap);
#if 0
	_rtt();
#else
	uexit(0);
#endif
	/*NOTREACHED*/
}

void
exit(void)
{
	if (tioc_valid)
		(void)tcsetattr(0, TCSADRAIN, &tioc);
	uexit(0);
}


code:
/*	$OpenBSD: libsa.h,v 1.3 2005/05/24 20:38:20 uwe Exp $	*/

/*
 * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
 *
 * 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 <lib/libsa/stand.h>

#include "compat_linux.h"

#define	EXEC_ELF

#define DEFAULT_KERNEL_ADDRESS	0xa0200000

struct zaurus_boot_probes {
	char *name;
	void (**probes)(void);
	int count;
};

void diskprobe(void);

extern const char bdevs[][4];
extern const int nbdevs;

extern struct zaurus_boot_probes probe_list[];
extern int nibprobes;
#if 0
extern void (*devboot_p)(dev_t, char *);
#endif

extern int debug;


code:
/* $NetBSD: loadfile.c,v 1.10 2000/12/03 02:53:04 tsutsui Exp $ */
/* $OpenBSD: loadfile.c,v 1.6 2013/10/17 15:54:11 deraadt Exp $ */

/*-
 * Copyright (c) 1997 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
 * NASA Ames Research Center and by Christos Zoulas.
 *
 * 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.
 */

/*
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Ralph Campbell.
 *
 * 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.
 *
 *	@(#)boot.c	8.1 (Berkeley) 6/10/93
 */

#ifdef _STANDALONE
#include <lib/libkern/libkern.h>
#include <lib/libsa/stand.h>
#else
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <err.h>
#endif

#include <sys/param.h>
#include <sys/exec.h>

#include "compat_linux.h"
#include "pathnames.h"
#include <lib/libsa/loadfile.h>
#include <stand/boot/cmd.h>

#define BOOT_ZBOOT

#ifdef BOOT_ELF
#include <sys/exec_elf.h>
static int elf_exec(int, Elf_Ehdr *, u_long *, int);
#endif
#ifdef BOOT_ZBOOT
#include <dev/cons.h>		/* XXX */
static int zboot_exec(int, u_long *, int);
#endif

/*
 * Open 'filename', read in program and and return 0 if ok 1 on error.
 * Fill in marks
 */
int
loadfile(const char *fname, u_long *marks, int flags)
{
	union {
#ifdef BOOT_ELF
		Elf_Ehdr elf;
#endif
	} hdr;
	ssize_t nr;
	int fd, rval;

	/* Open the file. */
	if ((fd = open(fname, 0)) < 0) {
		WARN(("open %s", fname ? fname : "<default>"));
		return -1;
	}

	/* Read the exec header. */
	if ((nr = read(fd, &hdr, sizeof(hdr))) != sizeof(hdr)) {
		WARN(("read header"));
		goto err;
	}

#ifdef BOOT_ELF
	if (memcmp(hdr.elf.e_ident, ELFMAG, SELFMAG) == 0 &&
	    hdr.elf.e_ident[EI_CLASS] == ELFCLASS) {
#ifdef BOOT_ZBOOT
		rval = zboot_exec(fd, marks, flags);
#else
		rval = elf_exec(fd, &hdr.elf, marks, flags);
#endif
	} else
#endif
	{
		rval = 1;
		errno = EFTYPE;
		WARN(("%s", fname ? fname : "<default>"));
	}

	if (rval == 0) {
		PROGRESS(("=0x%lx\n", marks[MARK_END] - marks[MARK_START]));
		return fd;
	}
err:
	(void)close(fd);
	return -1;
}

#ifdef BOOT_ELF
static int
elf_exec(int fd, Elf_Ehdr *elf, u_long *marks, int flags)
{
	Elf_Shdr *shp;
	Elf_Phdr *phdr;
	Elf_Off off;
	int i;
	size_t sz;
	int first;
	int havesyms;
	paddr_t minp = ~0, maxp = 0, pos = 0;
	paddr_t offset = marks[MARK_START], shpp, elfp;

	sz = elf->e_phnum * sizeof(Elf_Phdr);
	phdr = ALLOC(sz);

	if (lseek(fd, elf->e_phoff, SEEK_SET) == -1)  {
		WARN(("lseek phdr"));
		FREE(phdr, sz);
		return 1;
	}
	if (read(fd, phdr, sz) != sz) {
		WARN(("read program headers"));
		FREE(phdr, sz);
		return 1;
	}

	for (first = 1, i = 0; i < elf->e_phnum; i++) {

		if (phdr[i].p_type != PT_LOAD ||
		    (phdr[i].p_flags & (PF_W|PF_R|PF_X)) == 0)
			continue;

#define IS_TEXT(p)	(p.p_flags & PF_X)
#define IS_DATA(p)	((p.p_flags & PF_X) == 0)
#define IS_BSS(p)	(p.p_filesz < p.p_memsz)
		/*
		 * XXX: Assume first address is lowest
		 */
		if ((IS_TEXT(phdr[i]) && (flags & LOAD_TEXT)) ||
		    (IS_DATA(phdr[i]) && (flags & LOAD_DATA))) {

			/* Read in segment. */
			PROGRESS(("%s%lu", first ? "" : "+",
			    (u_long)phdr[i].p_filesz));

			if (lseek(fd, phdr[i].p_offset, SEEK_SET) == -1)  {
				WARN(("lseek text"));
				FREE(phdr, sz);
				return 1;
			}
			if (READ(fd, phdr[i].p_vaddr, phdr[i].p_filesz) !=
			    phdr[i].p_filesz) {
				WARN(("read text"));
				FREE(phdr, sz);
				return 1;
			}
			first = 0;

		}
		if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT|COUNT_TEXT))) ||
		    (IS_DATA(phdr[i]) && (flags & (LOAD_DATA|COUNT_TEXT)))) {
			pos = phdr[i].p_vaddr;
			if (minp > pos)
				minp = pos;
			pos += phdr[i].p_filesz;
			if (maxp < pos)
				maxp = pos;
		}

		/* Zero out bss. */
		if (IS_BSS(phdr[i]) && (flags & LOAD_BSS)) {
			PROGRESS(("+%lu",
			    (u_long)(phdr[i].p_memsz - phdr[i].p_filesz)));
			BZERO((phdr[i].p_vaddr + phdr[i].p_filesz),
			    phdr[i].p_memsz - phdr[i].p_filesz);
		}
		if (IS_BSS(phdr[i]) && (flags & (LOAD_BSS|COUNT_BSS))) {
			pos += phdr[i].p_memsz - phdr[i].p_filesz;
			if (maxp < pos)
				maxp = pos;
		}
	}
	FREE(phdr, sz);

	/*
	 * Copy the ELF and section headers.
	 */
	elfp = maxp = roundup(maxp, sizeof(long));
	if (flags & (LOAD_HDR|COUNT_HDR))
		maxp += sizeof(Elf_Ehdr);

	if (flags & (LOAD_SYM|COUNT_SYM)) {
		if (lseek(fd, elf->e_shoff, SEEK_SET) == -1)  {
			WARN(("lseek section headers"));
			return 1;
		}
		sz = elf->e_shnum * sizeof(Elf_Shdr);
		shp = ALLOC(sz);

		if (read(fd, shp, sz) != sz) {
			WARN(("read section headers"));
			return 1;
		}

		shpp = maxp;
		maxp += roundup(sz, sizeof(long));

		/*
		 * Now load the symbol sections themselves.  Make sure the
		 * sections are aligned. Don't bother with string tables if
		 * there are no symbol sections.
		 */
		off = roundup((sizeof(Elf_Ehdr) + sz), sizeof(long));

		for (havesyms = i = 0; i < elf->e_shnum; i++)
			if (shp[i].sh_type == SHT_SYMTAB)
				havesyms = 1;

		for (first = 1, i = 0; i < elf->e_shnum; i++) {
			if (shp[i].sh_type == SHT_SYMTAB ||
			    shp[i].sh_type == SHT_STRTAB) {
				if (havesyms && (flags & LOAD_SYM)) {
					PROGRESS(("%s%ld", first ? " [" : "+",
					    (u_long)shp[i].sh_size));
					if (lseek(fd, shp[i].sh_offset,
					    SEEK_SET) == -1) {
						WARN(("lseek symbols"));
						FREE(shp, sz);
						return 1;
					}
					if (READ(fd, maxp, shp[i].sh_size) !=
					    shp[i].sh_size) {
						WARN(("read symbols"));
						FREE(shp, sz);
						return 1;
					}
				}
				maxp += roundup(shp[i].sh_size,
				    sizeof(long));
				shp[i].sh_offset = off;
				off += roundup(shp[i].sh_size, sizeof(long));
				first = 0;
			}
		}
		if (flags & LOAD_SYM) {
			BCOPY(shp, shpp, sz);

			if (havesyms && first == 0)
				PROGRESS(("]"));
		}
		FREE(shp, sz);
	}

	/*
	 * Frob the copied ELF header to give information relative
	 * to elfp.
	 */
	if (flags & LOAD_HDR) {
		elf->e_phoff = 0;
		elf->e_shoff = sizeof(Elf_Ehdr);
		elf->e_phentsize = 0;
		elf->e_phnum = 0;
		BCOPY(elf, elfp, sizeof(*elf));
	}

	marks[MARK_START] = LOADADDR(minp);
	marks[MARK_ENTRY] = LOADADDR(elf->e_entry);
	marks[MARK_NSYM] = 1;	/* XXX: Kernel needs >= 0 */
	marks[MARK_SYM] = LOADADDR(elfp);
	marks[MARK_END] = LOADADDR(maxp);
	return 0;
}
#endif /* BOOT_ELF */

#ifdef BOOT_ZBOOT
static int
zboot_exec(int fd, u_long *marks, int flags)
{
	char buf[512];
	char *p;
	int tofd;
	int sz;
	int i;

	/* XXX cheating here by assuming that Xboot() was called before. */

	tofd = uopen(_PATH_ZBOOT, O_WRONLY);
	if (tofd == -1) {
		printf("%s: can't open (errno %d)\n", _PATH_ZBOOT, errno);
		return 1;
	}

	p = cmd.path;
	for (; *p != '\0'; p++)
		if (*p == ':') {
			strlcpy(buf, p+1, sizeof(buf));
			break;
		}
	if (*p == '\0')
		strlcpy(buf, cmd.path, sizeof(buf));

	p = buf;
	for (; *p == '/'; p++)
		;

	sz = strlen(p);
	if (uwrite(tofd, p, sz) != sz) {
		printf("zboot_exec: argument write error\n");
		goto err;
	}

	buf[0] = ' ';
	buf[1] = '-';
	if (uwrite(tofd, buf, 2) != 2) {
		printf("zboot_exec: argument write error\n");
		goto err;
	}

	i = (cmd.argc > 1 && cmd.argv[1][0] != '-') ? 2 : 1;
	for (; i < cmd.argc; i++) {
		p = cmd.argv[i];
		if (*p == '-')
			p++;
		sz = strlen(p);
		if (uwrite(tofd, p, sz) != sz) {
			printf("zboot_exec: argument write error\n");
			goto err;
		}
	}

	/* Select UART unit for serial console. */
	if (cn_tab && major(cn_tab->cn_dev) == 12) {
		buf[0] = '0' + minor(cn_tab->cn_dev);
		if (uwrite(tofd, buf, 1) != 1) {
			printf("zboot_exec: argument write error\n");
			goto err;
		}
	}

	/* Commit boot arguments. */
	uclose(tofd);

	tofd = uopen(_PATH_ZBOOT, O_WRONLY);
	if (tofd == -1) {
		printf("%s: can't open (errno %d)\n", _PATH_ZBOOT, errno);
		return 1;
	}

	if (lseek(fd, 0, SEEK_SET) != 0) {
		printf("%s: seek error\n", _PATH_ZBOOT);
		goto err;
	}

	while ((sz = read(fd, buf, sizeof(buf))) == sizeof(buf)) {
		if ((sz = uwrite(tofd, buf, sz)) != sizeof(buf)) {
			printf("%s: write error\n", _PATH_ZBOOT);
			goto err;
		}
	}

	if (sz < 0) {
		printf("zboot_exec: read error\n");
		goto err;
	}

	if (sz >= 0 && uwrite(tofd, buf, sz) != sz) {
		printf("zboot_exec: write error\n");
		goto err;
	}

	uclose(tofd);
	return 0;

err:
	uclose(tofd);
	return 1;
}
#endif /* BOOT_ZBOOT */


code:
/*	$OpenBSD: machdep.c,v 1.4 2005/05/24 20:38:20 uwe Exp $	*/

/*
 * Copyright (c) 2004 Tom Cosgrove
 * Copyright (c) 1997-1999 Michael Shalayeff
 * 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 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 OR HIS RELATIVES 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 MIND, 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 "libsa.h"

char _alloc_heap[4 * 1024 * 1024];

void
machdep(void)
{
	int i, j;
	struct zaurus_boot_probes *pr;

	/*
	 * The list of probe routines is now in conf.c.
	 */
	for (i = 0; i < nibprobes; i++) {
		pr = &probe_list[i];
		if (pr != NULL) {
			printf("%s: ", pr->name);

			for (j = 0; j < pr->count; j++)
				(*(pr->probes)[j])();
			printf("\n");
		}
	}
}


code:
/*	$OpenBSD: pathnames.h,v 1.3 2005/01/14 08:10:16 uwe Exp $	*/

/*
 * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
 *
 * 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.
 */

#define _PATH_ZBOOT "/proc/zboot"


code:
/*	$OpenBSD: termios.c,v 1.2 2005/05/24 20:38:20 uwe Exp $	*/

/*-
 * Copyright (c) 1989, 1993
 *	The Regents of the University of California.  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. 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 "libsa.h"

/* Linux-specific line speed handling from linux_termios.c */

static speed_t linux_speeds[] = {
	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
	9600, 19200, 38400, 57600, 115200, 230400
};

static const int linux_spmasks[] = {
	LINUX_B0, LINUX_B50, LINUX_B75, LINUX_B110, LINUX_B134, LINUX_B150,
	LINUX_B200, LINUX_B300, LINUX_B600, LINUX_B1200, LINUX_B1800,
	LINUX_B2400, LINUX_B4800, LINUX_B9600, LINUX_B19200, LINUX_B38400,
	LINUX_B57600, LINUX_B115200, LINUX_B230400
};

int
cfsetspeed(struct termios *t, speed_t speed)
{
	int mask;
	int i;

	mask = LINUX_B9600;	/* XXX default value should this be 0? */
	for (i = 0; i < sizeof (linux_speeds) / sizeof (speed_t); i++) {
		if (speed == linux_speeds[i]) {
			mask = linux_spmasks[i];
			break;
		}
	}
	t->c_cflag &= ~LINUX_CBAUD;
	t->c_cflag |= mask;

	return (0);
}

void
cfmakeraw(struct termios *t)
{
	t->c_iflag &= ~(IMAXBEL|IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
	t->c_oflag &= ~OPOST;
	t->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
	t->c_cflag &= ~(CSIZE|PARENB);
	t->c_cflag |= CS8;
}

int
tcgetattr(int fd, struct termios *t)
{
	return (uioctl(fd, TIOCGETA, t));
}

/* This function differs slightly from tcsetattr() in libc. */
int
tcsetattr(int fd, int action, struct termios *t)
{
	switch (action) {
	case TCSANOW:
		action = TIOCSETA;
		break;
	case TCSADRAIN:
		action = TIOCSETAW;
		break;
	case TCSAFLUSH:
		action = TIOCSETAF;
		break;
	default:
		errno = EINVAL;
		return (-1);
	}
	return (uioctl(fd, action, t));
}


code:
/*	$OpenBSD: unixcons.c,v 1.2 2008/01/23 16:37:57 jsing Exp $	*/

/*
 * Copyright (c) 1997-1999 Michael Shalayeff
 * 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 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 OR HIS RELATIVES 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 MIND, 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/types.h>
#include <dev/cons.h>
#include "libsa.h"
#include "unixdev.h"

struct termios tioc;
int	       tioc_valid = 0;

#define NCOM 3
const char *compath[NCOM] = {
	"/dev/ttyS0",		/* com0 */
	"/dev/ttyS2",		/* com1 */
	"/dev/ttyS1"		/* com2 */
};

int com_fd = -1;		/* open serial port */
int com_speed = 9600;		/* default speed is 9600 baud */

/* Local prototypes */
void	common_putc(dev_t, int);
int	common_getc(dev_t);

void
common_putc(dev_t dev, int c)
{
	/* Always send to stdout. */
	(void)uwrite(1, &c, 1);

	/* Copy to serial if open. */
	if (com_fd != -1)
		(void)uwrite(com_fd, &c, 1);
}

int
common_getc(dev_t dev)
{
	struct timeval tv;
	fd_set fdset;
	int fd, nfds, n;
	char c;

	while (1) {
		tv.tv_sec = 0;
		tv.tv_usec = 10000;
		FD_ZERO(&fdset);

		/* Always read from stdin. */
		fd = 0;
		nfds = 1;
		FD_SET(fd, &fdset);

		/* Read from serial if open. */
		if (com_fd != -1) {
			nfds = com_fd+1;
			FD_SET(com_fd, &fdset);
		}

		n = uselect(nfds, &fdset, NULL, NULL, &tv);
		if ((dev & 0x80) != 0)
			return (n > 0);

		if (n > 0)
			break;
	}

	for (fd = 0; fd < nfds; fd++)
		if (FD_ISSET(fd, &fdset))
			break;

	return (uread(fd, &c, 1) < 1 ? -1 : c);
}

void
cn_probe(struct consdev *cn)
{
	cn->cn_pri = CN_MIDPRI;
	cn->cn_dev = makedev(0,0);
	printf("cn%d ", minor(cn->cn_dev));
}

void
cn_init(struct consdev *cn)
{
	struct termios t;

	if (!tioc_valid && tcgetattr(0, &t) == 0) {
		tioc = t;
		tioc_valid = 1;
		cfmakeraw(&t);
		(void)tcsetattr(0, TCSAFLUSH, &t);
	}
}

void
cn_putc(dev_t dev, int c)
{
	common_putc(dev, c);
}

int
cn_getc(dev_t dev)
{
	return (common_getc(dev));
}

void
com_probe(struct consdev *cn)
{
	int i;
	struct linux_stat sb;

	for (i = 0; i < NCOM; i++) {
		if (ustat(compath[i], &sb) != 0)
			continue;
		printf("com%d ", i);
	}

	cn->cn_pri = CN_LOWPRI;
	/* XXX from arm/conf.c */
	cn->cn_dev = makedev(12, 0);
}

void
com_init(struct consdev *cn)
{
	struct termios t;
	int unit = minor(cn->cn_dev);

	if (unit >= NCOM)
		return;

	if (com_fd != -1)
		uclose(com_fd);

	com_fd = uopen(compath[unit], O_RDWR);
	if (com_fd == -1)
		return;

	if (tcgetattr(com_fd, &t) == 0) {
		cfmakeraw(&t);
		cfsetspeed(&t, (speed_t)com_speed);
		(void)tcsetattr(com_fd, TCSAFLUSH, &t);
	}
}

void
com_putc(dev_t dev, int c)
{
	common_putc(dev, c);
}

int
com_getc(dev_t dev)
{
	return (common_getc(dev));
}

int
cnspeed(dev_t dev, int sp)
{
	if (major(dev) == 12)	/* comN */
		return (comspeed(dev, sp));

	/* cn0 or anything else */
	return (9600);
}

/* call with sp == 0 to query the current speed */
int
comspeed(dev_t dev, int sp)
{
	struct termios t;

	if (sp <= 0)
		return (com_speed);

	/* check if the new speed is a valid baud rate */
	if (cfsetspeed(&t, (speed_t)sp) != 0)
		sp = com_speed;

	if (cn_tab && cn_tab->cn_dev == dev && com_speed != sp) {
		printf("com%d: changing speed to %d baud in 5 seconds, "
		    "change your terminal to match!\n\a",
		    minor(dev), sp);
		sleep(5);
		if (com_fd != -1 && tcgetattr(com_fd, &t) == 0) {
			(void)cfsetspeed(&t, (speed_t)sp);
			(void)tcsetattr(com_fd, TCSAFLUSH, &t);
		}
		printf("\n");
	}

	if (com_speed != sp) {
		printf("com%d: %d baud\n", minor(dev), sp);
		com_speed = sp;
	}

	return (com_speed);
}


code:
/*	$OpenBSD: unixdev.c,v 1.7 2011/03/13 00:13:53 deraadt Exp $	*/

/*
 * Copyright (c) 1996-1998 Michael Shalayeff
 * 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 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 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/reboot.h>
#include <sys/disklabel.h>
#include <sys/syscall.h>
#include <sys/time.h>
#define open uopen
#include <sys/fcntl.h>
#include <dev/cons.h>
#undef open
#include "disk.h"
#include "libsa.h"
#include <lib/libsa/unixdev.h>

int
unixstrategy(void *devdata, int rw, daddr32_t blk, size_t size, void *buf,
    size_t *rsize)
{
	int	rc = 0;
	off_t	off;

#ifdef UNIX_DEBUG
	printf("unixstrategy: %s %d bytes @ %d\n",
	    (rw==F_READ?"reading":"writing"), size, blk);
#endif

	off = (off_t)blk * DEV_BSIZE;
	if ((rc = ulseek((int)devdata, off, SEEK_SET)) >= 0)
		rc = (rw==F_READ) ? uread((int)devdata, buf, size) :
		    uwrite((int)devdata, buf, size);

	if (rc >= 0) {
		*rsize = (size_t)rc;
		rc = 0;
	} else
		rc = errno;

	return rc;
}

int
unixopen(struct open_file *f, ...)
{
	va_list	ap;
	char	path[PATH_MAX];
	char	*cp, **file;
	dev_t	maj, unit, part, bsd_dev;
	struct diskinfo *dip;

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

#ifdef UNIX_DEBUG
	if (debug)
		printf("unixopen: %s\n", cp);
#endif

	f->f_devdata = NULL;
	/* Search for device specification. */
	if (strlen(cp) < 4)
		return ENOENT;
	cp += 2;
	if (cp[2] != ':') {
		if (cp[3] != ':')
			return ENOENT;
		else
			cp++;
	}

	for (maj = 0;
	     maj < nbdevs && strncmp(*file, bdevs[maj], cp - *file) != 0;
	     maj++)
		;
	if (maj >= nbdevs) {
		printf("Unknown device: ");
		for (cp = *file; *cp != ':'; cp++)
			putchar(*cp);
		putchar('\n');
		return EADAPT;
	}

	/* Get unit. */
	if ('0' <= *cp && *cp <= '9')
		unit = *cp++ - '0';
	else {
		printf("Bad unit number\n");
		return EUNIT;
	}

	/* Get partition. */
	if ('a' <= *cp && *cp <= 'p')
		part = *cp++ - 'a';
	else {
		printf("Bad partition id\n");
		return EPART;
	}

	cp++;	/* skip ':' */
	if (*cp != 0)
		*file = cp;
	else
		f->f_flags |= F_RAW;

	/* Find device. */
	dip = dkdevice(maj, unit);
	if (dip == (struct diskinfo *)NULL)
		return ENOENT;

	/* Fix up bootdev. */
	bsd_dev = dip->bios_info.bsd_dev;
	dip->bsddev = MAKEBOOTDEV(B_TYPE(bsd_dev), B_ADAPTOR(bsd_dev),
	    B_CONTROLLER(bsd_dev), unit, part);
	dip->bootdev = MAKEBOOTDEV(B_TYPE(bsd_dev), B_ADAPTOR(bsd_dev),
	    B_CONTROLLER(bsd_dev), B_UNIT(bsd_dev), part);

	/* Try for disklabel again (might be removable media). */
	if (dip->bios_info.flags & BDI_BADLABEL) {
		const char *st = bios_getdisklabel(&dip->bios_info,
		    &dip->disklabel);
#ifdef UNIX_DEBUG
		if (debug && st)
			printf("%s\n", st);
#endif
		if (!st) {
			dip->bios_info.flags &= ~BDI_BADLABEL;
			dip->bios_info.flags |= BDI_GOODLABEL;
		} else
			return ERDLAB;
	}

	part = bios_getdospart(&dip->bios_info);
	bios_devpath(dip->bios_info.bios_number, part, path);
	f->f_devdata = (void *)uopen(path, O_RDONLY);
	if ((int)f->f_devdata == -1)
		return errno;

	return 0;
}

int
unixclose(struct open_file *f)
{
	return uclose((int)f->f_devdata);
}

int
unixioctl(struct open_file *f, u_long cmd, void *data)
{
	return uioctl((int)f->f_devdata, cmd, data);
}

off_t
ulseek(int fd, off_t off, int wh)
{
	extern	long ulseek32(int, long, int);
	off_t	r;

	/* XXX only SEEK_SET is used, so anything else can fail for now. */

	if (wh == SEEK_SET) {
		if (ulseek32(fd, 0, SEEK_SET) != 0)
			return -1;
		while (off > OFFT_OFFSET_MAX) {
			off -= OFFT_OFFSET_MAX;
			if (ulseek32(fd, OFFT_OFFSET_MAX, SEEK_CUR) < 0 &&
			    errno != LINUX_EOVERFLOW)
				return -1;
		}
		r = ulseek32(fd, (long)off, SEEK_CUR);
		if (r == -1 && errno == LINUX_EOVERFLOW)
			r = off;
	} else
		r = ulseek32(fd, (long)off, wh);

	return r;
}

time_t
getsecs(void)
{
	return (time_t)syscall(__NR_time, NULL);
}

unsigned int
sleep(unsigned int seconds)
{
	unsigned int start;

	start = getsecs();
	while (getsecs() - start < seconds)
		;

	return (0);
}


code:
/*	$OpenBSD: unixdev.h,v 1.2 2011/03/13 00:13:53 deraadt Exp $	*/

/*
 * Copyright (c) 1996 Michael Shalayeff
 * 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 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 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.
 *
 */

/* unixdev.c */
int	unixstrategy(void *, int, daddr32_t, size_t, void *, size_t *);
int	unixopen(struct open_file *, ...);
int	unixclose(struct open_file *);
int	unixioctl(struct open_file *, u_long, void *);

/* unixcons.c */
void	cn_probe(struct consdev *);
void	cn_init(struct consdev *);
void	cn_putc(dev_t, int);
int	cn_getc(dev_t);
void	com_probe(struct consdev *);
void	com_init(struct consdev *);
void	com_putc(dev_t, int);
int	com_getc(dev_t);
int	comspeed(dev_t, int);

/* unixsys.S */
int	uopen(const char *, int, ...);
int	uread(int, void *, size_t);
int	uwrite(int, void *, size_t);
int	uioctl(int, u_long, char *);
int	uclose(int);
off_t	ulseek(int, off_t, int);
void	uexit(int) __attribute__((noreturn));
int	uselect(int, fd_set *, fd_set *, fd_set *, struct timeval *);
int	syscall(int, ...);
int	__syscall(quad_t, ...);


code:
/*	$OpenBSD: unixsys.S,v 1.6 2005/05/24 20:38:20 uwe Exp $	*/

/*
 * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
 *
 * 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 <machine/asm.h>

#include "compat_linux.h"

	.text

#define RSYSCALL(x) \
	ENTRY(u##x); \
		swi	__NR_##x; \
		b	1f

RSYSCALL(exit)
RSYSCALL(read)
RSYSCALL(write)
RSYSCALL(open)
RSYSCALL(close)
RSYSCALL(lseek32)
RSYSCALL(ioctl)
RSYSCALL(stat)

1:
	cmn	r0, #4096
	movcc	pc, lr
	rsb	r0, r0, #0
	ldr	r1, .Lerrno	/* XXX clobbers arg1 */
	str	r0, [r1]
	mvn	r0, #0
	mov	pc, lr

.Lerrno:
	.word	errno

/* XXX only works for up to four arguments. */
ENTRY(syscall)
	swi	__NR_syscall
	b	1b

ENTRY(uselect)
	str	r4, [sp, #-4]!
	ldr	r4, [sp, #4]
	swi	__NR_select
	ldr	r4, [sp], #4
	cmn	r0, #4096
	movcc	pc, lr
	rsb	r0, r0, #0
	str	r1, [sp, #-4]!
	ldr	r1, .Lerrno
	str	r0, [r1]
	ldr	r1, [sp], #4
	mvn	r0, #0
	mov	pc, lr

.data

	.global errno
errno:
	.word	0


code: src/sys/arch/zaurus/stand/zbsdmod


path: sys/arch/zaurus/stand/zbsdmod/CVS/Tag


code:
#	$OpenBSD: Makefile,v 1.5 2012/09/11 17:12:06 deraadt Exp $

OBJS= zbsdmod.o
SRCS= zbsdmod.c
NOMAN=

all: ${OBJS}

clean:
	rm -f zbsdmod.o

.include <bsd.prog.mk>

afterinstall:
	${INSTALL} ${INSTALL_COPY} -o root -g wheel -m 644 \
		${OBJS} ${DESTDIR}${BINDIR}

CFLAGS= -fno-stack-protector -Wall
CFLAGS+= -DMACHINE=\"${MACHINE}\" -DUTS_RELEASE=\"2.4.20\"
CPPFLAGS= -I${.CURDIR}/../include -fno-pie
LDFLAGS+= -nopie

path: sys/arch/zaurus/stand/zbsdmod/Makefile


code:
/*	$OpenBSD: compat_linux.h,v 1.8 2011/03/13 00:13:53 deraadt Exp $	*/

/*
 * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
 *
 * 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.
 */

#if 0

/* Define these unconditionally to get the .modinfo section. */
#undef __KERNEL__
#undef MODULE
#define __KERNEL__
#define MODULE

/* Standard headers for Linux LKMs */
#include <linux/kernel.h>
#include <linux/modsetver.h>
#include <linux/module.h>

/*
 * Include Linux 2.4.x headers.
 */
#include <linux/elf.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
#include <linux/file.h>
#include <linux/slab.h>
#include <asm/mach/map.h>

#else

/*
 * Declare the things that we need from the Linux headers.
 */

#define	IS_ERR(ptr)	((unsigned long)(ptr) > (unsigned long)-1000L)

#define MKDEV(ma,mi)	((ma)<<8 | (mi))

#define S_IFBLK		0060000
#define S_IFCHR		0020000

struct file;
struct inode;

typedef long loff_t;

/* BSD headers */
#include <sys/types.h>
#include <sys/exec_elf.h>
#include <errno.h>

struct file_operations {
	struct module *owner;
	void (*llseek) (void);
	ssize_t (*read) (struct file *, char *, size_t, loff_t *);
	ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
	void (*readdir) (void);
	void (*poll) (void);
	void (*ioctl) (void);
	void (*mmap) (void);
	int (*open) (struct inode *, struct file *);
	void (*flush) (void);
	int (*release) (struct inode *, struct file *);
	void (*fsync) (void);
	void (*fasync) (void);
	void (*lock) (void);
	void (*readv) (void);
	void (*writev) (void);
	void (*sendpage) (void);
	void (*get_unmapped_area)(void);
#ifdef MAGIC_ROM_PTR
	void (*romptr) (void);
#endif /* MAGIC_ROM_PTR */
};

extern	struct file * open_exec(const char *);
extern	void fput(struct file *);
extern	int kernel_read(struct file *, unsigned long, char *, unsigned long);
extern	int memcmp(const void *, const void *, size_t);
extern	int register_chrdev(unsigned int, const char *, struct file_operations *);
extern	int unregister_chrdev(unsigned int, const char *);
extern	void printk(const char *, ...)
    __attribute__((__format__(printf, 1, 2)));
extern	void *memcpy(void *, const void *, size_t);

/* Linux LKM support */
static const char __module_kernel_version[] __attribute__((section(".modinfo"))) =
"kernel_version=" UTS_RELEASE;
#if 1 /* def MODVERSIONS */
static const char __module_using_checksums[] __attribute__((section(".modinfo"))) =
"using_checksums=1";
#endif

/* procfs support */
struct proc_dir_entry {
        unsigned short low_ino;
        unsigned short namelen;
        const char *name;
        unsigned short mode;
        unsigned short nlink;
        unsigned short uid;
        unsigned short gid;
        unsigned long size;
        void *proc_iops; /* inode operations */
        struct file_operations * proc_fops;
        void *get_info;
        struct module *owner;
        struct proc_dir_entry *next, *parent, *subdir;
        void *data;
        void *read_proc;
        void *write_proc;
        volatile int count;
        int deleted;
        unsigned short rdev;
};
extern	struct proc_dir_entry proc_root;
extern	struct proc_dir_entry *proc_mknod(const char*, unsigned short,
    struct proc_dir_entry*, unsigned short);
extern	void remove_proc_entry(const char *, struct proc_dir_entry *);

#endif


code:
/*	$OpenBSD: zbsdmod.c,v 1.11 2015/01/18 14:55:02 jsg Exp $	*/

/*
 * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
 *
 * 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.
 *
 * Zaurus OpenBSD bootstrap loader.
 */

#include "compat_linux.h"

#define BOOTARGS_BUFSIZ	256
#define BOOTARGS_MAGIC	0x4f425344

#define ZBOOTDEV_MAJOR	99
#define ZBOOTDEV_MODE	0222
#define ZBOOTDEV_NAME	"zboot"
#define ZBOOTMOD_NAME	"zbsdmod"

/* Prototypes */
void	elf32bsdboot(void);
int	init_module(void);
void	cleanup_module(void);

ssize_t	zbsdmod_write(struct file *, const char *, size_t, loff_t *);
int	zbsdmod_open(struct inode *, struct file *);
int	zbsdmod_close(struct inode *, struct file *);

static	struct file_operations fops = {
	0,			/* struct module *owner */
	0,			/* lseek */
	0,			/* read */
	zbsdmod_write,		/* write */
	0,			/* readdir */
	0,			/* poll */
	0,			/* ioctl */
	0,			/* mmap */
	zbsdmod_open,		/* open */
	0,			/* flush */
	zbsdmod_close,		/* release */
	0,			/* sync */
	0,			/* async */
	0,			/* check media change */
	0,			/* revalidate */
	0,			/* lock */
};

static	int isopen;
static	loff_t position;

/* Outcast local variables to avoid stack usage in elf32bsdboot(). */
static	int cpsr;
static	unsigned int sz;
static	int i;
static	vaddr_t minv, maxv, posv;
static	vaddr_t elfv, shpv;
static	int *addr;
static	vaddr_t *esymp;
static	Elf_Shdr *shp;
static	Elf_Off off;
static	int havesyms;

/* The maximum size of a kernel image is restricted to 5MB. */
static	int bsdimage[1310720];	/* XXX use kmalloc() */
static	char bootargs[BOOTARGS_BUFSIZ];

/*
 * Boot the loaded BSD kernel image, or return if an error is found.
 * Part of this routine is borrowed from sys/lib/libsa/loadfile.c.
 */
void
elf32bsdboot(void)
{

#define elf	((Elf32_Ehdr *)bsdimage)
#define phdr	((Elf32_Phdr *)((char *)elf + elf->e_phoff))

	if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 ||
	    elf->e_ident[EI_CLASS] != ELFCLASS32)
		return;

	minv = (vaddr_t)~0;
	maxv = (vaddr_t)0;
	posv = (vaddr_t)0;
	esymp = 0;

	/*
	 * Get min and max addresses used by the loaded kernel.
	 */
	for (i = 0; i < elf->e_phnum; i++) {

		if (phdr[i].p_type != PT_LOAD ||
		    (phdr[i].p_flags & (PF_W|PF_R|PF_X)) == 0)
			continue;

#define IS_TEXT(p)	(p.p_flags & PF_X)
#define IS_DATA(p)	((p.p_flags & PF_X) == 0)
#define IS_BSS(p)	(p.p_filesz < p.p_memsz)
		/*
		 * XXX: Assume first address is lowest
		 */
		if (IS_TEXT(phdr[i]) || IS_DATA(phdr[i])) {
			posv = phdr[i].p_vaddr;
			if (minv > posv)
				minv = posv;
			posv += phdr[i].p_filesz;
			if (maxv < posv)
				maxv = posv;
		}
		if (IS_DATA(phdr[i]) && IS_BSS(phdr[i])) {
			posv += phdr[i].p_memsz;
			if (maxv < posv)
				maxv = posv;
		}
		/*
		 * 'esym' is the first word in the .data section,
		 * and marks the end of the symbol table.
		 */
		if (IS_DATA(phdr[i]) && !IS_BSS(phdr[i]))
			esymp = (vaddr_t *)phdr[i].p_vaddr;
	}

	__asm__ volatile ("mrs %0, cpsr" : "=r" (cpsr));
	cpsr |= 0xc0;  /* set FI */
	__asm__ volatile ("msr cpsr_c, %0" :: "r" (cpsr));

	/*
	 * Copy the boot arguments.
	 */
	sz = BOOTARGS_BUFSIZ;
	while (sz > 0) {
		sz--;
		((char *)minv - BOOTARGS_BUFSIZ)[sz] = bootargs[sz];
	}

	/*
	 * Set up pointers to copied ELF and section headers.
	 */
#define roundup(x, y)	((((x)+((y)-1))/(y))*(y))
	elfv = maxv = roundup(maxv, sizeof(long));
	maxv += sizeof(Elf_Ehdr);

	sz = elf->e_shnum * sizeof(Elf_Shdr);
	shp = (Elf_Shdr *)((vaddr_t)elf + elf->e_shoff);
	shpv = maxv;
	maxv += roundup(sz, sizeof(long));

	/*
	 * Now load the symbol sections themselves.  Make sure the
	 * sections are aligned, and offsets are relative to the
	 * copied ELF header.  Don't bother with string tables if
	 * there are no symbol sections.
	 */
	off = roundup((sizeof(Elf_Ehdr) + sz), sizeof(long));
	for (havesyms = i = 0; i < elf->e_shnum; i++)
		if (shp[i].sh_type == SHT_SYMTAB)
			havesyms = 1;
	for (i = 0; i < elf->e_shnum; i++) {
		if (shp[i].sh_type == SHT_SYMTAB ||
		    shp[i].sh_type == SHT_STRTAB) {
			if (havesyms) {
				sz = shp[i].sh_size;
				while (sz > 0) {
					sz--;
					((char *)maxv)[sz] =
					    ((char *)elf +
						shp[i].sh_offset)[sz];
				}
			}
			maxv += roundup(shp[i].sh_size, sizeof(long));
			shp[i].sh_offset = off;
			off += roundup(shp[i].sh_size, sizeof(long));
		}
	}

	/*
	 * Copy the ELF and section headers.
	 */
	sz = sizeof(Elf_Ehdr);
	while (sz > 0) {
		sz--;
		((char *)elfv)[sz] = ((char *)elf)[sz];
	}
	sz = elf->e_shnum * sizeof(Elf_Shdr);
	while (sz > 0) {
		sz--;
		((char *)shpv)[sz] = ((char *)shp)[sz];
	}

	/*
	 * Frob the copied ELF header to give information relative
	 * to elfv.
	 */
	((Elf_Ehdr *)elfv)->e_phoff = 0;
	((Elf_Ehdr *)elfv)->e_shoff = sizeof(Elf_Ehdr);
	((Elf_Ehdr *)elfv)->e_phentsize = 0;
	((Elf_Ehdr *)elfv)->e_phnum = 0;

	/*
	 * Tell locore.S where the symbol table ends, and arrange
	 * to skip esym when loading the data section.
	 */
	if (esymp != 0)
		*esymp = (vaddr_t)maxv;
	for (i = 0; esymp != 0 && i < elf->e_phnum; i++) {
		if (phdr[i].p_type != PT_LOAD ||
		    (phdr[i].p_flags & (PF_W|PF_R|PF_X)) == 0)
			continue;
		if (phdr[i].p_vaddr == (vaddr_t)esymp) {
			phdr[i].p_vaddr = (vaddr_t)((char *)phdr[i].p_vaddr + sizeof(long));
			phdr[i].p_offset = (vaddr_t)((char *)phdr[i].p_offset + sizeof(long));
			phdr[i].p_filesz -= sizeof(long);
			break;
		}
	}

	/*
	 * Load text and data.
	 */
	for (i = 0; i < elf->e_phnum; i++) {

		if (phdr[i].p_type != PT_LOAD ||
		    (phdr[i].p_flags & (PF_W|PF_R|PF_X)) == 0)
			continue;

		if (IS_TEXT(phdr[i]) || IS_DATA(phdr[i])) {
			sz = phdr[i].p_filesz;
			while (sz > 0) {
				sz--;
				((char *)phdr[i].p_vaddr)[sz] =
				    (((char *)elf) + phdr[i].p_offset)[sz];
			}
		}
	}

	addr = (int *)(elf->e_entry);
	__asm__ volatile (
		"mov  r0, %0;"
		"mov  r2, #0;"
		"mov  r1, #(0x00000010 | 0x00000020);"
		"mcr  15, 0, r1, c1, c0, 0;"
		"mcr  15, 0, r2, c8, c7, 0    /* nail I+D TLB on ARMv4 and greater */;"
		"mov  pc, r0" :: "r"(addr) : "r0","r1","r2");
}

/*
 * Initialize the LKM.
 */
int
init_module()
{
	struct proc_dir_entry *entry;
	int rc;

	rc = register_chrdev(ZBOOTDEV_MAJOR, ZBOOTDEV_NAME, &fops);
	if (rc != 0) {
		printk("%s: register_chrdev(%d, ...): error %d\n",
		    ZBOOTMOD_NAME, ZBOOTDEV_MAJOR, -rc);
		return 1;
	}

	entry = proc_mknod(ZBOOTDEV_NAME, ZBOOTDEV_MODE | S_IFCHR,
	    &proc_root, MKDEV(ZBOOTDEV_MAJOR, 0));
	if (entry == (struct proc_dir_entry *)0) {
		(void)unregister_chrdev(ZBOOTDEV_MAJOR, ZBOOTDEV_NAME);
		return 1;
	}

	printk("%s: OpenBSD/" MACHINE " bootstrap device is %d,0\n",
	    ZBOOTMOD_NAME, ZBOOTDEV_MAJOR);

	return 0;
}

/*
 * Cleanup - undo whatever init_module did.
 */
void
cleanup_module()
{

	(void)unregister_chrdev(ZBOOTDEV_MAJOR, ZBOOTDEV_NAME);
	remove_proc_entry(ZBOOTDEV_NAME, &proc_root);

	printk("%s: OpenBSD/" MACHINE " bootstrap device unloaded\n",
	    ZBOOTMOD_NAME);
}

ssize_t
zbsdmod_write(struct file *f, const char *buf, size_t len, loff_t *offp)
{

	if (len < 1)
		return 0;

	if (*offp + len >= sizeof(bsdimage))
		return EFBIG;

	memcpy(((char *)bsdimage) + *offp, buf, len);

	*offp += len;
	if (*offp > position)
		position = *offp;

	return len;
}

int
zbsdmod_open(struct inode *ino, struct file *f)
{

	/* XXX superuser check */

	if (isopen)
		return -EBUSY;

	isopen = 1;
	position = 0;

	return 0;
}

int
zbsdmod_close(struct inode *ino, struct file *f)
{

	if (isopen) {
		if (position > 0) {
			printk("%s: loaded %ld bytes\n", ZBOOTDEV_NAME,
			    position);

			if (position < BOOTARGS_BUFSIZ) {
				*(int *)bootargs = BOOTARGS_MAGIC;
				bootargs[position + sizeof(int)] = '\0';
				memcpy(bootargs + sizeof(int), bsdimage,
				    position);
			} else {
#ifndef _TEST
				elf32bsdboot();
				printk("%s: boot failed\n", ZBOOTDEV_NAME);
#else
				printk("/* boot() */\n");
#endif
			}
		}
		isopen = 0;
		return 0;
	}

	return -EBUSY;
}


code:
/autoconf.c/1.15/Tue Sep 20 22:02:13 2011//TOPENBSD_5_8_BASE
/genassym.cf/1.1/Mon Apr 26 22:11:38 2010//TOPENBSD_5_8_BASE
/zaurus_lcd.c/1.28/Fri Dec  6 21:03:05 2013//TOPENBSD_5_8_BASE
/zaurus_machdep.c/1.59/Sun May 10 15:56:28 2015//TOPENBSD_5_8_BASE
/zaurus_start.S/1.3/Wed Feb 12 05:31:58 2014//TOPENBSD_5_8_BASE
D

path: sys/arch/zaurus/zaurus/CVS/Entries


code: src/sys/arch/zaurus/zaurus

path: sys/arch/zaurus/zaurus/CVS/Repository


code:
/*	$OpenBSD: autoconf.c,v 1.15 2011/09/20 22:02:13 miod Exp $	*/
/*	$NetBSD: autoconf.c,v 1.2 2001/09/05 16:17:36 matt Exp $	*/

/*
 * Copyright (c) 1994-1998 Mark Brinicombe.
 * Copyright (c) 1994 Brini.
 * 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 Mark Brinicombe for
 *      the NetBSD project.
 * 4. The name of the company nor the name of the author may 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 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.
 *
 * RiscBSD kernel project
 *
 * autoconf.c
 *
 * Autoconfiguration functions
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/reboot.h>
#include <sys/disklabel.h>
#include <sys/device.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/timeout.h>
#include <sys/malloc.h>

#include <uvm/uvm_extern.h>

#include <machine/bootconfig.h>
#include <machine/intr.h>
#include <dev/cons.h>

struct device *bootdv = NULL;

void dumpconf(void);

/*
 * Now that we are fully operational, we can checksum the
 * disks, and using some heuristics, hopefully are able to
 * always determine the correct root disk.
 */
void
diskconf()
{
	extern struct timeout	scoop_checkdisk;
	dev_t tmpdev;

#if 0
	/*
	 * Configure root, swap, and dump area.  This is
	 * currently done by running the same checksum
	 * algorithm over all known disks, as was done in
	 * /boot.  Then we basically fixup the *dev vars
	 * from the info we gleaned from this.
	 */
	dkcsumattach();
#endif

	/*
	 * XXX
	 * zaurus bootblocks currently pass in "bsd" instead of
	 * "device:bsd", or any such thing, making this a real pain.
	 */
	if (bootdv == NULL)
		bootdv = parsedisk("wd0a", strlen("wd0a"), 0, &tmpdev);
	if (bootdv == NULL)
		printf("boot device: lookup '%s' failed.\n", boot_file);
	else
		printf("boot device: %s\n", bootdv->dv_xname);

	setroot(bootdv, 0, RB_USERREQ);
	dumpconf();

	timeout_add(&scoop_checkdisk, hz/25);
}

void
device_register(struct device *dev, void *aux)
{
}

/*
 * void cpu_configure()
 *
 * Configure all the root devices
 * The root devices are expected to configure their own children
 */
void
cpu_configure(void)
{
	softintr_init();

	/*
	 * Since various PCI interrupts could be routed via the ICU
	 * (for PCI devices in the bridge) we need to set up the ICU
	 * now so that these interrupts can be established correctly
	 * i.e. This is a hack.
	 */

	config_rootfound("mainbus", NULL);

	/*
	 * We can not know which is our root disk, defer
	 * until we can checksum blocks to figure it out.
	 */
	cold = 0;

	/* Time to start taking interrupts so lets open the flood gates .... */
	(void)spl0();

}

struct nam2blk nam2blk[] = {
	{ "wd",		16 },
	{ "sd",		24 },
	{ "cd",		26 },
	{ "rd",		18 },
	{ "raid",	71 },
	{ "vnd",	19 },
	{ NULL,		-1 }
};


code: #	$OpenBSD: genassym.cf,v 1.1 2010/04/26 22:11:38 deraadt Exp $


code:
/*	$OpenBSD: zaurus_lcd.c,v 1.28 2013/12/06 21:03:05 deraadt Exp $	*/
/* $NetBSD: lubbock_lcd.c,v 1.1 2003/08/09 19:38:53 bsh Exp $ */

/*
 * Copyright (c) 2002, 2003  Genetec Corporation.  All rights reserved.
 * Written by Hiroyuki Bessho for Genetec Corporation.
 *
 * 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. The name of Genetec Corporation may not be used to endorse or
 *    promote products derived from this software without specific prior
 *    written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``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 GENETEC CORPORATION
 * 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.
 */

/*
 * LCD driver for Sharp Zaurus (based on the Intel Lubbock driver).
 *
 * Controlling LCD is almost completely done through PXA2X0's
 * integrated LCD controller.  Codes for it is arm/xscale/pxa2x0_lcd.c.
 *
 * Codes in this file provide platform specific things including:
 *   LCD on/off switch and backlight brightness
 *   LCD panel geometry
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/uio.h>
#include <sys/malloc.h>

#include <dev/cons.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/wscons/wscons_callbacks.h>

#include <machine/bus.h>
#include <arm/xscale/pxa2x0var.h>
#include <arm/xscale/pxa2x0reg.h>
#include <arm/xscale/pxa2x0_lcd.h>

#include <zaurus/dev/zaurus_scoopvar.h>
#include <zaurus/dev/zaurus_sspvar.h>

#include <dev/rasops/rasops.h>

int	lcd_match(struct device *, void *, void *);
void	lcd_attach(struct device *, struct device *, void *);
int	lcd_activate(struct device *, int);
int	lcd_cnattach(void (*)(u_int, int));

/*
 * wsdisplay glue
 */
struct pxa2x0_wsscreen_descr
lcd_bpp16_screen = {
	{
		"std"
	},
	16,				/* bits per pixel */
	RI_ROTATE_CW			/* quarter clockwise rotation */
};

static const struct wsscreen_descr *lcd_scr_descr[] = {
	&lcd_bpp16_screen.c
};

const struct wsscreen_list lcd_screen_list = {
	sizeof lcd_scr_descr / sizeof lcd_scr_descr[0], lcd_scr_descr
};

int	lcd_ioctl(void *, u_long, caddr_t, int, struct proc *);
int	lcd_show_screen(void *, void *, int,
	    void (*)(void *, int, int), void *);
void	lcd_burner(void *, u_int, u_int);

int	lcd_param(struct pxa2x0_lcd_softc *, u_long, struct wsdisplay_param *);

const struct wsdisplay_accessops lcd_accessops = {
	.ioctl = lcd_ioctl,
	.mmap = pxa2x0_lcd_mmap,
	.alloc_screen = pxa2x0_lcd_alloc_screen,
	.free_screen = pxa2x0_lcd_free_screen,
	.show_screen = lcd_show_screen,
	.load_font = pxa2x0_lcd_load_font,
	.list_font = pxa2x0_lcd_list_font,
	.burn_screen = lcd_burner
};

struct cfattach lcd_pxaip_ca = {
	sizeof (struct pxa2x0_lcd_softc), lcd_match, lcd_attach, NULL,
	lcd_activate
};

struct cfdriver lcd_cd = {
	NULL, "lcd", DV_DULL
};

#define CURRENT_DISPLAY &sharp_zaurus_C3000

const struct lcd_panel_geometry sharp_zaurus_C3000 =
{
	480,			/* Width */
	640,			/* Height */
	0,			/* No extra lines */

	LCDPANEL_ACTIVE | LCDPANEL_VSP | LCDPANEL_HSP,
	1,			/* clock divider */
	0,			/* AC bias pin freq */

	0x28,			/* horizontal sync pulse width */
	0x2e,			/* BLW */
	0x7d,			/* ELW */

	2,			/* vertical sync pulse width */
	1,			/* BFW */
	0,			/* EFW */
};

struct sharp_lcd_backlight {
	int	duty;		/* LZ9JG18 DAC value */
	int	cont;		/* BACKLIGHT_CONT signal */
	int	on;		/* BACKLIGHT_ON signal */
};

#define CURRENT_BACKLIGHT sharp_zaurus_C3000_bl

const struct sharp_lcd_backlight sharp_zaurus_C3000_bl[] = {
	{ 0x00, 0, 0 },		/* 0:     Off */
	{ 0x00, 0, 1 },		/* 1:      0% */
	{ 0x01, 0, 1 },		/* 2:     20% */
	{ 0x07, 0, 1 },		/* 3:     40% */
	{ 0x01, 1, 1 },		/* 4:     60% */
	{ 0x07, 1, 1 },		/* 5:     80% */
	{ 0x11, 1, 1 },		/* 6:    100% */
	{ -1, -1, -1 }		/* 7: Invalid */
};

int	lcd_max_brightness(void);
int	lcd_get_brightness(void);
void	lcd_set_brightness(int);
void	lcd_set_brightness_internal(int);
int	lcd_get_backlight(void);
void	lcd_set_backlight(int);
void	lcd_blank(int);

int
lcd_match(struct device *parent, void *cf, void *aux)
{
	return 1;
}

void
lcd_attach(struct device *parent, struct device *self, void *aux)
{
	struct pxa2x0_lcd_softc *sc = (struct pxa2x0_lcd_softc *)self;
	struct wsemuldisplaydev_attach_args aa;
	extern int glass_console;

	printf("\n");

	pxa2x0_lcd_attach_sub(sc, aux, &lcd_bpp16_screen, CURRENT_DISPLAY,
	    glass_console);

	aa.console = glass_console;
	aa.scrdata = &lcd_screen_list;
	aa.accessops = &lcd_accessops;
	aa.accesscookie = sc;
	aa.defaultscreens = 0;

	(void)config_found(self, &aa, wsemuldisplaydevprint);

	/* Start with approximately 40% of full brightness. */
	lcd_set_brightness(3);
}

int
lcd_cnattach(void (*clkman)(u_int, int))
{
	return
	    (pxa2x0_lcd_cnattach(&lcd_bpp16_screen, CURRENT_DISPLAY, clkman));
}

/*
 * wsdisplay accessops overrides
 */

int
lcd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
{
	struct pxa2x0_lcd_softc *sc = v;
	int res = EINVAL;

	switch (cmd) {
	case WSDISPLAYIO_GETPARAM:
	case WSDISPLAYIO_SETPARAM:
		res = lcd_param(sc, cmd, (struct wsdisplay_param *)data);
		break;
	}

	if (res == EINVAL)
		res = pxa2x0_lcd_ioctl(v, cmd, data, flag, p);

	return res;
}

void
lcd_burner(void *v, u_int on, u_int flags)
{

	lcd_set_brightness(on ? lcd_get_brightness() : 0);
}

int
lcd_show_screen(void *v, void *cookie, int waitok,
    void (*cb)(void *, int, int), void *cbarg)
{
	int rc;

	if ((rc = pxa2x0_lcd_show_screen(v, cookie, waitok, cb, cbarg)) != 0)
		return (rc);

	/* Turn on LCD */
	lcd_burner(v, 1, 0);

	return (0);
}

/*
 * wsdisplay I/O controls
 */

int
lcd_param(struct pxa2x0_lcd_softc *sc, u_long cmd,
    struct wsdisplay_param *dp)
{
	int res = EINVAL;

	switch (dp->param) {
	case WSDISPLAYIO_PARAM_BACKLIGHT:
		if (cmd == WSDISPLAYIO_GETPARAM) {
			dp->min = 0;
			dp->max = 1;
			dp->curval = lcd_get_backlight();
			res = 0;
		} else if (cmd == WSDISPLAYIO_SETPARAM) {
			lcd_set_backlight(dp->curval);
			res = 0;
		}
		break;

	case WSDISPLAYIO_PARAM_CONTRAST:
		/* unsupported */
		res = ENOTTY;
		break;

	case WSDISPLAYIO_PARAM_BRIGHTNESS:
		if (cmd == WSDISPLAYIO_GETPARAM) {
			dp->min = 1;
			dp->max = lcd_max_brightness();
			dp->curval = lcd_get_brightness();
			res = 0;
		} else if (cmd == WSDISPLAYIO_SETPARAM) {
			lcd_set_brightness(dp->curval);
			res = 0;
		}
		break;
	}

	return res;
}

/*
 * LCD backlight
 */

static	int lcdbrightnesscurval = 1;
static	int lcdislit = 1;
static	int lcdisblank = 0;

int
lcd_max_brightness(void)
{
	int i;

	for (i = 0; CURRENT_BACKLIGHT[i].duty != -1; i++)
		;
	return i - 1;
}

int
lcd_get_brightness(void)
{

	return lcdbrightnesscurval;
}

void
lcd_set_brightness(int newval)
{
	int max;

	max = lcd_max_brightness();
	if (newval < 0)
		newval = 0;
	else if (newval > max)
		newval = max;

	if (lcd_get_backlight() && !lcdisblank)
		lcd_set_brightness_internal(newval);

	if (newval > 0)
		lcdbrightnesscurval = newval;
}

void
lcd_set_brightness_internal(int newval)
{
	static int curval = 1;
	int i;

	/*
	 * It appears that the C3000 backlight can draw too much power if we
	 * switch it from a low to a high brightness.  Increasing brightness
	 * in steps avoids this issue.
	 */
	if (newval > curval) {
		for (i = curval + 1; i <= newval; i++) {
			(void)zssp_ic_send(ZSSP_IC_LZ9JG18,
			    CURRENT_BACKLIGHT[i].duty);
			scoop_set_backlight(CURRENT_BACKLIGHT[i].on,
			    CURRENT_BACKLIGHT[i].cont);
			delay(5000);
		}
	} else {
		(void)zssp_ic_send(ZSSP_IC_LZ9JG18,
		    CURRENT_BACKLIGHT[newval].duty);
		scoop_set_backlight(CURRENT_BACKLIGHT[newval].on,
		    CURRENT_BACKLIGHT[newval].cont);
	}

	curval = newval;
}

int
lcd_get_backlight(void)
{

	return lcdislit;
}

void
lcd_set_backlight(int on)
{

	if (!on) {
		lcd_set_brightness(0);
		lcdislit = 0;
	} else {
		lcdislit = 1;
		lcd_set_brightness(lcd_get_brightness());
	}
}

void
lcd_blank(int blank)
{

	if (blank) {
		lcd_set_brightness(0);
		lcdisblank = 1;
	} else {
		lcdisblank = 0;
		lcd_set_brightness(lcd_get_brightness());
	}
}

int
lcd_activate(struct device *self, int act)
{
	struct pxa2x0_lcd_softc *sc = (struct pxa2x0_lcd_softc *)self;
	int ret = 0;

	switch (act) {
	case DVACT_SUSPEND:
		lcd_set_brightness(0);
		pxa2x0_lcd_suspend(sc);
		break;
	case DVACT_RESUME:
		pxa2x0_lcd_resume(sc);
		lcd_set_brightness(lcd_get_brightness());
		break;
	default:
		ret = config_activate_children(self, act);
		break;
	}
	return (ret);
}