code:
/*	$OpenBSD: pci_machdep.h,v 1.2 2013/11/05 10:12:35 mpi Exp $	*/
/*	$NetBSD: pci_machdep.h,v 1.7 2001/07/20 00:07:14 eeh Exp $ */

/*
 * Copyright (c) 1999 Matthew R. Green
 * 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.
 */

#ifndef _MACHINE_PCI_MACHDEP_H_
#define _MACHINE_PCI_MACHDEP_H_

extern struct powerpc_bus_dma_tag pci_bus_dma_tag;

/*
 * Forward declarations.
 */
struct pci_attach_args;

/*
 * define some bits used to glue into the common PCI code.
 */

typedef struct ppc_pci_chipset *pci_chipset_tag_t;

typedef unsigned long pci_intr_handle_t;

/*
 * The stuuuuuuupid allegedly MI PCI code expects pcitag_t to be a
 * scalar type.  But we really need to store both the OFW node and
 * the bus/device/function info in it.  (We'd like to store more,
 * like all the ofw properties, but we don't need to.)  Luckily,
 * both are 32-bit values, so we can squeeze them into a u_int64_t
 * with a little help from some macros.
 */

#define PCITAG_NODE(x)		(int)(((x)>>32)&0xffffffff)
#define PCITAG_OFFSET(x)	((x)&0xffffffff)
#define PCITAG_BUS(t)		((PCITAG_OFFSET(t)>>16)&0xff)
#define PCITAG_DEV(t)		((PCITAG_OFFSET(t)>>11)&0x1f)
#define PCITAG_FUN(t)		((PCITAG_OFFSET(t)>>8)&0x7)
#define PCITAG_CREATE(n,b,d,f)	(((uint64_t)(n)<<32)|((b)<<16)|((d)<<11)|((f)<<8))
typedef uint64_t pcitag_t;

struct ppc_pci_chipset {
	void		*pc_conf_v;
	int		 pc_node;
	int		 busnode[256];

	pcireg_t	(*pc_conf_read)(void *, pcitag_t, int);
	void		(*pc_conf_write)(void *, pcitag_t, int, pcireg_t);
};

void		pci_attach_hook(struct device *, struct device *,
		    struct pcibus_attach_args *);
int		pci_bus_maxdevs(pci_chipset_tag_t, int);
pcitag_t	pci_make_tag(pci_chipset_tag_t, int, int, int);
void		pci_decompose_tag(pci_chipset_tag_t, pcitag_t, int *, int *,
		    int *);
int		pci_conf_size(pci_chipset_tag_t, pcitag_t);
pcireg_t	pci_conf_read(pci_chipset_tag_t, pcitag_t, int);
void		pci_conf_write(pci_chipset_tag_t, pcitag_t, int, pcireg_t);
int		pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
int		pci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *);
int		pci_intr_line(pci_chipset_tag_t, pci_intr_handle_t);
const char	*pci_intr_string(pci_chipset_tag_t, pci_intr_handle_t);
void		*pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t,
		    int, int (*)(void *), void *, const char *);
void		pci_intr_disestablish(pci_chipset_tag_t, void *);
int		pci_ether_hw_addr(pci_chipset_tag_t, uint8_t *);

#define pci_probe_device_hook(c, a)	(0)

#define pci_min_powerstate(c, t)	(PCI_PMCSR_STATE_D3)
#define pci_set_powerstate_md(c, t, s, p)

#define pci_dev_postattach(a, b)

int		ofw_intr_map(int, uint32_t *, uint32_t *);
int		ofw_enumerate_pcibus(struct pci_softc *,
		    int (*match)(struct pci_attach_args *),
		    struct pci_attach_args *);

#define PCI_MACHDEP_ENUMERATE_BUS	ofw_enumerate_pcibus

#endif /* _MACHINE_PCI_MACHDEP_H_ */


code:
/*	$OpenBSD: pio.h,v 1.1 2001/09/01 15:49:06 drahn Exp $	*/

#include <powerpc/pio.h>

license: unknown


code:
/*	$OpenBSD: pmap.h,v 1.5 2005/11/07 02:19:46 brad Exp $	*/

#include <powerpc/pmap.h>


code:
/*	$OpenBSD: proc.h,v 1.1 2001/09/01 15:49:06 drahn Exp $	*/

#include <powerpc/proc.h>


code:
/*	$OpenBSD: profile.h,v 1.1 2001/09/01 15:49:06 drahn Exp $	*/

#include <powerpc/profile.h>


code:
/*	$OpenBSD: psl.h,v 1.1 2001/09/01 15:49:06 drahn Exp $	*/

#include <powerpc/psl.h>


code:
/*	$OpenBSD: pte.h,v 1.1 2001/09/01 15:49:06 drahn Exp $	*/

#include <powerpc/pte.h>


code:
/*	$OpenBSD: ptrace.h,v 1.1 2001/09/01 15:49:06 drahn Exp $	*/

#include <powerpc/ptrace.h>


code:
/*	$OpenBSD: rbus_machdep.h,v 1.6 2011/03/23 16:54:36 pirofti Exp $ */
/*	$NetBSD: rbus_machdep.h,v 1.2 1999/10/15 06:43:05 haya Exp $	*/

/*
 * Copyright (c) 1999
 *     HAYAKAWA Koichi.  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 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.
 */

#if !defined _MACHINE_RBUS_MACHDEP_H_
#define _MACHINE_RBUS_MACHDEP_H_

struct pci_attach_args;		/* XXX */

void _bus_space_unmap(bus_space_tag_t, bus_space_handle_t,
			     bus_size_t, bus_addr_t *);

#define md_space_map(rbt, physaddr, size, flags, bshp) \
	bus_space_map((rbt)->rb_bt, (physaddr), (size), (flags), (bshp))

/* XXX */
bus_addr_t bus_space_unmap_p(bus_space_tag_t t, bus_space_handle_t bsh,
                          bus_size_t size);

#define md_space_unmap(rbt, bsh, size, adrp) \
	do { \
		*adrp = bus_space_unmap_p((rbt)->rb_bt, (bsh), (size)); \
		if ((rbt)->rb_bt->bus_io) { \
			*adrp = *adrp & 0xffff; \
		} \
	} while (0)

rbus_tag_t rbus_pccbb_parent_io(struct device *self,
    struct pci_attach_args *pa);
rbus_tag_t rbus_pccbb_parent_mem(struct device *self,
    struct pci_attach_args *pa);

void	pccbb_attach_hook(struct device *, struct device *,
	    struct pci_attach_args *);

#endif /* _MACHINE_RBUS_MACHDEP_H_ */


code:
/*	$OpenBSD: reg.h,v 1.1 2001/09/01 15:49:06 drahn Exp $	*/

#include <powerpc/reg.h>


code:
/*	$OpenBSD: reloc.h,v 1.1 2001/09/01 15:49:06 drahn Exp $	*/

#include <powerpc/reloc.h>


code:
/*	$OpenBSD: setjmp.h,v 1.1 2001/09/01 15:49:06 drahn Exp $	*/

#include <powerpc/setjmp.h>


code:
/*	$OpenBSD: signal.h,v 1.1 2001/09/01 15:49:06 drahn Exp $	*/

#include <powerpc/signal.h>


code:
/*	$OpenBSD: spinlock.h,v 1.1 2001/09/01 15:49:06 drahn Exp $	*/

#include <powerpc/spinlock.h>


code:
/*	$OpenBSD: stdarg.h,v 1.1 2001/09/01 15:49:06 drahn Exp $	*/

#include <powerpc/stdarg.h>


code:
/*	$OpenBSD: tcb.h,v 1.2 2013/06/01 21:20:54 jasper Exp $	*/
/* public domain */
#include <powerpc/tcb.h>


code:
/*	$OpenBSD: trap.h,v 1.1 2001/09/01 15:49:06 drahn Exp $	*/

#include <powerpc/trap.h>


code:
/*	$OpenBSD: varargs.h,v 1.1 2001/09/01 15:49:06 drahn Exp $	*/

#include <powerpc/varargs.h>


code:
/*	$OpenBSD: vmparam.h,v 1.30 2015/02/10 10:02:55 tedu Exp $	*/
/*	$NetBSD: vmparam.h,v 1.1 1996/09/30 16:34:38 ws Exp $	*/

/*-
 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
 * Copyright (C) 1995, 1996 TooLs GmbH.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by TooLs GmbH.
 * 4. The name of TooLs GmbH may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef MACHINE_VMPARAM_H
#define MACHINE_VMPARAM_H

#define	USRTEXT		PAGE_SIZE
#define	USRSTACK	VM_MAXUSER_ADDRESS

#ifndef	MAXTSIZ
#define	MAXTSIZ		(64*1024*1024)		/* max text size */
#endif

#ifndef	DFLDSIZ
#define	DFLDSIZ		(64*1024*1024)		/* default data size */
#endif

#ifndef	MAXDSIZ
#define	MAXDSIZ		(2UL*1024*1024*1024)	/* max data size */
#endif

#ifndef BRKSIZ
#define	BRKSIZ		MAXDSIZ			/* heap gap size */
#endif

#ifndef	DFLSSIZ
#define	DFLSSIZ		(2*1024*1024)		/* default stack size */
#endif

#ifndef	MAXSSIZ
#define	MAXSSIZ		(32*1024*1024)		/* max stack size */
#endif

#define STACKGAP_RANDOM	256*1024

/*
 * Size of shared memory map
 */
#ifndef	SHMMAXPGS
#define	SHMMAXPGS       8192			/* 32mb */
#endif

/*
 * Size of User Raw I/O map
 */
#define	USRIOSIZE	1024

/*
 * Would like to have MAX addresses = 0, but this doesn't (currently) work
 */
#define	VM_MIN_ADDRESS		((vaddr_t)PAGE_SIZE)
#define	VM_MAXUSER_ADDRESS	((vaddr_t)0xfffff000)
#define	VM_MAX_ADDRESS		VM_MAXUSER_ADDRESS
#define	VM_MIN_KERNEL_ADDRESS	((vaddr_t)(PPC_KERNEL_SR << ADDR_SR_SHIFT))

/* map PIE into approximately the first quarter of user va space */
#define VM_PIE_MIN_ADDR		PAGE_SIZE
#define VM_PIE_MAX_ADDR		0x40000000

/* ppc_kvm_stolen is so that vm space can be stolen before vm is fully
 * initialized.
 */
extern vaddr_t ppc_kvm_stolen;
#define VM_KERN_ADDRESS_SIZE  (PPC_SEGMENT_LENGTH - (32 * 1024 * 1024))
#define	VM_MAX_KERNEL_ADDRESS	(VM_MIN_KERNEL_ADDRESS + VM_KERN_ADDRESS_SIZE)

#define	VM_PHYS_SIZE		(USRIOSIZE * PAGE_SIZE)

#define	VM_PHYSSEG_MAX	32	/* actually we could have this many segments */
#define	VM_PHYSSEG_STRAT	VM_PSTRAT_BSEARCH
#define	VM_PHYSSEG_NOADD	/* can't add RAM after vm_mem_init */

#endif


