code:
/*	$OpenBSD: oosiop_gsc.c,v 1.3 2010/04/20 20:21:54 miod Exp $	*/
/*	$NetBSD: oosiop_gsc.c,v 1.2 2003/07/15 02:29:25 lukem Exp $	*/

/*
 * Copyright (c) 2001 Matt Fredette.  All rights reserved.
 * Copyright (c) 2001,2002 Izumi Tsutsui.  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 AUTHORS ``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 AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/*
 * Copyright (c) 1998 Michael Shalayeff
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/buf.h>
#include <sys/malloc.h>

#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>

#include <machine/cpu.h>
#include <machine/intr.h>
#include <machine/iomod.h>
#include <machine/autoconf.h>
#include <machine/bus.h>

#include <dev/ic/oosiopreg.h>
#include <dev/ic/oosiopvar.h>

#include <hppa/dev/cpudevs.h>
#include <hppa/gsc/gscbusvar.h>

#define	OOSIOP_GSC_RESET	0x0000
#define	OOSIOP_GSC_OFFSET	0x0100

int oosiop_gsc_match(struct device *, void *, void *);
void oosiop_gsc_attach(struct device *, struct device *, void *);
int oosiop_gsc_intr(void *);

struct cfattach oosiop_gsc_ca = {
	sizeof(struct oosiop_softc), oosiop_gsc_match, oosiop_gsc_attach
};

int
oosiop_gsc_match(parent, match, aux)
	struct device *parent;
	void *match, *aux;
{
	struct gsc_attach_args *ga = aux;

	if (ga->ga_type.iodc_type != HPPA_TYPE_FIO ||
	     ga->ga_type.iodc_sv_model != HPPA_FIO_SCSI)
		return 0;

	return 1;
}

void
oosiop_gsc_attach(parent, self, aux)
	struct device *parent, *self;
	void *aux;
{
	struct oosiop_softc *sc = (void *)self;
	struct gsc_attach_args *ga = aux;
	bus_space_handle_t ioh;

	sc->sc_bst = ga->ga_iot;
	sc->sc_dmat = ga->ga_dmatag;
	if (bus_space_map(sc->sc_bst, ga->ga_hpa,
	    OOSIOP_GSC_OFFSET + OOSIOP_NREGS, 0, &ioh))
		panic("oosiop_gsc_attach: couldn't map I/O ports");
	if (bus_space_subregion(sc->sc_bst, ioh,
	    OOSIOP_GSC_OFFSET, OOSIOP_NREGS, &sc->sc_bsh))
		panic("oosiop_gsc_attach: couldn't get chip ports");

	sc->sc_freq = ga->ga_ca.ca_pdc_iodc_read->filler2[14];
	if (!sc->sc_freq)
		sc->sc_freq = 50 * 1000000;

	sc->sc_chip = OOSIOP_700;
	sc->sc_id = 7;	/* XXX */

	/* default values */
	sc->sc_scntl0 = OOSIOP_SCNTL0_EPG;
	sc->sc_dmode = OOSIOP_DMODE_BL_8;
	sc->sc_dwt = 0xff;	/* Enable DMA timeout */
	sc->sc_ctest7 = 0;

	/*
	 * Reset the SCSI subsystem.
	 */
	bus_space_write_1(sc->sc_bst, ioh, OOSIOP_GSC_RESET, 0);
	DELAY(1000);

	/*
	 * Call common attachment
	 */
#ifdef OOSIOP_DEBUG
	{
		extern int oosiop_debug;
		oosiop_debug = -1;
	}
#endif /* OOSIOP_DEBUG */
	oosiop_attach(sc);

	(void)gsc_intr_establish((struct gsc_softc *)parent,
	    ga->ga_irq, IPL_BIO, oosiop_gsc_intr, sc, sc->sc_dev.dv_xname);
}

/*
 * interrupt handler
 */
int
oosiop_gsc_intr(arg)
	void *arg;
{
	struct oosiop_softc *sc = arg;
	int rv;

	rv = oosiop_intr(sc);

#ifdef USELEDS
	ledctl(PALED_DISK, 0, 0);
#endif

	return (rv);
}


code:
/*	$OpenBSD: osiop_gsc.c,v 1.12 2005/12/13 23:13:45 mickey Exp $	*/
/*	$NetBSD: osiop_gsc.c,v 1.6 2002/10/02 05:17:50 thorpej Exp $	*/

/*
 * Copyright (c) 2001 Matt Fredette.  All rights reserved.
 * Copyright (c) 2001 Izumi Tsutsui.  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 AUTHORS ``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 AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/*
 * Copyright (c) 1998 Michael Shalayeff
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/buf.h>
#include <sys/malloc.h>

#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>

#include <machine/cpu.h>
#include <machine/intr.h>
#include <machine/iomod.h>
#include <machine/autoconf.h>
#include <machine/bus.h>

#include <dev/ic/osiopreg.h>
#include <dev/ic/osiopvar.h>

#include <hppa/dev/cpudevs.h>
#include <hppa/gsc/gscbusvar.h>
/* #include <hppa/hppa/machdep.h> */

