code:
/*	$OpenBSD: pdc.c,v 1.21 2013/03/23 16:08:28 deraadt Exp $	*/

/*
 * Copyright (c) 1998-2004 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.
 */
/*
 * Copyright 1996 1995 by Open Software Foundation, Inc.
 *              All Rights Reserved
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appears in all copies and
 * that both the copyright notice and this permission notice appear in
 * supporting documentation.
 *
 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE.
 *
 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */
/*
 * Copyright (c) 1990 mt Xinu, Inc.  All rights reserved.
 * Copyright (c) 1990 University of Utah.  All rights reserved.
 *
 * This file may be freely distributed in any form as long as
 * this copyright notice is included.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 *	Utah $Hdr: pdc.c 1.8 92/03/14$
 */

#include <sys/param.h>
#include <sys/time.h>
#include "libsa.h"
#include <sys/reboot.h>
#include <sys/disklabel.h>

#include <machine/trap.h>
#include <machine/pdc.h>
#include <machine/iomod.h>
#include <machine/nvm.h>
#include <machine/cpufunc.h>

#include "dev_hppa.h"

/*
 * Interface routines to initialize and access the PDC.
 */

pdcio_t pdc;
int	pdcbuf[64] PDC_ALIGNMENT;/* PDC return buffer */
struct	stable_storage sstor;	/* contents of Stable Storage */
int	sstorsiz;		/* size of Stable Storage */
struct bootdata bd;
int bdsize = sizeof(struct bootdata);

/*
 * Initialize PDC and related variables.
 */
void
pdc_init()
{
	int err;

	/*
	 * Initialize important global variables (defined above).
	 */
	pdc = (pdcio_t)PAGE0->mem_pdc;

	err = (*pdc)(PDC_STABLE, PDC_STABLE_SIZE, pdcbuf, 0, 0);
	if (err >= 0) {
		sstorsiz = min(pdcbuf[0],sizeof(sstor));
		err = (*pdc)(PDC_STABLE, PDC_STABLE_READ, 0, &sstor, sstorsiz);
	}

	/*
	 * Now that we (may) have an output device, if we encountered
	 * an error reading Stable Storage (above), let them know.
	 */
#ifdef DEBUG
	if (debug && err)
		printf("Stable storage PDC_STABLE Read Ret'd %d\n", err);
#endif

	/*
	 * Clear the FAULT light (so we know when we get a real one)
	 */
	(*pdc)(PDC_CHASSIS, PDC_CHASSIS_DISP,
	    PDC_OSTAT(PDC_OSTAT_BOOT) | 0xCEC0);
}

/*
 * Generic READ/WRITE through IODC.  Takes pointer to PDC device
 * information, returns (positive) number of bytes actually read or
 * the (negative) error condition, or zero if at "EOF".
 */
int
iodcstrategy(devdata, rw, blk, size, buf, rsize)
	void *devdata;
	int rw;
	daddr32_t blk;
	size_t size;
	void *buf;
	size_t *rsize;
{
	struct hppa_dev *dp = devdata;
	struct pz_device *pzdev = dp->pz_dev;
	int	offset, xfer, ret;

#ifdef PDCDEBUG
	if (debug)
		printf("iodcstrategy(%p, %s, %u, %u, %p, %p)\n", devdata,
		    rw==F_READ? "READ" : "WRITE", blk, size, buf, rsize);

	if (debug > 1)
		PZDEV_PRINT(pzdev);
#endif

	blk += dp->fsoff;
	blk *= DEV_BSIZE;
	if ((pzdev->pz_class & PCL_CLASS_MASK) == PCL_SEQU) {
		/* rewind and re-read to seek */
		if (blk < dp->last_blk) {
#ifdef PDCDEBUG
			if (debug)
				printf("iodc: rewind ");
#endif
			if ((ret = ((iodcio_t)pzdev->pz_iodc_io)(pzdev->pz_hpa,
			    IODC_IO_READ, pzdev->pz_spa, pzdev->pz_layers,
			    pdcbuf, 0, dp->buf, 0, 0)) < 0) {
#ifdef DEBUG
				if (debug)
					printf("IODC_IO: %d\n", ret);
#endif
				return (EIO);
			} else {
				dp->last_blk = 0;
				dp->last_read = 0;
			}
		}

#ifdef PDCDEBUG
		if (debug)
			printf("seek %d ", dp->last_blk);
#endif
		for (; (dp->last_blk + dp->last_read) <= blk;
		     dp->last_read = ret) {
			twiddle();
			dp->last_blk += dp->last_read;
			if ((ret = ((iodcio_t)pzdev->pz_iodc_io)(pzdev->pz_hpa,
			    IODC_IO_READ, pzdev->pz_spa, pzdev->pz_layers,
			    pdcbuf, dp->last_blk, dp->buf, IODC_IOSIZ,
			    IODC_IOSIZ)) < 0) {
#ifdef DEBUG
				if (debug)
					printf("IODC_IO: %d\n", ret);
#endif
				return (EIO);
			}
			if ((ret = pdcbuf[0]) == 0)
				break;
#ifdef PDCDEBUG
			if (debug)
				printf("-");
#endif
		}
#ifdef PDCDEBUG
		if (debug)
			printf("> %d[%d]\n", dp->last_blk, dp->last_read);
#endif
	}

	xfer = 0;
	/* see if we can scratch anything from buffer */
	if (dp->last_blk <= blk && (dp->last_blk + dp->last_read) > blk) {
		twiddle();
		offset = blk - dp->last_blk;
		xfer = min(dp->last_read - offset, size);
		size -= xfer;
		blk += xfer;
#ifdef PDCDEBUG
		if (debug)
			printf("off=%d,xfer=%d,size=%d,blk=%d\n",
			    offset, xfer, size, blk);
#endif
		bcopy(dp->buf + offset, buf, xfer);
		buf += xfer;
	}

	/*
	 * double buffer it all the time, to cache
	 */
	for (; size; size -= ret, buf += ret, blk += ret, xfer += ret) {
		offset = blk & IOPGOFSET;
		if ((ret = ((iodcio_t)pzdev->pz_iodc_io)(pzdev->pz_hpa,
		    (rw == F_READ? IODC_IO_READ: IODC_IO_WRITE),
		    pzdev->pz_spa, pzdev->pz_layers, pdcbuf,
		    blk - offset, dp->buf, IODC_IOSIZ, IODC_IOSIZ)) < 0) {
#ifdef DEBUG
			if (debug)
				printf("iodc_read(%d,%d): %d\n",
				    blk - offset, IODC_IOSIZ, ret);
#endif
			if (xfer)
				break;
			else
				return (EIO);
		}
		if ((ret = pdcbuf[0]) <= 0)
			break;
		dp->last_blk = blk - offset;
		dp->last_read = ret;
		if ((ret -= offset) > size)
			ret = size;
		bcopy(dp->buf + offset, buf, ret);
#ifdef PDCDEBUG
		if (debug)
			printf("read %d(%d,%d)@%x ", ret,
			    dp->last_blk, dp->last_read, (u_int)buf);
#endif
	    }

#ifdef PDCDEBUG
	if (debug)
		printf("\n");
#endif

	if (rsize)
		*rsize = xfer;
	return (0);
}

/*
 * Find a device with specified unit number
 * (any if unit == -1), and of specified class (PCL_*).
 */
struct pz_device *
pdc_findev(unit, class)
	int unit, class;
{
	static struct pz_device pz;
	int layers[sizeof(pz.pz_layers)/sizeof(pz.pz_layers[0])];
	struct iomod *io;
	iodcio_t iodc;
	int err = 0;

#ifdef	PDCDEBUG
	if (debug)
		printf("pdc_finddev(%d, %x)\n", unit, class);
#endif
	iodc = (iodcio_t)(PAGE0->mem_free + IODC_MAXSIZE);
	io = (struct iomod *)PAGE0->mem_boot.pz_hpa;

	/* quick hack for boot device */
	if (PAGE0->mem_boot.pz_class == class &&
	    (unit == -1 || PAGE0->mem_boot.pz_layers[0] == unit)) {

		bcopy (&PAGE0->mem_boot.pz_dp, &pz.pz_dp, sizeof(pz.pz_dp));
		bcopy (pz.pz_layers, layers, sizeof(layers));
		if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, pdcbuf, io,
		    IODC_INIT, iodc, IODC_MAXSIZE)) < 0) {
#ifdef DEBUG
			if (debug)
				printf("IODC_READ: %d\n", err);
#endif
			return NULL;
		}
	} else {
		struct pdc_memmap memmap;
		struct iodc_data mptr;
		int i, stp;

		for (i = 0; i < 0xf; i++) {
			pz.pz_bc[0] = pz.pz_bc[1] =
			pz.pz_bc[2] = pz.pz_bc[3] = -1;
			pz.pz_bc[4] = 2;
			pz.pz_bc[5] = 0;	/* core bus */
			pz.pz_mod = i;
			if ((pdc)(PDC_MEMMAP, PDC_MEMMAP_HPA, &memmap,
			    &pz.pz_dp) < 0)
				continue;
#ifdef PDCDEBUG
			if (debug)
				printf("memap: %d.%d.%d, hpa=%x, mpgs=%x\n",
				    pz.pz_bc[4], pz.pz_bc[5], pz.pz_mod,
				    memmap.hpa, memmap.morepages);
#endif
			io = (struct iomod *) memmap.hpa;

			if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, &pdcbuf, io,
			    IODC_DATA, &mptr, sizeof(mptr))) < 0) {
#ifdef DEBUG
				if (debug)
					printf("IODC_DATA: %d\n", err);
#endif
				continue;
			}

			if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, pdcbuf, io,
			    IODC_INIT, iodc, IODC_MAXSIZE)) < 0) {
#ifdef DEBUG
				if (debug)
					printf("IODC_READ: %d\n", err);
#endif
				continue;
			}

			stp = IODC_INIT_FIRST;
			do {
				if ((err = (iodc)((u_int)io, stp, io->io_spa,
				    layers, pdcbuf, 0, 0, 0, 0)) < 0) {
#ifdef DEBUG
					if (debug && err != PDC_ERR_EOD)
						printf("IODC_INIT_%s: %d\n",
						    stp==IODC_INIT_FIRST?
						    "FIRST":"NEXT", err);
#endif
					break;
				}
#ifdef PDCDEBUG
				if (debug)
					printf("[%x,%x,%x,%x,%x,%x], "
					    "[%x,%x,%x,%x,%x,%x]\n",
					    pdcbuf[0], pdcbuf[1], pdcbuf[2],
					    pdcbuf[3], pdcbuf[4], pdcbuf[5],
					    layers[0], layers[1], layers[2],
					    layers[3], layers[4], layers[5]);
#endif
				stp = IODC_INIT_NEXT;

			} while (pdcbuf[1] != class &&
				 unit != -1 && unit != layers[0]);

			if (err >= 0)
				break;
		}
	}

	if (err >= 0) {
		/* init device */
		if (0  && (err = (iodc)((u_int)io, IODC_INIT_DEV, io->io_spa,
		    layers, pdcbuf, 0, 0, 0, 0)) < 0) {
#ifdef DEBUG
			if (debug)
				printf("INIT_DEV: %d\n", err);
#endif
			return NULL;
		}

		/* read i/o entry code */
		if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, pdcbuf, io,
		    IODC_IO, iodc, IODC_MAXSIZE)) < 0) {
#ifdef DEBUG
			if (debug)
				printf("IODC_READ: %d\n", err);
#endif
			return NULL;
		}

		pz.pz_flags = 0;
		bcopy(layers, pz.pz_layers, sizeof(pz.pz_layers));
		pz.pz_hpa = (u_int)io;
/* XXX		pz.pz_spa = io->io_spa; */
		pz.pz_iodc_io = (u_int)iodc;
		pz.pz_class = class;

		return &pz;
	}

	return NULL;
}

static __inline void
fall(int c_base, int c_count, int c_loop, int c_stride, int data)
{
        int loop;                  /* Internal vars */

        for (; c_count--; c_base += c_stride)
                for (loop = c_loop; loop--; )
			if (data)
				fdce(0, c_base);
			else
				fice(0, c_base);
}

/*
 * fcacheall - Flush all caches.
 *
 * This routine is just a wrapper around the real cache flush routine.
 */
struct pdc_cache pdc_cacheinfo PDC_ALIGNMENT;