code:
/*	$OpenBSD: z8530var.h,v 1.9 2013/04/21 14:44:16 sebastia Exp $	*/
/*	$NetBSD: z8530var.h,v 1.5 2002/03/17 19:40:45 atatat Exp $	*/

/*
 * Copyright (c) 1994 Gordon W. Ross
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This software was developed by the Computer Systems Engineering group
 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
 * contributed to Berkeley.
 *
 * All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Lawrence Berkeley Laboratory.
 *
 * 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.
 *
 *	@(#)zsvar.h	8.1 (Berkeley) 6/11/93
 */

#include <dev/ic/z8530sc.h>
#include <macppc/dev/dbdma.h>

/*
 * Clock source info structure, added here so xzs_chanstate works
 */
struct zsclksrc {
	long    clk;    /* clock rate, in MHz, present on signal line */
	int     flags;  /* Specifies how this source can be used
			   (RTxC divided, RTxC BRG, PCLK BRG, TRxC divided)
			   and also if the source is "external" and if it
			   is changeable (by an ioctl ex.). The
			   source usage flags are used by the tty
			   child. The other bits tell zsloadchannelregs
			   if it should call an md signal source
			   changing routine. ZSC_VARIABLE says if
			   an ioctl should be able to cahnge the
			   clock rate.*/
};
#define ZSC_PCLK        0x01
#define ZSC_RTXBRG      0x02
#define ZSC_RTXDIV      0x04
#define ZSC_TRXDIV      0x08
#define ZSC_VARIABLE    0x40
#define ZSC_EXTERN      0x80

#define ZSC_BRG         0x03
#define ZSC_DIV         0x0c

/*
 * These are the machine-dependent (extended) variants of
 * struct zs_chanstate and struct zsc_softc
 */
struct xzs_chanstate {
	/* machine-independent part (First!)*/
	struct zs_chanstate xzs_cs;
	/* machine-dependent extensions */
	int cs_hwflags;
	int	cs_chip;		/* type of chip */
	/* Clock source info... */
	int	cs_clock_count;		/* how many signal sources available */
	struct zsclksrc cs_clocks[4];	/* info on available signal sources */
	long	cs_cclk_flag;		/* flag for current clock source */
	long	cs_pclk_flag;		/* flag for pending clock source */
	int	cs_csource;		/* current source # */
	int	cs_psource;		/* pending source # */
};

struct zsc_softc {
	struct device		zsc_dev;	/* base device */
	struct zs_chanstate 	*zsc_cs[2];	/* channel A and B soft state */
	/* Machine-dependent part follows... */
	void			*zsc_softintr;
	struct xzs_chanstate	xzsc_xcs_store[2];
	dbdma_regmap_t		*zsc_txdmareg[2];
	dbdma_command_t		*zsc_txdmacmd[2];
	/* XXX tx only, for now */
};

/*
 * Functions to read and write individual registers in a channel.
 * The ZS chip requires a 1.6 uSec. recovery time between accesses,
 * and the Sun3 hardware does NOT take care of this for you.
 * MacII hardware DOES dake care of the delay for us. :-)
 * XXX - Then these should be inline functions! -gwr
 * Some clock-chirped macs lose serial ports. It could be that the
 * hardware delay is tied to the CPU speed, and that the minimum delay
 * no longer's respected. For them, ZS_DELAY might help.
 * XXX - no one seems to want to try and check this -wrs
 */

u_char zs_read_reg(struct zs_chanstate *cs, u_char reg);
u_char zs_read_csr(struct zs_chanstate *cs);
u_char zs_read_data(struct zs_chanstate *cs);

void  zs_write_reg(struct zs_chanstate *cs, u_char reg, u_char val);
void  zs_write_csr(struct zs_chanstate *cs, u_char val);
void  zs_write_data(struct zs_chanstate *cs, u_char val);

/* XXX - Could define splzs() here instead of in psl.h */
#define splzs spltty

/* Hook for MD ioctl support */
int	zsmdioctl(struct zs_chanstate *cs, u_long cmd, caddr_t data);
/* XXX - This is a bit gross... */
/*
#define ZS_MD_IOCTL(cs, cmd, data) zsmdioctl(cs, cmd, data)
*/

/* Callback for "external" clock sources */
void zsmd_setclock(struct zs_chanstate *cs);
#define ZS_MD_SETCLK(cs) zsmd_setclock(cs)

#define PCLK	(9600 * 384)	/* PCLK pin input clock rate */

/* The layout of this is hardware-dependent (padding, order). */
struct zschan {
	volatile u_char	zc_csr;		/* ctrl,status, and indirect access */
	u_char		zc_xxx0[15];
	volatile u_char	zc_data;	/* data */
	u_char		zc_xxx1[15];
};
void	zs_kgdb_init (void);

#ifndef ZSCCF_CHANNEL
#define ZSCCF_CHANNEL 0
#define ZSCCF_CHANNEL_DEFAULT -1
#endif


path: sys/arch/macppc/macppc/CVS/Entries


code: src/sys/arch/macppc/macppc

path: sys/arch/macppc/macppc/CVS/Repository


code:
/*	$OpenBSD: autoconf.c,v 1.43 2014/04/04 01:50:25 dlg Exp $	*/
/*
 * Copyright (c) 1996, 1997 Per Fogelstrom
 * Copyright (c) 1995 Theo de Raadt
 * Copyright (c) 1988 University of Utah.
 * Copyright (c) 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * the Systems Programming Group of the University of Utah Computer
 * Science Department and 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.
 *
 * from: Utah Hdr: autoconf.c 1.31 91/01/21
 *
 *	from: @(#)autoconf.c	8.1 (Berkeley) 6/10/93
 *      $Id: autoconf.c,v 1.43 2014/04/04 01:50:25 dlg Exp $
 */

/*
 * Setup the system to run on the current machine.
 *
 * cpu_configure() is called at boot time.  Available
 * devices are determined (from possibilities mentioned in ioconf.c),
 * and the drivers are initialized.
 */

#include "sd.h"
#include "mpath.h"

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/disklabel.h>
#include <sys/conf.h>
#include <sys/reboot.h>
#include <sys/device.h>
#include <dev/cons.h>
#include <uvm/uvm_extern.h>
#include <machine/autoconf.h>

#include <sys/disk.h>
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
#include <dev/ata/atavar.h>

#if NMPATH > 0
#include <scsi/mpathvar.h>
#endif

void	dumpconf(void);
static	struct devmap *findtype(char **);
void	parseofwbp(char *);
int	getpno(char **);

/*
 * The following several variables are related to
 * the configuration process, and are used in initializing
 * the machine.
 */
int	cold = 1;	/* if 1, still working on cold-start */
char	bootdev[16];	/* to hold boot dev name */
struct device *bootdv = NULL;
enum devclass bootdev_class = DV_DULL;
int	bootdev_type = 0;
int	bootdev_unit = 0;

/*
 *  Configure all devices found that we know about.
 *  This is done at boot time.
 */
void
cpu_configure()
{
	(void)splhigh();	/* To be really sure.. */

	softintr_init();

	if (config_rootfound("mainbus", "mainbus") == 0)
		panic("no mainbus found");
	(void)spl0();
	cold = 0;
}

struct devmap {
	char *att;
	char *dev;
	int   type;
};
#define	T_IFACE	0x10

#define	T_BUS	0x00
#define	T_SCSI	0x11
#define	T_IDE	0x12
#define	T_DISK	0x21

static struct devmap *
findtype(char **s)
{
	static struct devmap devmap[] = {
		{ "/ht",		NULL, T_BUS },
		{ "/ht@",		NULL, T_BUS },
		{ "/pci@",		NULL, T_BUS },
		{ "/pci",		NULL, T_BUS },
		{ "/AppleKiwi@",	NULL, T_BUS },
		{ "/AppleKiwi",		NULL, T_BUS },
		{ "/mac-io@",		NULL, T_BUS },
		{ "/mac-io",		NULL, T_BUS },
		{ "/@",			NULL, T_BUS },
		{ "/LSILogic,sas@",	"sd", T_SCSI },
		{ "/scsi@",		"sd", T_SCSI },
		{ "/ide",		"wd", T_IDE },
		{ "/ata",		"wd", T_IDE },
		{ "/k2-sata-root",	NULL, T_BUS },
		{ "/k2-sata",		"wd", T_IDE },
		{ "/disk@",		"sd", T_DISK },
		{ "/disk",		"wd", T_DISK },
		{ "/usb@",		"sd", T_SCSI },
		{ "/ADPT,2940U2B@",	"sd", T_SCSI },
		{ "/bcom5704@4",	"bge0", T_IFACE },
		{ "/bcom5704@4,1",	"bge1", T_IFACE },
		{ "/ethernet",		"gem0", T_IFACE },
		{ "/enet",		"mc0", T_IFACE },
		{ NULL, NULL }
	};
	struct devmap *dp = &devmap[0];

	while (dp->att) {
		if (strncmp(*s, dp->att, strlen(dp->att)) == 0) {
			*s += strlen(dp->att);
			break;
		}
		dp++;
	}
	if (dp->att == NULL)
		printf("string [%s] not found\n", *s);

	return(dp);
}

/*
 * Look at the string 'bp' and decode the boot device.
 * Boot names look like: '/pci/scsi@c/disk@0,0/bsd'
 *                       '/pci/mac-io/ide@20000/disk@0,0/bsd
 *                       '/pci/mac-io/ide/disk/bsd
 *			 '/ht@0,f2000000/pci@2/bcom5704@4/bsd'
 */
void
parseofwbp(char *bp)
{
	int	ptype;
	char   *dev, *cp;
	struct devmap *dp;

	cp = bp;
	do {
		while(*cp && *cp != '/')
			cp++;

		dp = findtype(&cp);
		if (!dp->att) {
			printf("Warning: bootpath unrecognized: %s\n", bp);
			return;
		}
	} while((dp->type & T_IFACE) == 0);

	if (dp->att && dp->type == T_IFACE) {
		bootdev_class = DV_IFNET;
		bootdev_type = dp->type;
		strlcpy(bootdev, dp->dev, sizeof bootdev);
		return;
	}
	dev = dp->dev;
	while(*cp && *cp != '/')
		cp++;
	ptype = dp->type;
	dp = findtype(&cp);
	if (dp->att && dp->type == T_DISK) {
		bootdev_class = DV_DISK;
		bootdev_type = ptype;
		bootdev_unit = getpno(&cp);
		return;
	}
	printf("Warning: boot device unrecognized: %s\n", bp);
}

int
getpno(char **cp)
{
	int val = 0, digit;
	char *cx = *cp;

	while (*cx) {
		if (*cx >= '0' && *cx <= '9')
			digit = *cx - '0';
		else if (*cx >= 'a' && *cx <= 'f')
			digit = *cx - 'a' + 0x0a;
		else
			break;
		val = val * 16 + digit;
		cx++;
	}
	*cp = cx;
	return (val);
}