#define	OSIOP_GSC_RESET		0x0000
#define	OSIOP_GSC_OFFSET	0x0100

int osiop_gsc_match(struct device *, void *, void *);
void osiop_gsc_attach(struct device *, struct device *, void *);
int osiop_gsc_intr(void *);

struct cfattach osiop_gsc_ca = {
	sizeof(struct osiop_softc), osiop_gsc_match, osiop_gsc_attach
};

int
osiop_gsc_match(parent, match, aux)
	struct device *parent;
	void *match, *aux;
{
	struct gsc_attach_args *ga = aux;

	if (ga->ga_type.iodc_type != HPPA_TYPE_FIO ||
	    ga->ga_type.iodc_sv_model != HPPA_FIO_GSCSI)
		return 0;

	return 1;
}

void
osiop_gsc_attach(parent, self, aux)
	struct device *parent, *self;
	void *aux;
{
	struct osiop_softc *sc = (void *)self;
	struct gsc_attach_args *ga = aux;
	bus_space_handle_t ioh;

	sc->sc_bst = ga->ga_iot;
	sc->sc_dmat = ga->ga_dmatag;
	if (bus_space_map(sc->sc_bst, ga->ga_hpa,
	    OSIOP_GSC_OFFSET + OSIOP_NREGS, 0, &ioh))
		panic("osiop_gsc_attach: couldn't map I/O ports");
	if (bus_space_subregion(sc->sc_bst, ioh,
	    OSIOP_GSC_OFFSET, OSIOP_NREGS, &sc->sc_reg))
		panic("osiop_gsc_attach: couldn't get chip ports");

	sc->sc_clock_freq = ga->ga_ca.ca_pdc_iodc_read->filler2[14] / 1000000;
	if (!sc->sc_clock_freq)
		sc->sc_clock_freq = 50;

	sc->sc_dcntl = OSIOP_DCNTL_EA;
	/* XXX set burst mode to 8 words (32 bytes) */
	sc->sc_ctest7 = OSIOP_CTEST7_CDIS;
	sc->sc_dmode = OSIOP_DMODE_BL8; /* | OSIOP_DMODE_FC2 */
	sc->sc_flags = 0;
	sc->sc_id = 7;	/* XXX */

	/*
	 * Reset the SCSI subsystem.
	 */
	bus_space_write_1(sc->sc_bst, ioh, OSIOP_GSC_RESET, 0);
	DELAY(1000);

	/*
	 * Call common attachment
	 */
#ifdef OSIOP_DEBUG
	{
		extern int osiop_debug;
		osiop_debug = -1;
	}
#endif /* OSIOP_DEBUG */
	osiop_attach(sc);

	(void)gsc_intr_establish((struct gsc_softc *)parent,
	    ga->ga_irq, IPL_BIO, osiop_gsc_intr, sc, sc->sc_dev.dv_xname);
}

/*
 * interrupt handler
 */
int
osiop_gsc_intr(arg)
	void *arg;
{
	struct osiop_softc *sc = arg;
	u_int8_t istat;

	/* This is potentially nasty, since the IRQ is level triggered... */
	if (sc->sc_flags & OSIOP_INTSOFF)
		return (0);

	istat = osiop_read_1(sc, OSIOP_ISTAT);

	if ((istat & (OSIOP_ISTAT_SIP | OSIOP_ISTAT_DIP)) == 0)
		return (0);

	/* Save interrupt details for the back-end interrupt handler */
	sc->sc_sstat0 = osiop_read_1(sc, OSIOP_SSTAT0);
	sc->sc_istat = istat;
	/*
	 * Per page 4-18 of the LSI 53C710 Technical Manual,
	 * "insert a delay equivalent to 12 BCLK periods between
	 * the reads [of DSTAT and SSTAT0] to ensure that the
	 * interrupts clear properly." 1 BCLK = 40ns. Pg. 6-10.
	 */
	DELAY(25);
	sc->sc_dstat = osiop_read_1(sc, OSIOP_DSTAT);

	/* Deal with the interrupt */
	osiop_intr(sc);

#ifdef USELEDS
	ledctl(PALED_DISK, 0, 0);
#endif

	return (1);
}

license: unknown