void
fcacheall()
{
	int err;

        if ((err = (*pdc)(PDC_CACHE, PDC_CACHE_DFLT, &pdc_cacheinfo)) < 0) {
#ifdef DEBUG
		if (debug)
			printf("fcacheall: PDC_CACHE failed (%d).\n", err);
#endif
		return;
        }
#if PDCDEBUG
	if (debug)
		printf("pdc_cache:\nic={%u,%x,%x,%u,%u,%u}\n"
		       "dc={%u,%x,%x,%u,%u,%u}\n",
		       pdc_cacheinfo.ic_size, *(u_int *)&pdc_cacheinfo.ic_conf,
		       pdc_cacheinfo.ic_base, pdc_cacheinfo.ic_stride,
		       pdc_cacheinfo.ic_count, pdc_cacheinfo.ic_loop,
		       pdc_cacheinfo.dc_size, *(u_int *)&pdc_cacheinfo.ic_conf,
		       pdc_cacheinfo.dc_base, pdc_cacheinfo.dc_stride,
		       pdc_cacheinfo.dc_count, pdc_cacheinfo.dc_loop);
#endif
        /*
         * Flush the instruction, then data cache.
         */
        fall(pdc_cacheinfo.ic_base, pdc_cacheinfo.ic_count,
	     pdc_cacheinfo.ic_loop, pdc_cacheinfo.ic_stride, 0);
	sync_caches();
        fall(pdc_cacheinfo.dc_base, pdc_cacheinfo.dc_count,
	     pdc_cacheinfo.dc_loop, pdc_cacheinfo.dc_stride, 1);
	sync_caches();
}


code:
/*	$OpenBSD: time.c,v 1.5 2004/04/07 18:24:20 mickey Exp $	*/

/*
 * Copyright (c) 1998-2004 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 <machine/pdc.h>
#include <sys/disklabel.h>
#include "libsa.h"
#include "dev_hppa.h"

time_t
getsecs()
{
	time_t tt;
	int err;

	if ((err = (*pdc)(PDC_TOD, PDC_TOD_READ, &pdcbuf)) < 0) {
		tt = 0;
#ifdef DEBUG
		if (debug)
			printf("getsecs: TOD read failed (%d)\n", err);
#endif
	} else {
		tt = ((struct pdc_tod *)pdcbuf)->sec;
#ifdef DEBUG
		if (debug && tt < 800000000)
			printf("getsecs: got %u seconds\n", tt);
#endif
	}

	return tt;
}

license: unknown


code:
/Makefile/1.4/Fri Aug 31 16:13:20 2012//TOPENBSD_5_8_BASE
D

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


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

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


code:
#	$OpenBSD: Makefile,v 1.4 2012/08/31 16:13:20 pascal Exp $

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

.PATH: ${S}/lib/libz

.include "${S}/lib/libz/Makefile"
CFLAGS+=${SACFLAGS} -I${S}/lib/libsa -fno-pie

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


path: sys/arch/hppa/stand/mkboot/CVS/Entries


path: sys/arch/hppa/stand/mkboot/CVS/Tag


code:
#	$OpenBSD: Makefile,v 1.6 2003/07/19 00:03:52 david Exp $

MAN=	mkboot.8
MANSUBDIR=hppa

.if ${MACHINE} == "hppa"
PROG=	mkboot
CC=	${HOSTCC}
LDSTATIC=	-static
.else
NOPROG=
.endif

.include <bsd.prog.mk>

path: sys/arch/hppa/stand/mkboot/Makefile


code:
/*	$OpenBSD: mkboot.c,v 1.20 2014/10/26 10:32:30 miod Exp $	*/

/*
 * Copyright (c) 1990, 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.
 *
 *	@(#)mkboot.c	8.1 (Berkeley) 7/15/93
 */

#include <sys/param.h>
#include <sys/exec.h>
#include <sys/exec_elf.h>
#include <sys/file.h>
#include <sys/stat.h>

#include <ctype.h>
#include <err.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#ifndef hppa
/* hack for cross compile XXX */
#include "../../include/disklabel.h"
#else
#include <sys/disklabel.h>
#endif

int putfile(char *, int);
void __dead usage(void);
void bcddate(char *, char *);
char *lifname(char *);
int cksum(int, int *, int);

char *to_file;
int loadpoint, verbose;
u_long entry;

/*
 * Old Format:
 *	sector 0:	LIF volume header (40 bytes)
 *	sector 1:	<unused>
 *	sector 2:	LIF directory (8 x 32 == 256 bytes)
 *	sector 3-:	LIF file 0, LIF file 1, etc.
 * where sectors are 256 bytes.
 *
 * New Format:
 *	sector 0:	LIF volume header (40 bytes)
 *	sector 1:	<unused>
 *	sector 2:	LIF directory (8 x 32 == 256 bytes)
 *	sector 3:	<unused>
 *	sector 4-31:	disklabel (~300 bytes right now)
 *	sector 32-:	LIF file 0, LIF file 1, etc.
 */
int
main(int argc, char **argv)
{
	int to;
	register int n, pos, c;
	char buf[LIF_FILESTART];
	struct lifvol *lifv = (struct lifvol *)buf;
	struct lifdir *lifd = (struct lifdir *)(buf + LIF_DIRSTART);

	while ((c = getopt(argc, argv, "vl:")) != -1) {
		switch (c) {
		case 'v':
			verbose++;
			break;
		case 'l':
			sscanf(optarg, "0x%x", &loadpoint);
			break;
		default:
			usage();
		}
	}
	if (argc - optind < 2)
		usage();
	else if (argc - optind > 8)
		errx(1, "too many boot programs (max 8 supported)");

	to_file = argv[--argc];
	if ((to = open(to_file, O_RDWR | O_TRUNC | O_CREAT, 0644)) < 0)
		err(1, "%s: open", to_file);

	bzero(buf, sizeof(buf));
	/* clear possibly unused directory entries */
	memset(lifd[1].dir_name, ' ', sizeof lifd[1].dir_name);
	lifd[1].dir_type = -1;
	lifd[1].dir_addr = 0;
	lifd[1].dir_length = 0;
	lifd[1].dir_flag = 0xFF;
	lifd[1].dir_implement = 0;
	lifd[7] = lifd[6] = lifd[5] = lifd[4] = lifd[3] = lifd[2] = lifd[1];

	/* record volume info */
	lifv->vol_id = htobe16(LIF_VOL_ID);
	strncpy(lifv->vol_label, "BOOT44", 6);
	lifv->vol_addr = htobe32(btolifs(LIF_DIRSTART));
	lifv->vol_oct = htobe16(LIF_VOL_OCT);
	lifv->vol_dirsize = htobe32(btolifs(LIF_DIRSIZE));
	lifv->vol_version = htobe16(1);
	lifv->vol_lastvol = lifv->vol_number =  htobe16(1);
	lifv->vol_length = LIF_FILESTART;
	bcddate(to_file, lifv->vol_toc);
	lifv->ipl_addr = htobe32(LIF_FILESTART);
	lifv->ipl_size = 0;
	lifv->ipl_entry = 0;

	argv += optind;
	argc -= optind;
	optind = 0;
	for (pos = LIF_FILESTART; optind < argc; optind++) {

		/* output bootfile */
		lseek(to, pos, 0);
		lifd[optind].dir_addr = htobe32(btolifs(pos));
		n = btolifs(putfile(argv[optind], to));
		if (lifv->ipl_entry == 0) {
			lifv->ipl_entry = htobe32(loadpoint + entry);
			lifv->ipl_size = htobe32(lifstob(n));
			lifd[optind].dir_type = htobe16(LIF_DIR_ISL);
			lifd[optind].dir_implement = 0;
		} else {
			lifd[optind].dir_type = htobe16(LIF_DIR_TYPE);
			lifd[1].dir_implement = htobe32(loadpoint + entry);
		}

		strlcpy(lifd[optind].dir_name, lifname(argv[optind]),
		    sizeof lifd[optind].dir_name);
		lifd[optind].dir_length = htobe32(n);
		bcddate(argv[optind], lifd[optind].dir_toc);
		lifd[optind].dir_flag = htobe16(LIF_DIR_FLAG);

		lifv->vol_length += n;
		pos += lifstob(n);
	}

	lifv->vol_length = htobe32(lifv->vol_length);

	/* output volume/directory header info */
	lseek(to, LIF_VOLSTART, 0);
	if (write(to, buf, sizeof(buf)) != sizeof(buf))
		err(1, "%s: write LIF volume", to_file);
	lseek(to, 0, SEEK_END);

	if (close(to) < 0)
		err(1, "%s", to_file);

	return (0);
}

int
putfile(char *from_file, int to)
{
	struct exec ex;
	register int n, total;
	char buf[2048];
	int from, check_sum = 0;
	struct lif_load load;

	if ((from = open(from_file, O_RDONLY)) < 0)
		err(1, "%s", from_file);

	n = read(from, &ex, sizeof(ex));
	if (n != sizeof(ex))
		err(1, "%s: reading file header", from_file);

	entry = ex.a_entry;
	if (N_GETMAGIC(ex) == OMAGIC || N_GETMAGIC(ex) == NMAGIC)
		entry += sizeof(ex);
	else if (IS_ELF(*(Elf32_Ehdr *)&ex)) {
		Elf32_Ehdr elf_header;
		Elf32_Phdr *elf_segments;
		int i, header_count, memory_needed, elf_load_image_segment;

		(void) lseek(from, 0, SEEK_SET);
		n = read(from, &elf_header, sizeof(elf_header));
		if (n != sizeof (elf_header))
			err(1, "%s: reading ELF header", from_file);
		header_count = ntohs(elf_header.e_phnum);
		elf_segments = reallocarray(NULL, header_count,
		    sizeof(*elf_segments));
		if (elf_segments == NULL)
			err(1, "malloc");
		memory_needed = header_count * sizeof(*elf_segments);
		(void) lseek(from, ntohl(elf_header.e_phoff), SEEK_SET);
		n = read(from, elf_segments, memory_needed);
		if (n != memory_needed)
			err(1, "%s: reading ELF segments", from_file);
		elf_load_image_segment = -1;
		for (i = 0; i < header_count; i++) {
			if (elf_segments[i].p_filesz &&
			    ntohl(elf_segments[i].p_flags) & PF_X) {
				if (elf_load_image_segment != -1)
					errx(1, "%s: more than one ELF program segment", from_file);
				elf_load_image_segment = i;
			}
		}
		if (elf_load_image_segment == -1)
			errx(1, "%s: no suitable ELF program segment", from_file);
		entry = ntohl(elf_header.e_entry) +
			ntohl(elf_segments[elf_load_image_segment].p_offset) -
			ntohl(elf_segments[elf_load_image_segment].p_vaddr);
		free(elf_segments);
	} else if (*(u_char *)&ex == 0x1f && ((u_char *)&ex)[1] == 0x8b) {
		entry = 0;
	} else
		errx(1, "%s: bad magic number", from_file);

	entry += sizeof(load);
	lseek(to, sizeof(load), SEEK_CUR);
	total = 0;
	n = sizeof(buf) - sizeof(load);
	/* copy the whole file */
	for (lseek(from, 0, 0); ; n = sizeof(buf)) {
		bzero(buf, sizeof(buf));
		if ((n = read(from, buf, n)) < 0)
			err(1, "%s", from_file);
		else if (n == 0)
			break;

		if (write(to, buf, n) != n)
			err(1, "%s", to_file);

		total += n;
		check_sum = cksum(check_sum, (int *)buf, n);
	}

	/* load header */
	load.address = htobe32(loadpoint + sizeof(load));
	load.count = htobe32(4 + total);
	check_sum = cksum(check_sum, (int *)&load, sizeof(load));

	if (verbose)
		warnx("wrote %d bytes of file \'%s\'", total, from_file);

	total += sizeof(load);
	/* insert the header */
	lseek(to, -total, SEEK_CUR);
	if (write(to, &load, sizeof(load)) != sizeof(load))
		err(1, "%s", to_file);
	lseek(to, total - sizeof(load), SEEK_CUR);

	bzero(buf, sizeof(buf));
	/* pad to int */
	n = sizeof(int) - total % sizeof(int);
	if (total % sizeof(int)) {
		if (write(to, buf, n) != n)
			err(1, "%s", to_file);
		else
			total += n;
	}

	/* pad to the blocksize */
	n = sizeof(buf) - total % sizeof(buf);

	if (n < sizeof(int)) {
		n += sizeof(buf);
		total += sizeof(buf);
	} else
		total += n;

	/* TODO should pad here to the 65k boundary for tape boot */

	if (verbose)
		warnx("checksum is 0x%08x", -check_sum);

	check_sum = htobe32(-check_sum);
	if (write(to, &check_sum, sizeof(int)) != sizeof(int))
		err(1, "%s", to_file);

	n -= sizeof(int);

	if (write(to, buf, n) != n)
		err(1, "%s", to_file);

	if (close(from) < 0 )
		err(1, "%s", from_file);

	return total;
}

int
cksum(int ck, int *p, int size)
{
	/* we assume size is int-aligned */
	for (size = (size + sizeof(int) - 1) / sizeof(int); size--; p++ )
		ck += betoh32(*p);

	return ck;
}

void __dead
usage(void)
{
	extern char *__progname;
	fprintf(stderr,
		"usage: %s [-v] [-l loadpoint] prog1 {progN} outfile\n",
		__progname);
	exit(1);
}

char *
lifname(char *str)
{
	static char lname[10] = "XXXXXXXXXX";
	register int i;

	for (i = 0; i < 9; i++) {
		if (islower(*str))
			lname[i] = toupper(*str);
		else if (isalnum(*str) || *str == '_')
			lname[i] = *str;
		else
			break;
		str++;
	}
	for ( ; i < 10; i++)
		lname[i] = ' ';
	return(lname);
}