void
device_register(struct device *dev, void *aux)
{
#if NSD > 0
	extern struct cfdriver scsibus_cd;
#endif
	const char *drvrname = dev->dv_cfdata->cf_driver->cd_name;
	const char *name = dev->dv_xname;

	if (bootdv != NULL || dev->dv_class != bootdev_class)
		return;

	switch (bootdev_type) {
#if NSD > 0
	case T_SCSI:
		if (dev->dv_parent->dv_cfdata->cf_driver == &scsibus_cd) {
			struct scsi_attach_args *sa = aux;

			if (sa->sa_sc_link->target == bootdev_unit)
				bootdv = dev;
		}
#endif
	case T_IDE:
		if (strcmp(drvrname, "wd") == 0) {
			struct ata_atapi_attach *aa = aux;

	    		if (aa->aa_drv_data->drive == bootdev_unit)
				bootdv = dev;
		}
		break;
	case T_IFACE:
		if (strcmp(name, bootdev) == 0)
			bootdv = dev;
		break;
	default:
		break;
	}
}

void
diskconf(void)
{
	printf("bootpath: %s\n", bootpath);

#if NMPATH > 0
	if (bootdv != NULL)
		bootdv = mpath_bootdv(bootdv);
#endif

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

struct nam2blk nam2blk[] = {
	{ "wd",		0 },
	{ "sd",		2 },
	{ "rd",		17 },
	{ "raid",	19 },
	{ "vnd",	14 },
	{ NULL,		-1 }
};


code:
/*	$OpenBSD: clock.c,v 1.40 2015/06/13 07:16:36 jsg Exp $	*/
/*	$NetBSD: clock.c,v 1.1 1996/09/30 16:34:40 ws Exp $	*/

/*
 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
 * Copyright (C) 1995, 1996 TooLs GmbH.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by TooLs GmbH.
 * 4. The name of TooLs GmbH may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/evcount.h>
#include <sys/timetc.h>

#include <machine/autoconf.h>
#include <machine/pio.h>
#include <machine/intr.h>
#include <machine/vmparam.h>
#include <dev/ofw/openfirm.h>

void decr_intr(struct clockframe *frame);
u_int tb_get_timecount(struct timecounter *);

/*
 * Initially we assume a processor with a bus frequency of 12.5 MHz.
 */
u_int32_t ticks_per_sec = 3125000;
u_int32_t ns_per_tick = 320;
static int32_t ticks_per_intr;

static struct timecounter tb_timecounter = {
	tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL
};

/* calibrate the timecounter frequency for the listed models */
static const char *calibrate_tc_models[] = {
	"PowerMac10,1"
};
extern char *hw_prod;

time_read_t  *time_read;
time_write_t *time_write;

/* vars for stats */
int statint;
u_int32_t statvar;
u_int32_t statmin;

static struct evcount clk_count;
static struct evcount stat_count;
static int clk_irq = PPC_CLK_IRQ;
static int stat_irq = PPC_STAT_IRQ;

/*
 * Set up the system's time, given a `reasonable' time value.
 */
void
inittodr(time_t base)
{
	int badbase = 0, waszero = base == 0;
	char *bad = NULL;
	struct timeval tv;
	struct timespec ts;

        if (base < 5 * SECYR) {
                /*
                 * If base is 0, assume filesystem time is just unknown
                 * instead of preposterous. Don't bark.
                 */
                if (base != 0)
                        printf("WARNING: preposterous time in file system\n");
                /* not going to use it anyway, if the chip is readable */
                base = 21*SECYR + 186*SECDAY + SECDAY/2;
                badbase = 1;
        }

	if (time_read != NULL) {
		time_t cursec;
		(*time_read)(&cursec);
		tv.tv_sec = cursec;
		tv.tv_usec = 0;
	} else {
		/* force failure */
		tv.tv_sec = tv.tv_usec = 0;
	}

	if (tv.tv_sec == 0) {
		/*
		 * Believe the time in the file system for lack of
		 * anything better, resetting the clock.
		 */
		bad = "WARNING: unable to get date/time";
		tv.tv_sec = base;
		tv.tv_usec = 0;
		if (!badbase)
			resettodr();
	} else {
		int deltat;

		tv.tv_sec += tz.tz_minuteswest * 60;
		if (tz.tz_dsttime)
			tv.tv_sec -= 3600;

		deltat = tv.tv_sec - base;

		if (deltat < 0)
			deltat = -deltat;
		if (!(waszero || deltat < 2 * SECDAY)) {
			printf("WARNING: clock %s %ld days",
			    tv.tv_sec < base ? "lost" : "gained", deltat / SECDAY);
			bad = "";

			if (tv.tv_sec < base && deltat > 1000 * SECDAY) {
				printf(", using FS time");
				tv.tv_sec = base;
			}
		}
	}

	ts.tv_sec = tv.tv_sec;
	ts.tv_nsec = tv.tv_usec * 1000;
	tc_setclock(&ts);

	if (bad) {
		printf("%s", bad);
		printf(" -- CHECK AND RESET THE DATE!\n");
	}
}

/*
 * Similar to the above
 */
void
resettodr(void)
{
	struct timeval tv;

	if (time_second == 1)
		return;

	microtime(&tv);

	if (time_write != NULL) {
		tv.tv_sec -= tz.tz_minuteswest * 60;
		if (tz.tz_dsttime) {
			tv.tv_sec += 3600;
		}
		(*time_write)(tv.tv_sec);
	}
}

void
decr_intr(struct clockframe *frame)
{
	u_int64_t tb;
	u_int64_t nextevent;
	struct cpu_info *ci = curcpu();
	int nstats;
	int s;

	/*
	 * Check whether we are initialized.
	 */
	if (!ticks_per_intr)
		return;

	/*
	 * Based on the actual time delay since the last decrementer reload,
	 * we arrange for earlier interrupt next time.
	 */

	tb = ppc_mftb();
	while (ci->ci_nexttimerevent <= tb)
		ci->ci_nexttimerevent += ticks_per_intr;

	ci->ci_prevtb = ci->ci_nexttimerevent - ticks_per_intr;

	for (nstats = 0; ci->ci_nextstatevent <= tb; nstats++) {
		int r;
		do {
			r = random() & (statvar -1);
		} while (r == 0); /* random == 0 not allowed */
		ci->ci_nextstatevent += statmin + r;
	}

	/* only count timer ticks for CLK_IRQ */
	stat_count.ec_count += nstats;

	if (ci->ci_nexttimerevent < ci->ci_nextstatevent)
		nextevent = ci->ci_nexttimerevent;
	else
		nextevent = ci->ci_nextstatevent;

	/*
	 * Need to work about the near constant skew this introduces???
	 * reloading tb here could cause a missed tick.
	 */
	ppc_mtdec(nextevent - tb);

	if (ci->ci_cpl >= IPL_CLOCK) {
		ci->ci_statspending += nstats;
	} else {
		nstats += ci->ci_statspending;
		ci->ci_statspending = 0;

		s = splclock();

		/*
		 * Reenable interrupts
		 */
		ppc_intr_enable(1);

		/*
		 * Do standard timer interrupt stuff.
		 */
		while (ci->ci_lasttb < ci->ci_prevtb) {
			/* sync lasttb with hardclock */
			ci->ci_lasttb += ticks_per_intr;
			clk_count.ec_count++;
			hardclock(frame);
		}

		while (nstats-- > 0)
			statclock(frame);

		splx(s);
		(void) ppc_intr_disable();

		/* if a tick has occurred while dealing with these,
		 * dont service it now, delay until the next tick.
		 */
	}
}

void cpu_startclock(void);

void
cpu_initclocks()
{
	int intrstate;
	int minint;
	u_int32_t first_tb, second_tb;
	time_t first_sec, sec;
	int calibrate = 0, n;

	/* check if we should calibrate the timecounter frequency */
	for (n = 0; n < sizeof(calibrate_tc_models) /
	    sizeof(calibrate_tc_models[0]); n++) {
		if (!strcmp(calibrate_tc_models[n], hw_prod)) {
			calibrate = 1;
			break;
		}
	}

	/* if a RTC is available, calibrate the timecounter frequency */
	if (calibrate && time_read != NULL) {
		time_read(&first_sec);
		do {
			first_tb = ppc_mftbl();
			time_read(&sec);
		} while (sec == first_sec);
		first_sec = sec;
		do {
			second_tb = ppc_mftbl();
			time_read(&sec);
		} while (sec == first_sec);
		ticks_per_sec = second_tb - first_tb;
#ifdef DEBUG
		printf("tb: using measured timecounter frequency of %ld Hz\n",
		    ticks_per_sec);
#endif
	}

	intrstate = ppc_intr_disable();

	ticks_per_intr = ticks_per_sec / hz;

	stathz = 100;
	profhz = 1000; /* must be a multiple of stathz */

	/* init secondary clock to stathz */
	statint = ticks_per_sec / stathz;
	statvar = 0x40000000; /* really big power of two */
	/* find largest 2^n which is nearly smaller than statint/2  */
	minint = statint / 2 + 100;
	while (statvar > minint)
		statvar >>= 1;
	statmin = statint - (statvar >> 1);

	evcount_attach(&clk_count, "clock", &clk_irq);
	evcount_attach(&stat_count, "stat", &stat_irq);

	cpu_startclock();

	tb_timecounter.tc_frequency = ticks_per_sec;
	tc_init(&tb_timecounter);
	ppc_intr_enable(intrstate);
}

void
cpu_startclock()
{
	struct cpu_info *ci = curcpu();
	u_int64_t nextevent;

	ci->ci_lasttb = ppc_mftb();

	/*
	 * no point in having random on the first tick,
	 * it just complicates the code.
	 */
	ci->ci_nexttimerevent = ci->ci_lasttb + ticks_per_intr;
	nextevent = ci->ci_nextstatevent = ci->ci_nexttimerevent;

	ci->ci_statspending = 0;

	ppc_mtdec(nextevent - ci->ci_lasttb);
}

/*
 * Wait for about n microseconds (us) (at least!).
 */
void
delay(unsigned n)
{
	u_int64_t tb;

	tb = ppc_mftb();
	tb += (n * 1000 + ns_per_tick - 1) / ns_per_tick;
	while (tb > ppc_mftb())
		;
}

/*
 * Nothing to do.
 */
void
setstatclockrate(int newhz)
{
	int minint;
	int intrstate;

	intrstate = ppc_intr_disable();

	statint = ticks_per_sec / newhz;
	statvar = 0x40000000; /* really big power of two */
	/* find largest 2^n which is nearly smaller than statint/2 */
	minint = statint / 2 + 100;
	while (statvar > minint)
		statvar >>= 1;

	statmin = statint - (statvar >> 1);
	ppc_intr_enable(intrstate);

	/*
	 * XXX this allows the next stat timer to occur then it switches
	 * to the new frequency. Rather than switching instantly.
	 */
}

u_int
tb_get_timecount(struct timecounter *tc)
{
	return ppc_mftbl();
}


code:
/*	$OpenBSD: conf.c,v 1.62 2014/12/11 19:44:17 tedu Exp $ */

/*
 * Copyright (c) 1997 Per Fogelstrom
 * Copyright (c) 1997 RTMX Inc, North Carolina
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed under OpenBSD for RTMX Inc,
 *	North Carolina, USA, by Per Fogelstrom, Opsycon AB, Sweden.
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */
#include <sys/param.h>
#include <sys/buf.h>
#include <sys/ioctl.h>
#include <sys/systm.h>
#include <sys/tty.h>
#include <sys/vnode.h>

#include <machine/conf.h>

#include "sd.h"
#include "st.h"
#include "cd.h"
#include "uk.h"
#include "rd.h"
#include "wd.h"
bdev_decl(wd);
cdev_decl(wd);

#include "vnd.h"

struct bdevsw bdevsw[] = {
	bdev_disk_init(NWD,wd),		/* 0: ST506/ESDI/IDE disk */
	bdev_swap_init(1,sw),		/* 1 swap pseudo device */
	bdev_disk_init(NSD,sd),		/* 2 SCSI Disk */
	bdev_disk_init(NCD,cd),		/* 3 SCSI CD-ROM */
	bdev_notdef(),			/* 4 unknown*/
	bdev_tape_init(NST,st),		/* 5 SCSI tape */
	bdev_notdef(),			/* 6 unknown*/
	bdev_notdef(),			/* 7 unknown*/
	bdev_notdef(),			/* 8 */
	bdev_notdef(),			/* 9 */
	bdev_notdef(),			/* 10 */
	bdev_notdef(),			/* 11 */
	bdev_notdef(),			/* 12 */
	bdev_notdef(),			/* 13 */
	bdev_disk_init(NVND,vnd),	/* 14 vnode disk driver*/
	bdev_notdef(),			/* 15 unknown*/
	bdev_notdef(),			/* 16 was: concatenated disk driver*/
	bdev_disk_init(NRD,rd),		/* 17 ram disk driver*/
	bdev_notdef(),			/* 18 unknown*/
	bdev_notdef(),			/* 19 was: RAIDframe disk driver */
};
int nblkdev = nitems(bdevsw);

#include "pty.h"
#include "zstty.h"

cdev_decl(kbd);
cdev_decl(ms);

#include "com.h"
cdev_decl(com);

#include "wsdisplay.h"
#include "wskbd.h"
#include "wsmouse.h"

#include "bpfilter.h"

#include "tun.h"

#include "ksyms.h"
#include "usb.h"
#include "uhid.h"
#include "ugen.h"
#include "ulpt.h"
#include "ucom.h"

#include "apm.h"
#include "drm.h"
cdev_decl(drm);

#include "wsmux.h"

#ifdef USER_PCICONF
#include "pci.h"
cdev_decl(pci);
#endif

#include "audio.h"
#include "video.h"
#include "midi.h"

#include "pf.h"

#include "systrace.h"

#include "radio.h"
#include "bktr.h"
#include "hotplug.h"
#include "gpio.h"
#include "bio.h"
#include "vscsi.h"
#include "pppx.h"
#include "fuse.h"

struct cdevsw cdevsw[] = {
	cdev_cn_init(1,cn),		/* 0: virtual console */
	cdev_ctty_init(1,ctty),		/* 1: controlling terminal */
	cdev_mm_init(1,mm),		/* 2: /dev/{null,mem,kmem,...} */
	cdev_notdef(),			/* 3 was /dev/drum */
	cdev_tty_init(NPTY,pts),	/* 4: pseudo-tty slave */
	cdev_ptc_init(NPTY,ptc),	/* 5: pseudo-tty master */
	cdev_log_init(1,log),		/* 6: /dev/klog */
	cdev_tty_init(NZSTTY,zs),	/* 7: Serial ports */
	cdev_disk_init(NSD,sd),		/* 8: SCSI disk */
	cdev_disk_init(NCD,cd),		/* 9: SCSI CD-ROM */
	cdev_notdef(),			/* 10: SCSI changer */
	cdev_disk_init(NWD,wd),		/* 11: ST506/ESDI/IDE disk */
	cdev_notdef(),			/* 12 */
	cdev_notdef(),			/* 13 */
	cdev_notdef(),			/* 14 */
	cdev_notdef(),			/* 15 */
	cdev_notdef(),			/* 16 */
	cdev_disk_init(NRD,rd),		/* 17 ram disk driver*/
	cdev_notdef(),			/* 18 was: concatenated disk driver */
	cdev_disk_init(NVND,vnd),	/* 19: vnode disk */
	cdev_tape_init(NST,st),		/* 20: SCSI tape */
	cdev_fd_init(1,filedesc),	/* 21: file descriptor pseudo-dev */
	cdev_bpf_init(NBPFILTER,bpf),	/* 22: berkeley packet filter */
	cdev_tun_init(NTUN,tun),	/* 23: network tunnel */
	cdev_notdef(),			/* 24 was LKM */
	cdev_apm_init(NAPM,apm),	/* 25: APM interface */
	cdev_tty_init(NCOM,com),        /* 26: Serial Ports via com(4) */
	cdev_notdef(),			/* 27 */
	cdev_notdef(),			/* 28 */
	cdev_notdef(),			/* 29 */
	cdev_notdef(),			/* 30 */
	cdev_notdef(),			/* 31 */
	cdev_notdef(),			/* 32 */
	cdev_notdef(),			/* 33 */
	cdev_notdef(),			/* 34 */
	cdev_notdef(),			/* 35 */
	cdev_notdef(),			/* 36 */
	cdev_notdef(),			/* 37 */
	cdev_notdef(),			/* 38 */
	cdev_pf_init(NPF,pf),		/* 39: packet filter */
	cdev_random_init(1,random),	/* 40: random data source */
	cdev_uk_init(NUK,uk),		/* 41: unknown SCSI */
	cdev_notdef(),			/* 42 */
	cdev_ksyms_init(NKSYMS,ksyms),	/* 43: Kernel symbols device */
	cdev_audio_init(NAUDIO,audio),	/* 44: generic audio I/O */
	cdev_video_init(NVIDEO,video),	/* 45: generic video I/O */
	cdev_notdef(),			/* 46 */
	cdev_notdef(),			/* 47: was: /dev/crypto */
	cdev_notdef(),			/* 48 */
	cdev_notdef(),			/* 49 */
	cdev_systrace_init(NSYSTRACE,systrace),	/* 50 system call tracing */
	cdev_notdef(),			/* 51 */
	cdev_midi_init(NMIDI,midi),	/* 52: MIDI I/O */
	cdev_notdef(),			/* 53 was: sequencer I/O */
	cdev_notdef(),			/* 54 was: RAIDframe disk driver */
	cdev_notdef(),			/* 55 */
	/* The following slots are reserved for isdn4bsd. */
	cdev_notdef(),			/* 56: i4b main device */
	cdev_notdef(),			/* 57: i4b control device */
	cdev_notdef(),			/* 58: i4b raw b-channel access */
	cdev_notdef(),			/* 59: i4b trace device */
	cdev_notdef(),			/* 60: i4b phone device */
	/* End of reserved slots for isdn4bsd. */
	cdev_usb_init(NUSB,usb),	/* 61: USB controller */
	cdev_usbdev_init(NUHID,uhid),	/* 62: USB generic HID */
	cdev_usbdev_init(NUGEN,ugen),	/* 63: USB generic driver */
	cdev_ulpt_init(NULPT,ulpt),	/* 64: USB printers */
	cdev_notdef(),			/* 65: was urio */
	cdev_tty_init(NUCOM,ucom),	/* 66: USB tty */
	cdev_wsdisplay_init(NWSDISPLAY,	/* 67: frame buffers, etc. */
		wsdisplay),
	cdev_mouse_init(NWSKBD, wskbd),	/* 68: keyboards */
	cdev_mouse_init(NWSMOUSE,	/* 69: mice */
		wsmouse),
	cdev_mouse_init(NWSMUX, wsmux),	/* 70: ws multiplexor */
#ifdef USER_PCICONF
	cdev_pci_init(NPCI,pci),	/* 71: PCI user */
#else
	cdev_notdef(),
#endif
	cdev_notdef(),			/* 72: ALTQ (deprecated) */
	cdev_notdef(),
	cdev_notdef(),			/* 74: was USB scanners */
	cdev_bktr_init(NBKTR,bktr),	/* 75: Bt848 video capture device */
	cdev_radio_init(NRADIO, radio),	/* 76: generic radio I/O */
	cdev_ptm_init(NPTY,ptm),	/* 77: pseudo-tty ptm device */
	cdev_hotplug_init(NHOTPLUG,hotplug), /* 78: devices hot plugging */
	cdev_gpio_init(NGPIO,gpio),	/* 79: GPIO interface */
	cdev_bio_init(NBIO,bio),	/* 80: ioctl tunnel */
	cdev_notdef(),
	cdev_openprom_init(1,openprom),	/* 82: /dev/openprom */
	cdev_vscsi_init(NVSCSI,vscsi),	/* 83: vscsi */
	cdev_disk_init(1,diskmap),	/* 84: disk mapper */
	cdev_pppx_init(NPPPX,pppx),	/* 85: pppx */
	cdev_notdef(),			/* 86 */
	cdev_drm_init(NDRM,drm),	/* 87: drm */
	cdev_fuse_init(NFUSE,fuse),	/* 88: fuse */
};
int nchrdev = nitems(cdevsw);

int mem_no = 2;				/* major number of /dev/mem */

/*
 * Swapdev is a fake device implemented in sw.c.
 * It is used only internally to get to swstrategy.
 */
dev_t swapdev = makedev(1, 0);

/*
 * Check whether dev is /dev/mem or /dev/kmem.
 */
int
iskmemdev(dev_t dev)
{
	return major(dev) == mem_no && minor(dev) < 2;
}

/*
 * Check whether dev is /dev/zero.
 */
int
iszerodev(dev_t dev)
{
	return major(dev) == mem_no && minor(dev) == 12;
}

dev_t
getnulldev()
{
	return makedev(mem_no, 2);
}

int chrtoblktbl[] = {
	/*VCHR*/	/*VBLK*/
	/*  0 */	NODEV,
	/*  1 */	NODEV,
	/*  2 */	NODEV,
	/*  3 */	NODEV,
	/*  4 */	NODEV,
	/*  5 */	NODEV,
	/*  6 */	NODEV,
	/*  7 */	NODEV,
	/*  8 */	2,		/* sd */
	/*  9 */	3,		/* cd */
	/* 10 */	NODEV,
	/* 11 */	0,		/* wd */
	/* 12 */	NODEV,
	/* 13 */	NODEV,
	/* 14 */	NODEV,
	/* 15 */	NODEV,
	/* 16 */	NODEV,
	/* 17 */	17,		/* rd */
	/* 18 */	NODEV,
	/* 19 */	14,		/* vnd */
	/* 20 */	5,		/* st */
	/* 21 */	NODEV,
	/* 22 */	NODEV,
	/* 23 */	NODEV,
	/* 24 */	NODEV,
	/* 25 */	NODEV,
	/* 26 */	NODEV,
	/* 27 */	NODEV,
	/* 28 */	NODEV,
	/* 29 */	NODEV,
	/* 30 */	NODEV,
	/* 31 */	NODEV,
	/* 32 */	NODEV,
	/* 33 */	NODEV,
	/* 34 */	NODEV,
	/* 35 */	NODEV,
	/* 36 */	NODEV,
	/* 37 */	NODEV,
	/* 38 */	NODEV,
	/* 39 */	NODEV,
	/* 40 */	NODEV,
	/* 41 */	NODEV,
	/* 42 */	NODEV,
	/* 43 */	NODEV,
	/* 44 */	NODEV,
	/* 45 */	NODEV,
	/* 46 */	NODEV,
	/* 47 */	NODEV,
	/* 48 */	NODEV,
	/* 49 */	NODEV,
	/* 50 */	NODEV,
	/* 51 */	NODEV,
	/* 52 */	NODEV,
	/* 53 */	NODEV,
	/* 54 */	19,		/* raid */
};
int nchrtoblktbl = nitems(chrtoblktbl);

#include <dev/cons.h>

cons_decl(ws);
cons_decl(zs);

struct consdev constab[] = {
#if NWSDISPLAY > 0
	cons_init(ws),
#endif
#if NZSTTY > 0
	cons_init(zs),
#endif
	{ 0 },
};


code:
/*	$OpenBSD: cpu.c,v 1.82 2015/06/04 18:01:44 kettenis Exp $ */

/*
 * Copyright (c) 1997 Per Fogelstrom
 * Copyright (c) 1997 RTMX Inc
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed under OpenBSD for RTMX Inc
 *	North Carolina, USA, by Per Fogelstrom, Opsycon AB, Sweden.
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/task.h>
#include <sys/device.h>
#include <dev/rndvar.h>

#include <uvm/uvm_extern.h>

#include <dev/ofw/openfirm.h>

#include <machine/autoconf.h>
#include <powerpc/bat.h>
#include <machine/cpu.h>
#include <machine/trap.h>
#include <powerpc/hid.h>

/* SCOM addresses (24-bit) */
#define SCOM_PCR	0x0aa001 /* Power Control Register */
#define SCOM_PSR	0x408001 /* Power Tuning Status Register */

/* SCOMC format */
#define SCOMC_ADDR_SHIFT	8
#define SCOMC_ADDR_MASK		0xffff0000
#define SCOMC_READ		0x00008000

/* Power (Tuning) Status Register */
#define PSR_CMD_RECEIVED	0x2000000000000000LL
#define PSR_CMD_COMPLETED	0x1000000000000000LL
#define PSR_FREQ_MASK		0x0300000000000000LL
#define PSR_FREQ_HALF		0x0100000000000000LL

struct cpu_info cpu_info[PPC_MAXPROCS];

char cpu_model[80];
char machine[] = MACHINE;	/* cpu architecture */

/* Definition of the driver for autoconfig. */
int	cpumatch(struct device *, void *, void *);
void	cpuattach(struct device *, struct device *, void *);

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

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

void ppc64_scale_frequency(u_int);
void (*ppc64_slew_voltage)(u_int);
void ppc64_setperf(int);

void config_l2cr(int);

int
cpumatch(struct device *parent, void *cfdata, void *aux)
{
	struct confargs *ca = aux;
	int *reg = ca->ca_reg;

	/* make sure that we're looking for a CPU. */
	if (strcmp(ca->ca_name, cpu_cd.cd_name) != 0)
		return (0);

	if (reg[0] >= PPC_MAXPROCS)
		return (0);

	return (1);
}

u_int32_t ppc_curfreq;
u_int32_t ppc_maxfreq;

int
ppc_cpuspeed(int *freq)
{
	*freq = ppc_curfreq;

	return (0);
}

static u_int32_t ppc_power_mode_data[2];

void
ppc64_scale_frequency(u_int freq_scale)
{
	u_int64_t psr;
	int s;

	s = ppc_intr_disable();

	/* Clear PCRH and PCR. */
	ppc_mtscomd(0x00000000);
	ppc_mtscomc(SCOM_PCR << SCOMC_ADDR_SHIFT);
	ppc_mtscomd(0x80000000);
	ppc_mtscomc(SCOM_PCR << SCOMC_ADDR_SHIFT);

	/* Set PCR. */
	ppc_mtscomd(ppc_power_mode_data[freq_scale] | 0x80000000);
	ppc_mtscomc(SCOM_PCR << SCOMC_ADDR_SHIFT);

	/* Wait until frequency change is completed. */
	do {
		ppc64_mtscomc((SCOM_PSR << SCOMC_ADDR_SHIFT) | SCOMC_READ);
		psr = ppc64_mfscomd();
		ppc64_mfscomc();
		if (psr & PSR_CMD_COMPLETED)
			break;
		DELAY(100);
	} while (psr & PSR_CMD_RECEIVED);

	if ((psr & PSR_FREQ_MASK) == PSR_FREQ_HALF)
		ppc_curfreq = ppc_maxfreq / 2;
	else
		ppc_curfreq = ppc_maxfreq;

	ppc_intr_enable(s);
}

extern int perflevel;

struct task ppc64_setperf_task;
int ppc64_perflevel;

void
ppc64_do_setperf(void *arg)
{
	if (ppc64_perflevel <= 50) {
		if (ppc_curfreq == ppc_maxfreq / 2)
			return;

		ppc64_scale_frequency(FREQ_HALF);
		if (ppc64_slew_voltage)
			ppc64_slew_voltage(FREQ_HALF);
	} else {
		if (ppc_curfreq == ppc_maxfreq)
			return;

		if (ppc64_slew_voltage)
			ppc64_slew_voltage(FREQ_FULL);
		ppc64_scale_frequency(FREQ_FULL);
	}
}

void
ppc64_setperf(int level)
{
	ppc64_perflevel = level;
	task_add(systq, &ppc64_setperf_task);
}

void
cpuattach(struct device *parent, struct device *dev, void *aux)
{
	struct confargs *ca = aux;
	int *reg = ca->ca_reg;
	u_int32_t cpu, pvr, hid0;
	char name[32];
	int qhandle, phandle, len;
	u_int32_t clock_freq = 0, timebase = 0;
	struct cpu_info *ci;

	ci = &cpu_info[reg[0]];
	ci->ci_cpuid = reg[0];
	ci->ci_intrdepth = -1;
	ci->ci_dev = dev;

	pvr = ppc_mfpvr();
	cpu = pvr >> 16;
	switch (cpu) {
	case PPC_CPU_MPC601:
		snprintf(cpu_model, sizeof(cpu_model), "601");
		break;
	case PPC_CPU_MPC603:
		snprintf(cpu_model, sizeof(cpu_model), "603");
		break;
	case PPC_CPU_MPC604:
		snprintf(cpu_model, sizeof(cpu_model), "604");
		break;
	case PPC_CPU_MPC603e:
		snprintf(cpu_model, sizeof(cpu_model), "603e");
		break;
	case PPC_CPU_MPC603ev:
		snprintf(cpu_model, sizeof(cpu_model), "603ev");
		break;
	case PPC_CPU_MPC750:
		snprintf(cpu_model, sizeof(cpu_model), "750");
		break;
	case PPC_CPU_MPC604ev:
		snprintf(cpu_model, sizeof(cpu_model), "604ev");
		break;
	case PPC_CPU_MPC7400:
		ppc_altivec = 1;
		snprintf(cpu_model, sizeof(cpu_model), "7400");
		break;
	case PPC_CPU_MPC7447A:
		ppc_altivec = 1;
		snprintf(cpu_model, sizeof(cpu_model), "7447A");
		break;
	case PPC_CPU_MPC7448:
		ppc_altivec = 1;
		snprintf(cpu_model, sizeof(cpu_model), "7448");
		break;
	case PPC_CPU_IBM970:
		ppc_altivec = 1;
		snprintf(cpu_model, sizeof(cpu_model), "970");
		break;
	case PPC_CPU_IBM970FX:
		ppc_altivec = 1;
		snprintf(cpu_model, sizeof(cpu_model), "970FX");
		break;
	case PPC_CPU_IBM970MP:
		ppc_altivec = 1;
		snprintf(cpu_model, sizeof(cpu_model), "970MP");
		break;
	case PPC_CPU_IBM750FX:
		snprintf(cpu_model, sizeof(cpu_model), "750FX");
		break;
	case PPC_CPU_MPC7410:
		ppc_altivec = 1;
		snprintf(cpu_model, sizeof(cpu_model), "7410");
		break;
	case PPC_CPU_MPC7450:
		ppc_altivec = 1;
		if ((pvr & 0xf) < 3)
			snprintf(cpu_model, sizeof(cpu_model), "7450");
		 else
			snprintf(cpu_model, sizeof(cpu_model), "7451");
		break;
	case PPC_CPU_MPC7455:
		ppc_altivec = 1;
		snprintf(cpu_model, sizeof(cpu_model), "7455");
		break;
	case PPC_CPU_MPC7457:
		ppc_altivec = 1;
		snprintf(cpu_model, sizeof(cpu_model), "7457");
		break;
	default:
		snprintf(cpu_model, sizeof(cpu_model), "Version %x", cpu);
		break;
	}
	snprintf(cpu_model + strlen(cpu_model),
	    sizeof(cpu_model) - strlen(cpu_model),
	    " (Revision 0x%x)", pvr & 0xffff);
	printf(": %s", cpu_model);

	for (qhandle = OF_peer(0); qhandle; qhandle = phandle) {
                len = OF_getprop(qhandle, "device_type", name, sizeof(name));
                if (len >= 0 && strcmp(name, "cpu") == 0) {
			OF_getprop(qhandle, "clock-frequency", &clock_freq,
			    sizeof(clock_freq));
			OF_getprop(qhandle, "timebase-frequency", &timebase,
			    sizeof(timebase));
			break;
		}
                if ((phandle = OF_child(qhandle)))
                        continue;
                while (qhandle) {
                        if ((phandle = OF_peer(qhandle)))
                                break;
                        qhandle = OF_parent(qhandle);
                }
	}

	if (timebase != 0) {
		ticks_per_sec = timebase;
		ns_per_tick = 1000000000 / ticks_per_sec;
	}

	if (clock_freq != 0) {
		/* Openfirmware stores clock in Hz, not MHz */
		clock_freq /= 1000000;
		printf(": %d MHz", clock_freq);
		ppc_curfreq = ppc_maxfreq = clock_freq;
		cpu_cpuspeed = ppc_cpuspeed;
	}

	if (cpu == PPC_CPU_IBM970FX) {
		u_int64_t psr;
		int s;

		s = ppc_intr_disable();
		ppc64_mtscomc((SCOM_PSR << SCOMC_ADDR_SHIFT) | SCOMC_READ);
		psr = ppc64_mfscomd();
		ppc64_mfscomc();
		ppc_intr_enable(s);

		if ((psr & PSR_FREQ_MASK) == PSR_FREQ_HALF) {
			ppc_curfreq = ppc_maxfreq / 2;
			perflevel = 50;
		}

		if (OF_getprop(qhandle, "power-mode-data",
		    &ppc_power_mode_data, sizeof ppc_power_mode_data) >= 8) {
			task_set(&ppc64_setperf_task, ppc64_do_setperf, NULL);
			cpu_setperf = ppc64_setperf;
		}
	}

	/* power savings mode */
	hid0 = ppc_mfhid0();

	switch (cpu) {
	case PPC_CPU_MPC603:
	case PPC_CPU_MPC603e:
	case PPC_CPU_MPC750:
	case PPC_CPU_MPC7400:
	case PPC_CPU_IBM750FX:
	case PPC_CPU_MPC7410:
		/* select DOZE mode */
		hid0 &= ~(HID0_NAP | HID0_SLEEP);
		hid0 |= HID0_DOZE | HID0_DPM;
		ppc_cpuidle = 1;
		break;
	case PPC_CPU_MPC7447A:
	case PPC_CPU_MPC7448:
	case PPC_CPU_MPC7450:
	case PPC_CPU_MPC7455:
	case PPC_CPU_MPC7457:
		/* select NAP mode */
		hid0 &= ~(HID0_DOZE | HID0_SLEEP);
		hid0 |= HID0_NAP | HID0_DPM;
		/* try some other flags */
		hid0 |= HID0_SGE | HID0_BTIC;
		hid0 |= HID0_LRSTK | HID0_FOLD | HID0_BHT;
		/* Disable BTIC on 7450 Rev 2.0 or earlier */
		if (cpu == PPC_CPU_MPC7450 && (pvr & 0xffff) < 0x0200)
			hid0 &= ~HID0_BTIC;
		ppc_cpuidle = 1;
		break;
	case PPC_CPU_IBM970:
	case PPC_CPU_IBM970FX:
		/* select NAP mode */
		hid0 &= ~(HID0_DOZE | HID0_DEEPNAP);
		hid0 |= HID0_NAP | HID0_DPM;
		ppc_cpuidle = 1;
		break;
	case PPC_CPU_IBM970MP:
		/* select DEEPNAP mode, which requires NAP */
		hid0 &= ~HID0_DOZE;
		hid0 |= HID0_DEEPNAP | HID0_NAP | HID0_DPM;
		ppc_cpuidle = 1;
		break;
	}
	ppc_mthid0(hid0);

	/* if processor is G3 or G4, configure L2 cache */
	switch (cpu) {
	case PPC_CPU_MPC750:
	case PPC_CPU_MPC7400:
	case PPC_CPU_IBM750FX:
	case PPC_CPU_MPC7410:
	case PPC_CPU_MPC7447A:
	case PPC_CPU_MPC7448:
	case PPC_CPU_MPC7450:
	case PPC_CPU_MPC7455:
	case PPC_CPU_MPC7457:
		config_l2cr(cpu);
		break;
	}
	printf("\n");
}

/* L2CR bit definitions */
#define L2CR_L2E        0x80000000 /* 0: L2 enable */
#define L2CR_L2PE       0x40000000 /* 1: L2 data parity enable */
#define L2CR_L2SIZ      0x30000000 /* 2-3: L2 size */
#define  L2SIZ_RESERVED         0x00000000
#define  L2SIZ_256K             0x10000000
#define  L2SIZ_512K             0x20000000
#define  L2SIZ_1M       0x30000000
#define L2CR_L2CLK      0x0e000000 /* 4-6: L2 clock ratio */
#define  L2CLK_DIS              0x00000000 /* disable L2 clock */
#define  L2CLK_10               0x02000000 /* core clock / 1   */
#define  L2CLK_15               0x04000000 /*            / 1.5 */
#define  L2CLK_20               0x08000000 /*            / 2   */
#define  L2CLK_25               0x0a000000 /*            / 2.5 */
#define  L2CLK_30               0x0c000000 /*            / 3   */
#define L2CR_L2RAM      0x01800000 /* 7-8: L2 RAM type */
#define  L2RAM_FLOWTHRU_BURST   0x00000000
#define  L2RAM_PIPELINE_BURST   0x01000000
#define  L2RAM_PIPELINE_LATE    0x01800000
#define L2CR_L2DO       0x00400000 /* 9: L2 data-only.
                                      Setting this bit disables instruction
                                      caching. */
#define L2CR_L2I        0x00200000 /* 10: L2 global invalidate. */
#define L2CR_L2CTL      0x00100000 /* 11: L2 RAM control (ZZ enable).
                                      Enables automatic operation of the
                                      L2ZZ (low-power mode) signal. */
#define L2CR_L2WT       0x00080000 /* 12: L2 write-through. */
#define L2CR_L2TS       0x00040000 /* 13: L2 test support. */
#define L2CR_L2OH       0x00030000 /* 14-15: L2 output hold. */
#define L2CR_L2SL       0x00008000 /* 16: L2 DLL slow. */
#define L2CR_L2DF       0x00004000 /* 17: L2 differential clock. */
#define L2CR_L2BYP      0x00002000 /* 18: L2 DLL bypass. */
#define L2CR_L2IP       0x00000001 /* 31: L2 global invalidate in progress
				       (read only). */
#ifdef L2CR_CONFIG
u_int l2cr_config = L2CR_CONFIG;
#else
u_int l2cr_config = 0;
#endif

/* L3CR bit definitions */
#define   L3CR_L3E                0x80000000 /*  0: L3 enable */
#define   L3CR_L3SIZ              0x10000000 /*  3: L3 size (0=1MB, 1=2MB) */

void
config_l2cr(int cpu)
{
	u_int l2cr, x;

	l2cr = ppc_mfl2cr();

	/*
	 * Configure L2 cache if not enabled.
	 */
	if ((l2cr & L2CR_L2E) == 0 && l2cr_config != 0) {
		l2cr = l2cr_config;
		ppc_mtl2cr(l2cr);

		/* Wait for L2 clock to be stable (640 L2 clocks). */
		delay(100);

		/* Invalidate all L2 contents. */
		l2cr |= L2CR_L2I;
		ppc_mtl2cr(l2cr);
		do {
			x = ppc_mfl2cr();
		} while (x & L2CR_L2IP);

		/* Enable L2 cache. */
		l2cr &= ~L2CR_L2I;
		l2cr |= L2CR_L2E;
		ppc_mtl2cr(l2cr);
	}

	if (l2cr & L2CR_L2E) {
		if (cpu == PPC_CPU_MPC7450 || cpu == PPC_CPU_MPC7455) {
			u_int l3cr;

			printf(": 256KB L2 cache");

			l3cr = ppc_mfl3cr();
			if (l3cr & L3CR_L3E)
				printf(", %cMB L3 cache",
				    l3cr & L3CR_L3SIZ ? '2' : '1');
		} else if (cpu == PPC_CPU_IBM750FX ||
			   cpu == PPC_CPU_MPC7447A || cpu == PPC_CPU_MPC7457)
			printf(": 512KB L2 cache");
		else if (cpu == PPC_CPU_MPC7448)
			printf(": 1MB L2 cache");
		else {
			switch (l2cr & L2CR_L2SIZ) {
			case L2SIZ_256K:
				printf(": 256KB");
				break;
			case L2SIZ_512K:
				printf(": 512KB");
				break;
			case L2SIZ_1M:
				printf(": 1MB");
				break;
			default:
				printf(": unknown size");
			}
			printf(" backside cache");
		}
#if 0
		switch (l2cr & L2CR_L2RAM) {
		case L2RAM_FLOWTHRU_BURST:
			printf(" Flow-through synchronous burst SRAM");
			break;
		case L2RAM_PIPELINE_BURST:
			printf(" Pipelined synchronous burst SRAM");
			break;
		case L2RAM_PIPELINE_LATE:
			printf(" Pipelined synchronous late-write SRAM");
			break;
		default:
			printf(" unknown type");
		}

		if (l2cr & L2CR_L2PE)
			printf(" with parity");
#endif
	} else
		printf(": L2 cache not enabled");
}

#ifdef MULTIPROCESSOR

#define	INTSTK	(8*1024)		/* 8K interrupt stack */

int cpu_spinup(struct device *, struct cpu_info *);
void cpu_hatch(void);
void cpu_spinup_trampoline(void);

struct cpu_hatch_data {
	uint64_t tb;
	struct cpu_info *ci;
	uint32_t hid0;
	uint64_t hid1;
	uint64_t hid4;
	uint64_t hid5;
	int l2cr;
	int running;
};

volatile struct cpu_hatch_data *cpu_hatch_data;
volatile void *cpu_hatch_stack;

/*
 * XXX Due to a bug in our OpenFirmware interface/memory mapping,
 * machines with 64bit CPUs hang in the OF_finddevice() call below
 * if this array is stored on the stack.
 */
char cpuname[64];

int
cpu_spinup(struct device *self, struct cpu_info *ci)
{
	volatile struct cpu_hatch_data hatch_data, *h = &hatch_data;
	int i;
	struct pglist mlist;
	struct vm_page *m;
	int error;
	int size = 0;
	char *cp;
	u_char *reset_cpu;
	u_int node;

        /*
         * Allocate some contiguous pages for the interrupt stack
         * from the lowest 256MB (because bat0 always maps it va == pa).
         */
        size += INTSTK;
        size += 8192;   /* SPILLSTK(1k) + DDBSTK(7k) */

	TAILQ_INIT(&mlist);
	error = uvm_pglistalloc(size, 0x0, 0x10000000 - 1, 0, 0,
	    &mlist, 1, UVM_PLA_WAITOK);
	if (error) {
		printf(": unable to allocate idle stack\n");
		return -1;
	}

	m = TAILQ_FIRST(&mlist);
	cp = (char *)VM_PAGE_TO_PHYS(m);
	bzero(cp, size);

	ci->ci_intstk = cp + INTSTK;
	cpu_hatch_stack = ci->ci_intstk - sizeof(struct trapframe);

	h->ci = ci;
	h->running = 0;
	h->hid0 = ppc_mfhid0();
	if (ppc_proc_is_64b) {
		h->hid1 = ppc64_mfhid1();
		h->hid4 = ppc64_mfhid4();
		h->hid5 = ppc64_mfhid5();
	} else {
		h->l2cr = ppc_mfl2cr();
	}
	cpu_hatch_data = h;

	__asm volatile ("sync; isync");

	/* XXX OpenPIC */
	{
		int off;

		*(u_int *)EXC_RST = 0x48000002 | (u_int)cpu_spinup_trampoline;
		syncicache((void *)EXC_RST, 0x100);

		h->running = -1;

		snprintf(cpuname, sizeof(cpuname), "/cpus/@%x", ci->ci_cpuid);
		node = OF_finddevice(cpuname);
		if (node == -1) {
			printf(": unable to locate OF node %s\n", cpuname);
			return  -1;
		}
		if (OF_getprop(node, "soft-reset", &off, 4) == 4) {
			reset_cpu = mapiodev(0x80000000 + off, 1);
			*reset_cpu = 0x4;
			__asm volatile ("eieio" ::: "memory");
			*reset_cpu = 0x0;
			__asm volatile ("eieio" ::: "memory");
		} else {
			/* Start secondary CPU. */
			reset_cpu = mapiodev(0x80000000 + 0x5c, 1);
			*reset_cpu = 0x4;
			__asm volatile ("eieio" ::: "memory");
			*reset_cpu = 0x0;
			__asm volatile ("eieio" ::: "memory");
		}

		/* Sync timebase. */
		h->tb = ppc_mftb() + 100000;	/* 3ms @ 33MHz  */

		while (h->tb > ppc_mftb())
			;
                __asm volatile ("sync; isync");
                h->running = 0;

                delay(500000);
	}

	for (i = 0; i < 0x3fffffff; i++)
		if (h->running) {
			break;
		}

	return 0;
}

volatile static int start_secondary_cpu;

void
cpu_boot_secondary_processors(void)
{
	struct cpu_info *ci;
	int i;

	for (i = 0; i < PPC_MAXPROCS; i++) {
		ci = &cpu_info[i];
		if (ci->ci_cpuid == 0)
			continue;
		ci->ci_randseed = (arc4random() & 0x7fffffff) + 1;

		sched_init_cpu(ci);

		cpu_spinup(NULL, ci);
	}

	start_secondary_cpu = 1;
	__asm volatile ("sync");
}

void cpu_startclock(void);

void
cpu_hatch(void)
{
	volatile struct cpu_hatch_data *h = cpu_hatch_data;
	int intrstate, s;

        /* Initialize timebase. */
	ppc_mttb(0);

	/* Initialize curcpu(). */
	ppc_mtsprg0((u_int)h->ci);

	ppc_mtibat0u(0);
	ppc_mtibat1u(0);
	ppc_mtibat2u(0);
	ppc_mtibat3u(0);
	ppc_mtdbat0u(0);
	ppc_mtdbat1u(0);
	ppc_mtdbat2u(0);
	ppc_mtdbat3u(0);

	if (ppc_proc_is_64b) {
		/*
		 * The Hardware Interrupt Offset Register should be
		 * cleared after initialization.
		 */
		ppc_mthior(0);
		__asm volatile ("sync");

		ppc_mthid0(h->hid0);
		ppc64_mthid1(h->hid1);
		ppc64_mthid4(h->hid4);
		ppc64_mthid5(h->hid5);
	} else if (h->l2cr != 0) {
		u_int x;

		ppc_mthid0(h->hid0);
		ppc_mtl2cr(h->l2cr & ~L2CR_L2E);

		/* Wait for L2 clock to be stable (640 L2 clocks). */
		delay(100);

		/* Invalidate all L2 contents. */
		ppc_mtl2cr((h->l2cr & ~L2CR_L2E)|L2CR_L2I);
		do {
			x = ppc_mfl2cr();
		} while (x & L2CR_L2IP);

		ppc_mtl2cr(h->l2cr);
	}

	/*
	 * Now enable translation (and machine checks/recoverable interrupts).
	 */
	pmap_enable_mmu();

	/* XXX OpenPIC */
	{
		/* Sync timebase. */
		while (h->running == -1)
			;
                __asm volatile ("sync; isync");
                ppc_mttb(h->tb);
	}

	ncpus++;
	h->running = 1;
	__asm volatile ("eieio" ::: "memory");

	while (start_secondary_cpu == 0)
		;

	__asm volatile ("sync; isync");

	curcpu()->ci_ipending = 0;
	curcpu()->ci_cpl = 0;

	s = splhigh();
	nanouptime(&curcpu()->ci_schedstate.spc_runtime);
	splx(s);

	intrstate = ppc_intr_disable();
	cpu_startclock();
	ppc_intr_enable(intrstate);

	/* Enable inter-processor interrupts. */
	openpic_set_priority(curcpu()->ci_cpuid, 14);

	SCHED_LOCK(s);
	cpu_switchto(NULL, sched_chooseproc());
}
#endif


code:
/*	$OpenBSD: db_interface.c,v 1.10 2015/02/06 10:54:08 mpi Exp $	*/
/*      $NetBSD: db_interface.c,v 1.12 2001/07/22 11:29:46 wiz Exp $ */

/*
 * Mach Operating System
 * Copyright (c) 1991,1990 Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie the
 * rights to redistribute these changes.
 *
 *      db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU)
 */

#include <sys/param.h>
#include <sys/proc.h>
#include <sys/systm.h>

#include <dev/cons.h>

#include <machine/db_machdep.h>
#include <ddb/db_extern.h>
#include <ddb/db_interface.h>
#include <ddb/db_command.h>
#include <ddb/db_output.h>
#include <ddb/db_run.h>

#ifdef MULTIPROCESSOR
struct mutex ddb_mp_mutex = MUTEX_INITIALIZER(IPL_HIGH);
volatile int ddb_state = DDB_STATE_NOT_RUNNING;
volatile cpuid_t ddb_active_cpu;
boolean_t        db_switch_cpu;
long             db_switch_to_cpu;
#endif

int db_active;
extern db_regs_t ddb_regs;

#ifdef MULTIPROCESSOR
void db_cpuinfo_cmd(db_expr_t, int, db_expr_t, char *);
void db_startproc_cmd(db_expr_t, int, db_expr_t, char *);
void db_stopproc_cmd(db_expr_t, int, db_expr_t, char *);
void db_ddbproc_cmd(db_expr_t, int, db_expr_t, char *);
#endif

int db_active = 0;

int ddb_trap_glue(struct trapframe *frame); /* called from locore */

void
Debugger()
{
	ddb_trap();
}

int
ddb_trap_glue(struct trapframe *frame)
{
	int s;

	if (!(frame->srr1 & PSL_PR)
	    && (frame->exc == EXC_TRC
		|| (frame->exc == EXC_PGM && (frame->srr1 & 0x20000))
		|| frame->exc == EXC_BPT)) {

#ifdef MULTIPROCESSOR
		mtx_enter(&ddb_mp_mutex);
		if (ddb_state == DDB_STATE_EXITING)
			ddb_state = DDB_STATE_NOT_RUNNING;
		mtx_leave(&ddb_mp_mutex);

		while (db_enter_ddb()) {
#endif
			bcopy(frame->fixreg, DDB_REGS->tf.fixreg,
				32 * sizeof(u_int32_t));
			DDB_REGS->tf.srr0 = frame->srr0;
			DDB_REGS->tf.srr1 = frame->srr1;

			s = splhigh();
			db_active++;
			cnpollc(TRUE);
			db_trap(T_BREAKPOINT, 0);
			cnpollc(FALSE);
			db_active--;
			splx(s);

			bcopy(DDB_REGS->tf.fixreg, frame->fixreg,
				32 * sizeof(u_int32_t));
#ifdef MULTIPROCESSOR
			if (!db_switch_cpu)
				ddb_state = DDB_STATE_EXITING;
		}
#endif
		return 1;
	}
	return 0;
}

int
db_enter_ddb(void)
{
#ifdef MULTIPROCESSOR
	int i;
	struct cpu_info *ci = curcpu();

	mtx_enter(&ddb_mp_mutex);

	/* If we are first in, grab ddb and stop all other CPUs */
	if (ddb_state == DDB_STATE_NOT_RUNNING) {
		ddb_active_cpu = cpu_number();
		ddb_state = DDB_STATE_RUNNING;
		ci->ci_ddb_paused = CI_DDB_INDDB;
		mtx_leave(&ddb_mp_mutex);
		for (i = 0; i < ncpus; i++) {
			if (i != cpu_number() &&
			    cpu_info[i].ci_ddb_paused != CI_DDB_STOPPED) {
				cpu_info[i].ci_ddb_paused = CI_DDB_SHOULDSTOP;
				ppc_send_ipi(&cpu_info[i], PPC_IPI_DDB);
			}
		}
		return (1);
	}

	/* Leaving ddb completely.  Start all other CPUs and return 0 */
	if (ddb_active_cpu == cpu_number() && ddb_state == DDB_STATE_EXITING) {
		for (i = 0; i < ncpus; i++) {
			cpu_info[i].ci_ddb_paused = CI_DDB_RUNNING;
		}
		mtx_leave(&ddb_mp_mutex);
		return (0);
	}

	/* We are switching to another CPU. ddb_ddbproc_cmd() has made sure
	 * it is waiting for ddb, we just have to set ddb_active_cpu. */
	if (ddb_active_cpu == cpu_number() && db_switch_cpu) {
		ci->ci_ddb_paused = CI_DDB_SHOULDSTOP;
		db_switch_cpu = 0;
		ddb_active_cpu = db_switch_to_cpu;
		cpu_info[db_switch_to_cpu].ci_ddb_paused = CI_DDB_ENTERDDB;
	}

	/* Wait until we should enter ddb or resume */
	while (ddb_active_cpu != cpu_number() &&
	    ci->ci_ddb_paused != CI_DDB_RUNNING) {
		if (ci->ci_ddb_paused == CI_DDB_SHOULDSTOP)
			ci->ci_ddb_paused = CI_DDB_STOPPED;
		mtx_leave(&ddb_mp_mutex);

		/* Busy wait without locking, we will confirm with lock later */
		while (ddb_active_cpu != cpu_number() &&
		    ci->ci_ddb_paused != CI_DDB_RUNNING)
			;	/* Do nothing */

		mtx_enter(&ddb_mp_mutex);
	}

	/* Either enter ddb or exit */
	if (ddb_active_cpu == cpu_number() && ddb_state == DDB_STATE_RUNNING) {
		ci->ci_ddb_paused = CI_DDB_INDDB;
		mtx_leave(&ddb_mp_mutex);
		return (1);
	} else {
		mtx_leave(&ddb_mp_mutex);
		return (0);
	}
#else
	return (1);
#endif
}

#ifdef MULTIPROCESSOR
void
ppc_ipi_db(struct cpu_info *ci)
{
	Debugger();
}

void
db_cpuinfo_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
{
	int i;

	for (i = 0; i < ncpus; i++) {
		db_printf("%c%4d: ", (i == cpu_number()) ? '*' : ' ',
		    cpu_info[i].ci_cpuid);
		switch(cpu_info[i].ci_ddb_paused) {
		case CI_DDB_RUNNING:
			db_printf("running\n");
			break;
		case CI_DDB_SHOULDSTOP:
			db_printf("stopping\n");
			break;
		case CI_DDB_STOPPED:
			db_printf("stopped\n");
			break;
		case CI_DDB_ENTERDDB:
			db_printf("entering ddb\n");
			break;
		case CI_DDB_INDDB:
			db_printf("ddb\n");
			break;
		default:
			db_printf("? (%d)\n",
			    cpu_info[i].ci_ddb_paused);
			break;
		}
	}
}
#endif

struct db_command db_machine_command_table[] = {
#ifdef MULTIPROCESSOR
	{ "cpuinfo",    db_cpuinfo_cmd,         0,      NULL },
	{ "startcpu",   db_startproc_cmd,       0,      NULL },
	{ "stopcpu",    db_stopproc_cmd,        0,      NULL },
	{ "ddbcpu",     db_ddbproc_cmd,         0,      NULL },
#endif
	{ (char *)NULL }
};

void
db_machine_init(void)
{
#ifdef MULTIPROCESSOR
	int i;
#endif

	db_machine_commands_install(db_machine_command_table);
#ifdef MULTIPROCESSOR
	for (i = 0; i < ncpus; i++) {
		cpu_info[i].ci_ddb_paused = CI_DDB_RUNNING;
	}
#endif
}

#ifdef MULTIPROCESSOR
void
db_ddbproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
{
	int cpu_n;

	if (have_addr) {
		cpu_n = addr;
		if (cpu_n >= 0 && cpu_n < ncpus &&
		    cpu_n != cpu_number()) {
			db_switch_to_cpu = cpu_n;
			db_switch_cpu = 1;
			db_cmd_loop_done = 1;
		} else {
			db_printf("Invalid cpu %d\n", (int)addr);
		}
	} else {
		db_printf("CPU not specified\n");
	}
}

void
db_startproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
{
	int cpu_n;

	if (have_addr) {
		cpu_n = addr;
		if (cpu_n >= 0 && cpu_n < ncpus &&
		    cpu_n != cpu_number())
			db_startcpu(cpu_n);
		else
			db_printf("Invalid cpu %d\n", (int)addr);
	} else {
		for (cpu_n = 0; cpu_n < ncpus; cpu_n++) {
			if (cpu_n != cpu_number()) {
				db_startcpu(cpu_n);
			}
		}
	}
}

void
db_stopproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
{
	int cpu_n;

	if (have_addr) {
		cpu_n = addr;
		if (cpu_n >= 0 && cpu_n < ncpus &&
		    cpu_n != cpu_number())
			db_stopcpu(cpu_n);
		else
			db_printf("Invalid cpu %d\n", (int)addr);
	} else {
		for (cpu_n = 0; cpu_n < ncpus; cpu_n++) {
			if (cpu_n != cpu_number()) {
				db_stopcpu(cpu_n);
			}
		}
	}
}

void
db_startcpu(int cpu)
{
	if (cpu != cpu_number() && cpu < ncpus) {
		mtx_enter(&ddb_mp_mutex);
		cpu_info[cpu].ci_ddb_paused = CI_DDB_RUNNING;
		mtx_leave(&ddb_mp_mutex);
	}
}

void
db_stopcpu(int cpu)
{
	mtx_enter(&ddb_mp_mutex);
	if (cpu != cpu_number() && cpu < ncpus &&
	    cpu_info[cpu].ci_ddb_paused != CI_DDB_STOPPED) {
		cpu_info[cpu].ci_ddb_paused = CI_DDB_SHOULDSTOP;
		mtx_leave(&ddb_mp_mutex);
		ppc_send_ipi(&cpu_info[cpu], PPC_IPI_DDB);
	} else {
		mtx_leave(&ddb_mp_mutex);
	}
}
#endif


code:
/*	$OpenBSD: disksubr.c,v 1.78 2013/10/19 09:32:14 krw Exp $	*/
/*	$NetBSD: disksubr.c,v 1.21 1996/05/03 19:42:03 christos Exp $	*/

/*
 * Copyright (c) 1996 Theo de Raadt
 * Copyright (c) 1982, 1986, 1988 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 <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/disklabel.h>
#include <sys/disk.h>

int	readdpmelabel(struct buf *, void (*)(struct buf *),
	    struct disklabel *, daddr_t *, int);

/*
 * Attempt to read a disk label from a device
 * using the indicated strategy routine.
 * The label must be partly set up before this:
 * secpercyl, secsize and anything required for a block i/o read
 * operation in the driver's strategy/start routines
 * must be filled in before calling us.
 *
 * If dos partition table requested, attempt to load it and
 * find disklabel inside a DOS partition.
 *
 * We would like to check if each MBR has a valid DOSMBR_SIGNATURE, but
 * we cannot because it doesn't always exist. So.. we assume the
 * MBR is valid.
 */
int
readdisklabel(dev_t dev, void (*strat)(struct buf *),
    struct disklabel *lp, int spoofonly)
{
	struct buf *bp = NULL;
	int error;

	if ((error = initdisklabel(lp)))
		goto done;

	/* get a buffer and initialize it */
	bp = geteblk((int)lp->d_secsize);
	bp->b_dev = dev;

	error = readdpmelabel(bp, strat, lp, NULL, spoofonly);
	if (error == 0)
		goto done;

	error = readdoslabel(bp, strat, lp, NULL, spoofonly);
	if (error == 0)
		goto done;

#if defined(CD9660)
	error = iso_disklabelspoof(dev, strat, lp);
	if (error == 0)
		goto done;
#endif
#if defined(UDF)
	error = udf_disklabelspoof(dev, strat, lp);
	if (error == 0)
		goto done;
#endif

done:
	if (bp) {
		bp->b_flags |= B_INVAL;
		brelse(bp);
	}
	disk_change = 1;
	return (error);
}

int
readdpmelabel(struct buf *bp, void (*strat)(struct buf *),
    struct disklabel *lp, daddr_t *partoffp, int spoofonly)
{
	int i, part_cnt, n, hfspartoff = -1;
	long long hfspartend = DL_GETDSIZE(lp);
	struct part_map_entry *part;

	/* First check for a DPME (HFS) disklabel */
	bp->b_blkno = LABELSECTOR;
	bp->b_bcount = lp->d_secsize;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
	(*strat)(bp);
	if (biowait(bp))
		return (bp->b_error);

	/* if successful, wander through DPME partition table */
	part = (struct part_map_entry *)bp->b_data;
	/* if first partition is not valid, assume not HFS/DPME partitioned */
	if (part->pmSig != PART_ENTRY_MAGIC)
		return (EINVAL);	/* not a DPME partition */
	part_cnt = part->pmMapBlkCnt;
	n = 8;
	for (i = 0; i < part_cnt; i++) {
		struct partition *pp;
		char *s;

		bp->b_blkno = LABELSECTOR + i;
		bp->b_bcount = lp->d_secsize;
		CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
		SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
		(*strat)(bp);
		if (biowait(bp))
			return (bp->b_error);

		part = (struct part_map_entry *)bp->b_data;
		/* toupper the string, in case caps are different... */
		for (s = part->pmPartType; *s; s++)
			if ((*s >= 'a') && (*s <= 'z'))
				*s = (*s - 'a' + 'A');

		if (strcmp(part->pmPartType, PART_TYPE_OPENBSD) == 0) {
			hfspartoff = part->pmPyPartStart;
			hfspartend = hfspartoff + part->pmPartBlkCnt;
			if (partoffp) {
				*partoffp = hfspartoff;
				return (0);
			} else {
				DL_SETBSTART(lp, hfspartoff);
				DL_SETBEND(lp,
				    hfspartend < DL_GETDSIZE(lp) ? hfspartend :
				    DL_GETDSIZE(lp));
			}
			continue;
		}

		if (n >= MAXPARTITIONS || partoffp)
			continue;

		/* Currently we spoof HFS partitions only. */
		if (strcmp(part->pmPartType, PART_TYPE_MAC) == 0) {
			pp = &lp->d_partitions[n];
			DL_SETPOFFSET(pp, part->pmPyPartStart);
			DL_SETPSIZE(pp, part->pmPartBlkCnt);
			pp->p_fstype = FS_HFS;
			n++;
		}

	}

	if (hfspartoff == -1)
		return (EINVAL);	/* no OpenBSD partition inside DPME label */

	if (spoofonly)
		return (0);

	/* next, dig out disk label */
	bp->b_blkno = hfspartoff;
	bp->b_bcount = lp->d_secsize;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
	(*strat)(bp);
	if (biowait(bp))
		return(bp->b_error);

	/*
	 * Do OpenBSD disklabel validation/adjustment.
	 *
	 * N.B: No matter what the bits are on the disk, we now have the
	 * disklabel for this dpme disk. DO NOT proceed to readdoslabel(),
	 * iso_spooflabel(), * etc.
	 */
	checkdisklabel(bp->b_data + LABELOFFSET, lp, hfspartoff, hfspartend);
	return (0);
}

/*
 * Write disk label back to device after modification.
 */
int
writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp)
{
	daddr_t partoff = -1;
	int error = EIO;
	int offset;
	struct disklabel *dlp;
	struct buf *bp = NULL;

	/* get a buffer and initialize it */
	bp = geteblk((int)lp->d_secsize);
	bp->b_dev = dev;

	if (readdpmelabel(bp, strat, lp, &partoff, 1) == 0) {
		bp->b_blkno = partoff;
		offset = 0;
	} else if (readdoslabel(bp, strat, lp, &partoff, 1) == 0) {
		bp->b_blkno = DL_BLKTOSEC(lp, partoff + DOS_LABELSECTOR) *
		    DL_BLKSPERSEC(lp);
		offset = DL_BLKOFFSET(lp, partoff + DOS_LABELSECTOR);
	} else
		goto done;

	/* Read it in, slap the new label in, and write it back out */
	bp->b_bcount = lp->d_secsize;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
	(*strat)(bp);
	if ((error = biowait(bp)) != 0)
		goto done;

	dlp = (struct disklabel *)(bp->b_data + offset);
	*dlp = *lp;
	CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
	SET(bp->b_flags, B_BUSY | B_WRITE | B_RAW);
	(*strat)(bp);
	error = biowait(bp);

done:
	if (bp) {
		bp->b_flags |= B_INVAL;
		brelse(bp);
	}
	disk_change = 1;
	return (error);
}