code:
/*	$OpenBSD: siop_gsc.c,v 1.4 2007/08/23 21:01: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/device.h>
#include <sys/systm.h>

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

#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>

#include <dev/ic/siopreg.h>
#include <dev/ic/siopvar_common.h>
#include <dev/ic/siopvar.h>

#include <hppa/dev/cpudevs.h>
#include <hppa/gsc/gscbusvar.h>

#define	SIOP_GSC_RESET	0x0000
#define	SIOP_GSC_OFFSET	0x0100

int siop_gsc_match(struct device *, void *, void *);
void siop_gsc_attach(struct device *, struct device *, void *);
int siop_gsc_intr(void *);
void siop_gsc_reset(struct siop_common_softc *);

u_int8_t siop_gsc_r1(void *, bus_space_handle_t, bus_size_t);
u_int16_t siop_gsc_r2(void *, bus_space_handle_t, bus_size_t);
void siop_gsc_w1(void *, bus_space_handle_t, bus_size_t, u_int8_t);
void siop_gsc_w2(void *, bus_space_handle_t, bus_size_t, u_int16_t);

struct siop_gsc_softc {
	struct siop_softc sc_siop;
	bus_space_tag_t sc_iot;
	bus_space_handle_t sc_ioh;
	struct hppa_bus_space_tag sc_bustag;
};

struct cfattach siop_gsc_ca = {
	sizeof(struct siop_gsc_softc), siop_gsc_match, siop_gsc_attach
};

int
siop_gsc_match(struct device *parent, void *match, void *aux)
{
	struct gsc_attach_args *ga = aux;

	if (ga->ga_type.iodc_type != HPPA_TYPE_FIO ||
	    ga->ga_type.iodc_sv_model != HPPA_FIO_FWSCSI)
		return 0;

	return 1;
}

void
siop_gsc_attach(struct device *parent, struct device *self, void *aux)
{
	struct siop_gsc_softc *sc = (struct siop_gsc_softc *)self;
	struct gsc_attach_args *ga = aux;

	sc->sc_iot = ga->ga_iot;
	if (bus_space_map(sc->sc_iot, ga->ga_hpa,
	    IOMOD_HPASIZE, 0, &sc->sc_ioh)) {
		printf(": cannot map io space\n");
		return;
	}

	sc->sc_bustag = *sc->sc_iot;
	sc->sc_bustag.hbt_r1 = siop_gsc_r1;
	sc->sc_bustag.hbt_r2 = siop_gsc_r2;
	sc->sc_bustag.hbt_w1 = siop_gsc_w1;
	sc->sc_bustag.hbt_w2 = siop_gsc_w2;

	sc->sc_siop.sc_c.features = SF_CHIP_PF | SF_CHIP_BE | SF_BUS_WIDE;
	sc->sc_siop.sc_c.maxburst = 4;
	sc->sc_siop.sc_c.maxoff = 8;
	sc->sc_siop.sc_c.clock_div = 3;
	sc->sc_siop.sc_c.clock_period = 250;
	sc->sc_siop.sc_c.ram_size = 0;

	sc->sc_siop.sc_c.sc_reset = siop_gsc_reset;
	sc->sc_siop.sc_c.sc_dmat = ga->ga_dmatag;

	sc->sc_siop.sc_c.sc_rt = &sc->sc_bustag;
	bus_space_subregion(sc->sc_iot, sc->sc_ioh, SIOP_GSC_OFFSET,
	    IOMOD_HPASIZE - SIOP_GSC_OFFSET, &sc->sc_siop.sc_c.sc_rh);

	/*
	 * Reset the SCSI subsystem.
	 */
	bus_space_write_1(sc->sc_iot, sc->sc_ioh, SIOP_GSC_RESET, 0);
	DELAY(1000);
	siop_gsc_reset(&sc->sc_siop.sc_c);

	gsc_intr_establish((struct gsc_softc *)parent, ga->ga_irq,
	    IPL_BIO, siop_intr, sc, sc->sc_siop.sc_c.sc_dev.dv_xname);

	printf(": NCR53C720 rev %d\n", bus_space_read_1(sc->sc_siop.sc_c.sc_rt,
	    sc->sc_siop.sc_c.sc_rh, SIOP_CTEST3) >> 4);

	siop_attach(&sc->sc_siop);
}

void
siop_gsc_reset(struct siop_common_softc *sc)
{
	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL, DCNTL_EA);
	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST0, CTEST0_EHP);
	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST4, CTEST4_MUX);

	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STIME0,
	    (0xc << STIME0_SEL_SHIFT));
}

u_int8_t
siop_gsc_r1(void *v, bus_space_handle_t h, bus_size_t o)
{
	return *(volatile u_int8_t *)(h + (o ^ 3));
}

u_int16_t
siop_gsc_r2(void *v, bus_space_handle_t h, bus_size_t o)
{
	if (o == SIOP_SIST0) {
		u_int16_t reg;

		reg = siop_gsc_r1(v, h, SIOP_SIST0);
		reg |= siop_gsc_r1(v, h, SIOP_SIST1) << 8;
		return reg;
	}
	return *(volatile u_int16_t *)(h + (o ^ 2));
}