void
bcddate(char *file, char *toc)
{
	struct stat statb;
	struct tm *tm;

	stat(file, &statb);
	tm = localtime(&statb.st_ctime);
	*toc = (tm->tm_year / 10) << 4;
	*toc++ |= tm->tm_year % 10;
	*toc = ((tm->tm_mon+1) / 10) << 4;
	*toc++ |= (tm->tm_mon+1) % 10;
	*toc = (tm->tm_mday / 10) << 4;
	*toc++ |= tm->tm_mday % 10;
	*toc = (tm->tm_hour / 10) << 4;
	*toc++ |= tm->tm_hour % 10;
	*toc = (tm->tm_min / 10) << 4;
	*toc++ |= tm->tm_min % 10;
	*toc = (tm->tm_sec / 10) << 4;
	*toc |= tm->tm_sec % 10;
}


code:
/Makefile/1.8/Sun Dec  8 14:46:39 2013//TOPENBSD_5_8_BASE
D/compile////
D/conf////
D/dev////
D/hppa64////
D/include////
D/stand////


code:
#	$OpenBSD: Makefile,v 1.8 2013/12/08 14:46:39 espie Exp $

S=	${.CURDIR}/../..
KFILE=	GENERIC
.if exists(conf/GENERIC.MP)
KFILE=	GENERIC.MP
.endif
TDIRS=	${_arch} include
TAGS=	${.CURDIR}/tags

NOPROG=
NOMAN=
NOOBJ=
SUBDIR=	stand

# config the fattest kernel we can find into a temporary dir
# to create a Makefile.  Then use make to pull some variables
# out and push them into the sub-shell to expand the paths,
# and finally run ctags.
tags::
	TDIR=`mktemp -d /tmp/_tagXXXXXXXXXX` || exit 1; \
	eval "S=${S}" && \
	config -s ${S} -b $${TDIR} ${.CURDIR}/conf/${KFILE} && \
	eval "_arch=\"`make -V _arch -f $${TDIR}/Makefile`\"" && \
	eval "_mach=\"`make -V _mach -f $${TDIR}/Makefile`\"" && \
	eval "_machdir=\$S/arch/$${_mach}" && \
	eval "_archdir=\$S/arch/$${_arch}" && \
	eval "HFILES=\"`find $S \( -path $S/'arch' -o -path $S/stand -o -path $S/lib/libsa -o -path $S'/lib/libkern/arch' \) -prune -o -name '*.h'; find $${_machdir} $${_archdir} $S/lib/libkern/arch/$${_mach} \( -name boot -o -name stand \) -prune -o -name '*.h'`\"" && \
	eval "SFILES=\"`make -V SFILES -f $${TDIR}/Makefile`\"" && \
	eval "CFILES=\"`make -V CFILES -f $${TDIR}/Makefile`\"" && \
	eval "AFILES=\"`make -V AFILES -f $${TDIR}/Makefile`\"" && \
	ctags -wd -f ${TAGS} $${CFILES} $${HFILES} && \
	egrep "^[_A-Z]*ENTRY[_A-Z]*\(.*\)" $${SFILES} $${AFILES} | \
	    sed "s;\\([^:]*\\):\\([^(]*\\)(\\([^, )]*\\)\\(.*\\);\\3	\\1	/^\\2(\\3\\4$$/;" \
	    >> ${TAGS} && \
	sort -o ${TAGS} ${TAGS} && \
	rm -rf $${TDIR}

links:
	-for i in conf ${TDIRS}; do \
	    (cd $$i && rm -f tags; ln -s tags tags); done

obj:	_SUBDIRUSE

.include <bsd.prog.mk>


code:
/.cvsignore/1.1/Fri Apr  1 10:40:47 2005//TOPENBSD_5_8_BASE
D


code:
#	$OpenBSD: GENERIC,v 1.36 2015/04/16 09:09:49 mpi Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
#
# For further information on hardware support for this architecture, see
# the intro(4) man page.  For further information about kernel options
# for this architecture, see the options(4) man page.  For an explanation
# of each device driver in this file see the section 4 man page for the
# device.

machine		hppa64
include		"../../../conf/GENERIC"
maxusers	80			# estimated number of users

#option		DEBUG
option		USER_PCICONF	# user-space PCI configuration

config	bsd swap generic

mainbus0 at root		# root bus

mem*	at mainbus0 flags 0x00	# /dev/*mem and memory controller
pdc0	at mainbus0		# PDC/IODC wrapper for boot console
#power0	at mainbus0		# power/fail manager (iv 30)
cpu*	at mainbus0		# HP PA-RISC cpu
astro*	at mainbus0		# Astro Runway-Ropes, MIOC and IOA

elroy*	at astro?
pci*	at elroy?
option	PCIVERBOSE

ppb*	at pci?
pci*	at ppb?

ssio*	at pci?
com0	at ssio? irq 4
com1	at ssio? irq 3
#lpt0	at ssio?

# CardBus bus support
#cbb*		at pci?
#cardslot*	at cbb?
#option		CARDBUS_DEBUG,CARDSLOT_DEBUG,CARDBUS_MAP_DEBUG
#cardbus*	at cardslot?
#option		PCMCIADEBUG,PCMCIAVERBOSE
#pcmcia*	at cardslot?

# PCI USB Controllers
#ehci*	at pci?			# Enhanced Host Controller
#uhci*	at pci?			# Universal Host Controller (Intel)
#ohci*	at pci?			# Open Host Controller

# USB bus support
#usb*	at ehci?
#usb*	at uhci?
#usb*	at ohci?

# USB devices
#uhub*	at usb?			# USB Hubs
#uhub*	at uhub?		# USB Hubs
#ualea*	at uhub?		# Araneus Alea II TRNG
#umodem*	at uhub?	# USB Modems/Serial
#ucom*	at umodem?
#uvisor*	at uhub?	# Handspring Visor
#ucom*	at uvisor?
#uvscom*	at uhub?	# SUNTAC Slipper U VS-10U serial
#ucom*	at uvscom?
#ubsa*	at uhub?		# Belkin serial adapter
#ucom*	at ubsa?
#uftdi*	at uhub?		# FTDI FT8U100AX serial adapter
#ucom*	at uftdi?
#uplcom* at uhub?		# I/O DATA USB-RSAQ2 serial adapter
#ucom*	at uplcom?
#umct*	at uhub?		# MCT USB-RS232 serial adapter
#ucom*	at umct?
#uslcom*	at uhub?		# Silicon Laboratories CP210x serial
#ucom*	at uslcom?
#uark*	at uhub?		# Arkmicro ARK3116 serial
#ucom*	at uark?
#uipaq*	at uhub?		# iPAQ serial adapter
#ucom*	at uipaq?
#umsm*	at uhub?		# Qualcomm MSM EVDO
#ucom*	at umsm?
#uaudio* at uhub?		# USB Audio
#audio*	at uaudio?
#umidi*	at uhub?		# USB MIDI
#midi*	at umidi?
#ulpt*	at uhub?		# USB Printers
#umass*	at uhub?		# USB Mass Storage devices
#uhidev*	at uhub?	# Human Interface Devices
#ums*	at uhidev?		# USB mouse
#wsmouse* at ums? mux 0
#ukbd*	at uhidev?		# USB keyboard
#wskbd*	at ukbd? mux 1
#uhid*	at uhidev?		# USB generic HID support
#aue*	at uhub?		# ADMtek AN986 Pegasus Ethernet
#axe*	at uhub?		# ASIX Electronics AX88172 USB Ethernet
#axen*	at uhub?		# ASIX Electronics AX88179 USB Ethernet
#cue*	at uhub?		# CATC USB-EL1201A based Ethernet
#kue*	at uhub?		# Kawasaki KL5KUSB101B based Ethernet
#smsc*	at uhub?		# SMSC LAN95xx Ethernet
#cdce*	at uhub?		# CDC Ethernet
#urndis*	at uhub?		# Remote NDIS Ethernet
#udav*	at uhub?		# Davicom DM9601 based Ethernet
#upl*	at uhub?		# Prolific PL2301/PL2302 host-to-host `network'
#ugl*	at uhub?		# Genesys Logic GL620USB-A host-to-host `network'
#url*	at uhub?		# Realtek RTL8150L based adapters
#wi*	at uhub?		# WaveLAN IEEE 802.11DS
#udsbr*	at uhub?		# D-Link DSB-R100 radio
#radio*	at udsbr?		# USB radio
#ugen*	at uhub?		# USB Generic driver
#uow*	at uhub?		# Maxim/Dallas DS2490 1-Wire adapter
#onewire* at uow?

#sti*	at pci?			# EG-PCI, FX*
#wsdisplay*	at sti?

#com*	at pcmcia?		# PCMCIA modems

#ie*	at pci?

siop*	at pci?			# NCR 538XX SCSI controllers(new)
#ahd*	at pci?			# Adaptec 79?? SCSI controllers

#em*	at pci?			# Intel Pro/1000 ethernet
#ti*	at pci?			# Alteon Tigon 1Gb ethernet
#txp*	at pci?			# 3com 3CR990
#epic*	at pci?			# SMC EPIC/100 ethernet
dc*	at pci?			# 21143, "tulip" clone ethernet
#dc*	at cardbus?
#rl*	at pci?			# Realtek 81[23]9 ethernet
#rl*	at cardbus?
#ep*	at pci?			# 3c59x
#ep*	at cardbus?
#xl*	at pci?			# 3C9xx ethernet
#xl*	at cardbus?
#fxp*	at pci?			# EtherExpress 10/100B ethernet
#fxp*	at cardbus?
#ne*	at pci?			# NE2000-compatible Ethernet
#ne*	at pcmcia?
#an*	at pci?			# Cisco/Aironet 802.11DS
#an*	at pcmcia?
#wi*	at pci?			# WaveLAN IEEE 802.11DS
#wi*	at pcmcia?

dcphy*		at mii?		# Digital Clone PHYs
#amphy*		at mii?		# AMD 79C873 PHYs
#exphy*		at mii?		# 3Com internal PHYs
#inphy*		at mii?		# Intel 82555 PHYs
#iophy*		at mii?		# Intel 82553 PHYs
#icsphy*	at mii?		# ICS1890 PHYs
lxtphy*		at mii?		# Level One LXT-970 PHYs
nsphy*		at mii?		# NS83840 PHYs
#nsphyter*	at mii?		# NS83843 PHYs
#mtdphy*	at mii?		# Myson MTD972 PHYs
#qsphy*		at mii?		# Quality Semi QS6612 PHYs
#sqphy*		at mii?		# Seeq 8022[013] PHYs
#tlphy*		at mii?		# ThunderLAN PHYs
#tqphy*		at mii?		# TDK Semiconductor PHYs
#brgphy*	at mii?		# Broadcom 10/100/1000 PHYs
#bmtphy*	at mii?		# Broadcom 10/100 PHYs
#eephy*		at mii?		# Marvell 88E1000 Gigabit PHYs
ukphy*		at mii?		# generic unknown PHYs

#pciide*	at pci? flags 0x0000
#wdc*	at pcmcia?
#wd*	at wdc? flags 0x0000
#wd*	at pciide? flags 0x0000
#atapiscsi* at pciide?

# These entries find devices on all SCSI busses and assign
# unit numers dynamically.
scsibus* at scsi?
sd*	at scsibus?
#st*	at scsibus?
#cd*	at scsibus?
#ch*	at scsibus?
#uk*	at scsibus?
#safte*	at scsibus?
#ses*	at scsibus?

# 1-Wire devices
#option ONEWIREVERBOSE
#owid*	at onewire?		# ID
#owsbm*	at onewire?		# Smart Battery Monitor
#owtemp* at onewire?		# Temperature
#owctn*	at onewire?			# Counter device

#pseudo-device	wsmux	2	# mouse and keyboard multiplexor


code:
#	$OpenBSD: Makefile.hppa64,v 1.52 2015/01/13 01:12:49 deraadt Exp $

# For instructions on building kernels consult the config(8) and options(4)
# manual pages.
#
# N.B.: NO DEPENDENCIES ON FOLLOWING FLAGS ARE VISIBLE TO MAKEFILE
#	IF YOU CHANGE THE DEFINITION OF ANY OF THESE RECOMPILE EVERYTHING
# DEBUG is set to -g by config if debugging is requested (config -g).
# PROF is set to -pg by config if profiling is requested (config -p).

.include <bsd.own.mk>

SIZE?=	size
STRIP?=	strip

# source tree is located via $S relative to the compilation directory
.ifndef S
S!=	cd ../../../..; pwd
.endif

_machdir?=	$S/arch/${_mach}
_archdir?=	$S/arch/${_arch}