code:
#	$OpenBSD: genassym.cf,v 1.24 2014/09/06 10:45:29 mpi Exp $
#
# Copyright (c) 1982, 1990 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.
#
#	@(#)genassym.c	7.8 (Berkeley) 5/7/91
#

include <sys/param.h>
include <sys/time.h>
include <sys/proc.h>
include <uvm/uvm_extern.h>

include <machine/pcb.h>
include <machine/pmap.h>
include <machine/cpu.h>
include <machine/mutex.h>

export	FRAMELEN
struct	trapframe	FRAME_
member	0		fixreg[0]
member	1		fixreg[1]
member	2		fixreg[2]
member	3		fixreg[3]
member	lr
member	cr
member	ctr
member	xer
member	srr0
member	srr1
member	dar
member	dsisr
member	exc

define	SFRAMELEN	roundup(sizeof(struct switchframe), 16)

struct	pcb
member	PCB_PMR		pcb_pmreal
member	pcb_sp
member	PCB_FAULT	pcb_onfault

struct	pmap
member	PM_SR		pm_sr[0]
member	PM_USRSR	pm_sr[PPC_USER_SR]
member	PM_KERNELSR	pm_sr[PPC_KERNEL_SR]

struct	proc
member	p_addr
member	p_stat
member	p_cpu
member  P_MD_ASTPENDING	p_md.md_astpending

struct	sigframe
member	sf_sc

struct fpsig

export	SONPROC

struct	cpu_info
member	ci_curproc
member	ci_curpcb
member	ci_curpm
member	ci_want_resched
member	ci_cpl
member	ci_flags
export	CI_FLAGS_SLEEPING
member	ci_intrdepth
member	ci_intstk
member	ci_tempsave
member	ci_ddbsave
member	ci_disisave
ifdef DIAGNOSTIC
member	ci_mutex_level
endif

struct	mutex
member	mtx_wantipl
member	mtx_oldcpl
member	mtx_owner