void
siop_gsc_w1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv)
{
	*(volatile u_int8_t *)(h + (o ^ 3)) = vv;
}

void
siop_gsc_w2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv)
{
	*(volatile u_int16_t *)(h + (o ^ 2)) = vv;
}


code: src/sys/arch/hppa/hppa

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


code:
/*	$OpenBSD: autoconf.c,v 1.61 2014/09/15 19:08:21 miod Exp $	*/

/*
 * Copyright (c) 1998-2003 Michael Shalayeff
 * 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.
 *
 *	@(#)autoconf.c	8.4 (Berkeley) 10/1/93
 */

#include "pci.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 <sys/timeout.h>

#include <uvm/uvm_extern.h>

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

#include <dev/cons.h>

#include <hppa/dev/cpudevs.h>

#if NPCI > 0
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#endif

/* device we booted from */
struct device *bootdv;
void	dumpconf(void);

void (*cold_hook)(int); /* see below */

/*
 * LED blinking thing
 */
#ifdef USELEDS
#include <sys/kernel.h>

struct timeout heartbeat_tmo;
void heartbeat(void *);
#endif

#include "cd.h"
#include "sd.h"
#include "st.h"
#include "mpath.h"

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

#ifdef USELEDS
/*
 * turn the heartbeat alive.
 * right thing would be to pass counter to each subsequent timeout
 * as an argument to heartbeat() incrementing every turn,
 * i.e. avoiding the static hbcnt, but doing timeout_set() on each
 * timeout_add() sounds ugly, guts of struct timeout looks ugly
 * to ponder in even more.
 */
void
heartbeat(v)
	void *v;
{
	static u_int hbcnt = 0, ocp_total, ocp_idle;
	int toggle, cp_mask, cp_total, cp_idle;
	struct schedstate_percpu *spc = &(curcpu()->ci_schedstate);

	timeout_add(&heartbeat_tmo, hz / 16);

	cp_idle = spc->spc_cp_time[CP_IDLE];
	cp_total = spc->spc_cp_time[CP_USER] + spc->spc_cp_time[CP_NICE] +
	    spc->spc_cp_time[CP_SYS] + spc->spc_cp_time[CP_INTR] +
	    spc->spc_cp_time[CP_IDLE];
	if (cp_total == ocp_total)
		cp_total = ocp_total + 1;
	if (cp_idle == ocp_idle)
		cp_idle = ocp_idle + 1;
	cp_mask = 0xf0 >> (cp_idle - ocp_idle) * 4 / (cp_total - ocp_total);
	cp_mask &= 0xf0;
	ocp_total = cp_total;
	ocp_idle = cp_idle;
	/*
	 * do this:
	 *
	 *   |~| |~|
	 *  _| |_| |_,_,_,_
	 *   0 1 2 3 4 6 7
	 */
	toggle = 0;
	if (hbcnt++ < 8 && hbcnt & 1)
		toggle = PALED_HEARTBEAT;
	hbcnt &= 15;
	ledctl(cp_mask,
	    (~cp_mask & 0xf0) | PALED_NETRCV | PALED_NETSND | PALED_DISK,
	    toggle);
}
#endif

/*
 * This is called by configure to set dumplo and dumpsize.
 * Dumps always skip the first CLBYTES of disk space
 * in case there might be a disk label stored there.
 * If there is extra space, put dump at the end to
 * reduce the chance that swapping trashes it.
 */