INCLUDES=	-nostdinc -I$S -I. -I$S/arch
CPPFLAGS=	${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL -MD -MP
CWARNFLAGS=	-Werror -Wall -Wimplicit-function-declaration \
		-Wno-main -Wno-uninitialized \
		-Wframe-larger-than=2047

CMACHFLAGS=	-mpa-risc-2-0 -mno-space-regs -mdisable-fpregs
CMACHFLAGS+=	-fno-builtin-printf -fno-builtin-snprintf \
		-fno-builtin-vsnprintf -fno-builtin-log \
		-fno-builtin-log2 -fno-builtin-malloc ${NOPIE_FLAGS}
CMACHFLAGS+=	-fno-stack-protector

COPTS?=		-O2
CFLAGS=		${DEBUG} ${CWARNFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE}
AFLAGS=		-D_LOCORE -x assembler-with-cpp ${CWARNFLAGS} ${CMACHFLAGS}
LDSCRIPT=	${_machdir}/conf/ld.script
LINKFLAGS=	-X -T ${LDSCRIPT} -Ttext 80000 --warn-common -nopie

.if ${IDENT:M-DDDB} != ""
CFLAGS+=	-fno-omit-frame-pointer
.endif

.if ${IDENT:M-DDDB_STRUCT}
DB_STRUCTINFO=	db_structinfo.h
.else
DB_STRUCTINFO=
.endif

HOSTCC?=	${CC}
HOSTED_CPPFLAGS=${CPPFLAGS:S/^-nostdinc$//}
HOSTED_CFLAGS=	${CFLAGS}
HOSTED_C=	${HOSTCC} ${HOSTED_CFLAGS} ${HOSTED_CPPFLAGS} -c $<

NORMAL_C_NOP=	${CC} ${CFLAGS} ${CPPFLAGS} -c $<
NORMAL_C=	${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
NORMAL_S=	${CC} ${AFLAGS} ${CPPFLAGS} -c $<

%OBJS

%CFILES

%SFILES

# load lines for config "xxx" will be emitted as:
# xxx: ${SYSTEM_DEP} swapxxx.o
#	${SYSTEM_LD_HEAD}
#	${SYSTEM_LD} swapxxx.o
#	${SYSTEM_LD_TAIL}
SYSTEM_HEAD=	locore.o param.o ioconf.o
SYSTEM_OBJ=	${SYSTEM_HEAD} ${OBJS}
SYSTEM_DEP=	Makefile ${SYSTEM_OBJ} ${LDSCRIPT}
SYSTEM_LD_HEAD=	@rm -f $@
SYSTEM_LD=	@echo ${LD} ${LINKFLAGS} -o $@ '$${SYSTEM_HEAD} vers.o $${OBJS}'; \
		${LD} ${LINKFLAGS} -o $@ ${SYSTEM_HEAD} vers.o ${OBJS}
SYSTEM_LD_TAIL=	@${SIZE} $@; chmod 755 $@

DEBUG?=
.if ${DEBUG} == "-g"
STRIPFLAGS=	-g -x
SYSTEM_LD_TAIL+=; \
		echo mv $@ $@.gdb; rm -f $@.gdb; mv $@ $@.gdb; \
		echo ${STRIP} ${STRIPFLAGS} -o $@ $@.gdb; \
		${STRIP} ${STRIPFLAGS} -o $@ $@.gdb
.else
LINKFLAGS+=	-S
.endif

%LOAD

# cc's -MD puts the source and output paths in the dependency file;
# since those are temp files here we need to fix it up.  It also
# puts the file in /tmp, so we use -MF to put it in the current
# directory as assym.P and then generate assym.d from it with a
# good target name
assym.h: $S/kern/genassym.sh Makefile \
	 ${_archdir}/${_arch}/genassym.cf ${_machdir}/${_mach}/genassym.cf
	cat ${_archdir}/${_arch}/genassym.cf ${_machdir}/${_mach}/genassym.cf | \
	    sh $S/kern/genassym.sh ${CC} ${CFLAGS} ${CPPFLAGS} -MF assym.P > assym.h.tmp
	sed '1s/.*/assym.h: \\/' assym.P > assym.d
	sort -u assym.h.tmp > assym.h

param.c: $S/conf/param.c
	rm -f param.c
	cp $S/conf/param.c .

param.o: param.c Makefile
	${NORMAL_C}

mcount.o: $S/lib/libkern/mcount.c Makefile
	${NORMAL_C_NOP}

ioconf.o: ioconf.c
	${NORMAL_C}

vers.o: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP}
	sh $S/conf/newvers.sh
	${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c vers.c

clean::
	rm -f eddep *bsd *bsd.gdb tags *.[dio] [a-z]*.s \
	    [Ee]rrs linterrs assym.h ${DB_STRUCTINFO}

lint:
	@lint -hbxncez -Dvolatile= ${CPPFLAGS} -UKGDB \
	    ${CFILES} ioconf.c param.c | \
	    grep -v 'static function .* unused'

depend:
	@touch $@

tags:
	@echo "see $S/kern/Makefile for tags"

db_structinfo.h: $S/ddb/db_structinfo.c $S/ddb/parse_structinfo.pl
	${CC} ${CFLAGS} ${CPPFLAGS} -MT $@ -gstabs -c $S/ddb/db_structinfo.c
	objdump -g db_structinfo.o | perl $S/ddb/parse_structinfo.pl > $@
	rm -f db_structinfo.o

locore.o: ${_machdir}/${_mach}/locore.S assym.h
spcopy.o: assym.h

# The install target can be redefined by putting a
# install-kernel-${MACHINE_NAME} target into /etc/mk.conf
MACHINE_NAME!=  uname -n
install: install-kernel-${MACHINE_NAME}
.if !target(install-kernel-${MACHINE_NAME}})
install-kernel-${MACHINE_NAME}:
	cmp -s bsd /bsd || ln -f /bsd /obsd
	cp bsd /nbsd
	mv /nbsd /bsd
.endif

# pull in the dependency information
.if !empty(DB_STRUCTINFO) && !exists(${DB_STRUCTINFO})
 ${SYSTEM_OBJ}: ${DB_STRUCTINFO}
.endif
.ifnmake clean
. for o in ${SYSTEM_OBJ} assym.h ${DB_STRUCTINFO}
.  if exists(${o:R}.d)
.   include "${o:R}.d"
.  elif exists($o)
    .PHONY: $o
.  endif
. endfor
.endif

%RULES


code:
#	$OpenBSD: RAMDISK,v 1.23 2015/07/17 22:52:28 tedu Exp $

machine		hppa64
maxusers	4

option		TIMEZONE=0
option		DST=0
option		SMALL_KERNEL
option		NO_PROPOLICE
option		BOOT_CONFIG

option		RAMDISK_HOOKS
option		MINIROOTSIZE=5120

option		PCIVERBOSE

option		FFS
option		NFSCLIENT
option		CD9660
option		INET6

config		bsd root on rd0a swap on rd0b # and sd0b

mainbus0	at root

mem*		at mainbus0 flags 0x00	# /dev/*mem and memory controller
pdc0		at mainbus0		# PDC/IODC wrapper for boot console
#power0		at mainbus0		# power/fail manager (iv 30)
cpu*		at mainbus0		# HP PA-RISC cpu
astro0		at mainbus0		# Astro Runway-Ropes, MIOC and IOA

elroy*		at astro0
pci*		at elroy?

ppb*		at pci?
pci*		at ppb?

cbb*		at pci?
cardslot*	at cbb?
cardbus*	at cardslot?
pcmcia*		at cardslot?

ahc*		at pci?			# Adaptec 2940 SCSI controllers
siop*		at pci?			# NCR 538XX SCSI controllers(new)

dc*		at pci?			# 21143, "tulip" clone ethernet
fxp*		at pci?			# EtherExpress 10/100B ethernet
ne*		at pci?			# NE2000-compatible Ethernet
ne*		at pcmcia?
an*		at pcmcia?
wi*		at pcmcia?

dcphy*		at mii?		# Digital Clone PHYs
amphy*		at mii?		# AMD 79C873 PHYs
inphy*		at mii?		# Intel 82555 PHYs
icsphy*		at mii?		# ICS1890 PHYs
lxtphy*		at mii?		# Level One LXT-970 PHYs
nsphy*		at mii?		# NS83840 PHYs
nsphyter*	at mii?		# NS83843 PHYs
bmtphy*		at mii?		# Broadcom 10/100 PHYs
ukphy*		at mii?		# generic unknown PHYs

scsibus*	at scsi?
sd*		at scsibus?
cd*		at scsibus?

pseudo-device	rd 1
pseudo-device	loop 1
pseudo-device	bpfilter 1


code:
#	$OpenBSD: files.hppa64,v 1.19 2015/07/17 22:52:28 tedu Exp $
#
# hppa64-specific configuration info

# maxpartitions must be the first item in files.${ARCH}
maxpartitions 16

maxusers 2 8 128

#
# "workstation console" routines
#
include "dev/wscons/files.wscons"
file	arch/hppa64/hppa64/wscons_machdep.c	wsdisplay

#
# Media Independent Interface (mii)
#
include "dev/mii/files.mii"

#
# Machine-independent SCSI drivers
#
include "scsi/files.scsi"
major	{ sd = 4 }
major	{ st = 5 }
major	{ cd = 6 }

#
# MI ATAPI drivers
#
include "dev/atapiscsi/files.atapiscsi"
include "dev/ata/files.ata"

#
# PCI Bus support
#
include "dev/pci/files.pci"

#
# CardBus support
#
include	"dev/cardbus/files.cardbus"

#
# Machine-independent PCMCIA drivers
#
include	"dev/pcmcia/files.pcmcia"

#
# Machine-independent USB drivers
#
include "dev/usb/files.usb"

#
# Machine-independent 1-Wire drivers
#
include "dev/onewire/files.onewire"

#
# Mainbus
#

define	gedoens {}
device	mainbus: gedoens
attach	mainbus at root
file	arch/hppa64/hppa64/mainbus.c	mainbus

device	pdc
attach	pdc at gedoens
file	arch/hppa64/dev/pdc.c		pdc

device	power
attach	power at gedoens
file	arch/hppa64/dev/power.c		power needs-flag

device	mem
attach	mem at gedoens
file	arch/hppa64/dev/mem.c		mem

device	cpu
attach	cpu at gedoens
file	arch/hppa64/dev/cpu.c		cpu

# Astro/Pluto, integrated Runway-Ropes bridge, MIOC and IOA
device	astro: gedoens
attach	astro at gedoens
file	arch/hppa64/dev/astro.c		astro

# Elroy, Ropes to PCI Bridge. Supports 4X PCI and dual address cycle.
# Mercury; QuickSilver is an AGP also
device	elroy: pcibus
attach	elroy at gedoens
file	arch/hppa64/dev/elroy.c		elroy
file	arch/hppa64/dev/apic.c		elroy

device	ssio {[irq = -1]}
attach	ssio at pci
file	arch/hppa64/dev/ssio.c			ssio

attach	com at ssio with com_ssio
file	arch/hppa64/dev/com_ssio.c		com_ssio

#attach	lpt at ssio with lpt_ssio
#file	arch/hppa64/dev/lpt_ssio.c		lpt_ssio

###

major	{vnd = 2}
major	{rd = 3}

# PS/2 mouse
include	"dev/pckbc/files.pckbc"

#
# Non-device files
#

file	arch/hppa64/hppa64/autoconf.c
file	arch/hppa64/hppa64/conf.c
file	arch/hppa64/hppa64/db_interface.c	ddb
file	arch/hppa64/hppa64/db_disasm.c		ddb
file	arch/hppa64/hppa64/disksubr.c		disk
file	arch/hppa64/hppa64/fpu.c
file	arch/hppa64/hppa64/intr.c
file	arch/hppa64/hppa64/machdep.c
file	arch/hppa64/hppa64/mutex.c
file	arch/hppa64/hppa64/pmap.c
file	arch/hppa64/hppa64/process_machdep.c
file	arch/hppa64/hppa64/sys_machdep.c
file	arch/hppa64/hppa64/trap.c
file	arch/hppa64/hppa64/vm_machdep.c
file	arch/hppa64/hppa64/in_cksum.c
file	netinet/in4_cksum.c
file	arch/hppa64/dev/clock.c

# hppa64 doesn't have multiplication or division instructions
file	lib/libkern/divdi3.c
file	lib/libkern/moddi3.c
file	lib/libkern/muldi3.c
file	lib/libkern/qdivrem.c
file	lib/libkern/udivdi3.c
file	lib/libkern/umoddi3.c

# kern..
file	lib/libkern/arch/hppa64/milli.S
file	lib/libkern/arch/hppa64/spcopy.S


code:
/* 	$OpenBSD: ld.script,v 1.1 2005/04/01 10:40:47 mickey Exp $	*/

/*
 * Copyright (c) 2005 Michael Shalayeff
 * All rights reserved.
 *
 * 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 MIND, 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.
 */

OUTPUT_FORMAT("elf64-hppa")
OUTPUT_ARCH(hppa2.0w)
ENTRY($start)
SECTIONS
{
	. = + SIZEOF_HEADERS;
	.text :
	{
		kernel_text = . ;
		*(.text) *(.text.*)
		*(.reginfo)
		*(.init)
		*(.stub)
		/* .gnu.warning sections are handled specially by elf32.em.  */
		*(.gnu.warning)
		. = ALIGN(4096);
		etext = ABSOLUTE(.);
	} = 0x08000240	/* nop filled */
	. = 0x400000;

	.rodata :
	{
		__rodata_start = .;
		*(.rodata) *(.rodata1)
		__unwind_start = .;
		*(.PARISC.unwind)
		__unwind_end = .;
		__rodata_end = .;
	} = 0
	__data_start = ABSOLUTE(.);

	.data  :
	{
		*(.data)
		CONSTRUCTORS
		. = ALIGN(4096);
		edata = ABSOLUTE(.);
	} = 0
	.ctors	: { *(.ctors) }
	.dtors	: { *(.dtors) }

	.opd	: { *(.opd) }
	PROVIDE(__gp = .);
	.plt	: { *(.plt) }
	.dlt	: { *(.dlt) }

	. = ALIGN(4096);

	__bss_start = .;
	/* .sbss	: { *(.sbss) *(.scommon) } */
	.bss :
	{
		*(.dynbss) *(.bss)
		*(COMMON) *($COMMON$)
		. = ALIGN(4096);
		__kernel_pagedir = ABSOLUTE(.);
		. += 5*4096;	/* PIT + 4*PIE */
	}
	end = ABSOLUTE(.);

	/DISCARD/ : {
		*(.exitcall.exit)
		*(.interp)
		*(.dynsym)
		*(.dynstr)
		*(.dynamic)
		*(.hash)
	}
}


code:
/*	$OpenBSD: apic.c,v 1.8 2014/12/09 06:58:28 doug Exp $	*/

/*
 * Copyright (c) 2005 Michael Shalayeff
 * Copyright (c) 2007 Mark Kettenis
 * All rights reserved.
 *
 * 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 MIND, 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 <sys/systm.h>
#include <sys/device.h>
#include <sys/evcount.h>
#include <sys/malloc.h>

#include <machine/autoconf.h>
#include <machine/pdc.h>

#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>

#include <hppa64/dev/elroyreg.h>
#include <hppa64/dev/elroyvar.h>

#define APIC_INT_LINE_MASK	0x0000ff00
#define APIC_INT_LINE_SHIFT	8
#define APIC_INT_IRQ_MASK	0x0000001f

#define APIC_INT_LINE(x) (((x) & APIC_INT_LINE_MASK) >> APIC_INT_LINE_SHIFT)
#define APIC_INT_IRQ(x) ((x) & APIC_INT_IRQ_MASK)

/*
 * Interrupt types match the Intel MP Specification.
 */

#define MPS_INTPO_DEF		0
#define MPS_INTPO_ACTHI		1
#define MPS_INTPO_ACTLO		3
#define MPS_INTPO_SHIFT		0
#define MPS_INTPO_MASK		3

#define MPS_INTTR_DEF		0
#define MPS_INTTR_EDGE		1
#define MPS_INTTR_LEVEL		3
#define MPS_INTTR_SHIFT		2
#define MPS_INTTR_MASK		3

#define MPS_INT(p,t) \
    ((((p) & MPS_INTPO_MASK) << MPS_INTPO_SHIFT) | \
     (((t) & MPS_INTTR_MASK) << MPS_INTTR_SHIFT))

struct apic_iv {
	struct elroy_softc *sc;
	pci_intr_handle_t ih;
	int (*handler)(void *);
	void *arg;
	struct apic_iv *next;
	struct evcount *cnt;
};

struct apic_iv *apic_intr_list[CPU_NINTS];

void		apic_get_int_tbl(struct elroy_softc *);
u_int32_t	apic_get_int_ent0(struct elroy_softc *, int);

void		apic_write(volatile struct elroy_regs *r, u_int32_t reg,
		    u_int32_t val);
u_int32_t	apic_read(volatile struct elroy_regs *r, u_int32_t reg);

#ifdef DEBUG
void	apic_dump(struct elroy_softc *);
#endif

void
apic_write(volatile struct elroy_regs *r, u_int32_t reg, u_int32_t val)
{
	elroy_write32(&r->apic_addr, htole32(reg));
	elroy_write32(&r->apic_data, htole32(val));
	elroy_read32(&r->apic_data);
}

u_int32_t
apic_read(volatile struct elroy_regs *r, u_int32_t reg)
{
	elroy_write32(&r->apic_addr, htole32(reg));
	return letoh32(elroy_read32(&r->apic_data));
}

void
apic_attach(struct elroy_softc *sc)
{
	volatile struct elroy_regs *r = sc->sc_regs;
	u_int32_t data;

	data = apic_read(r, APIC_VERSION);
	sc->sc_nints = (data & APIC_VERSION_NENT) >> APIC_VERSION_NENT_SHIFT;
	printf(" APIC ver %x, %d pins",
	    data & APIC_VERSION_MASK, sc->sc_nints);

	sc->sc_irq = mallocarray(sc->sc_nints, sizeof(int), M_DEVBUF,
	    M_NOWAIT | M_ZERO);
	if (sc->sc_irq == NULL)
		panic("apic_attach: cannot allocate irq table");

	apic_get_int_tbl(sc);

#ifdef DEBUG
	apic_dump(sc);
#endif
}

int
apic_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
{
	struct elroy_softc *sc = pa->pa_pc->_cookie;
	pci_chipset_tag_t pc = pa->pa_pc;
	pcitag_t tag = pa->pa_tag;
	pcireg_t reg;
	int line;

	reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
#ifdef DEBUG
	printf(" pin=%d line=%d ", PCI_INTERRUPT_PIN(reg),
	    PCI_INTERRUPT_LINE(reg));
#endif
	line = PCI_INTERRUPT_LINE(reg);
	if (sc->sc_irq[line] == 0)
		sc->sc_irq[line] = cpu_intr_findirq();
	*ihp = (line << APIC_INT_LINE_SHIFT) | sc->sc_irq[line];
	return (APIC_INT_IRQ(*ihp) == 0);
}

const char *
apic_intr_string(void *v, pci_intr_handle_t ih)
{
	static char buf[32];

	snprintf(buf, 32, "line %ld irq %ld",
	    APIC_INT_LINE(ih), APIC_INT_IRQ(ih));

	return (buf);
}

void *
apic_intr_establish(void *v, pci_intr_handle_t ih,
    int pri, int (*handler)(void *), void *arg, const char *name)
{
	struct elroy_softc *sc = v;
	volatile struct elroy_regs *r = sc->sc_regs;
	hppa_hpa_t hpa = cpu_gethpa(0);
	struct evcount *cnt;
	struct apic_iv *aiv, *biv;
	void *iv;
	int irq = APIC_INT_IRQ(ih);
	int line = APIC_INT_LINE(ih);
	u_int32_t ent0;

	/* no mapping or bogus */
	if (irq <= 0 || irq > 63)
		return (NULL);

	aiv = malloc(sizeof(struct apic_iv), M_DEVBUF, M_NOWAIT);
	if (aiv == NULL) {
		free(cnt, M_DEVBUF, 0);
		return NULL;
	}

	aiv->sc = sc;
	aiv->ih = ih;
	aiv->handler = handler;
	aiv->arg = arg;
	aiv->next = NULL;
	aiv->cnt = NULL;
	if (apic_intr_list[irq]) {
		cnt = malloc(sizeof(struct evcount), M_DEVBUF, M_NOWAIT);
		if (!cnt) {
			free(aiv, M_DEVBUF, 0);
			return (NULL);
		}

		evcount_attach(cnt, name, NULL);
		biv = apic_intr_list[irq];
		while (biv->next)
			biv = biv->next;
		biv->next = aiv;
		aiv->cnt = cnt;
		return (arg);
	}

	if ((iv = cpu_intr_establish(pri, irq, apic_intr, aiv, name))) {
		ent0 = (63 - irq) & APIC_ENT0_VEC;
		ent0 |= apic_get_int_ent0(sc, line);
#if 0
		if (cold) {
			sc->sc_imr |= (1 << irq);
			ent0 |= APIC_ENT0_MASK;
		}
#endif
		apic_write(sc->sc_regs, APIC_ENT0(line), APIC_ENT0_MASK);
		apic_write(sc->sc_regs, APIC_ENT1(line),
		    ((hpa & 0x0ff00000) >> 4) | ((hpa & 0x000ff000) << 12));
		apic_write(sc->sc_regs, APIC_ENT0(line), ent0);

		/* Signal EOI. */
		elroy_write32(&r->apic_eoi,
		    htole32((63 - irq) & APIC_ENT0_VEC));

		apic_intr_list[irq] = aiv;
	}

	return (arg);
}

void
apic_intr_disestablish(void *v, void *cookie)
{
}

int
apic_intr(void *v)
{
	struct apic_iv *iv = v;
	struct elroy_softc *sc = iv->sc;
	volatile struct elroy_regs *r = sc->sc_regs;
	pci_intr_handle_t ih = iv->ih;
	int claimed = 0;

	while (iv) {
		if (iv->handler(iv->arg)) {
			if (iv->cnt)
				iv->cnt->ec_count++;
			else
				claimed = 1;
		}
		iv = iv->next;
	}

	/* Signal EOI. */
	elroy_write32(&r->apic_eoi,
	    htole32((63 - APIC_INT_IRQ(ih)) & APIC_ENT0_VEC));

	return (claimed);
}

/* Maximum number of supported interrupt routing entries. */
#define MAX_INT_TBL_SZ	16

void
apic_get_int_tbl(struct elroy_softc *sc)
{
	struct pdc_pat_io_num int_tbl_sz PDC_ALIGNMENT;
	struct pdc_pat_pci_rt int_tbl[MAX_INT_TBL_SZ] PDC_ALIGNMENT;
	size_t size;

	/*
	 * XXX int_tbl should not be allocated on the stack, but we need a
	 * 1:1 mapping, and malloc doesn't provide that.
	 */

	if (pdc_call((iodcio_t)pdc, 0, PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SZ,
	    &int_tbl_sz, 0, 0, 0, 0, 0))
		return;

	if (int_tbl_sz.num > MAX_INT_TBL_SZ)
		panic("interrupt routing table too big (%d entries)",
		    int_tbl_sz.num);

	size = int_tbl_sz.num * sizeof(struct pdc_pat_pci_rt);
	sc->sc_int_tbl_sz = int_tbl_sz.num;
	sc->sc_int_tbl = malloc(size, M_DEVBUF, M_NOWAIT);
	if (sc->sc_int_tbl == NULL)
		return;

	if (pdc_call((iodcio_t)pdc, 0, PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL,
	    &int_tbl_sz, 0, &int_tbl, 0, 0, 0))
		return;

	memcpy(sc->sc_int_tbl, int_tbl, size);
}

u_int32_t
apic_get_int_ent0(struct elroy_softc *sc, int line)
{
	volatile struct elroy_regs *r = sc->sc_regs;
	int trigger = MPS_INT(MPS_INTPO_DEF, MPS_INTTR_DEF);
	u_int32_t ent0 = APIC_ENT0_LOW | APIC_ENT0_LEV;
	int bus, mpspo, mpstr;
	int i;

	bus = letoh32(elroy_read32(&r->busnum)) & 0xff;
	for (i = 0; i < sc->sc_int_tbl_sz; i++) {
		if (bus == sc->sc_int_tbl[i].bus &&
		    line == sc->sc_int_tbl[i].line)
			trigger = sc->sc_int_tbl[i].trigger;
	}

	mpspo = (trigger >> MPS_INTPO_SHIFT) & MPS_INTPO_MASK;
	mpstr = (trigger >> MPS_INTTR_SHIFT) & MPS_INTTR_MASK;

	switch (mpspo) {
	case MPS_INTPO_DEF:
		break;
	case MPS_INTPO_ACTHI:
		ent0 &= ~APIC_ENT0_LOW;
		break;
	case MPS_INTPO_ACTLO:
		ent0 |= APIC_ENT0_LOW;
		break;
	default:
		panic("unknown MPS interrupt polarity %d", mpspo);
	}

	switch(mpstr) {
	case MPS_INTTR_DEF:
		break;
	case MPS_INTTR_LEVEL:
		ent0 |= APIC_ENT0_LEV;
		break;
	case MPS_INTTR_EDGE:
		ent0 &= ~APIC_ENT0_LEV;
		break;
	default:
		panic("unknown MPS interrupt trigger %d", mpstr);
	}

	return ent0;
}

#ifdef DEBUG
void
apic_dump(struct elroy_softc *sc)
{
	int i;

	for (i = 0; i < sc->sc_nints; i++)
		printf("0x%04x 0x%04x\n", apic_read(sc->sc_regs, APIC_ENT0(i)),
		    apic_read(sc->sc_regs, APIC_ENT1(i)));

	for (i = 0; i < sc->sc_int_tbl_sz; i++) {
		printf("type=%x ", sc->sc_int_tbl[i].type);
		printf("len=%d ", sc->sc_int_tbl[i].len);
		printf("itype=%d ", sc->sc_int_tbl[i].itype);
		printf("trigger=%x ", sc->sc_int_tbl[i].trigger);
		printf("pin=%x ", sc->sc_int_tbl[i].pin);
		printf("bus=%d ", sc->sc_int_tbl[i].bus);
		printf("line=%d ", sc->sc_int_tbl[i].line);
		printf("addr=%x\n", sc->sc_int_tbl[i].addr);
	}
}
#endif


code:
/*	$OpenBSD: astro.c,v 1.8 2014/11/16 12:30:57 deraadt Exp $	*/

/*
 * Copyright (c) 2007 Mark Kettenis
 *
 * 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 <sys/systm.h>
#include <sys/device.h>
#include <sys/extent.h>
#include <sys/malloc.h>
#include <sys/reboot.h>
#include <sys/tree.h>

#include <uvm/uvm_extern.h>

#include <machine/iomod.h>
#include <machine/autoconf.h>
#include <machine/cpufunc.h>

#include <hppa/dev/cpudevs.h>

struct astro_regs {
	u_int32_t	rid;
	u_int32_t	pad0000;
	u_int32_t	ioc_ctrl;
	u_int32_t	pad0008;
	u_int8_t	resv1[0x0300 - 0x0010];
	u_int64_t	lmmio_direct0_base;
	u_int64_t	lmmio_direct0_mask;
	u_int64_t	lmmio_direct0_route;
	u_int64_t	lmmio_direct1_base;
	u_int64_t	lmmio_direct1_mask;
	u_int64_t	lmmio_direct1_route;
	u_int64_t	lmmio_direct2_base;
	u_int64_t	lmmio_direct2_mask;
	u_int64_t	lmmio_direct2_route;
	u_int64_t	lmmio_direct3_base;
	u_int64_t	lmmio_direct3_mask;
	u_int64_t	lmmio_direct3_route;
	u_int64_t	lmmio_dist_base;
	u_int64_t	lmmio_dist_mask;
	u_int64_t	lmmio_dist_route;
	u_int64_t	gmmio_dist_base;
	u_int64_t	gmmio_dist_mask;
	u_int64_t	gmmio_dist_route;
	u_int64_t	ios_dist_base;
	u_int64_t	ios_dist_mask;
	u_int64_t	ios_dist_route;
	u_int8_t	resv2[0x03c0 - 0x03a8];
	u_int64_t	ios_direct_base;
	u_int64_t	ios_direct_mask;
	u_int64_t	ios_direct_route;
	u_int8_t	resv3[0x22000 - 0x03d8];
	u_int64_t	func_id;
	u_int64_t	func_class;
	u_int8_t	resv4[0x22040 - 0x22010];
	u_int64_t	rope_config;
	u_int8_t	resv5[0x22050 - 0x22048];
	u_int64_t	rope_debug;
	u_int8_t	resv6[0x22200 - 0x22058];
	u_int64_t	rope0_control;
	u_int64_t	rope1_control;
	u_int64_t	rope2_control;
	u_int64_t	rope3_control;
	u_int64_t	rope4_control;
	u_int64_t	rope5_control;
	u_int64_t	rope6_control;
	u_int64_t	rope7_control;
	u_int8_t	resv7[0x22300 - 0x22240];
	u_int32_t	tlb_ibase;
	u_int32_t	pad22300;
	u_int32_t	tlb_imask;
	u_int32_t	pad22308;
	u_int32_t	tlb_pcom;
	u_int32_t	pad22310;
	u_int32_t	tlb_tcnfg;
	u_int32_t	pad22318;
	u_int64_t	tlb_pdir_base;
};

#define ASTRO_IOC_CTRL_TE	0x0001	/* TOC Enable */
#define ASTRO_IOC_CTRL_CE	0x0002	/* Coalesce Enable */
#define ASTRO_IOC_CTRL_DE	0x0004	/* Dillon Enable */
#define ASTRO_IOC_CTRL_IE	0x0008	/* IOS Enable */
#define ASTRO_IOC_CTRL_OS	0x0010	/* Outbound Synchronous */
#define ASTRO_IOC_CTRL_IS	0x0020	/* Inbound Synchronous */
#define ASTRO_IOC_CTRL_RC	0x0040	/* Read Current Enable */
#define ASTRO_IOC_CTRL_L0	0x0080	/* 0-length Read Enable */
#define ASTRO_IOC_CTRL_RM	0x0100	/* Real Mode */
#define ASTRO_IOC_CTRL_NC	0x0200	/* Non-coherent Mode */
#define ASTRO_IOC_CTRL_ID	0x0400	/* Interrupt Disable */
#define ASTRO_IOC_CTRL_D4	0x0800	/* Disable 4-byte Coalescing */
#define ASTRO_IOC_CTRL_CC	0x1000	/* Increase Coalescing counter value */
#define ASTRO_IOC_CTRL_DD	0x2000	/* Disable distr. range coalescing */
#define ASTRO_IOC_CTRL_DC	0x4000	/* Disable the coalescing counter */

#define IOTTE_V		0x8000000000000000LL	/* Entry valid */
#define IOTTE_PAMASK	0x000000fffffff000LL
#define IOTTE_CI	0x00000000000000ffLL	/* Coherent index */

struct astro_softc {
	struct device sc_dv;

	bus_dma_tag_t sc_dmat;
	struct astro_regs volatile *sc_regs;
	u_int64_t *sc_pdir;

	char sc_dvmamapname[20];
	struct extent *sc_dvmamap;
	struct hppa64_bus_dma_tag sc_dmatag;
};

/*
 * per-map DVMA page table
 */
struct iommu_page_entry {
	SPLAY_ENTRY(iommu_page_entry) ipe_node;
	paddr_t	ipe_pa;
	vaddr_t	ipe_va;
	bus_addr_t ipe_dva;
};

struct iommu_page_map {
	SPLAY_HEAD(iommu_page_tree, iommu_page_entry) ipm_tree;
	int ipm_maxpage;	/* Size of allocated page map */
	int ipm_pagecnt;	/* Number of entries in use */
	struct iommu_page_entry	ipm_map[1];
};

/*
 * per-map IOMMU state
 */
struct iommu_map_state {
	struct astro_softc *ims_sc;
	bus_addr_t ims_dvmastart;
	bus_size_t ims_dvmasize;
	struct iommu_page_map ims_map;	/* map must be last (array at end) */
};

int	astro_match(struct device *, void *, void *);
void	astro_attach(struct device *, struct device *, void *);

struct cfattach astro_ca = {
	sizeof(struct astro_softc), astro_match, astro_attach
};

struct cfdriver astro_cd = {
	NULL, "astro", DV_DULL
};

int	iommu_dvmamap_create(void *, bus_size_t, int, bus_size_t, bus_size_t,
	    int, bus_dmamap_t *);
void	iommu_dvmamap_destroy(void *, bus_dmamap_t);
int	iommu_dvmamap_load(void *, bus_dmamap_t, void *, bus_size_t,
	    struct proc *, int);
int	iommu_iomap_load_map(struct astro_softc *, bus_dmamap_t, int);
int	iommu_dvmamap_load_mbuf(void *, bus_dmamap_t, struct mbuf *, int);
int	iommu_dvmamap_load_uio(void *, bus_dmamap_t, struct uio *, int);
int	iommu_dvmamap_load_raw(void *, bus_dmamap_t, bus_dma_segment_t *,
	    int, bus_size_t, int);
void	iommu_dvmamap_unload(void *, bus_dmamap_t);
void	iommu_dvmamap_sync(void *, bus_dmamap_t, bus_addr_t, bus_size_t, int);
int	iommu_dvmamem_alloc(void *, bus_size_t, bus_size_t, bus_size_t,
	    bus_dma_segment_t *, int, int *, int);
void	iommu_dvmamem_free(void *, bus_dma_segment_t *, int);
int	iommu_dvmamem_map(void *, bus_dma_segment_t *, int, size_t,
	    caddr_t *, int);
void	iommu_dvmamem_unmap(void *, caddr_t, size_t);
paddr_t	iommu_dvmamem_mmap(void *, bus_dma_segment_t *, int, off_t, int, int);

void	iommu_enter(struct astro_softc *, bus_addr_t, paddr_t, vaddr_t, int);
void	iommu_remove(struct astro_softc *, bus_addr_t);

struct iommu_map_state *iommu_iomap_create(int);
void	iommu_iomap_destroy(struct iommu_map_state *);
int	iommu_iomap_insert_page(struct iommu_map_state *, vaddr_t, paddr_t);
bus_addr_t iommu_iomap_translate(struct iommu_map_state *, paddr_t);
void	iommu_iomap_clear_pages(struct iommu_map_state *);

const struct hppa64_bus_dma_tag astro_dmat = {
	NULL,
	iommu_dvmamap_create, iommu_dvmamap_destroy,
	iommu_dvmamap_load, iommu_dvmamap_load_mbuf,
	iommu_dvmamap_load_uio, iommu_dvmamap_load_raw,
	iommu_dvmamap_unload, iommu_dvmamap_sync,

	iommu_dvmamem_alloc, iommu_dvmamem_free, iommu_dvmamem_map,
	iommu_dvmamem_unmap, iommu_dvmamem_mmap
};

int
astro_match(struct device *parent, void *cfdata, void *aux)
{
	struct confargs *ca = aux;

	/* Astro is a U-Turn variant. */
	if (ca->ca_type.iodc_type != HPPA_TYPE_IOA ||
	    ca->ca_type.iodc_sv_model != HPPA_IOA_UTURN)
		return 0;

	if (ca->ca_type.iodc_model == 0x58 &&
	    ca->ca_type.iodc_revision >= 0x20)
		return 1;

	return 0;
}

void
astro_attach(struct device *parent, struct device *self, void *aux)
{
	struct confargs *ca = aux, nca;
	struct astro_softc *sc = (struct astro_softc *)self;
	volatile struct astro_regs *r;
	bus_space_handle_t ioh;
	u_int32_t rid, ioc_ctrl;
	psize_t size;
	vaddr_t va;
	paddr_t pa;
	struct vm_page *m;
	struct pglist mlist;
	int iova_bits;

	sc->sc_dmat = ca->ca_dmatag;
	if (bus_space_map(ca->ca_iot, ca->ca_hpa, sizeof(struct astro_regs),
	    0, &ioh)) {
		printf(": can't map IO space\n");
		return;
	}
	sc->sc_regs = r = bus_space_vaddr(ca->ca_iot, ioh);

	rid = letoh32(r->rid);
	printf(": Astro rev %d.%d\n", (rid & 7) + 1, (rid >> 3) & 3);

	ioc_ctrl = letoh32(r->ioc_ctrl);
	ioc_ctrl &= ~ASTRO_IOC_CTRL_CE;
	ioc_ctrl &= ~ASTRO_IOC_CTRL_RM;
	ioc_ctrl &= ~ASTRO_IOC_CTRL_NC;
	r->ioc_ctrl = htole32(ioc_ctrl);

	/*
	 * Setup the iommu.
	 */

	/* XXX This gives us 256MB of iova space. */
	iova_bits = 28;

	r->tlb_ibase = htole32(0);
	r->tlb_imask = htole32(0xffffffff << iova_bits);

	/* Page size is 4K. */
	r->tlb_tcnfg = htole32(0);

	/* Flush TLB. */
	r->tlb_pcom = htole32(31);

	/*
	 * Allocate memory for I/O pagetables.  They need to be physically
	 * contiguous.
	 */

	size = (1 << (iova_bits - PAGE_SHIFT)) * sizeof(u_int64_t);
	TAILQ_INIT(&mlist);
	if (uvm_pglistalloc(size, 0, -1, PAGE_SIZE, 0, &mlist,
	    1, UVM_PLA_NOWAIT) != 0)
		panic("astrottach: no memory");

	va = (vaddr_t)km_alloc(size, &kv_any, &kp_none, &kd_nowait);
	if (va == 0)
		panic("astroattach: no memory");
	sc->sc_pdir = (u_int64_t *)va;

	m = TAILQ_FIRST(&mlist);
	r->tlb_pdir_base = htole64(VM_PAGE_TO_PHYS(m));

	/* Map the pages. */
	for (; m != NULL; m = TAILQ_NEXT(m, pageq)) {
		pa = VM_PAGE_TO_PHYS(m);
		pmap_enter(pmap_kernel(), va, pa,
		    PROT_READ | PROT_WRITE, PMAP_WIRED);
		va += PAGE_SIZE;
	}
	pmap_update(pmap_kernel());
	memset(sc->sc_pdir, 0, size);

	/*
	 * The PDC might have set up some devices to do DMA.  It will do
	 * this for the onboard USB controller if an USB keyboard is used
	 * for console input.  In that case, bad things will happen if we
	 * enable iova space.  So reset the PDC devices before we do that.
	 * Don't do this if we're using a serial console though, since it
	 * will stop working if we do.  This is fine since the serial port
	 * doesn't do DMA.
	 */
	if (PAGE0->mem_cons.pz_class != PCL_DUPLEX)
		pdc_call((iodcio_t)pdc, 0, PDC_IO, PDC_IO_RESET_DEVICES);

	/* Enable iova space. */
	r->tlb_ibase = htole32(1);

        /*
         * Now all the hardware's working we need to allocate a dvma map.
         */
	snprintf(sc->sc_dvmamapname, sizeof(sc->sc_dvmamapname),
	    "%s_dvma", sc->sc_dv.dv_xname);
        sc->sc_dvmamap = extent_create(sc->sc_dvmamapname, 0, (1 << iova_bits),
            M_DEVBUF, 0, 0, EX_NOWAIT);

	sc->sc_dmatag = astro_dmat;
	sc->sc_dmatag._cookie = sc;

	nca = *ca;	/* clone from us */
	nca.ca_dmatag = &sc->sc_dmatag;
	pdc_scan(self, &nca);
}

int
iommu_dvmamap_create(void *v, bus_size_t size, int nsegments,
    bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamap)
{
	struct astro_softc *sc = v;
	bus_dmamap_t map;
	struct iommu_map_state *ims;
	int error;

	error = bus_dmamap_create(sc->sc_dmat, size, nsegments, maxsegsz,
	    boundary, flags, &map);
	if (error)
		return (error);

	ims = iommu_iomap_create(atop(round_page(size)));
	if (ims == NULL) {
		bus_dmamap_destroy(sc->sc_dmat, map);
		return (ENOMEM);
	}

	ims->ims_sc = sc;
	map->_dm_cookie = ims;
	*dmamap = map;

	return (0);
}

void
iommu_dvmamap_destroy(void *v, bus_dmamap_t map)
{
	struct astro_softc *sc = v;

	/*
	 * The specification (man page) requires a loaded
	 * map to be unloaded before it is destroyed.
	 */
	if (map->dm_nsegs)
		iommu_dvmamap_unload(sc, map);

        if (map->_dm_cookie)
                iommu_iomap_destroy(map->_dm_cookie);
	map->_dm_cookie = NULL;

	bus_dmamap_destroy(sc->sc_dmat, map);
}

int
iommu_iomap_load_map(struct astro_softc *sc, bus_dmamap_t map, int flags)
{
	struct iommu_map_state *ims = map->_dm_cookie;
	struct iommu_page_map *ipm = &ims->ims_map;
	struct iommu_page_entry *e;
	int err, seg, s;
	paddr_t pa, paend;
	vaddr_t va;
	bus_size_t sgsize;
	bus_size_t align, boundary;
	u_long dvmaddr;
	bus_addr_t dva;
	int i;

	/* XXX */
	boundary = map->_dm_boundary;
	align = PAGE_SIZE;

	iommu_iomap_clear_pages(ims);

	for (seg = 0; seg < map->dm_nsegs; seg++) {
		struct hppa64_bus_dma_segment *ds = &map->dm_segs[seg];

		paend = round_page(ds->ds_addr + ds->ds_len);
		for (pa = trunc_page(ds->ds_addr), va = trunc_page(ds->_ds_va);
		     pa < paend; pa += PAGE_SIZE, va += PAGE_SIZE) {
			err = iommu_iomap_insert_page(ims, va, pa);
			if (err) {
                               printf("iomap insert error: %d for "
                                    "va 0x%lx pa 0x%lx\n", err, va, pa);
				bus_dmamap_unload(sc->sc_dmat, map);
				iommu_iomap_clear_pages(ims);
			}
		}
	}

	sgsize = ims->ims_map.ipm_pagecnt * PAGE_SIZE;
	s = splhigh();
	err = extent_alloc(sc->sc_dvmamap, sgsize, align, 0, boundary,
	    EX_NOWAIT | EX_BOUNDZERO, &dvmaddr);
	splx(s);
	if (err)
		return (err);

	ims->ims_dvmastart = dvmaddr;
	ims->ims_dvmasize = sgsize;

	dva = dvmaddr;
	for (i = 0, e = ipm->ipm_map; i < ipm->ipm_pagecnt; ++i, ++e) {
		e->ipe_dva = dva;
		iommu_enter(sc, e->ipe_dva, e->ipe_pa, e->ipe_va, flags);
		dva += PAGE_SIZE;
	}

	for (seg = 0; seg < map->dm_nsegs; seg++) {
		struct hppa64_bus_dma_segment *ds = &map->dm_segs[seg];
		ds->ds_addr = iommu_iomap_translate(ims, ds->ds_addr);
	}

	return (0);
}

int
iommu_dvmamap_load(void *v, bus_dmamap_t map, void *addr, bus_size_t size,
    struct proc *p, int flags)
{
	struct astro_softc *sc = v;
	int err;

	err = bus_dmamap_load(sc->sc_dmat, map, addr, size, p, flags);
	if (err)
		return (err);

	return iommu_iomap_load_map(sc, map, flags);
}

int
iommu_dvmamap_load_mbuf(void *v, bus_dmamap_t map, struct mbuf *m, int flags)
{
	struct astro_softc *sc = v;
	int err;

	err = bus_dmamap_load_mbuf(sc->sc_dmat, map, m, flags);
	if (err)
		return (err);

	return iommu_iomap_load_map(sc, map, flags);
}

int
iommu_dvmamap_load_uio(void *v, bus_dmamap_t map, struct uio *uio, int flags)
{
	struct astro_softc *sc = v;

	printf("load_uio\n");

	return (bus_dmamap_load_uio(sc->sc_dmat, map, uio, flags));
}

int
iommu_dvmamap_load_raw(void *v, bus_dmamap_t map, bus_dma_segment_t *segs,
    int nsegs, bus_size_t size, int flags)
{
	struct astro_softc *sc = v;

	printf("load_raw\n");

	return (bus_dmamap_load_raw(sc->sc_dmat, map, segs, nsegs, size, flags));
}

void
iommu_dvmamap_unload(void *v, bus_dmamap_t map)
{
	struct astro_softc *sc = v;
	struct iommu_map_state *ims = map->_dm_cookie;
	struct iommu_page_map *ipm = &ims->ims_map;
	struct iommu_page_entry *e;
	int err, i, s;

	/* Remove the IOMMU entries. */
	for (i = 0, e = ipm->ipm_map; i < ipm->ipm_pagecnt; ++i, ++e)
		iommu_remove(sc, e->ipe_dva);

	/* Clear the iomap. */
	iommu_iomap_clear_pages(ims);

	bus_dmamap_unload(sc->sc_dmat, map);

	s = splhigh();
	err = extent_free(sc->sc_dvmamap, ims->ims_dvmastart,
	    ims->ims_dvmasize, EX_NOWAIT);
	ims->ims_dvmastart = 0;
	ims->ims_dvmasize = 0;
	splx(s);
	if (err)
		printf("warning: %ld of DVMA space lost\n", ims->ims_dvmasize);
}

void
iommu_dvmamap_sync(void *v, bus_dmamap_t map, bus_addr_t off,
    bus_size_t len, int ops)
{
	/* Nothing to do; DMA is cache-coherent. */
}

int
iommu_dvmamem_alloc(void *v, bus_size_t size, bus_size_t alignment,
    bus_size_t boundary, bus_dma_segment_t *segs,
    int nsegs, int *rsegs, int flags)
{
	struct astro_softc *sc = v;

	return (bus_dmamem_alloc(sc->sc_dmat, size, alignment, boundary,
	    segs, nsegs, rsegs, flags));
}

void
iommu_dvmamem_free(void *v, bus_dma_segment_t *segs, int nsegs)
{
	struct astro_softc *sc = v;

	bus_dmamem_free(sc->sc_dmat, segs, nsegs);
}

int
iommu_dvmamem_map(void *v, bus_dma_segment_t *segs, int nsegs, size_t size,
    caddr_t *kvap, int flags)
{
	struct astro_softc *sc = v;

	return (bus_dmamem_map(sc->sc_dmat, segs, nsegs, size, kvap, flags));
}

void
iommu_dvmamem_unmap(void *v, caddr_t kva, size_t size)
{
	struct astro_softc *sc = v;

	bus_dmamem_unmap(sc->sc_dmat, kva, size);
}

paddr_t
iommu_dvmamem_mmap(void *v, bus_dma_segment_t *segs, int nsegs, off_t off,
    int prot, int flags)
{
	struct astro_softc *sc = v;

	return (bus_dmamem_mmap(sc->sc_dmat, segs, nsegs, off, prot, flags));
}

/*
 * Utility function used by splay tree to order page entries by pa.
 */
static inline int
iomap_compare(struct iommu_page_entry *a, struct iommu_page_entry *b)
{
	return ((a->ipe_pa > b->ipe_pa) ? 1 :
		(a->ipe_pa < b->ipe_pa) ? -1 : 0);
}

SPLAY_PROTOTYPE(iommu_page_tree, iommu_page_entry, ipe_node, iomap_compare);

SPLAY_GENERATE(iommu_page_tree, iommu_page_entry, ipe_node, iomap_compare);

/*
 * Create a new iomap.
 */
struct iommu_map_state *
iommu_iomap_create(int n)
{
	struct iommu_map_state *ims;

	/* Safety for heavily fragmented data, such as mbufs */
	n += 4;
	if (n < 16)
		n = 16;

	ims = malloc(sizeof(*ims) + (n - 1) * sizeof(ims->ims_map.ipm_map[0]),
	    M_DEVBUF, M_NOWAIT | M_ZERO);
	if (ims == NULL)
		return (NULL);

	/* Initialize the map. */
	ims->ims_map.ipm_maxpage = n;
	SPLAY_INIT(&ims->ims_map.ipm_tree);

	return (ims);
}

/*
 * Destroy an iomap.
 */
void
iommu_iomap_destroy(struct iommu_map_state *ims)
{
#ifdef DIAGNOSTIC
	if (ims->ims_map.ipm_pagecnt > 0)
		printf("iommu_iomap_destroy: %d page entries in use\n",
		    ims->ims_map.ipm_pagecnt);
#endif

	free(ims, M_DEVBUF, 0);
}

/*
 * Insert a pa entry in the iomap.
 */
int
iommu_iomap_insert_page(struct iommu_map_state *ims, vaddr_t va, paddr_t pa)
{
	struct iommu_page_map *ipm = &ims->ims_map;
	struct iommu_page_entry *e;

	if (ipm->ipm_pagecnt >= ipm->ipm_maxpage) {
		struct iommu_page_entry ipe;

		ipe.ipe_pa = pa;
		if (SPLAY_FIND(iommu_page_tree, &ipm->ipm_tree, &ipe))
			return (0);

		return (ENOMEM);
	}

	e = &ipm->ipm_map[ipm->ipm_pagecnt];

	e->ipe_pa = pa;
	e->ipe_va = va;
	e->ipe_dva = 0;

	e = SPLAY_INSERT(iommu_page_tree, &ipm->ipm_tree, e);

	/* Duplicates are okay, but only count them once. */
	if (e)
		return (0);

	++ipm->ipm_pagecnt;

	return (0);
}

/*
 * Translate a physical address (pa) into a DVMA address.
 */
bus_addr_t
iommu_iomap_translate(struct iommu_map_state *ims, paddr_t pa)
{
	struct iommu_page_map *ipm = &ims->ims_map;
	struct iommu_page_entry *e;
	struct iommu_page_entry pe;
	paddr_t offset = pa & PAGE_MASK;

	pe.ipe_pa = trunc_page(pa);

	e = SPLAY_FIND(iommu_page_tree, &ipm->ipm_tree, &pe);

	if (e == NULL) {
		panic("couldn't find pa %lx", pa);
		return 0;
	}

	return (e->ipe_dva | offset);
}

/*
 * Clear the iomap table and tree.
 */
void
iommu_iomap_clear_pages(struct iommu_map_state *ims)
{
        ims->ims_map.ipm_pagecnt = 0;
        SPLAY_INIT(&ims->ims_map.ipm_tree);
}

/*
 * Add an entry to the IOMMU table.
 */
void
iommu_enter(struct astro_softc *sc, bus_addr_t dva, paddr_t pa, vaddr_t va,
    int flags)
{
	volatile u_int64_t *tte_ptr = &sc->sc_pdir[dva >> PAGE_SHIFT];
	u_int64_t tte;
	u_int32_t ci;

#ifdef DEBUG
	printf("iommu_enter dva %lx, pa %lx, va %lx\n", dva, pa, va);
#endif

#ifdef DIAGNOSTIC
	tte = letoh64(*tte_ptr);

	if (tte & IOTTE_V) {
		printf("Overwriting valid tte entry (dva %lx pa %lx "
		    "&tte %p tte %llx)\n", dva, pa, tte_ptr, tte);
		extent_print(sc->sc_dvmamap);
		panic("IOMMU overwrite");
	}
#endif

	mtsp(HPPA_SID_KERNEL, 1);
	__asm volatile("lci 0(%%sr1, %1), %0" : "=r" (ci) : "r" (va));

	tte = (pa & IOTTE_PAMASK) | ((ci >> 12) & IOTTE_CI);
	tte |= IOTTE_V;

	*tte_ptr = htole64(tte);
	__asm volatile("fdc 0(%%sr1, %0)\n\tsync" : : "r" (tte_ptr));
}

/*
 * Remove an entry from the IOMMU table.
 */
void
iommu_remove(struct astro_softc *sc, bus_addr_t dva)
{
	volatile struct astro_regs *r = sc->sc_regs;
	u_int64_t *tte_ptr = &sc->sc_pdir[dva >> PAGE_SHIFT];
	u_int64_t tte;

#ifdef DIAGNOSTIC
	if (dva != trunc_page(dva)) {
		printf("iommu_remove: unaligned dva: %lx\n", dva);
		dva = trunc_page(dva);
	}
#endif

	tte = letoh64(*tte_ptr);

#ifdef DIAGNOSTIC
	if ((tte & IOTTE_V) == 0) {
		printf("Removing invalid tte entry (dva %lx &tte %p "
		    "tte %llx)\n", dva, tte_ptr, tte);
		extent_print(sc->sc_dvmamap);
		panic("IOMMU remove overwrite");
	}
#endif

	*tte_ptr = htole64(tte & ~IOTTE_V);

	/* Flush IOMMU. */
	r->tlb_pcom = htole32(dva | PAGE_SHIFT);
}


code:
/*	$OpenBSD: clock.c,v 1.5 2011/07/04 17:14:14 kettenis Exp $	*/

/*
 * Copyright (c) 2005 Michael Shalayeff
 * All rights reserved.
 *
 * 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 MIND, 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 <sys/systm.h>
#include <sys/kernel.h>
#include <sys/timetc.h>

#include <machine/iomod.h>
#include <machine/reg.h>

#include <dev/clock_subr.h>

u_long	cpu_hzticks;
int	timeset;

u_int	itmr_get_timecount(struct timecounter *);

struct timecounter itmr_timecounter = {
	itmr_get_timecount, NULL, 0xffffffff, 0, "itmr", 0, NULL
};

void
cpu_initclocks(void)
{
	struct cpu_info *ci = curcpu();
	u_long __itmr;

	cpu_hzticks = (PAGE0->mem_10msec * 100) / hz;

	itmr_timecounter.tc_frequency = PAGE0->mem_10msec * 100;
	tc_init(&itmr_timecounter);

	__itmr = mfctl(CR_ITMR);
	ci->ci_itmr = __itmr;
	__itmr += cpu_hzticks;
	mtctl(__itmr, CR_ITMR);
}

/*
 * initialize the system time from the time of day clock
 */
void
inittodr(time_t t)
{
	struct pdc_tod tod PDC_ALIGNMENT;
	int 	error, tbad = 0;
	struct timespec ts;

	if (t < 12*SECYR) {
		printf ("WARNING: preposterous time in file system");
		t = 6*SECYR + 186*SECDAY + SECDAY/2;
		tbad = 1;
	}

	if ((error = pdc_call((iodcio_t)pdc,
	    1, PDC_TOD, PDC_TOD_READ, &tod, 0, 0, 0, 0, 0)))
		printf("clock: failed to fetch (%d)\n", error);

	ts.tv_sec = tod.sec;
	ts.tv_nsec = tod.usec * 1000;
	tc_setclock(&ts);
	timeset = 1;

	if (!tbad) {
		u_long	dt;

		dt = (tod.sec < t)?  t - tod.sec : tod.sec - t;

		if (dt < 2 * SECDAY)
			return;
		printf("WARNING: clock %s %ld days",
		    tod.sec < t? "lost" : "gained", dt / SECDAY);
	}

	printf (" -- CHECK AND RESET THE DATE!\n");
}

/*
 * reset the time of day clock to the value in time
 */
void
resettodr(void)
{
	struct timeval tv;
	int error;

	/*
	 * We might have been called by boot() due to a crash early
	 * on.  Don't reset the clock chip in this case.
	 */
	if (!timeset)
		return;

	microtime(&tv);

	if ((error = pdc_call((iodcio_t)pdc, 1, PDC_TOD, PDC_TOD_WRITE,
	    tv.tv_sec, tv.tv_usec)))
		printf("clock: failed to save (%d)\n", error);
}

void
setstatclockrate(int newhz)
{
	/* nothing we can do */
}

u_int
itmr_get_timecount(struct timecounter *tc)
{
	return (mfctl(CR_ITMR));
}


code:
/*	$OpenBSD: com_ssio.c,v 1.1 2011/08/07 20:36:22 kettenis Exp $	*/

/*
 * Copyright (c) 2007 Mark Kettenis
 *
 * 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 <sys/systm.h>
#include <sys/device.h>
#include <sys/tty.h>

#include <machine/bus.h>
#include <machine/iomod.h>

#include <dev/ic/comreg.h>
#include <dev/ic/comvar.h>

#include <hppa64/dev/ssiovar.h>

#define COM_SSIO_FREQ	1843200

int com_ssio_match(struct device *, void *, void *);
void com_ssio_attach(struct device *, struct device *, void *);

struct cfattach com_ssio_ca = {
	sizeof(struct com_softc), com_ssio_match, com_ssio_attach
};

int
com_ssio_match(struct device *parent, void *match, void *aux)
{
	struct cfdata *cf = match;
	struct ssio_attach_args *saa = aux;

	if (strcmp(saa->saa_name, "com") != 0)
		return (0);

	/* Check locators. */
	if (cf->ssiocf_irq != SSIO_UNK_IRQ && cf->ssiocf_irq != saa->saa_irq)
		return (0);

	return (1);
}

void
com_ssio_attach(struct device *parent, struct device *self, void *aux)
{
	struct com_softc *sc = (void *)self;
	struct ssio_attach_args *saa = aux;

	sc->sc_iot = saa->saa_iot;
	sc->sc_iobase = saa->saa_iobase;
	if (bus_space_map(sc->sc_iot, sc->sc_iobase, COM_NPORTS,
	    0, &sc->sc_ioh)) {
		printf(": cannot map io space\n");
		return;
	}

	if (PAGE0->mem_cons.pz_class == PCL_DUPLEX &&
	    PAGE0->mem_cons.pz_hpa == (sc->sc_ioh & 0xffffffff)) {
		bus_space_unmap(sc->sc_iot, sc->sc_ioh, COM_NPORTS);
		comcnattach(sc->sc_iot, sc->sc_iobase, comdefaultrate,
		    COM_SSIO_FREQ, comconscflag);
	}

	sc->sc_frequency = COM_SSIO_FREQ;
	com_attach_subr(sc);

	sc->sc_ih = ssio_intr_establish(IPL_TTY, saa->saa_irq,
	    comintr, sc, sc->sc_dev.dv_xname);
}


code:
/*	$OpenBSD: cpu.c,v 1.6 2014/03/29 18:09:29 guenther Exp $	*/

/*
 * Copyright (c) 2005 Michael Shalayeff
 * All rights reserved.
 *
 * 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 MIND, 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 <sys/systm.h>
#include <sys/device.h>
#include <sys/reboot.h>

#include <machine/pdc.h>
#include <machine/reg.h>
#include <machine/iomod.h>
#include <machine/autoconf.h>

#include <arch/hppa/dev/cpudevs.h>

struct cpu_softc {
	struct device sc_dev;
};

int	cpumatch(struct device *, void *, void *);
void	cpuattach(struct device *, struct device *, void *);

int	cpu_hardclock(void *);

struct cfattach cpu_ca = {
	sizeof(struct cpu_softc), cpumatch, cpuattach
};

struct cfdriver cpu_cd = {
	NULL, "cpu", DV_DULL
};

int
cpumatch(struct device *parent, void *cfdata, void *aux)
{
	struct cfdata *cf = cfdata;
	struct confargs *ca = aux;

	if (ca->ca_type.iodc_type != HPPA_TYPE_NPROC ||
	    ca->ca_type.iodc_sv_model != HPPA_NPROC_HPPA)
		return 0;

	if (cf->cf_unit >= MAXCPUS)
		return 0;

	return 1;
}

int
cpu_hardclock(void *v)
{
	struct cpu_info *ci = curcpu();
	u_long __itmr, delta, eta;
	extern u_long cpu_hzticks;
	register_t eiem;
	int wrap;

	/*
	 * Invoke hardclock as many times as there has been cpu_hzticks
	 * ticks since the last interrupt.
	 */
	for (;;) {
		__itmr = mfctl(CR_ITMR);
		delta = __itmr - ci->ci_itmr;
		if (delta >= cpu_hzticks) {
			hardclock(v);
			ci->ci_itmr += cpu_hzticks;
		} else
			break;
	}

	/*
	 * Program the next clock interrupt, making sure it will
	 * indeed happen in the future. This is done with interrupts
	 * disabled to avoid a possible race.
	 */
	eta = ci->ci_itmr + cpu_hzticks;
	wrap = eta < ci->ci_itmr;	/* watch out for a wraparound */
	__asm volatile("mfctl	%%cr15, %0": "=r" (eiem));
	__asm volatile("mtctl	%r0, %cr15");
	mtctl(eta, CR_ITMR);
	__itmr = mfctl(CR_ITMR);

	/*
	 * If we were close enough to the next tick interrupt
	 * value, by the time we have programmed itmr, it might
	 * have passed the value, which would cause a complete
	 * cycle until the next interrupt occurs. On slow
	 * models, this would be a disaster (a complete cycle
	 * taking over two minutes on a 715/33).
	 *
	 * We expect that it will only be necessary to postpone
	 * the interrupt once. Thus, there are two cases:
	 * - We are expecting a wraparound: eta < cpu_itmr.
	 *   itmr is in tracks if either >= cpu_itmr or < eta.
	 * - We are not wrapping: eta > cpu_itmr.
	 *   itmr is in tracks if >= cpu_itmr and < eta (we need
	 *   to keep the >= cpu_itmr test because itmr might wrap
	 *   before eta does).
	 */
	if ((wrap && !(eta > __itmr || __itmr >= ci->ci_itmr)) ||
	    (!wrap && !(eta > __itmr && __itmr >= ci->ci_itmr))) {
		eta += cpu_hzticks;
		mtctl(eta, CR_ITMR);
	}
	__asm volatile("mtctl	%0, %%cr15":: "r" (eiem));

	return (1);
}

void
cpuattach(struct device *parent, struct device *self, void *aux)
{
	/* machdep.c */
	extern struct pdc_model pdc_model;
	extern struct pdc_cache pdc_cache;
	extern u_int cpu_ticksnum, cpu_ticksdenom;
	extern u_int fpu_enable;

	/* struct cpu_softc *sc = (struct cpu_softc *)self; */
	/* struct confargs *ca = aux; */
	u_int mhz = 100 * cpu_ticksnum / cpu_ticksdenom;
	const char *p;

	printf (": %s ", cpu_typename);
	if (pdc_model.hvers) {
		static const char lvls[4][4] = { "0", "1", "1.5", "2" };

		printf("L%s-%c ", lvls[pdc_model.pa_lvl], "AB"[pdc_model.mc]);
	}

	printf ("%d", mhz / 100);
	if (mhz % 100 > 9)
		printf(".%02d", mhz % 100);
	printf("MHz");

	if (fpu_enable) {
		extern u_int fpu_version;
		u_int32_t ver[2];

		mtctl(fpu_enable, CR_CCR);
		__asm volatile(
		    "fstds   %%fr0,0(%0)\n\t"
		    "copr,0,0\n\t"
		    "fstds   %%fr0,0(%0)"
		    :: "r" (&ver) : "memory");
		mtctl(0, CR_CCR);
		fpu_version = HPPA_FPUVER(ver[0]);
		printf(", FPU %s rev %d",
		    hppa_mod_info(HPPA_TYPE_FPU, fpu_version >> 5),
		    fpu_version & 0x1f);
	}

	printf("\n%s: ", self->dv_xname);
	p = "";
	if (!pdc_cache.dc_conf.cc_sh) {
		printf("%uK(%db/l) Icache, ",
		    pdc_cache.ic_size / 1024, pdc_cache.ic_conf.cc_line * 16);
		p = "D";
	}
	printf("%uK(%db/l) wr-%s %scoherent %scache, ",
	    pdc_cache.dc_size / 1024, pdc_cache.dc_conf.cc_line * 16,
	    pdc_cache.dc_conf.cc_wt? "thru" : "back",
	    pdc_cache.dc_conf.cc_cst? "" : "in", p);

	p = "";
	if (!pdc_cache.dt_conf.tc_sh) {
		printf("%u ITLB, ", pdc_cache.it_size);
		p = "D";
	}
	printf("%u %scoherent %sTLB\n",
	    pdc_cache.dt_size, pdc_cache.dt_conf.tc_cst? "" : "in", p);

	cpu_intr_establish(IPL_CLOCK, 63, cpu_hardclock, NULL, "clock");
}