void
dumpconf(void)
{
	extern int dumpsize;
	int nblks, dumpblks;	/* size of dump area */

	if (dumpdev == NODEV ||
	    (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
		return;
	if (nblks <= ctod(1))
		return;

	dumpblks = cpu_dumpsize();
	if (dumpblks < 0)
		return;
	dumpblks += ctod(physmem);

	/* If dump won't fit (incl. room for possible label), punt. */
	if (dumpblks > (nblks - ctod(1)))
		return;

	/* Put dump at end of partition */
	dumplo = nblks - dumpblks;

	/* dumpsize is in page units, and doesn't include headers. */
	dumpsize = physmem;
}

void	print_devpath(const char *label, struct pz_device *pz);

void
print_devpath(const char *label, struct pz_device *pz)
{
	int i;

	printf("%s: ", label);

	for (i = 0; i < 6; i++)
		if (pz->pz_bc[i] >= 0)
			printf("%d/", pz->pz_bc[i]);

	printf("%d.%x", pz->pz_mod, pz->pz_layers[0]);
	for (i = 1; i < 6 && pz->pz_layers[i]; i++)
		printf(".%x", pz->pz_layers[i]);

	printf(" class=%d flags=%b hpa=0x%x spa=0x%x io=0x%x\n", pz->pz_class,
	    pz->pz_flags, PZF_BITS, pz->pz_hpa, pz->pz_spa, pz->pz_iodc_io);
}

struct pdc_memmap pdc_memmap PDC_ALIGNMENT;
struct pdc_sysmap_find pdc_find PDC_ALIGNMENT;
struct pdc_sysmap_addrs pdc_addr PDC_ALIGNMENT;
struct pdc_iodc_read pdc_iodc_read PDC_ALIGNMENT;

void
pdc_scanbus(struct device *self, struct confargs *ca, int maxmod,
    hppa_hpa_t hpa, int cpu_scan)
{
	int start, end, incr, i;

	/* Scan forwards for CPUs, backwards for everything else. */
	if (cpu_scan) {
		start = 0;
		incr = 1;
		end = maxmod;
	} else {
		start = maxmod - 1;
		incr = -1;
		end = -1;
	}

	for (i = start; i != end; i += incr) {
		struct confargs nca;
		int error;

		bzero(&nca, sizeof(nca));
		nca.ca_iot = ca->ca_iot;
		nca.ca_dmatag = ca->ca_dmatag;
		nca.ca_dp.dp_bc[0] = ca->ca_dp.dp_bc[1];
		nca.ca_dp.dp_bc[1] = ca->ca_dp.dp_bc[2];
		nca.ca_dp.dp_bc[2] = ca->ca_dp.dp_bc[3];
		nca.ca_dp.dp_bc[3] = ca->ca_dp.dp_bc[4];
		nca.ca_dp.dp_bc[4] = ca->ca_dp.dp_bc[5];
		nca.ca_dp.dp_bc[5] = ca->ca_dp.dp_mod;
		nca.ca_dp.dp_mod = i;
		nca.ca_hpamask = ca->ca_hpamask;
		nca.ca_naddrs = 0;
		nca.ca_hpa = 0;

		if (hpa) {
			nca.ca_hpa = hpa + IOMOD_HPASIZE * i;
			nca.ca_dp.dp_mod = i;
		} else if ((error = pdc_call((iodcio_t)pdc, 0, PDC_MEMMAP,
		    PDC_MEMMAP_HPA, &pdc_memmap, &nca.ca_dp)) == 0)
			nca.ca_hpa = pdc_memmap.hpa;
		else if ((error = pdc_call((iodcio_t)pdc, 0, PDC_SYSMAP,
		    PDC_SYSMAP_HPA, &pdc_memmap, &nca.ca_dp)) == 0) {
			struct device_path path;
			int im, ia;

			nca.ca_hpa = pdc_memmap.hpa;

			for (im = 0; !(error = pdc_call((iodcio_t)pdc, 0,
			    PDC_SYSMAP, PDC_SYSMAP_FIND,
			    &pdc_find, &path, im)) &&
			    pdc_find.hpa != nca.ca_hpa; im++)
				;

			if (!error)
				nca.ca_hpasz = pdc_find.size << PGSHIFT;

			if (!error && pdc_find.naddrs) {
				nca.ca_naddrs = pdc_find.naddrs;
				if (nca.ca_naddrs > 16) {
					nca.ca_naddrs = 16;
					printf("WARNING: too many (%d) addrs\n",
					    pdc_find.naddrs);
				}

				if (autoconf_verbose)
					printf(">> ADDRS:");

				for (ia = 0; !(error = pdc_call((iodcio_t)pdc,
				    0, PDC_SYSMAP, PDC_SYSMAP_ADDR, &pdc_addr,
				    im, ia + 1)) && ia < nca.ca_naddrs; ia++) {
					nca.ca_addrs[ia].addr = pdc_addr.hpa;
					nca.ca_addrs[ia].size =
					    pdc_addr.size << PGSHIFT;

					if (autoconf_verbose)
						printf(" 0x%lx[0x%x]",
						    nca.ca_addrs[ia].addr,
						    nca.ca_addrs[ia].size);
				}
				if (autoconf_verbose)
					printf("\n");
			}
		}

		if (!nca.ca_hpa)
			continue;

		if (autoconf_verbose)
			printf(">> HPA 0x%lx[0x%x]\n",
			    nca.ca_hpa, nca.ca_hpasz);

		if ((error = pdc_call((iodcio_t)pdc, 0, PDC_IODC,
		    PDC_IODC_READ, &pdc_iodc_read, nca.ca_hpa, IODC_DATA,
		    &nca.ca_type, sizeof(nca.ca_type))) < 0) {
			if (autoconf_verbose)
				printf(">> iodc_data error %d\n", error);
			continue;
		}

		nca.ca_pdc_iodc_read = &pdc_iodc_read;
		nca.ca_name = hppa_mod_info(nca.ca_type.iodc_type,
					    nca.ca_type.iodc_sv_model);

		if (autoconf_verbose) {
			printf(">> probing: flags %b bc %d/%d/%d/%d/%d/%d ",
			    nca.ca_dp.dp_flags, PZF_BITS,
			    nca.ca_dp.dp_bc[0], nca.ca_dp.dp_bc[1],
			    nca.ca_dp.dp_bc[2], nca.ca_dp.dp_bc[3],
			    nca.ca_dp.dp_bc[4], nca.ca_dp.dp_bc[5]);
			printf("mod %x hpa %lx type %x sv %x\n",
			    nca.ca_dp.dp_mod, nca.ca_hpa,
			    nca.ca_type.iodc_type, nca.ca_type.iodc_sv_model);
		}

		if (cpu_scan && nca.ca_type.iodc_type == HPPA_TYPE_NPROC &&
		    nca.ca_type.iodc_sv_model == HPPA_NPROC_HPPA)
			ncpusfound++;

		if (cpu_scan &&
		    ((nca.ca_type.iodc_type != HPPA_TYPE_NPROC ||
	            nca.ca_type.iodc_sv_model != HPPA_NPROC_HPPA) &&
		    (nca.ca_type.iodc_type != HPPA_TYPE_MEMORY ||
		    nca.ca_type.iodc_sv_model != HPPA_MEMORY_PDEP)))
			continue;

		if (!cpu_scan &&
		    ((nca.ca_type.iodc_type == HPPA_TYPE_NPROC &&
		    nca.ca_type.iodc_sv_model == HPPA_NPROC_HPPA) ||
		    (nca.ca_type.iodc_type == HPPA_TYPE_MEMORY &&
		    nca.ca_type.iodc_sv_model == HPPA_MEMORY_PDEP)))
			continue;

		config_found_sm(self, &nca, mbprint, mbsubmatch);
	}
}

const struct hppa_mod_info hppa_knownmods[] = {
#include <hppa/dev/cpudevs_data.h>
};

const char *
hppa_mod_info(type, sv)
	int type, sv;
{
	const struct hppa_mod_info *mi;
	static char fakeid[32];

	for (mi = hppa_knownmods; mi->mi_type >= 0 &&
	    (mi->mi_type != type || mi->mi_sv != sv); mi++);

	if (mi->mi_type < 0) {
		snprintf(fakeid, sizeof fakeid, "type %x, sv %x", type, sv);
		return fakeid;
	} else
		return mi->mi_name;
}

void
device_register(struct device *dev, void *aux)
{
#if NPCI > 0
	extern struct cfdriver pci_cd;
#endif
#if NCD > 0 || NSD > 0 || NST > 0
	extern struct cfdriver scsibus_cd;
#endif
	struct confargs *ca = aux;
	static struct device *elder = NULL;

	if (bootdv != NULL)
		return;	/* We already have a winner */

#if NPCI > 0
	if (dev->dv_parent &&
	    dev->dv_parent->dv_cfdata->cf_driver == &pci_cd) {
		struct pci_attach_args *pa = aux;
		pcireg_t addr;
		int reg;

		for (reg = PCI_MAPREG_START; reg < PCI_MAPREG_END; reg += 4) {
			addr = pci_conf_read(pa->pa_pc, pa->pa_tag, reg);
			if (PCI_MAPREG_TYPE(addr) == PCI_MAPREG_TYPE_IO)
				addr = PCI_MAPREG_IO_ADDR(addr);
			else
				addr = PCI_MAPREG_MEM_ADDR(addr);

			if (addr == (pcireg_t)PAGE0->mem_boot.pz_hpa) {
				elder = dev;
				break;
			}
		}
	} else
#endif
	if (ca->ca_hpa == (hppa_hpa_t)PAGE0->mem_boot.pz_hpa) {
		/*
		 * If hpa matches, the only thing we know is that the
		 * booted device is either this one or one of its children.
		 * And the children will not necessarily have the correct
		 * hpa value.
		 * Save this elder for now.
		 */
		elder = dev;
	} else if (elder == NULL) {
		return;	/* not the device we booted from */
	}

	/*
	 * Unfortunately, we can not match on pz_class vs dv_class on
	 * older snakes netbooting using the rbootd protocol.
	 * In this case, we'll end up with pz_class == PCL_RANDOM...
	 * Instead, trust the device class from what the kernel attached
	 * now...
	 */
	switch (dev->dv_class) {
	case DV_IFNET:
		/*
		 * Netboot is the top elder
		 */
		if (elder == dev) {
			bootdv = dev;
		}
		return;
	case DV_DISK:
	case DV_DULL:
		if ((PAGE0->mem_boot.pz_class & PCL_CLASS_MASK) != PCL_RANDOM)
			return;
		break;
	case DV_TAPE:
		if ((PAGE0->mem_boot.pz_class & PCL_CLASS_MASK) != PCL_SEQU)
			return;
		break;
	default:
		/* No idea what we were booted from, but better ask the user */
		return;
	}

	/*
	 * If control goes here, we are booted from a block device and we
	 * matched a block device.
	 *
	 * We only grok SCSI boot currently.  Match on proper device
	 * hierarchy and unit/lun values.
	 */

#if NCD > 0 || NSD > 0 || NST > 0
	if (dev->dv_parent &&
	    dev->dv_parent->dv_cfdata->cf_driver == &scsibus_cd) {
		struct scsi_attach_args *sa = aux;
		struct scsi_link *sl = sa->sa_sc_link;

		/*
		 * sd/st/cd is attached to scsibus which is attached to
		 * the controller. Hence the grandparent here should be
		 * the elder.
		 */
		if (dev->dv_parent->dv_parent != elder) {
			return;
		}

		/*
		 * And now check for proper target and lun values
		 */
		if (sl->target == PAGE0->mem_boot.pz_layers[0] &&
		    sl->lun == PAGE0->mem_boot.pz_layers[1]) {
			bootdv = dev;
		}
	}
#endif
}

/*
 * cpu_configure:
 * called at boot time, configure all devices on system
 */
void
cpu_configure(void)
{
	splhigh();
	if (config_rootfound("mainbus", "mainbus") == NULL)
		panic("no mainbus found");

	cpu_intr_init();
	spl0();

	if (cold_hook)
		(*cold_hook)(HPPA_COLD_HOT);

#ifdef USELEDS
	timeout_set(&heartbeat_tmo, heartbeat, NULL);
	heartbeat(NULL);
#endif
	cold = 0;
}

void
diskconf(void)
{
	print_devpath("bootpath", &PAGE0->mem_boot);

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

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

struct nam2blk nam2blk[] = {
	{ "rd",		3 },
	{ "sd",		4 },
	{ "st",		5 },
	{ "cd",		6 },
	{ "fd",		7 },
	{ "wd",		8 },
	{ "vnd",	2 },
	{ NULL,		-1 }
};


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

/*-
 * Copyright (c) 1991 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.
 *
 *     @(#)conf.c	7.9 (Berkeley) 5/28/91
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/ioctl.h>
#include <sys/tty.h>
#include <sys/vnode.h>

#include <machine/conf.h>

#include "vnd.h"
#include "rd.h"
#include "sd.h"
#include "st.h"
#include "cd.h"
#include "ch.h"
#include "uk.h"
#include "wd.h"
bdev_decl(wd);
cdev_decl(wd);
#if 0
#include "fd.h"
#else
#define NFD 0
#endif
bdev_decl(fd);
cdev_decl(fd);

struct bdevsw   bdevsw[] =
{
	bdev_swap_init(1,sw),		/*  0: swap pseudo-device */
	bdev_notdef(),			/*  1: was: concatenated disk driver */
	bdev_disk_init(NVND,vnd),	/*  2: vnode disk driver */
	bdev_disk_init(NRD,rd),		/*  3: RAM disk */
	bdev_disk_init(NSD,sd),		/*  4: SCSI disk */
	bdev_tape_init(NST,st),		/*  5: SCSI tape */
	bdev_disk_init(NCD,cd),		/*  6: SCSI CD-ROM */
	bdev_disk_init(NFD,fd),		/*  7: floppy drive */
	bdev_disk_init(NWD,wd),		/*  8: ST506 drive */
	bdev_notdef(),			/*  9: */
	bdev_notdef(),			/* 10: */
	bdev_notdef(),			/* 11: */
	bdev_notdef(),			/* 12: */
	bdev_notdef(),			/* 13: */
	bdev_notdef(),			/* 14: */
};
int	nblkdev = nitems(bdevsw);

#include "audio.h"
#include "video.h"
#include "bio.h"
#include "pty.h"
#include "wsdisplay.h"
#include "wskbd.h"
#include "wsmouse.h"
#include "wsmux.h"

#include "bpfilter.h"
#include "tun.h"

#include "ksyms.h"

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

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

#include "pf.h"

#include "systrace.h"
#include "hotplug.h"
#include "vscsi.h"
#include "pppx.h"

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

#include "usb.h"
#include "uhid.h"
#include "ugen.h"
#include "ulpt.h"
#include "ucom.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_notdef(),			/*  7: was: concatenated disk */
	cdev_disk_init(NVND,vnd),	/*  8: vnode disk driver */
	cdev_disk_init(NRD,rd),		/*  9: RAM disk */
	cdev_disk_init(NSD,sd),		/* 10: SCSI disk */
	cdev_tape_init(NST,st),		/* 11: SCSI tape */
	cdev_disk_init(NCD,cd),		/* 12: SCSI cd-rom */
	cdev_ch_init(NCH,ch),		/* 13: SCSI changer */
	cdev_notdef(),			/* 14: */
	cdev_uk_init(NUK,uk),		/* 15: SCSI unknown */
	cdev_fd_init(1,filedesc),	/* 16: file descriptor pseudo-device */
	cdev_bpf_init(NBPFILTER,bpf),	/* 17: Berkeley packet filter */
	cdev_tun_init(NTUN,tun),	/* 18: network tunnel */
	cdev_notdef(),			/* 19: was LKM */
	cdev_random_init(1,random),	/* 20: random generator */
	cdev_pf_init(NPF,pf),		/* 21: packet filter */
	cdev_tty_init(1,pdc),		/* 22: PDC device */
	cdev_tty_init(NCOM,com),	/* 23: RS232 */
	cdev_disk_init(NFD,fd),		/* 24: floppy drive */
	cdev_ksyms_init(NKSYMS,ksyms),	/* 25: Kernel symbols device */
	cdev_lpt_init(NLPT,lpt),	/* 26: parallel printer */
	cdev_wsdisplay_init(NWSDISPLAY,	/* 27: workstation console */
	    wsdisplay),
	cdev_mouse_init(NWSKBD,wskbd),	/* 28: keyboards */
	cdev_mouse_init(NWSMOUSE,wsmouse), /* 29: mice */
	cdev_mouse_init(NWSMUX,wsmux),	/* 30: mux */
#ifdef USER_PCICONF
	cdev_pci_init(NPCI,pci),	/* 31: PCI user */
#else
	cdev_notdef(),			/* 31: */
#endif
	cdev_notdef(),
	cdev_video_init(NVIDEO,video),	/* 33: generic video I/O */
	cdev_systrace_init(NSYSTRACE,systrace),	/* 34: system call tracing */
	cdev_audio_init(NAUDIO,audio),	/* 35: /dev/audio */
	cdev_notdef(),			/* 36: was: /dev/crypto */
	cdev_bio_init(NBIO,bio),	/* 37: ioctl tunnel */
	cdev_ptm_init(NPTY,ptm),	/* 38: pseudo-tty ptm device */
	cdev_disk_init(NWD,wd),		/* 39: ST506 disk */
	cdev_usb_init(NUSB,usb),	/* 40: USB controller */
	cdev_usbdev_init(NUHID,uhid),	/* 41: USB generic HID */
	cdev_usbdev_init(NUGEN,ugen),	/* 42: USB generic driver */
	cdev_ulpt_init(NULPT,ulpt),	/* 43: USB printers */
	cdev_notdef(),			/* 44: was urio */
	cdev_tty_init(NUCOM,ucom),	/* 45: USB tty */
	cdev_notdef(),			/* 46: was USB scanners */
	cdev_hotplug_init(NHOTPLUG,hotplug), /* 47: devices hot plugging */
	cdev_notdef(),			/* 48: */
	cdev_notdef(),			/* 49: */
	cdev_notdef(),			/* 50: */
	cdev_notdef(),			/* 51: */
	cdev_notdef(),			/* 52: */
	cdev_notdef(),			/* 53: */
	cdev_vscsi_init(NVSCSI,vscsi),	/* 54: vscsi */
	cdev_notdef(),
	cdev_disk_init(1,diskmap),	/* 56: disk mapper */
	cdev_pppx_init(NPPPX,pppx),	/* 57: pppx */
	cdev_fuse_init(NFUSE,fuse),	/* 58: fuse */
};
int nchrdev = nitems(cdevsw);

int mem_no = 2;		/* major device number of memory special file */

/*
 * Swapdev is a fake device implemented
 * in sw.c used only internally to get to swstrategy.
 * It cannot be provided to the users, because the
 * swstrategy routine munches the b_dev and b_blkno entries
 * before calling the appropriate driver.  This would horribly
 * confuse, e.g. the hashing routines. Instead, /dev/drum is
 * provided as a character (raw) device.
 */
dev_t   swapdev = makedev(0, 0);

int chrtoblktbl[] = {
	/*VCHR*/	/*VBLK*/
	/*  0 */	NODEV,
	/*  1 */	NODEV,
	/*  2 */	NODEV,
	/*  3 */	NODEV,
	/*  4 */	NODEV,
	/*  5 */	NODEV,
	/*  6 */	NODEV,
	/*  7 */	NODEV,
	/*  8 */	2,		/* vnd */
	/*  9 */	3,		/* rd */
	/* 10 */	4,		/* sd */
	/* 11 */	5,		/* st */
	/* 12 */	6,		/* cd */
	/* 13 */	NODEV,
	/* 14 */	NODEV,
	/* 15 */	NODEV,
	/* 16 */	NODEV,
	/* 17 */	NODEV,
	/* 18 */	NODEV,
	/* 19 */	NODEV,
	/* 20 */	NODEV,
	/* 21 */	NODEV,
	/* 22 */	NODEV,
	/* 23 */	NODEV,
	/* 24 */	7,		/* fd */
	/* 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 */	8,		/* wd */
};
int nchrtoblktbl = nitems(chrtoblktbl);

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

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

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