code:
/*	$OpenBSD: vsaudio.c,v 1.5 2015/05/11 06:46:21 ratchov Exp $	*/

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

/*
 * Audio backend for the VAXstation 4000 AMD79C30 audio chip.
 * Currently working in pseudo-DMA mode; DMA operation may be possible and
 * needs to be investigated.
 */
/*
 * Although he did not claim copyright for his work, this code owes a lot
 * to Blaz Antonic <blaz.antonic@siol.net> who figured out a working
 * interrupt triggering routine in vsaudio_match().
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/device.h>

#include <machine/cpu.h>
#include <machine/sid.h>
#include <machine/scb.h>
#include <machine/vsbus.h>

#include <sys/audioio.h>
#include <dev/audio_if.h>

#include <dev/ic/am7930reg.h>
#include <dev/ic/am7930var.h>

#ifdef AUDIO_DEBUG
#define DPRINTF(x)	if (am7930debug) printf x
#define DPRINTFN(n,x)	if (am7930debug>(n)) printf x
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
#endif	/* AUDIO_DEBUG */

/* physical addresses of the AM79C30 chip */
#define	VSAUDIO_CSR			0x200d0000
#define	VSAUDIO_CSR_KA49		0x26800000

struct vsaudio_softc {
	struct am7930_softc sc_am7930;	/* base device */
	bus_space_tag_t sc_bt;
	bus_space_handle_t sc_bh;	/* device registers */

	void	(*sc_rintr)(void*);	/* input completion intr handler */
	void	*sc_rarg;		/* arg for sc_rintr() */
	void	(*sc_pintr)(void*);	/* output completion intr handler */
	void	*sc_parg;		/* arg for sc_pintr() */

	uint8_t	*sc_rdata;		/* record data */
	uint8_t	*sc_rend;		/* end of record data */
	uint8_t	*sc_pdata;		/* play data */
	uint8_t	*sc_pend;		/* end of play data */

	void	*sc_swintr;		/* soft interrupt cookie */
	int	sc_cvec;
	struct evcount sc_intrcnt;
};

void	vsaudio_attach(struct device *, struct device *, void *);
int	vsaudio_match(struct device *, void *, void *);

struct cfdriver vsaudio_cd = {
	NULL, "vsaudio", DV_DULL
};

const struct cfattach vsaudio_ca = {
	sizeof(struct vsaudio_softc), vsaudio_match, vsaudio_attach
};

/*
 * Hardware access routines for the MI code.
 */

uint8_t	 vsaudio_codec_iread(struct am7930_softc *, int);
uint16_t vsaudio_codec_iread16(struct am7930_softc *, int);
uint8_t	 vsaudio_codec_dread(struct vsaudio_softc *, int);
void	 vsaudio_codec_iwrite(struct am7930_softc *, int, uint8_t);
void	 vsaudio_codec_iwrite16(struct am7930_softc *, int, uint16_t);
void	 vsaudio_codec_dwrite(struct vsaudio_softc *, int, uint8_t);
void	 vsaudio_onopen(struct am7930_softc *sc);
void	 vsaudio_onclose(struct am7930_softc *sc);

struct am7930_glue vsaudio_glue = {
	vsaudio_codec_iread,
	vsaudio_codec_iwrite,
	vsaudio_codec_iread16,
	vsaudio_codec_iwrite16,
	vsaudio_onopen,
	vsaudio_onclose,
	8
};

/*
 * Interface to the MI audio layer.
 */
int	vsaudio_start_output(void *, void *, int, void (*)(void *), void *);
int	vsaudio_start_input(void *, void *, int, void (*)(void *), void *);
int	vsaudio_getdev(void *, struct audio_device *);

struct audio_hw_if vsaudio_hw_if = {
	am7930_open,
	am7930_close,
	NULL,
	am7930_query_encoding,
	am7930_set_params,
	am7930_round_blocksize,
	am7930_commit_settings,
	NULL,
	NULL,
	vsaudio_start_output,
	vsaudio_start_input,
	am7930_halt_output,
	am7930_halt_input,
	NULL,
	vsaudio_getdev,
	NULL,
	am7930_set_port,
	am7930_get_port,
	am7930_query_devinfo,
	NULL,
	NULL,
	NULL,
	NULL,
	am7930_get_props,
	NULL,
	NULL,
	NULL
};

struct audio_device vsaudio_device = {
	"am7930",
	"x",
	"vsaudio"
};

void	vsaudio_hwintr(void *);
void	vsaudio_swintr(void *);

int
vsaudio_match(struct device *parent, void *vcf, void *aux)
{
	struct vsbus_attach_args *va = aux;
	volatile uint32_t *regs;
	int i;

	switch (vax_boardtype) {
#if defined(VAX46) || defined(VAX48)
	case VAX_BTYP_46:
	case VAX_BTYP_48:
		if (va->va_paddr != VSAUDIO_CSR)
			return 0;
		break;
#endif
#if defined(VAX49)
	case VAX_BTYP_49:
		if (va->va_paddr != VSAUDIO_CSR_KA49)
			return 0;
		break;
#endif
	default:
		return 0;
	}

	regs = (volatile uint32_t *)va->va_addr;
	regs[AM7930_DREG_CR] = AM7930_IREG_INIT;
	regs[AM7930_DREG_DR] = AM7930_INIT_PMS_ACTIVE | AM7930_INIT_INT_ENABLE;

	regs[AM7930_DREG_CR] = AM7930_IREG_MUX_MCR1;
	regs[AM7930_DREG_DR] = 0;

	regs[AM7930_DREG_CR] = AM7930_IREG_MUX_MCR2;
	regs[AM7930_DREG_DR] = 0;

	regs[AM7930_DREG_CR] = AM7930_IREG_MUX_MCR3;
	regs[AM7930_DREG_DR] = (AM7930_MCRCHAN_BB << 4) | AM7930_MCRCHAN_BA;

	regs[AM7930_DREG_CR] = AM7930_IREG_MUX_MCR4;
	regs[AM7930_DREG_DR] = AM7930_MCR4_INT_ENABLE;

	for (i = 10; i < 20; i++)
		regs[AM7930_DREG_BBTB] = i;
	delay(1000000);	/* XXX too large */

	return 1;
}

void
vsaudio_attach(struct device *parent, struct device *self, void *aux)
{
	struct vsbus_attach_args *va = aux;
	struct vsaudio_softc *sc = (struct vsaudio_softc *)self;

	if (bus_space_map(va->va_iot, va->va_paddr, AM7930_DREG_SIZE << 2, 0,
	    &sc->sc_bh) != 0) {
		printf(": can't map registers\n");
		return;
	}
	sc->sc_bt = va->va_iot;

	/*
	 * Set up glue for MI code early; we use some of it here.
	 */
	sc->sc_am7930.sc_glue = &vsaudio_glue;
	am7930_init(&sc->sc_am7930, AUDIOAMD_POLL_MODE);

	scb_vecalloc(va->va_cvec, vsaudio_hwintr, sc, SCB_ISTACK,
	    &sc->sc_intrcnt);
	sc->sc_cvec = va->va_cvec;
	evcount_attach(&sc->sc_intrcnt, self->dv_xname, &sc->sc_cvec);

	sc->sc_swintr = softintr_establish(IPL_SOFT, &vsaudio_swintr, sc);

	printf("\n");
	audio_attach_mi(&vsaudio_hw_if, sc, &sc->sc_am7930.sc_dev);
}

void
vsaudio_onopen(struct am7930_softc *sc)
{
	struct vsaudio_softc *vssc = (struct vsaudio_softc *)sc;

	/* reset pdma state */
	vssc->sc_rintr = NULL;
	vssc->sc_rarg = 0;
	vssc->sc_pintr = NULL;
	vssc->sc_parg = 0;

	vssc->sc_rdata = NULL;
	vssc->sc_pdata = NULL;
}

void
vsaudio_onclose(struct am7930_softc *sc)
{
	am7930_halt_input(sc);
	am7930_halt_output(sc);
}

/*
 * this is called by interrupt code-path, don't lock
 */
int
vsaudio_start_output(void *addr, void *p, int cc,
    void (*intr)(void *), void *arg)
{
	struct vsaudio_softc *sc = addr;

	DPRINTFN(1, ("sa_start_output: cc=%d %p (%p)\n", cc, intr, arg));

	if (!sc->sc_am7930.sc_locked) {
		vsaudio_codec_iwrite(&sc->sc_am7930,
		    AM7930_IREG_INIT, AM7930_INIT_PMS_ACTIVE);
		sc->sc_am7930.sc_locked = 1;
		DPRINTF(("sa_start_output: started intrs.\n"));
	}
	sc->sc_pintr = intr;
	sc->sc_parg = arg;
	sc->sc_pdata = p;
	sc->sc_pend = (char *)p + cc - 1;
	return 0;
}

/*
 * this is called by interrupt code-path, don't lock
 */
int
vsaudio_start_input(void *addr, void *p, int cc,
    void (*intr)(void *), void *arg)
{
	struct vsaudio_softc *sc = addr;

	DPRINTFN(1, ("sa_start_input: cc=%d %p (%p)\n", cc, intr, arg));

	if (!sc->sc_am7930.sc_locked) {
		vsaudio_codec_iwrite(&sc->sc_am7930,
			AM7930_IREG_INIT, AM7930_INIT_PMS_ACTIVE);
		sc->sc_am7930.sc_locked = 1;
		DPRINTF(("sa_start_input: started intrs.\n"));
	}
	sc->sc_rintr = intr;
	sc->sc_rarg = arg;
	sc->sc_rdata = p;
	sc->sc_rend = (char *)p + cc -1;
	return 0;
}

/*
 * Pseudo-DMA support
 */

void
vsaudio_hwintr(void *v)
{
	struct vsaudio_softc *sc = v;
	uint8_t *d, *e;
	int k;

	mtx_enter(&audio_lock);
	/* clear interrupt */
	k = vsaudio_codec_dread(sc, AM7930_DREG_IR);
#if 0	/* interrupt is not shared, this shouldn't happen */
	if ((k & (AM7930_IR_DTTHRSH | AM7930_IR_DRTHRSH | AM7930_IR_DSRI |
	    AM7930_IR_DERI | AM7930_IR_BBUFF)) == 0) {
		mtx_leave(&audio_lock);
		return 0;
	}
#endif

	/* receive incoming data */
	d = sc->sc_rdata;
	e = sc->sc_rend;
	if (d != NULL && d <= e) {
		*d = vsaudio_codec_dread(sc, AM7930_DREG_BBRB);
		sc->sc_rdata++;
		if (d == e) {
			DPRINTFN(1, ("vsaudio_hwintr: swintr(r) requested"));
			softintr_schedule(sc->sc_swintr);
		}
	}

	/* send outgoing data */
	d = sc->sc_pdata;
	e = sc->sc_pend;
	if (d != NULL && d <= e) {
		vsaudio_codec_dwrite(sc, AM7930_DREG_BBTB, *d);
		sc->sc_pdata++;
		if (d == e) {
			DPRINTFN(1, ("vsaudio_hwintr: swintr(p) requested"));
			softintr_schedule(sc->sc_swintr);
		}
	}
	mtx_leave(&audio_lock);
}

void
vsaudio_swintr(void *v)
{
	struct vsaudio_softc *sc = v;
	int dor, dow;

	DPRINTFN(1, ("audiointr: sc=%p\n", sc));

	dor = dow = 0;
	mtx_enter(&audio_lock);
	if (sc->sc_rdata > sc->sc_rend && sc->sc_rintr != NULL)
		dor = 1;
	if (sc->sc_pdata > sc->sc_pend && sc->sc_pintr != NULL)
		dow = 1;
	mtx_leave(&audio_lock);

	if (dor != 0)
		(*sc->sc_rintr)(sc->sc_rarg);
	if (dow != 0)
		(*sc->sc_pintr)(sc->sc_parg);
}

/* indirect write */
void
vsaudio_codec_iwrite(struct am7930_softc *sc, int reg, uint8_t val)
{
	struct vsaudio_softc *vssc = (struct vsaudio_softc *)sc;

	vsaudio_codec_dwrite(vssc, AM7930_DREG_CR, reg);
	vsaudio_codec_dwrite(vssc, AM7930_DREG_DR, val);
}

void
vsaudio_codec_iwrite16(struct am7930_softc *sc, int reg, uint16_t val)
{
	struct vsaudio_softc *vssc = (struct vsaudio_softc *)sc;

	vsaudio_codec_dwrite(vssc, AM7930_DREG_CR, reg);
	vsaudio_codec_dwrite(vssc, AM7930_DREG_DR, val);
	vsaudio_codec_dwrite(vssc, AM7930_DREG_DR, val >> 8);
}

/* indirect read */
uint8_t
vsaudio_codec_iread(struct am7930_softc *sc, int reg)
{
	struct vsaudio_softc *vssc = (struct vsaudio_softc *)sc;

	vsaudio_codec_dwrite(vssc, AM7930_DREG_CR, reg);
	return vsaudio_codec_dread(vssc, AM7930_DREG_DR);
}

uint16_t
vsaudio_codec_iread16(struct am7930_softc *sc, int reg)
{
	struct vsaudio_softc *vssc = (struct vsaudio_softc *)sc;
	uint lo, hi;

	vsaudio_codec_dwrite(vssc, AM7930_DREG_CR, reg);
	lo = vsaudio_codec_dread(vssc, AM7930_DREG_DR);
	hi = vsaudio_codec_dread(vssc, AM7930_DREG_DR);
	return (hi << 8) | lo;
}

/* direct read */
uint8_t
vsaudio_codec_dread(struct vsaudio_softc *sc, int reg)
{
	return bus_space_read_1(sc->sc_bt, sc->sc_bh, reg << 2);
}

/* direct write */
void
vsaudio_codec_dwrite(struct vsaudio_softc *sc, int reg, uint8_t val)
{
	bus_space_write_1(sc->sc_bt, sc->sc_bh, reg << 2, val);
}

int
vsaudio_getdev(void *addr, struct audio_device *retp)
{
	*retp = vsaudio_device;
	return 0;
}


code:
/*	$OpenBSD: vsbus.c,v 1.23 2011/09/11 19:29:01 miod Exp $ */
/*	$NetBSD: vsbus.c,v 1.29 2000/06/29 07:14:37 mrg Exp $ */
/*
 * Copyright (c) 1996, 1999 Ludd, University of Lule}, Sweden.
 * All rights reserved.
 *
 * This code is derived from software contributed to Ludd by Bertram Barth.
 *
 * 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 at Ludd, University of
 *	Lule}, Sweden and its contributors.
 * 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/buf.h>
#include <sys/conf.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/device.h>
#include <sys/disklabel.h>
#include <sys/syslog.h>
#include <sys/stat.h>

#include <uvm/uvm_extern.h>

#define _VAX_BUS_DMA_PRIVATE
#include <machine/bus.h>
#include <machine/pte.h>
#include <machine/sid.h>
#include <machine/scb.h>
#include <machine/cpu.h>
#include <machine/trap.h>
#include <machine/nexus.h>

#include <machine/uvax.h>
#include <machine/ka410.h>
#include <machine/ka420.h>

#include <machine/vsbus.h>

int	vsbus_match(struct device *, struct cfdata *, void *);
void	vsbus_attach(struct device *, struct device *, void *);
int	vsbus_print(void *, const char *);
int	vsbus_search(struct device *, void *, void *);

static struct vax_bus_dma_tag vsbus_bus_dma_tag = {
	NULL,
	0,
	0,
	0,
	NULL,
	_bus_dmamap_create,
	_bus_dmamap_destroy,
	_bus_dmamap_load,
	_bus_dmamap_load_mbuf,
	_bus_dmamap_load_uio,
	_bus_dmamap_load_raw,
	_bus_dmamap_unload,
	_bus_dmamap_sync,
	_bus_dmamem_alloc,
	_bus_dmamem_free,
	_bus_dmamem_map,
	_bus_dmamem_unmap,
	_bus_dmamem_mmap,
};

extern struct vax_bus_space vax_mem_bus_space;
static SIMPLEQ_HEAD(, vsbus_dma) vsbus_dma;

struct	cfattach vsbus_ca = {
	sizeof(struct vsbus_softc), (cfmatch_t)vsbus_match, vsbus_attach
};

struct  cfdriver vsbus_cd = {
	    NULL, "vsbus", DV_DULL
};

int	oldvsbus;

int
vsbus_print(aux, name)
	void *aux;
	const char *name;
{
	struct vsbus_attach_args *va = aux;

	printf(" csr 0x%lx vec %d ipl %x maskbit %d", va->va_paddr,
	    va->va_cvec & 511, va->va_br, va->va_maskno - 1);
	return(UNCONF);
}

int
vsbus_match(parent, cf, aux)
	struct	device	*parent;
	struct	cfdata	*cf;
	void	*aux;
{
	struct mainbus_attach_args *maa = aux;

	if (maa->maa_bustype == VAX_VSBUS)
		return 1;
	return 0;
}

void
vsbus_attach(parent, self, aux)
	struct	device	*parent, *self;
	void	*aux;
{
	struct	vsbus_softc *sc = (void *)self;
	int dbase, dsize;

	printf("\n");

	sc->sc_dmatag = vsbus_bus_dma_tag;

	switch (vax_boardtype) {
#if VAX49 || VAX53
	case VAX_BTYP_1303:
	case VAX_BTYP_49:
		sc->sc_vsregs = vax_map_physmem(VS_REGS_KA49, 1);
		sc->sc_intreq = (char *)sc->sc_vsregs + 12;
		sc->sc_intclr = (char *)sc->sc_vsregs + 12;
		sc->sc_intmsk = (char *)sc->sc_vsregs + 8;
		vsbus_dma_init(sc, 8192);
		break;
#endif

#if VAX46 || VAX48
	case VAX_BTYP_48:
	case VAX_BTYP_46:
		sc->sc_vsregs = vax_map_physmem(VS_REGS, 1);
		sc->sc_intreq = (char *)sc->sc_vsregs + 15;
		sc->sc_intclr = (char *)sc->sc_vsregs + 15;
		sc->sc_intmsk = (char *)sc->sc_vsregs + 12;
		vsbus_dma_init(sc, 32768);
		break;
#endif

	default:
		sc->sc_vsregs = vax_map_physmem(VS_REGS, 1);
		sc->sc_intreq = (char *)sc->sc_vsregs + 15;
		sc->sc_intclr = (char *)sc->sc_vsregs + 15;
		sc->sc_intmsk = (char *)sc->sc_vsregs + 12;
		if (vax_boardtype == VAX_BTYP_410) {
			dbase = KA410_DMA_BASE;
			dsize = KA410_DMA_SIZE;
		} else {
			dbase = KA420_DMA_BASE;
			dsize = KA420_DMA_SIZE;
			*(char *)(sc->sc_vsregs + 0xe0) = 1; /* Big DMA */
		}
		sc->sc_dmasize = dsize;
		sc->sc_dmaaddr = uvm_km_valloc(kernel_map, dsize);
		ioaccess(sc->sc_dmaaddr, dbase, dsize/VAX_NBPG);
		break;
	}

	SIMPLEQ_INIT(&vsbus_dma);
	/*
	 * First: find which interrupts we won't care about.
	 * There are interrupts that interrupt on a periodic basic
	 * that we don't want to interfere with the rest of the
	 * interrupt probing.
	 */
	*sc->sc_intmsk = 0;
	*sc->sc_intclr = 0xff;
	DELAY(1000000); /* Wait a second */
	sc->sc_mask = *sc->sc_intreq;

#if VAX48
	/*
	 * It's possible for the 4000/VLC to generate an DZ-11 rx interrupt
	 * (0x20) during the delay period, unmask that bit.
	 */
	if (vax_boardtype == VAX_BTYP_48)
		sc->sc_mask &= ~0x20;
#endif

	printf("%s: interrupt mask %x\n", self->dv_xname, sc->sc_mask);

	/*
	 * now check for all possible devices on this "bus"
	 */
	config_search(vsbus_search, self, NULL);

	/* Autoconfig finished, enable interrupts */
	*sc->sc_intmsk = ~sc->sc_mask;
}

int
vsbus_search(parent, cfd, aux)
	struct device *parent;
	void *cfd;
	void *aux;
{
	struct	vsbus_softc *sc = (void *)parent;
	struct	vsbus_attach_args va;
	struct	cfdata *cf = cfd;
	int rc, i, vec, br;
	u_char c;

	va.va_paddr = cf->cf_loc[0];
	va.va_addr = vax_map_physmem(va.va_paddr, 1);
	va.va_dmat = &sc->sc_dmatag;
	va.va_iot = &vax_mem_bus_space;

	*sc->sc_intmsk = 0;
	*sc->sc_intclr = 0xff;
	scb_vecref(0, 0); /* Clear vector ref */

	rc = (*cf->cf_attach->ca_match) (parent, cf, &va);
	vax_unmap_physmem(va.va_addr, 1);
	c = *sc->sc_intreq & ~sc->sc_mask;

	if (rc == 0)
		goto forgetit;
	if (rc > 10)
		c = sc->sc_mask; /* Fooling interrupt */
	else if (c == 0)
		goto forgetit;

	*sc->sc_intmsk = c;
	DELAY(1000);
	*sc->sc_intmsk = 0;
	va.va_maskno = ffs((u_int)c);
	i = scb_vecref(&vec, &br);
	if (i == 0)
		goto fail;
	if (vec == 0)
		goto fail;

	/*
	 * For proper splassert operation, we need to know if we are on
	 * a vsbus system where its devices interrupt at level 0x14 instead
	 * of 0x15.
	 */
	if (br == 0x14)
		oldvsbus = 1;

	va.va_br = br;
	va.va_cvec = vec;
	va.va_dmaaddr = sc->sc_dmaaddr;
	va.va_dmasize = sc->sc_dmasize;
	*sc->sc_intmsk = c; /* Allow interrupts during attach */
	config_attach(parent, cf, &va, vsbus_print);
	*sc->sc_intmsk = 0;
	return rc;

fail:
	printf("%s%d at %s csr 0x%x %s\n",
	    cf->cf_driver->cd_name, cf->cf_unit, parent->dv_xname,
	    cf->cf_loc[0], (i ? "zero vector" : "didn't interrupt"));
forgetit:
	return 0;
}

/*
 * Sets a new interrupt mask. Returns the old one.
 * Works like spl functions.
 */
unsigned char
vsbus_setmask(mask)
	unsigned char mask;
{
	struct vsbus_softc *sc;
	unsigned char ch;

	if (vsbus_cd.cd_ndevs == 0)
		return 0;
	sc = vsbus_cd.cd_devs[0];

	ch = *sc->sc_intmsk;
	*sc->sc_intmsk = mask;
	return ch;
}

/*
 * Clears the interrupts in mask.
 */
void
vsbus_clrintr(mask)
	unsigned char mask;
{
	struct vsbus_softc *sc;

	if (vsbus_cd.cd_ndevs == 0)
		return;
	sc = vsbus_cd.cd_devs[0];

	*sc->sc_intclr = mask;
}

/*
 * Copy data from/to a user process' space from the DMA area.
 * Use the physical memory directly.
 */
void
vsbus_copytoproc(struct proc *p, caddr_t from, caddr_t to, int len)
{
	pt_entry_t *pte;
	paddr_t pa;

	if ((vaddr_t)to & KERNBASE) { /* In kernel space */
		bcopy(from, to, len);
		return;
	}
	pte = uvtopte(trunc_page((vaddr_t)to), (&p->p_addr->u_pcb));
	if ((vaddr_t)to & PGOFSET) {
		int cz = round_page((vaddr_t)to) - (vaddr_t)to;

		pa = ((*pte & PG_FRAME) << VAX_PGSHIFT) |
		    (NBPG - cz) | KERNBASE;
		bcopy(from, (caddr_t)pa, min(cz, len));
		from += cz;
		to += cz;
		len -= cz;
		pte += 8; /* XXX */
	}
	while (len > 0) {
		pa = ((*pte & PG_FRAME) << VAX_PGSHIFT) | KERNBASE;
		bcopy(from, (caddr_t)pa, min(NBPG, len));
		from += NBPG;
		to += NBPG;
		len -= NBPG;
		pte += 8; /* XXX */
	}
}

void
vsbus_copyfromproc(struct proc *p, caddr_t from, caddr_t to, int len)
{
	pt_entry_t *pte;
	paddr_t pa;

	if ((vaddr_t)from & KERNBASE) { /* In kernel space */
		bcopy(from, to, len);
		return;
	}
	pte = uvtopte(trunc_page((vaddr_t)from), (&p->p_addr->u_pcb));
	if ((vaddr_t)from & PGOFSET) {
		int cz = round_page((vaddr_t)from) - (vaddr_t)from;

		pa = ((*pte & PG_FRAME) << VAX_PGSHIFT) |
		    (NBPG - cz) | KERNBASE;
		bcopy((caddr_t)pa, to, min(cz, len));
		from += cz;
		to += cz;
		len -= cz;
		pte += 8; /* XXX */
	}
	while (len > 0) {
		pa = ((*pte & PG_FRAME) << VAX_PGSHIFT) | KERNBASE;
		bcopy((caddr_t)pa, to, min(NBPG, len));
		from += NBPG;
		to += NBPG;
		len -= NBPG;
		pte += 8; /* XXX */
	}
}

/*
 * There can only be one user of the DMA area on VS2k/VS3100 at one
 * time, so keep track of it here.
 */
static int vsbus_active = 0;

void
vsbus_dma_start(struct vsbus_dma *vd)
{

	SIMPLEQ_INSERT_TAIL(&vsbus_dma, vd, vd_q);

	if (vsbus_active == 0)
		vsbus_dma_intr();
}

void
vsbus_dma_intr(void)
{
	struct vsbus_dma *vd;

	vd = SIMPLEQ_FIRST(&vsbus_dma);
	if (vd == NULL) {
		vsbus_active = 0;
		return;
	}
	vsbus_active = 1;
	SIMPLEQ_REMOVE_HEAD(&vsbus_dma, vd_q);
	(*vd->vd_go)(vd->vd_arg);
}

license: unknown


code:
/* $OpenBSD: vsbus_dma.c,v 1.5 2008/06/26 05:42:14 ray Exp $ */
/* $NetBSD: vsbus_dma.c,v 1.7 2000/07/26 21:50:49 matt Exp $ */

/*-
 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
 * NASA Ames Research Center.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

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

#include <uvm/uvm_extern.h>

#define _VAX_BUS_DMA_PRIVATE
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/sid.h>
#include <machine/sgmap.h>
#include <machine/vsbus.h>

static int vsbus_bus_dmamap_create_sgmap(bus_dma_tag_t, bus_size_t, int,
	    bus_size_t, bus_size_t, int, bus_dmamap_t *);

static void vsbus_bus_dmamap_destroy_sgmap(bus_dma_tag_t, bus_dmamap_t);

static int vsbus_bus_dmamap_load_sgmap(bus_dma_tag_t, bus_dmamap_t, void *,
	    bus_size_t, struct proc *, int);

static int vsbus_bus_dmamap_load_mbuf_sgmap(bus_dma_tag_t, bus_dmamap_t,
	    struct mbuf *, int);

static int vsbus_bus_dmamap_load_uio_sgmap(bus_dma_tag_t, bus_dmamap_t,
	    struct uio *, int);

static int vsbus_bus_dmamap_load_raw_sgmap(bus_dma_tag_t, bus_dmamap_t,
	    bus_dma_segment_t *, int, bus_size_t, int);

static void vsbus_bus_dmamap_unload_sgmap(bus_dma_tag_t, bus_dmamap_t);

static void vsbus_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
	    bus_size_t, int);

void
vsbus_dma_init(sc, ptecnt)
	struct vsbus_softc *sc;
	unsigned ptecnt;
{
	bus_dma_tag_t t;
	bus_dma_segment_t segs[1];
	pt_entry_t *pte;
	int nsegs, error;
	unsigned mapsize = ptecnt * sizeof(pt_entry_t);

	/*
	 * Initialize the DMA tag used for sgmap-mapped DMA.
	 */
	t = &sc->sc_dmatag;
	t->_cookie = sc;
	t->_wbase = 0;
	t->_wsize = ptecnt * VAX_NBPG;
	t->_boundary = 0;
	t->_sgmap = &sc->sc_sgmap;
	t->_dmamap_create = vsbus_bus_dmamap_create_sgmap;
	t->_dmamap_destroy = vsbus_bus_dmamap_destroy_sgmap;
	t->_dmamap_load = vsbus_bus_dmamap_load_sgmap;
	t->_dmamap_load_mbuf = vsbus_bus_dmamap_load_mbuf_sgmap;
	t->_dmamap_load_uio = vsbus_bus_dmamap_load_uio_sgmap;
	t->_dmamap_load_raw = vsbus_bus_dmamap_load_raw_sgmap;
	t->_dmamap_unload = vsbus_bus_dmamap_unload_sgmap;
	t->_dmamap_sync = vsbus_bus_dmamap_sync;

	t->_dmamem_alloc = _bus_dmamem_alloc;
	t->_dmamem_free = _bus_dmamem_free;
	t->_dmamem_map = _bus_dmamem_map;
	t->_dmamem_unmap = _bus_dmamem_unmap;
	t->_dmamem_mmap = _bus_dmamem_mmap;

	if (vax_boardtype == VAX_BTYP_46 || vax_boardtype == VAX_BTYP_48) {
		/*
		 * Allocate and map the VS4000 scatter gather map.
		 */
		error = bus_dmamem_alloc(t, mapsize, mapsize, mapsize,
		    segs, 1, &nsegs, BUS_DMA_NOWAIT);
		if (error) {
			panic("vsbus_dma_init: error allocating memory for "
			    "hw sgmap: error=%d", error);
		}

		error = bus_dmamem_map(t, segs, nsegs, mapsize,
		   (caddr_t *) &pte, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
		if (error) {
			panic("vsbus_dma_init: error mapping memory for "
			    "hw sgmap: error=%d", error);
		}
		memset(pte, 0, mapsize);
		*(int *) (sc->sc_vsregs + 8) = segs->ds_addr;	/* set MAP BASE 0x2008008 */
	} else {
		pte = (pt_entry_t *) vax_map_physmem(KA49_SCSIMAP, mapsize / VAX_NBPG);
		for (nsegs = ptecnt; nsegs > 0; ) {
			((u_int32_t *) pte)[--nsegs] = 0;
		}
		segs->ds_addr = KA49_SCSIMAP;
	}
	printf("%s: %uK entry DMA SGMAP at PA 0x%lx (VA %p)\n",
		sc->sc_dev.dv_xname, ptecnt / 1024, segs->ds_addr, pte);

	/*
	 * Initialize the SGMAP.
	 */
	vax_sgmap_init(t, &sc->sc_sgmap, "vsbus_sgmap", t->_wbase, t->_wsize, pte, 0);

}

/*
 * Create a VSBUS SGMAP-mapped DMA map.
 */
int
vsbus_bus_dmamap_create_sgmap(t, size, nsegments, maxsegsz, boundary,
    flags, dmamp)
	bus_dma_tag_t t;
	bus_size_t size;
	int nsegments;
	bus_size_t maxsegsz;
	bus_size_t boundary;
	int flags;
	bus_dmamap_t *dmamp;
{
	bus_dmamap_t map;
	int error;

	error = _bus_dmamap_create(t, size, nsegments, maxsegsz,
	    boundary, flags, dmamp);
	if (error)
		return (error);

	map = *dmamp;

	if (flags & BUS_DMA_ALLOCNOW) {
		error = vax_sgmap_alloc(map, vax_round_page(size),
		    t->_sgmap, flags);
		if (error)
			vsbus_bus_dmamap_destroy_sgmap(t, map);
	}

	return (error);
}

/*
 * Destroy a VSBUS SGMAP-mapped DMA map.
 */
static void
vsbus_bus_dmamap_destroy_sgmap(t, map)
	bus_dma_tag_t t;
	bus_dmamap_t map;
{

	if (map->_dm_flags & DMAMAP_HAS_SGMAP)
		vax_sgmap_free(map, t->_sgmap);

	_bus_dmamap_destroy(t, map);
}

/*
 * Load a VSBUS SGMAP-mapped DMA map with a linear buffer.
 */
static int
vsbus_bus_dmamap_load_sgmap(t, map, buf, buflen, p, flags)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	void *buf;
	bus_size_t buflen;
	struct proc *p;
	int flags;
{
	return vax_sgmap_load(t, map, buf, buflen, p, flags, t->_sgmap);
}

/*
 * Load a VSBUS SGMAP-mapped DMA map with an mbuf chain.
 */
static int
vsbus_bus_dmamap_load_mbuf_sgmap(t, map, m, flags)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	struct mbuf *m;
	int flags;
{
	return vax_sgmap_load_mbuf(t, map, m, flags, t->_sgmap);
}

/*
 * Load a VSBUS SGMAP-mapped DMA map with a uio.
 */
static int
vsbus_bus_dmamap_load_uio_sgmap(t, map, uio, flags)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	struct uio *uio;
	int flags;
{
	return vax_sgmap_load_uio(t, map, uio, flags, t->_sgmap);
}

/*
 * Load a VSBUS SGMAP-mapped DMA map with raw memory.
 */
static int
vsbus_bus_dmamap_load_raw_sgmap(t, map, segs, nsegs, size, flags)
	bus_dma_tag_t t;
	bus_dmamap_t map;
	bus_dma_segment_t *segs;
	int nsegs;
	bus_size_t size;
	int flags;
{
	return vax_sgmap_load_raw(t, map, segs, nsegs, size, flags, t->_sgmap);
}

/*
 * Unload a VSBUS DMA map.
 */
static void
vsbus_bus_dmamap_unload_sgmap(t, map)
	bus_dma_tag_t t;
	bus_dmamap_t map;
{
	/*
	 * Invalidate any SGMAP page table entries used by this
	 * mapping.
	 */
	vax_sgmap_unload(t, map, t->_sgmap);

	/*
	 * Do the generic bits of the unload.
	 */
	_bus_dmamap_unload(t, map);
}

/*
 * Sync the bus map.
 */
static void
vsbus_bus_dmamap_sync(tag, dmam, offset, len, ops)
	bus_dma_tag_t tag;
	bus_dmamap_t dmam;
	bus_addr_t offset;
	bus_size_t len;
	int ops;
{
	/* not needed */
}


code: src/sys/arch/vax/vxt

path: sys/arch/vax/vxt/CVS/Repository


code:
/*	$OpenBSD: if_ze_vxtbus.c,v 1.3 2008/08/22 17:09:08 deraadt Exp $	*/
/*
 * Copyright (c) 1999 Ludd, University of Lule}, Sweden. 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 at Ludd, University of
 *      Lule}, Sweden and its contributors.
 * 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/device.h>
#include <sys/socket.h>

#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_media.h>

#include <netinet/in.h>
#include <netinet/if_ether.h>

#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/nexus.h>

#include <vax/if/sgecreg.h>
#include <vax/if/sgecvar.h>

#include <vax/vxt/vxtbusvar.h>

int	ze_vxt_match(struct device *, void *, void *);
void	ze_vxt_attach(struct device *, struct device *, void *);

struct	cfattach ze_vxtbus_ca = {
	sizeof(struct ze_softc), ze_vxt_match, ze_vxt_attach
};

int
ze_vxt_match(struct device *parent, void *vcf, void	*aux)
{
	struct bp_conf *bp = aux;

	if (strcmp(bp->type, "sgec") == 0)
		return (1);
	return (0);
}

void
ze_vxt_attach(struct device *parent, struct device *self, void *aux)
{
	extern struct vax_bus_dma_tag vax_bus_dma_tag;
	struct ze_softc *sc = (void *)self;
	int *ea, i;

	/*
	 * Map in SGEC registers.
	 */
	sc->sc_ioh = vax_map_physmem(SGECADDR_VXT, 1);
	sc->sc_iot = 0; /* :-) */
	sc->sc_dmat = &vax_bus_dma_tag;

	sc->sc_intvec = VXT_INTRVEC;
	vxtbus_intr_establish(self->dv_xname, IPL_NET,
	    (int (*)(void *))sgec_intr, sc);

	/*
	 * Map in, read and release ethernet rom address.
	 */
	ea = (int *)vax_map_physmem(NISA_ROM_VXT, 1);
	for (i = 0; i < ETHER_ADDR_LEN; i++)
		sc->sc_ac.ac_enaddr[i] = ea[i] & 0xff;
	vax_unmap_physmem((vaddr_t)ea, 1);

	SET(sc->sc_flags, SGECF_VXTQUIRKS);
	sgec_attach(sc);
}


code:
/*	$OpenBSD: qsc.c,v 1.8 2010/07/02 17:27:01 nicm Exp $	*/
/*
 * Copyright (c) 2006 Miodrag Vallat.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice, this permission notice, and the disclaimer below
 * 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.
 */
/*
 * Mach Operating System
 * Copyright (c) 1993-1991 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 AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON AND OMRON DISCLAIM 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.
 */

#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/proc.h>
#include <sys/tty.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/syslog.h>
#include <sys/conf.h>

#include <machine/bus.h>
#include <machine/nexus.h>
#include <machine/sid.h>

#include <dev/cons.h>

#include <vax/vxt/vxtbusvar.h>

#include <vax/vxt/qscreg.h>
#include <vax/vxt/qscvar.h>

#ifdef	DDB
#include <machine/cpu.h>
#include <ddb/db_var.h>
#endif

#include "qsckbd.h"
#include "qscms.h"

struct cfdriver qsc_cd = {
	NULL, "qsc", DV_TTY
};

/* console storage */
struct qsc_sv_reg qsccn_sv;

/* prototypes */
cdev_decl(qsc);
cons_decl(qsc);
int	qscintr(void *);
int	qscparam(struct tty *, struct termios *);
void	qscrint(struct qscsoftc *, u_int);
int	qscspeed(int);
void	qscstart(struct tty *);
struct tty *qsctty(dev_t);
void	qscxint(struct qscsoftc *, u_int);

/*
 * Registers are mapped as the least-significant byte of 32-bit
 * addresses. The following macros hide this.
 */

#define	qsc_readp(sc, reg) \
	bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, 4 * (reg))
#define	qsc_read(sc, line, reg) \
	bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, \
	    (sc)->sc_regaddr[line][reg])
#define	qsc_writep(sc, reg, val) \
	bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, 4 * (reg), (val))
#define	qsc_write(sc, line, reg, val) \
	bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, \
	    (sc)->sc_regaddr[line][reg], (val))

#define SC_LINE(dev)	(minor(dev))

/*
 * Attachment glue.
 */

int	qsc_match(struct device *parent, void *self, void *aux);
void	qsc_attach(struct device *parent, struct device *self, void *aux);
int	qsc_print(void *, const char *);

struct cfattach qsc_ca = {
	sizeof(struct qscsoftc), qsc_match, qsc_attach
};

int
qsc_match(struct device *parent, void *cf, void *aux)
{
	struct bp_conf *bp = aux;

	if (strcmp(bp->type, qsc_cd.cd_name) == 0)
		return (1);
	return (0);
}

void
qsc_attach(struct device *parent, struct device *self, void *aux)
{
	extern struct vax_bus_space vax_mem_bus_space;
	struct qscsoftc *sc = (struct qscsoftc *)self;
	bus_space_handle_t ioh;
	u_int line, pair, reg;
#if NQSCKBD > 0 || NQSCMS > 0
	struct qsc_attach_args qa;
#endif

	sc->sc_iot = &vax_mem_bus_space;
	if (bus_space_map(sc->sc_iot, QSCADDR, VAX_NBPG, 0, &ioh) != 0) {
		printf(": can't map registers!\n");
		return;
	}
	sc->sc_ioh = ioh;

	if (cn_tab->cn_putc == qsccnputc) {
		sc->sc_console = 1;
		printf(": console");
	}

	/*
	 * Initialize line-specific data (register addresses)
	 */

	for (line = 0; line < SC_NLINES; line++) {
		sc->sc_regaddr[line][SC_MR] = line * 8 + SC_MRA;
		sc->sc_regaddr[line][SC_CSR] = line * 8 + SC_CSRA;
		sc->sc_regaddr[line][SC_CR] = line * 8 + SC_CRA;
		sc->sc_regaddr[line][SC_TXFIFO] = line * 8 + SC_TXFIFOA;

		sc->sc_regaddr[line][SC_IOPCR] = (line < 2 ? 0 : 0x10) +
		    (line & 1) + SC_IOPCRA;

		sc->sc_regaddr[line][SC_ACR] = (line < 2 ? 0 : 0x10) + SC_ACRAB;
		sc->sc_regaddr[line][SC_IMR] = (line < 2 ? 0 : 0x10) + SC_IMRAB;
		sc->sc_regaddr[line][SC_OPR] = (line < 2 ? 0 : 0x10) + SC_OPRAB;
	}
	for (line = 0; line < SC_NLINES; line++)
		for (reg = 0; reg < SC_LOGICAL; reg++)
			sc->sc_regaddr[line][reg] =
			    0 + 4 * sc->sc_regaddr[line][reg];

	/*
	 * Initialize all lines.
	 */
	sc->sc_sv_reg = sc->sc_console ? &qsccn_sv : &sc->sc_sv_reg_storage;
	for (line = 0; line < SC_NLINES; line++) {
		/* do not reinitialize the console line... */
		if (sc->sc_console && line == QSC_LINE_SERIAL)
			continue;

		sc->sc_sv_reg->sv_mr1[line] =
		    (line == 3 ? ODDPAR | PAREN : PARDIS) | RXRTS | CL8;
		sc->sc_sv_reg->sv_mr2[line] = /* TXCTS | */ SB1;
		sc->sc_sv_reg->sv_csr[line] = line < 2 ? BD9600 : BD4800;
		sc->sc_sv_reg->sv_cr[line]  = TXEN | RXEN;

		pair = line >> 1;

		if (sc->sc_console && pair == (QSC_LINE_SERIAL >> 1))
			continue;

		/* Start out with Tx and RX interrupts disabled */
		sc->sc_sv_reg->sv_imr[pair] = 0;
	}

	for (line = 0; line < SC_NLINES; line++) {
		/* do not reset the console line... */
		if (sc->sc_console && line == QSC_LINE_SERIAL)
			continue;

		qsc_write(sc, line, SC_CR, RXRESET | TXDIS | RXDIS);
		DELAY(1);
		qsc_write(sc, line, SC_CR, TXRESET | TXDIS | RXDIS);
		DELAY(1);
		qsc_write(sc, line, SC_CR, ERRRESET | TXDIS | RXDIS);
		DELAY(1);
		qsc_write(sc, line, SC_CR, BRKINTRESET | TXDIS | RXDIS);
		DELAY(1);
		qsc_write(sc, line, SC_CR, MRZERO | TXDIS | RXDIS);
		DELAY(1);

		qsc_write(sc, line, SC_MR, 0);
		qsc_write(sc, line, SC_MR, sc->sc_sv_reg->sv_mr1[line]);
		qsc_write(sc, line, SC_MR, sc->sc_sv_reg->sv_mr2[line]);
		qsc_write(sc, line, SC_CSR, sc->sc_sv_reg->sv_csr[line]);
		qsc_write(sc, line, SC_CR, sc->sc_sv_reg->sv_cr[line]);
		DELAY(1);
	}

	for (pair = 0; pair < SC_NLINES / 2; pair++)
		qsc_write(sc, pair << 1, SC_IMR,
		    sc->sc_sv_reg->sv_imr[pair]);

	for (line = 0; line < SC_NLINES; line++) {
		sc->sc_tty[line] = NULL;
		sc->sc_swflags[line] = 0;
	}
	if (sc->sc_console)
		sc->sc_swflags[QSC_LINE_SERIAL] |= TIOCFLAG_SOFTCAR;

	printf("\n");

	/*
	 * Configure interrupts. We are bidding in 2681 mode for now.
	 */

	qsc_writep(sc, SC_ICR, 0x00);
	for (line = SC_BIDCRA; line <= SC_BIDCRD; line++)
		qsc_writep(sc, line, 0x00);
	qsc_writep(sc, SC_IVR, VXT_INTRVEC >> 2);

	vxtbus_intr_establish(self->dv_xname, IPL_TTY, qscintr, sc);

	/*
	 * Attach subdevices, and enable RX and TX interrupts on their lines
	 * if successful.
	 */
#if NQSCKBD > 0
	/* keyboard */
	qa.qa_line = QSC_LINE_KEYBOARD;
	qa.qa_console = !sc->sc_console;
	qa.qa_hook = &sc->sc_hook[QSC_LINE_KEYBOARD];
	if (config_found(self, &qa, qsc_print) != NULL)
		sc->sc_sv_reg->sv_imr[QSC_LINE_KEYBOARD >> 1] |= IRXRDYA;
#endif
#if NQSCMS > 0
	/* mouse */
	qa.qa_line = QSC_LINE_MOUSE;
	qa.qa_console = 0;
	qa.qa_hook = &sc->sc_hook[QSC_LINE_MOUSE];
	if (config_found(self, &qa, qsc_print) != NULL)
		sc->sc_sv_reg->sv_imr[QSC_LINE_MOUSE >> 1] |= IRXRDYB;
#endif

	for (pair = 0; pair < SC_NLINES / 2; pair++)
		qsc_write(sc, pair << 1, SC_IMR,
		    sc->sc_sv_reg->sv_imr[pair]);

	sc->sc_rdy = 1;
}

/* speed tables */
const struct qsc_s {
	int kspeed;
	int dspeed;
} qsc_speeds[] = {
	{ B0,		0	},	/* 0 baud, special HUP condition */
        { B50,		NOBAUD	},	/* 50 baud, not implemented */
	{ B75,		BD75	},	/* 75 baud */
	{ B110,		BD110	},	/* 110 baud */
	{ B134,		BD134	},	/* 134.5 baud */
	{ B150,		BD150	},	/* 150 baud */
	{ B200,		NOBAUD	},	/* 200 baud, not implemented */
	{ B300,		BD300	},	/* 300 baud */
	{ B600,		BD600	},	/* 600 baud */
	{ B1200,	BD1200	},	/* 1200 baud */
	{ B1800,	BD1800	},	/* 1800 baud */
	{ B2400,	BD2400	},	/* 2400 baud */
	{ B4800,	BD4800	},	/* 4800 baud */
	{ B9600,	BD9600	},	/* 9600 baud */
	{ B19200,	BD19200	},	/* 19200 baud */
	{ -1,		NOBAUD	},	/* anything more is uncivilized */
};

int
qscspeed(int speed)
{
	const struct qsc_s *ds;

	for (ds = qsc_speeds; ds->kspeed != -1; ds++)
		if (ds->kspeed == speed)
			return ds->dspeed;

	return NOBAUD;
}

struct tty *
qsctty(dev_t dev)
{
	u_int line;
	struct qscsoftc *sc;

	line = SC_LINE(dev);
	if (qsc_cd.cd_ndevs == 0 || line >= SC_NLINES)
		return (NULL);

	sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
	if (sc == NULL)
		return (NULL);

	return sc->sc_tty[line];
}

void
qscstart(struct tty *tp)
{
	struct qscsoftc *sc;
	dev_t dev;
	int s;
	u_int line;
	int c, tries;

	if ((tp->t_state & TS_ISOPEN) == 0)
		return;

	dev = tp->t_dev;
	line = SC_LINE(dev);
	sc = (struct qscsoftc *)qsc_cd.cd_devs[0];

	s = spltty();

	if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
		goto bail;

	ttwakeupwr(tp);
	if (tp->t_outq.c_cc == 0)
		goto bail;

	tp->t_state |= TS_BUSY;
	while (tp->t_outq.c_cc != 0) {

		/* load transmitter until it is full */
		for (tries = 10000; tries != 0; tries --)
			if (qsc_read(sc, line, SC_SR) & TXRDY)
				break;

		if (tries == 0) {
			timeout_add(&tp->t_rstrt_to, 1);
			tp->t_state |= TS_TIMEOUT;
			break;
		} else {
			c = getc(&tp->t_outq);

			qsc_write(sc, line, SC_TXFIFO, c & 0xff);

			sc->sc_sv_reg->sv_imr[line >> 1] |=
			    line & 1 ? ITXRDYB : ITXRDYA;
			qsc_write(sc, line, SC_IMR,
			    sc->sc_sv_reg->sv_imr[line >> 1]);
		}
	}
	tp->t_state &= ~TS_BUSY;

bail:
	splx(s);
}

int
qscstop(struct tty *tp, int flag)
{
	int s;

	s = spltty();
	if (tp->t_state & TS_BUSY) {
		if ((tp->t_state & TS_TTSTOP) == 0)
			tp->t_state |= TS_FLUSH;
	}
	splx(s);

	return 0;
}

int
qscioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
{
	int error;
	u_int line;
	struct tty *tp;
	struct qscsoftc *sc;

	line = SC_LINE(dev);
	sc = (struct qscsoftc *)qsc_cd.cd_devs[0];

	tp = sc->sc_tty[line];
	if (tp == NULL)
		return (ENXIO);

	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
	if (error >= 0)
		return(error);

	error = ttioctl(tp, cmd, data, flag, p);
	if (error >= 0)
		return(error);

	switch (cmd) {
	case TIOCGFLAGS:
		*(int *)data = sc->sc_swflags[line];
		break;
	case TIOCSFLAGS:
		error = suser(p, 0);
		if (error != 0)
			return (EPERM);

		sc->sc_swflags[line] = *(int *)data &
		    /* only allow valid flags */
		    (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
		break;
	default:
		return (ENOTTY);
	}

	return (0);
}

int
qscparam(struct tty *tp, struct termios *t)
{
	int flags;
	u_int line, pair;
	int speeds;
	u_int8_t mr1, mr2;
	struct qscsoftc *sc;
	dev_t dev;

	dev = tp->t_dev;
	line = SC_LINE(dev);
	pair = line >> 1;
	sc = (struct qscsoftc *)qsc_cd.cd_devs[0];

	tp->t_ispeed = t->c_ispeed;
	tp->t_ospeed = t->c_ospeed;
	tp->t_cflag = t->c_cflag;

	flags = tp->t_flags;

	/* disable Tx and Rx */
	if (sc->sc_console == 0 || line != QSC_LINE_SERIAL) {
		if (line & 1)
			sc->sc_sv_reg->sv_imr[pair] &= ~(ITXRDYB | IRXRDYB);
		else
			sc->sc_sv_reg->sv_imr[pair] &= ~(ITXRDYA | IRXRDYA);
		qsc_write(sc, line, SC_IMR, sc->sc_sv_reg->sv_imr[pair]);

		/* set baudrate */
		speeds = qscspeed(tp->t_ispeed);
		if (speeds == NOBAUD)
			speeds = DEFBAUD;
		qsc_write(sc, line, SC_CSR, speeds);
		sc->sc_sv_reg->sv_csr[line] = speeds;

		/* get saved mode registers and clear set up parameters */
		mr1 = sc->sc_sv_reg->sv_mr1[line];
		mr1 &= ~(CLMASK | PARTYPEMASK | PARMODEMASK);

		mr2 = sc->sc_sv_reg->sv_mr2[line];
		mr2 &= ~SBMASK;

		/* set up character size */
		switch (t->c_cflag & CSIZE) {
		case CL8:
			mr1 |= CL8;
			break;
		case CL7:
			mr1 |= CL7;
			break;
		case CL6:
			mr1 |= CL6;
			break;
		case CL5:
			mr1 |= CL5;
			break;
		}

		/* set up stop bits */
		if (tp->t_ospeed == B110)
			mr2 |= SB2;
		else
			mr2 |= SB1;

		/* set up parity */
		if (t->c_cflag & PARENB) {
			mr1 |= PAREN;
			if (t->c_cflag & PARODD)
				mr1 |= ODDPAR;
			else
				mr1 |= EVENPAR;
		} else
			mr1 |= PARDIS;

		if (sc->sc_sv_reg->sv_mr1[line] != mr1 ||
		    sc->sc_sv_reg->sv_mr2[line] != mr2) {
			/* write mode registers to duart */
			qsc_write(sc, line, SC_CR, MRONE);
			DELAY(1);
			qsc_write(sc, line, SC_MR, mr1);
			qsc_write(sc, line, SC_MR, mr2);

			/* save changed mode registers */
			sc->sc_sv_reg->sv_mr1[line] = mr1;
			sc->sc_sv_reg->sv_mr2[line] = mr2;
		}
	}

	/* enable transmitter? */
	if (tp->t_state & TS_BUSY) {
		sc->sc_sv_reg->sv_imr[pair] |= line & 1 ? ITXRDYB : ITXRDYA;
	}

	/* re-enable the receiver */
	sc->sc_sv_reg->sv_imr[pair] |= line & 1 ? IRXRDYB : IRXRDYA;
	qsc_write(sc, line, SC_IMR, sc->sc_sv_reg->sv_imr[pair]);

	return (0);
}

int
qscopen(dev_t dev, int flag, int mode, struct proc *p)
{
	int s;
	u_int line;
	struct qscsoftc *sc;
	struct tty *tp;

	line = SC_LINE(dev);
	if (qsc_cd.cd_ndevs == 0 || line >= SC_NLINES)
		return (ENXIO);
	/* Line B is not wired... */
	if (line == QSC_LINE_DEAD)
		return (ENXIO);
	sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
	if (sc == NULL)
		return (ENXIO);

	/* if some other device is using the line, it's not available */
	if (sc->sc_hook[line].fn != NULL)
		return (ENXIO);

	s = spltty();
	if (sc->sc_tty[line] != NULL)
		tp = sc->sc_tty[line];
	else
		tp = sc->sc_tty[line] = ttymalloc(0);

	tp->t_oproc = qscstart;
	tp->t_param = qscparam;
	tp->t_dev = dev;

	if ((tp->t_state & TS_ISOPEN) == 0) {
		ttychars(tp);

		if (tp->t_ispeed == 0) {
			tp->t_iflag = TTYDEF_IFLAG;
			tp->t_oflag = TTYDEF_OFLAG;
			tp->t_lflag = TTYDEF_LFLAG;
			tp->t_ispeed = tp->t_ospeed = B9600;
			if (sc->sc_console && line == QSC_LINE_SERIAL) {
				/* console is 8N1 */
				tp->t_cflag = (CREAD | CS8 | HUPCL);
			} else {
				tp->t_cflag = TTYDEF_CFLAG;
			}
		}

		if (sc->sc_swflags[line] & TIOCFLAG_CLOCAL)
			tp->t_cflag |= CLOCAL;
		if (sc->sc_swflags[line] & TIOCFLAG_CRTSCTS)
			tp->t_cflag |= CRTSCTS;
		if (sc->sc_swflags[line] & TIOCFLAG_MDMBUF)
			tp->t_cflag |= MDMBUF;

		qscparam(tp, &tp->t_termios);
		ttsetwater(tp);

		tp->t_state |= TS_CARR_ON;
	} else if (tp->t_state & TS_XCLUDE && suser(p, 0) != 0) {
		splx(s);
		return (EBUSY);
	}

	/*
	 * Reset the tty pointer, as there could have been a dialout
	 * use of the tty with a dialin open waiting.
	 */
	tp->t_dev = dev;
	splx(s);
	return ((*linesw[tp->t_line].l_open)(dev, tp, p));
}

int
qscclose(dev_t dev, int flag, int mode, struct proc *p)
{
	struct tty *tp;
	struct qscsoftc *sc;
	u_int line;

	line = SC_LINE(dev);
	sc = (struct qscsoftc *)qsc_cd.cd_devs[0];

	tp = sc->sc_tty[line];
	(*linesw[tp->t_line].l_close)(tp, flag, p);
	ttyclose(tp);

	return (0);
}

int
qscread(dev_t dev, struct uio *uio, int flag)
{
	u_int line;
	struct tty *tp;
	struct qscsoftc *sc;

	line = SC_LINE(dev);
	sc = (struct qscsoftc *)qsc_cd.cd_devs[0];

	tp = sc->sc_tty[line];
	if (tp == NULL)
		return (ENXIO);
	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
}

int
qscwrite(dev_t dev, struct uio *uio, int flag)
{
	u_int line;
	struct tty *tp;
	struct qscsoftc *sc;

	line = SC_LINE(dev);
	sc = (struct qscsoftc *)qsc_cd.cd_devs[0];

	tp = sc->sc_tty[line];
	if (tp == NULL)
		return (ENXIO);
	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
}

void
qscrint(struct qscsoftc *sc, u_int line)
{
	struct tty *tp;
	int data;
	unsigned char sr;
	int overrun = 0;

	tp = sc->sc_tty[line];

	/* read status reg */
	while ((sr = qsc_read(sc, line, SC_SR)) & RXRDY) {
		/* read data and reset receiver */
		data = qsc_read(sc, line, SC_RXFIFO);

		if (sr & RBRK) {
			/* clear break state */
			qsc_write(sc, line, SC_CR, BRKINTRESET);
			DELAY(1);
			qsc_write(sc, line, SC_CR, ERRRESET);
			DELAY(1);
			continue;
		}

		if ((sr & ROVRN) && cold == 0 && overrun == 0) {
			log(LOG_WARNING, "%s line %d: receiver overrun\n",
			    sc->sc_dev.dv_xname, line);
			overrun = 1;
		}

		if (sr & FRERR)
			data |= TTY_FE;
		if (sr & PERR)
			data |= TTY_PE;

		/* clear error state */
		if (sr & (ROVRN | FRERR | PERR)) {
			qsc_write(sc, line, SC_CR, ERRRESET);
			DELAY(1);
		}

		if (sc->sc_hook[line].fn != NULL) {
			if ((data & TTY_ERRORMASK) != 0 ||
			   (*sc->sc_hook[line].fn)(sc->sc_hook[line].arg, data))
			continue;
		}

		if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) == 0 &&
		    (sc->sc_console == 0 || line != QSC_LINE_SERIAL)) {
			continue;
		}

		/* no errors */
#if defined(DDB)
		if (tp->t_dev == cn_tab->cn_dev) {
			int j = kdbrint(data);

			if (j == 1)
				continue;

			if (j == 2)
				(*linesw[tp->t_line].l_rint)(27, tp);
		}
#endif
		(*linesw[tp->t_line].l_rint)(data, tp);
	}
}

void
qscxint(struct qscsoftc *sc, u_int line)
{
	struct tty *tp;
	u_int pair;

	tp = sc->sc_tty[line];

	if ((tp->t_state & (TS_ISOPEN|TS_WOPEN))==0)
		goto out;

	if (tp->t_state & TS_BUSY) {
		tp->t_state &= ~(TS_BUSY | TS_FLUSH);
		qscstart(tp);
		if (tp->t_state & TS_BUSY) {
			/* do not disable transmitter, yet */
			return;
		}
	}
out:

	/* disable transmitter */
	pair = line >> 1;
	sc->sc_sv_reg->sv_imr[pair] &= line & 1 ? ~ITXRDYB : ~ITXRDYA;
	qsc_write(sc, line, SC_IMR, sc->sc_sv_reg->sv_imr[pair]);
}

int
qscintr(void *arg)
{
	struct qscsoftc *sc = arg;
	u_int8_t isr[SC_NLINES >> 1], curisr;
	u_int pair, line;
	int rc = 0;

	for (pair = 0; pair < SC_NLINES >> 1; pair++) {
		line = pair << 1;

		/* read interrupt status register and mask with imr */
		isr[pair] = curisr = qsc_read(sc, line, SC_ISR);
		curisr &= sc->sc_sv_reg->sv_imr[pair];
		if (curisr == 0)
			continue;

		rc = 1;

		if (curisr & IRXRDYA)
			qscrint(sc, line);
		if (curisr & ITXRDYA)
			qscxint(sc, line);
		if (curisr & IBRKA) {
			qsc_write(sc, line, SC_CR, BRKINTRESET);
			DELAY(1);
		}

		if (curisr & IRXRDYB)
			qscrint(sc, line + 1);
		if (curisr & ITXRDYB)
			qscxint(sc, line + 1);
		if (curisr & IBRKB) {
			qsc_write(sc, line + 1, SC_CR, BRKINTRESET);
			DELAY(1);
		}
	}

	return (rc);
}

/*
 * Console interface routines.
 */

vaddr_t qsc_cnregs;
#define	qsc_cnread(reg) \
	*(volatile u_int8_t *)(qsc_cnregs + 4 * (reg))
#define	qsc_cnwrite(reg, val) \
	*(volatile u_int8_t *)(qsc_cnregs + 4 * (reg)) = (val)

void
qsccnprobe(struct consdev *cp)
{
	int maj;
	extern int getmajor(void *);
	extern vaddr_t iospace;

	if (vax_boardtype != VAX_BTYP_VXT)
		return;

	/* locate the major number */
	if ((maj = getmajor(qscopen)) < 0)
		return;

	qsc_cnregs = iospace;
	ioaccess(iospace, QSCADDR, 1);

	cp->cn_dev = makedev(maj, QSC_LINE_SERIAL);
	cp->cn_pri = vax_confdata & 2 ? CN_LOWPRI : CN_HIGHPRI;
}

void
qsccninit(cp)
	struct consdev *cp;
{
	qsccn_sv.sv_mr1[QSC_LINE_SERIAL] = PARDIS | RXRTS | CL8;
	qsccn_sv.sv_mr2[QSC_LINE_SERIAL] = /* TXCTS | */ SB1;
	qsccn_sv.sv_csr[QSC_LINE_SERIAL] = BD9600;
	qsccn_sv.sv_cr[QSC_LINE_SERIAL]  = TXEN | RXEN;
	qsccn_sv.sv_imr[QSC_LINE_SERIAL] = 0;

	qsc_cnwrite(SC_CRA, RXRESET | TXDIS | RXDIS);
	DELAY(1);
	qsc_cnwrite(SC_CRA, TXRESET | TXDIS | RXDIS);
	DELAY(1);
	qsc_cnwrite(SC_CRA, ERRRESET | TXDIS | RXDIS);
	DELAY(1);
	qsc_cnwrite(SC_CRA, BRKINTRESET | TXDIS | RXDIS);
	DELAY(1);
	qsc_cnwrite(SC_CRA, MRZERO | TXDIS | RXDIS);
	DELAY(1);

	qsc_cnwrite(SC_MRA, 0);
	qsc_cnwrite(SC_MRA, qsccn_sv.sv_mr1[QSC_LINE_SERIAL]);
	qsc_cnwrite(SC_MRA, qsccn_sv.sv_mr2[QSC_LINE_SERIAL]);
	qsc_cnwrite(SC_CSRA, qsccn_sv.sv_csr[QSC_LINE_SERIAL]);
	qsc_cnwrite(SC_CRA, qsccn_sv.sv_cr[QSC_LINE_SERIAL]);
	DELAY(1);

	qsc_cnwrite(SC_IMRAB, qsccn_sv.sv_imr[QSC_LINE_SERIAL]);
	qsc_cnwrite(SC_IMRCD, 0);
}

int
qsccngetc(dev_t dev)
{
	unsigned char sr;	/* status reg of line a/b */
	u_char c;		/* received character */
	int s;

	s = spltty();

	/* disable interrupts for this line and enable receiver */
	qsc_cnwrite(SC_IMRAB, qsccn_sv.sv_imr[QSC_LINE_SERIAL] & ~ITXRDYA);
	qsc_cnwrite(SC_CRA, RXEN);
	DELAY(1);

	for (;;) {
		/* read status reg */
		sr = qsc_cnread(SC_SRA);

		/* receiver interrupt handler*/
		if (sr & RXRDY) {
			/* read character from line */
			c = qsc_cnread(SC_RXFIFOA);

			/* check break condition */
			if (sr & RBRK) {
				/* clear break state */
				qsc_cnwrite(SC_CRA, BRKINTRESET);
				DELAY(1);
				qsc_cnwrite(SC_CRA, ERRRESET);
				DELAY(1);
				break;
			}

			if (sr & (FRERR | PERR | ROVRN)) {
				/* clear error state */
				qsc_cnwrite(SC_CRA, ERRRESET);
				DELAY(1);
			} else {
				break;
			}
		}
	}

	/* restore the previous state */
	qsc_cnwrite(SC_IMRAB, qsccn_sv.sv_imr[QSC_LINE_SERIAL]);
	qsc_cnwrite(SC_CRA, qsccn_sv.sv_cr[QSC_LINE_SERIAL]);

	splx(s);

	return ((int)c);
}

void
qsccnputc(dev_t dev, int c)
{
	int s;

	if (mfpr(PR_MAPEN) == 0)
		return;

	s = spltty();

	/* disable interrupts for this line and enable transmitter */
	qsc_cnwrite(SC_IMRAB, qsccn_sv.sv_imr[QSC_LINE_SERIAL] & ~ITXRDYA);
	qsc_cnwrite(SC_CRA, TXEN);
	DELAY(1);

	while ((qsc_cnread(SC_SRA) & TXRDY) == 0)
		;
	qsc_cnwrite(SC_TXFIFOA, c);

	/* wait for transmitter to empty */
	while ((qsc_cnread(SC_SRA) & TXEMT) == 0)
		;

	/* restore the previous state */
	qsc_cnwrite(SC_IMRAB, qsccn_sv.sv_imr[QSC_LINE_SERIAL]);
	qsc_cnwrite(SC_CRA, qsccn_sv.sv_cr[QSC_LINE_SERIAL]);
	DELAY(1);

	splx(s);
}

void
qsccnpollc(dev, pollflag)
	dev_t dev;
	int pollflag;
{
}

/*
 * Keyboard and mouse helper routines
 */

#if NQSCKBD > 0 || NQSCMS > 0
int
qsc_print(void *aux, const char *name)
{
	struct qsc_attach_args *qa = aux;

	if (name != NULL)
		printf(qa->qa_line == QSC_LINE_KEYBOARD ?
		    "lkkbd at %s" : "lkms at %s", name);
	else
		printf(" line %d", qa->qa_line);

	return (UNCONF);
}

int
qscgetc(u_int line)
{
	bus_addr_t craddr;
	struct qscsoftc *sc = NULL;
	int s;
	u_int8_t sr, imr, imrmask, cr, c;

	s = spltty();

	craddr = line == QSC_LINE_KEYBOARD ? SC_CRC : SC_CRD;
	imrmask = line & 1 ? ~IRXRDYB : ~IRXRDYA;
	imr = sc != NULL ? sc->sc_sv_reg->sv_imr[line / 2] : 0;
	cr = sc != NULL ? sc->sc_sv_reg->sv_cr[line] : 0;

	/* disable interrupts for this line and enable receiver */
	qsc_cnwrite(SC_IMRCD, imr & imrmask);
	qsc_cnwrite(craddr, RXEN);
	DELAY(1);

	for (;;) {
		/* read status reg */
		sr = qsc_cnread(line == QSC_LINE_KEYBOARD ? SC_SRC : SC_SRD);

		/* receiver interrupt handler*/
		if (sr & RXRDY) {
			/* read character from line */
			c = qsc_cnread(line == QSC_LINE_KEYBOARD ?
			    SC_RXFIFOC : SC_RXFIFOD);

			/* check break condition */
			if (sr & RBRK) {
				/* clear break state */
				qsc_cnwrite(craddr, BRKINTRESET);
				DELAY(1);
				qsc_cnwrite(craddr, ERRRESET);
				DELAY(1);
				break;
			}

			if (sr & (FRERR | PERR | ROVRN)) {
				/* clear error state */
				qsc_cnwrite(craddr, ERRRESET);
				DELAY(1);
			} else {
				break;
			}
		}
	}

	/* restore the previous state */
	qsc_cnwrite(SC_IMRCD, imr);
	qsc_cnwrite(craddr, cr);
	DELAY(1);

	splx(s);

	return ((int)c);
}

void
qscputc(u_int line, int c)
{
	bus_addr_t craddr;
	struct qscsoftc *sc = NULL;
	int s;
	u_int8_t imr, imrmask, cr;

	s = spltty();

	if (qsc_cd.cd_ndevs != 0 &&
	    (sc = (struct qscsoftc *)qsc_cd.cd_devs[0]) != NULL)
		if (sc->sc_rdy == 0)
			sc = NULL;

	craddr = line == QSC_LINE_KEYBOARD ? SC_CRC : SC_CRD;
	imrmask = line & 1 ? ~ITXRDYB : ~ITXRDYA;
	imr = sc != NULL ? sc->sc_sv_reg->sv_imr[line / 2] : 0;
	cr = sc != NULL ? sc->sc_sv_reg->sv_cr[line] : 0;

	/* disable interrupts for this line and enable transmitter */
	qsc_cnwrite(SC_IMRCD, imr & imrmask);
	qsc_cnwrite(craddr, TXEN);
	DELAY(1);

	while ((qsc_cnread(line == QSC_LINE_KEYBOARD ? SC_SRC : SC_SRD) &
	    TXRDY) == 0)
		;
	qsc_cnwrite(line == QSC_LINE_KEYBOARD ? SC_TXFIFOC : SC_TXFIFOD, c);

	/* wait for transmitter to empty */
	while ((qsc_cnread(line == QSC_LINE_KEYBOARD ? SC_SRC : SC_SRD) &
	    TXEMT) == 0)
		;

	/* restore the previous state */
	qsc_cnwrite(SC_IMRCD, imr);
	qsc_cnwrite(craddr, cr);
	DELAY(1);

	splx(s);
}
#endif


code:
/*	$OpenBSD: qsckbd.c,v 1.2 2014/01/26 17:48:07 miod Exp $	*/
/*	from OpenBSD: dzkbd.c,v 1.11 2006/08/05 22:05:55 miod Exp */
/*
 * Copyright (c) 2006 Miodrag Vallat.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice, this permission notice, and the disclaimer below
 * 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.
 */

/*
 * 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.
 *
 *	@(#)kbd.c	8.2 (Berkeley) 10/30/93
 */

/*
 * LK200/LK400 keyboard attached to line C of the SC26C94
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/ioctl.h>
#include <sys/syslog.h>
#include <sys/malloc.h>
#include <sys/timeout.h>

#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wskbdvar.h>
#include <dev/wscons/wsksymdef.h>
#include <dev/wscons/wsksymvar.h>
#include <vax/dec/wskbdmap_lk201.h>

#include <machine/bus.h>

#include <vax/dec/lk201reg.h>
#include <vax/dec/lk201var.h>

#include <vax/vxt/qscvar.h>

struct qsckbd_internal {
	u_int	dzi_line;
	struct lk201_state dzi_ks;
};

struct qsckbd_internal qsckbd_console_internal;

struct qsckbd_softc {
	struct device qsckbd_dev;	/* required first: base device */

	struct qsckbd_internal *sc_itl;
	int sc_enabled;
	struct device *sc_wskbddev;
};

int	qsckbd_match(struct device *, void *, void *);
void	qsckbd_attach(struct device *, struct device *, void *);

struct cfattach qsckbd_ca = {
	sizeof(struct qsckbd_softc), qsckbd_match, qsckbd_attach,
};

int	qsckbd_enable(void *, int);
void	qsckbd_set_leds(void *, int);
int	qsckbd_ioctl(void *, u_long, caddr_t, int, struct proc *);

const struct wskbd_accessops qsckbd_accessops = {
	qsckbd_enable,
	qsckbd_set_leds,
	qsckbd_ioctl,
};

void	qsckbd_cngetc(void *, u_int *, int *);
void	qsckbd_cnpollc(void *, int);

const struct wskbd_consops qsckbd_consops = {
	qsckbd_cngetc,
	qsckbd_cnpollc,
};

const struct wskbd_mapdata qsckbd_keymapdata = {
	lkkbd_keydesctab,
#ifdef LKKBD_LAYOUT
	LKKBD_LAYOUT,
#else
	KB_US | KB_DEFAULT,
#endif
};

int	qsckbd_input(void *, int);
int	qsckbd_sendchar(void *, int);

int
qsckbd_match(struct device *parent, void *vcf, void *aux)
{
	struct qsc_attach_args *qa = aux;
	struct cfdata *cf = vcf;

	if (cf->cf_loc[0] == qa->qa_line)
		return 1;

	return 0;
}

void
qsckbd_attach(struct device *parent, struct device *self, void *aux)
{
	struct qsckbd_softc *sc = (void *)self;
	struct qsc_attach_args *qa = aux;
	struct qsckbd_internal *dzi;
	struct wskbddev_attach_args a;
	int isconsole;

	qa->qa_hook->fn = qsckbd_input;
	qa->qa_hook->arg = self;

	isconsole = qa->qa_console;

	if (isconsole) {
		dzi = &qsckbd_console_internal;
		sc->sc_enabled = 1;
	} else {
		dzi = malloc(sizeof(struct qsckbd_internal), M_DEVBUF, M_NOWAIT);
		if (dzi == NULL) {
			printf(": out of memory\n");
			return;
		}
		dzi->dzi_ks.attmt.sendchar = qsckbd_sendchar;
		dzi->dzi_ks.attmt.cookie = (void *)qa->qa_line;
	}
	dzi->dzi_ks.device = self;
	dzi->dzi_line = qa->qa_line;
	sc->sc_itl = dzi;

	printf("\n");

	if (!isconsole)
		lk201_init(&dzi->dzi_ks);

	a.console = dzi == &qsckbd_console_internal;
	a.keymap = &qsckbd_keymapdata;
	a.accessops = &qsckbd_accessops;
	a.accesscookie = sc;

	sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
}

int
qsckbd_cnattach(u_int line)
{

	qsckbd_console_internal.dzi_ks.attmt.sendchar = qsckbd_sendchar;
	qsckbd_console_internal.dzi_ks.attmt.cookie = (void *)line;
	lk201_init(&qsckbd_console_internal.dzi_ks);
	qsckbd_console_internal.dzi_line = line;

	wskbd_cnattach(&qsckbd_consops, &qsckbd_console_internal,
	    &qsckbd_keymapdata);

	return 0;
}

int
qsckbd_enable(void *v, int on)
{
	struct qsckbd_softc *sc = v;

	sc->sc_enabled = on;
	return 0;
}

void
qsckbd_cngetc(void *v, u_int *type, int *data)
{
	struct qsckbd_internal *dzi = v;
	int c;

	do {
		c = qscgetc(dzi->dzi_line);
	} while (lk201_decode(&dzi->dzi_ks, 1, 0, c, type, data) == LKD_NODATA);
}

void
qsckbd_cnpollc(void *v, int on)
{
}

void
qsckbd_set_leds(void *v, int leds)
{
	struct qsckbd_softc *sc = (struct qsckbd_softc *)v;

	lk201_set_leds(&sc->sc_itl->dzi_ks, leds);
}

int
qsckbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
{
	struct qsckbd_softc *sc = (struct qsckbd_softc *)v;

	switch (cmd) {
	case WSKBDIO_GTYPE:
		*(int *)data = lk201_get_type(&sc->sc_itl->dzi_ks);
		return 0;
	case WSKBDIO_SETLEDS:
		lk201_set_leds(&sc->sc_itl->dzi_ks, *(int *)data);
		return 0;
	case WSKBDIO_GETLEDS:
		*(int *)data = lk201_get_leds(&sc->sc_itl->dzi_ks);
		return 0;
	case WSKBDIO_COMPLEXBELL:
		lk201_bell(&sc->sc_itl->dzi_ks,
			   (struct wskbd_bell_data *)data);
		return 0;
	}
	return -1;
}

int
qsckbd_input(void *v, int data)
{
	struct qsckbd_softc *sc = (struct qsckbd_softc *)v;
	u_int type;
	int val;
	int decode;

	/*
	 * We want to run through lk201_decode always, so that a late plugged
	 * keyboard will get configured correctly.
	 */
	do {
		decode = lk201_decode(&sc->sc_itl->dzi_ks, sc->sc_enabled, 1,
		    data, &type, &val);
		if (decode != LKD_NODATA)
			wskbd_input(sc->sc_wskbddev, type, val);
	} while (decode == LKD_MORE);

	return(1);
}

int
qsckbd_sendchar(void *v, int c)
{
	qscputc((u_int)v, c);
	return (0);
}


code:
/*	$OpenBSD: qscms.c,v 1.2 2008/08/22 21:05:07 miod Exp $	*/
/*	from OpenBSD: qscms.c,v 1.6 2006/07/31 18:50:13 miod Exp	*/
/*
 * Copyright (c) 2006 Miodrag Vallat.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice, this permission notice, and the disclaimer below
 * 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.
 */
/*
 * 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.
 *
 *	@(#)ms.c	8.1 (Berkeley) 6/11/93
 */

/*
 * VSXXX mouse or tablet, attached to line D of the SC26C94
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/ioctl.h>
#include <sys/syslog.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/tty.h>

#include <machine/bus.h>

#include <vax/qbus/dzreg.h>
#include <vax/qbus/dzvar.h>

#include <vax/vxt/qscvar.h>
#include <vax/dec/vsmsvar.h>

#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsmousevar.h>

struct qscms_softc {
	struct lkms_softc	sc_base;
	u_int			sc_line;
};

int	qscms_match(struct device *, void *, void *);
void	qscms_attach(struct device *, struct device *, void *);

struct cfattach qscms_ca = {
	sizeof(struct qscms_softc), qscms_match, qscms_attach,
};

int	qscms_enable(void *);
void	qscms_disable(void *);

const struct wsmouse_accessops qscms_accessops = {
	qscms_enable,
	lkms_ioctl,
	qscms_disable,
};

int
qscms_match(struct device *parent, void *vcf, void *aux)
{
	struct qsc_attach_args *qa = aux;
	struct cfdata *cf = vcf;

	if (cf->cf_loc[0] == qa->qa_line)
		return 1;

	return 0;
}

void
qscms_attach(struct device *parent, struct device *self, void *aux)
{
	struct qscms_softc *qscms = (void *)self;
	struct lkms_softc *sc = (void *)self;
	struct qsc_attach_args *qa = aux;
	struct wsmousedev_attach_args a;

	qa->qa_hook->fn = lkms_input;
	qa->qa_hook->arg = self;
	qscms->sc_line = qa->qa_line;

	printf("\n");

	a.accessops = &qscms_accessops;
	a.accesscookie = qscms;

	sc->sc_flags = 0;
	sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
}

int
qscms_enable(void *v)
{
	struct qscms_softc *qscms = v;
	struct lkms_softc *sc = v;

	if (ISSET(sc->sc_flags, MS_ENABLED))
		return EBUSY;

	SET(sc->sc_flags, MS_SELFTEST);
	qscputc(qscms->sc_line, VS_SELF_TEST);
	/* selftest is supposed to complete within 500ms */
	(void)tsleep(&sc->sc_flags, TTIPRI, "qscmsopen", hz / 2);
	if (ISSET(sc->sc_flags, MS_SELFTEST)) {
		CLR(sc->sc_flags, MS_SELFTEST);
		return ENXIO;
	}
	DELAY(150);
	qscputc(qscms->sc_line, VS_INCREMENTAL);
	SET(sc->sc_flags, MS_ENABLED);
	return 0;
}

void
qscms_disable(void *v)
{
	struct lkms_softc *sc = v;

	CLR(sc->sc_flags, MS_ENABLED);
}


code:
/*	$OpenBSD: qscreg.h,v 1.1 2006/08/27 16:55:41 miod Exp $	*/
/*
 * Copyright (c) 2006 Miodrag Vallat.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice, this permission notice, and the disclaimer below
 * 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.
 */

/*
 * SC26C94 registers
 */

#define	SC_MRA		0x00	/* R/W	Mode Register A */
#define	SC_SRA		0x01	/* R	Status Register A */
#define	SC_CSRA		0x01	/* W	Clock Select Register A */
#define	SC_CRA		0x02	/* W	Command Register A */
#define	SC_RXFIFOA	0x03	/* R	Receive Holding Register A */
#define	SC_TXFIFOA	0x03	/* W	Transmit Holding Register A */
#define	SC_IPCRAB	0x04	/* R	Input Port Change Register AB */
#define	SC_ACRAB	0x04	/* W	Auxiliary Control Register AB */
#define	SC_ISRAB	0x05	/* R	Interrupt Status Register AB */
#define	SC_IMRAB	0x05	/* W	Interrupt Mask Register AB */
#define	SC_CTURAB	0x06	/* R/W	Counter/Timer Upper Register AB */
#define	SC_CTLRAB	0x07	/* R/W	Counter/Timer Lower Register AB */
#define	SC_MRB		0x08	/* R/W	Mode Register A */
#define	SC_SRB		0x09	/* R	Status Register A */
#define	SC_CSRB		0x09	/* W	Clock Select Register A */
#define	SC_CRB		0x0a	/* W	Command Register A */
#define	SC_RXFIFOB	0x0b	/* R	Receive Holding Register A */
#define	SC_TXFIFOB	0x0b	/* W	Transmit Holding Register A */
#define	SC_OPRAB	0x0c	/* R/W	Output Port Register AB */
#define	SC_IPRAB	0x0d	/* R	Input Port Register AB */
#define	SC_IOPCRA	0x0d	/* W	I/O Port Control Register A */
#define	SC_IOPCRB	0x0e	/* W	I/O Port Control Register A */
#define	SC_CTSTARTAB	0x0e	/* R	Start Counter AB */
#define	SC_CTSTOPAB	0x0f	/* R	Start Counter AB */

#define	SC_MRC		0x10	/* R/W	Mode Register C */
#define	SC_SRC		0x11	/* R	Status Register C */
#define	SC_CSRC		0x11	/* W	Clock Select Register C */
#define	SC_CRC		0x12	/* W	Command Register C */
#define	SC_RXFIFOC	0x13	/* R	Receive Holding Register C */
#define	SC_TXFIFOC	0x13	/* W	Transmit Holding Register C */
#define	SC_IPCRCD	0x14	/* R	Input Port Change Register CD */
#define	SC_ACRCD	0x14	/* W	Auxiliary Control Register CD */
#define	SC_ISRCD	0x15	/* R	Interrupt Status Register CD */
#define	SC_IMRCD	0x15	/* W	Interrupt Mask Register CD */
#define	SC_CTURCD	0x16	/* R/W	Counter/Timer Upper Register CD */
#define	SC_CTLRCD	0x17	/* R/W	Counter/Timer Lower Register CD */
#define	SC_MRD		0x18	/* R/W	Mode Register C */
#define	SC_SRD		0x19	/* R	Status Register C */
#define	SC_CSRD		0x19	/* W	Clock Select Register C */
#define	SC_CRD		0x1a	/* W	Command Register C */
#define	SC_RXFIFOD	0x1b	/* R	Receive Holding Register C */
#define	SC_TXFIFOD	0x1b	/* W	Transmit Holding Register C */
#define	SC_OPRCD	0x1c	/* R/W	Output Port Register CD */
#define	SC_IPRCD	0x1d	/* R	Input Port Register CD */
#define	SC_IOPCRC	0x1d	/* W	I/O Port Control Register C */
#define	SC_IOPCRD	0x1e	/* W	I/O Port Control Register C */
#define	SC_CTSTARTCD	0x1e	/* R	Start Counter CD */
#define	SC_CTSTOPCD	0x1f	/* R	Start Counter CD */

#define	SC_BIDCRA	0x20	/* R/W	Bidding Control Register A */
#define	SC_BIDCRB	0x21	/* R/W	Bidding Control Register B */
#define	SC_BIDCRC	0x22	/* R/W	Bidding Control Register C */
#define	SC_BIDCRD	0x23	/* R/W	Bidding Control Register D */
#define	SC_POWERDOWN	0x24	/* W	Power Down */
#define	SC_POWERUP	0x25	/* W	Power Up */
#define	SC_DDACKN	0x26	/* W	Disable DACKN */
#define	SC_EDACKN	0x27	/* W	Enable DACKN */

#define	SC_CIR		0x28	/* R	Current Interrupt Register */
#define	SC_GICR		0x29	/* R	Global Interrupting Channel Register */
#define	SC_IVR		0x29	/* W	Interrupt Vector Register */
#define	SC_GBICR	0x2a	/* R	Global Int Byte Count Register */
#define	SC_UCIR		0x2a	/* W	Update CIR */
#define	SC_GRXFIFO	0x2b	/* R	Global Receive Holding Register */
#define	SC_GTXFIFO	0x2b	/* W	Global Transmit Holding Register */
#define	SC_ICR		0x2c	/* R/W	Interrupt Control Register */
#define	SC_BRGRATE	0x2d	/* W	BRG Rate */
#define	SC_X1DIV2	0x2e	/* W	Set X1/CLK divide by two */
#define	SC_X1NORM	0x2f	/* W	Set X1/CLK normal */

/* mode register 1: MR1x operations */
#define RXRTS        0x80  /* enable receiver RTS */
#define PAREN        0x00  /* with parity */
#define PARDIS       0x10  /* no parity */
#define EVENPAR      0x00  /* even parity */
#define ODDPAR       0x04  /* odd parity */
#define CL5          0x00  /* 5 bits per char */
#define CL6          0x01  /* 6 bits per char */
#define CL7          0x02  /* 7 bits per char */
#define CL8          0x03  /* 8 bits per char */
#define PARMODEMASK  0x18  /* parity mode mask */
#define PARTYPEMASK  0x04  /* parity type mask */
#define CLMASK       0x03  /* character length mask */

/* mode register 2: MR2x operations */
#define TXRTS        0x20  /* enable transmitter RTS */
#define TXCTS        0x10  /* enable transmitter CTS */
#define SB2          0x0f  /* 2 stop bits */
#define SB1          0x07  /* 1 stop bit */
#define SB1L5        0x00  /* 1 stop bit at 5 bits per character */

#define SBMASK       0x0f  /* stop bit mask */

/* clock-select register: CSRx operations */
#define NOBAUD       -1    /* 50 and 200 baud are not possible */
/* they are not in Baud register set 2 */
#define BD75         0x00  /* 75 baud */
#define BD110        0x11  /* 110 baud */
#define BD134        0x22  /* 134.5 baud */
#define BD150        0x33  /* 150 baud */
#define BD300        0x44  /* 300 baud */
#define BD600        0x55  /* 600 baud */
#define BD1200       0x66  /* 1200 baud */
#define BD1800       0xaa  /* 1800 baud */
#define BD2400       0x88  /* 2400 baud */
#define BD4800       0x99  /* 4800 baud */
#define BD9600       0xbb  /* 9600 baud */
#define BD19200      0xcc  /* 19200 baud */

#define DEFBAUD      BD9600   /* default value if baudrate is not possible */

/* channel command register: CRx operations */
#define MRONE      	0x10  /* reset mr pointer to mr1 */
#define RXRESET      0x20  /* reset receiver */
#define TXRESET      0x30  /* reset transmitter */
#define ERRRESET     0x40  /* reset error status */
#define BRKINTRESET  0x50  /* reset channel's break interrupt */
#define BRKSTART     0x60  /* start break */
#define BRKSTOP      0x70  /* stop break */
#define MRZERO      	0xb0  /* reset mr pointer to mr0 */
#define TXDIS        0x08  /* disable transmitter */
#define TXEN         0x04  /* enable transmitter */
#define RXDIS        0x02  /* disable receiver */
#define RXEN         0x01  /* enable receiver */

/* status register: SRx status */
#define RBRK         0x80  /* received break */
#define FRERR        0x40  /* frame error */
#define PERR         0x20  /* parity error */
#define ROVRN        0x10  /* receiver overrun error */
#define TXEMT        0x08  /* transmitter empty */
#define TXRDY        0x04  /* transmitter ready */
#define FFULL        0x02  /* receiver FIFO full */
#define RXRDY        0x01  /* receiver ready */

/* auxiliary control register: ACR operations */
#define BDSET1       0x00  /* baudrate generator set 1 */
#define BDSET2       0x80  /* baudrate generator set 2 */
#define CCLK1        0x60  /* timer clock: external rate.  TA */
#define CCLK16       0x30  /* counter clock: x1 clk divided by 16 */

/* interrupt status and mask register: ISR status and IMR mask */
#define	IIPCHG		0x80	/* I/O Port Change */
#define IBRKB        0x40  /* delta break b */
#define IRXRDYB      0x20  /* receiver ready b */
#define ITXRDYB      0x10  /* transmitter ready b */
#define ITIMER       0x08  /* Counter Ready */
#define IBRKA        0x04  /* delta break a */
#define IRXRDYA      0x02  /* receiver ready a */
#define ITXRDYA      0x01  /* transmitter ready a */


code:
/*	$OpenBSD: qscvar.h,v 1.1 2006/08/27 16:55:41 miod Exp $	*/
/*
 * Copyright (c) 2006 Miodrag Vallat.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice, this permission notice, and the disclaimer below
 * 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.
 */
/*
 * Mach Operating System
 * Copyright (c) 1993-1991 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 AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON AND OMRON DISCLAIM 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.
 */

/*
 * Logical, per port, registers (serial functions only)
 */

#define	SC_MR		0x00	/* R/W	Mode Register */
#define	SC_SR		0x01	/* R	Status Register */
#define	SC_CSR		0x01	/* W	Clock Select Register */
#define	SC_CR		0x02	/* W	Command Register */
#define	SC_RXFIFO	0x03	/* R	Receive Holding Register */
#define	SC_TXFIFO	0x03	/* W	Transmit Holding Register */
#define	SC_IPCR		0x04	/* R	Input Port Change Register */
#define	SC_ACR		0x04	/* W	Auxiliary Control Register */
#define	SC_ISR		0x05	/* R	Interrupt Status Register */
#define	SC_IMR		0x05	/* W	Interrupt Mask Register */
#define	SC_OPR		0x06	/* R/W	Output Port Register */
#define	SC_IPR		0x07	/* R	Input Port Register */
#define	SC_IOPCR	0x07	/* W	I/O Port Control Register */
#define	SC_LOGICAL	0x08

#define	SC_NLINES	4

/* saved registers */
struct qsc_sv_reg {
	u_int8_t	sv_mr1[SC_NLINES];
	u_int8_t	sv_mr2[SC_NLINES];
	u_int8_t	sv_csr[SC_NLINES];
	u_int8_t	sv_cr[SC_NLINES];
	u_int8_t	sv_imr[SC_NLINES / 2];
};

struct qsc_input_hook {
	int	(*fn)(void *, int);
	void	*arg;
};

struct qscsoftc {
	struct device		sc_dev;
	bus_space_tag_t		sc_iot;
	bus_space_handle_t	sc_ioh;
	bus_addr_t		sc_regaddr[SC_NLINES][SC_LOGICAL];

	int			sc_console;
	int			sc_rdy;

	struct qsc_sv_reg	*sc_sv_reg;
	struct qsc_sv_reg	sc_sv_reg_storage;

	struct tty		*sc_tty[SC_NLINES];
	u_int		 	sc_swflags[SC_NLINES];

	struct qsc_input_hook	sc_hook[SC_NLINES];
};

/*
 * Line assignments on the VXT2000
 */

#define	QSC_LINE_SERIAL		0
#define	QSC_LINE_DEAD		1
#define	QSC_LINE_KEYBOARD	2
#define	QSC_LINE_MOUSE		3

struct	qsc_attach_args {
	u_int	qa_line;
	int	qa_console;	/* for keyboard attachment */
	struct qsc_input_hook *qa_hook;
};

int	qscgetc(u_int);
void	qscputc(u_int, int);

int	qsckbd_cnattach(u_int);


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

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

#include <machine/cpu.h>
#include <machine/nexus.h>
#include <machine/scb.h>

#include <vax/vxt/vxtbusvar.h>

struct vxtbus_softc {
	struct device 		sc_dev;
	LIST_HEAD(, vxtbus_ih)	sc_intrlist;
};

void	vxtbus_attach(struct device *, struct device *, void *);
int	vxtbus_match(struct device *, void*, void *);

struct	cfdriver vxtbus_cd = {
	NULL, "vxtbus", DV_DULL
};

struct	cfattach vxtbus_ca = {
	sizeof(struct vxtbus_softc), vxtbus_match, vxtbus_attach
};

void	vxtbus_intr(void *);
int	vxtbus_print(void *, const char *);

int
vxtbus_match(struct device *parent, void *vcf, void *aux)
{
	struct mainbus_attach_args *maa = aux;

	return (maa->maa_bustype == VAX_VXTBUS ? 1 : 0);
}

void
vxtbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct vxtbus_softc *sc = (void *)self;
	struct bp_conf bp;

	LIST_INIT(&sc->sc_intrlist);
	scb_vecalloc(VXT_INTRVEC, vxtbus_intr, sc, SCB_ISTACK, NULL);

	printf("\n");

	bp.type = "sgec";
	config_found(self, &bp, vxtbus_print);

	bp.type = "qsc";
	config_found(self, &bp, vxtbus_print);

	bp.type = "lcspx";
	config_found(self, &bp, vxtbus_print);
}

int
vxtbus_print(void *aux, const char *name)
{
	struct bp_conf *bp = aux;

	if (name)
		printf("%s at %s", bp->type, name);

	return (UNCONF);
}

/*
 * VXT2000 interrupt code.
 *
 * All device interrupts end up on the same vector, which is controllable
 * by the SC26C94 chip.
 *
 * Interrupts are handled at spl4 (ipl 0x14).
 *
 * The following routines implement shared interrupts for vxtbus subdevices.
 */

struct vxtbus_ih {
	LIST_ENTRY(vxtbus_ih)	ih_link;
	int			(*ih_fn)(void *);
	void *			ih_arg;
	int			ih_vec;
	struct evcount		ih_cnt;
};

void
vxtbus_intr_establish(const char *name, int ipl, int (*fn)(void *), void *arg)
{
	struct vxtbus_softc *sc = (void *)vxtbus_cd.cd_devs[0];
	struct vxtbus_ih *ih;

	ih = (struct vxtbus_ih *)malloc(sizeof(*ih), M_DEVBUF, M_WAITOK);

	ih->ih_fn = fn;
	ih->ih_arg = arg;
	ih->ih_vec = VXT_INTRVEC;
	evcount_attach(&ih->ih_cnt, name, &ih->ih_vec);

	LIST_INSERT_HEAD(&sc->sc_intrlist, ih, ih_link);
}

void
vxtbus_intr(void *arg)
{
	struct vxtbus_softc *sc = arg;
	struct vxtbus_ih *ih;
	int rc;
#ifdef DIAGNOSTIC
	int handled = 0;
	static int strayintr = 0;
#endif

	LIST_FOREACH(ih, &sc->sc_intrlist, ih_link) {
		rc = (*ih->ih_fn)(ih->ih_arg);
		if (rc != 0) {
#ifdef DIAGNOSTIC
			handled = 1;
#endif
			ih->ih_cnt.ec_count++;
			if (rc > 0)
				break;
		}
	}

#ifdef DIAGNOSTIC
	if (handled == 0) {
		if (++strayintr == 10)
			panic("%s: too many stray interrupts",
			    sc->sc_dev.dv_xname);
		else
			printf("%s: stray interrupt\n", sc->sc_dev.dv_xname);
	}
#endif
}


code:
/*	$OpenBSD: vxtbusvar.h,v 1.1 2006/08/27 16:55:41 miod Exp $	*/
/*
 * Copyright (c) 2006 Miodrag Vallat.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice, this permission notice, and the disclaimer below
 * 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.
 */

/*
 * VXT2000 Hardware addresses
 */
#define	SGECADDR_VXT	0x20008000
#define	QSCADDR		0x200a0000
#define	NISA_ROM_VXT	0x200c4000

#define	VXT_INTRVEC	0x200

void	vxtbus_intr_establish(const char *, int, int (*)(void *), void *);


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

path: sys/arch/zaurus/CVS/Entries


code: src/sys/arch/zaurus

path: sys/arch/zaurus/CVS/Repository


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

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

NOPROG=
NOMAN=
NOOBJ=
SUBDIR=	stand

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

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

obj:	_SUBDIRUSE

.include <bsd.prog.mk>

path: sys/arch/zaurus/Makefile


code:
/.cvsignore/1.1/Fri Dec 31 00:04:35 2004//TOPENBSD_5_8_BASE
D

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


code: src/sys/arch/zaurus/compile

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


code: src/sys/arch/zaurus/conf

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


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

machine		zaurus arm
include		"../../../conf/GENERIC"
maxusers	32			# estimated number of users

options		ARM32
options		PXAGPIO_HAS_GPION_INTRS

makeoptions	KERNEL_BASE_PHYS="0xa0200000"
makeoptions	KERNEL_BASE_VIRT="0xc0200000"

# CPU options
options		CPU_XSCALE_PXA2X0	# Support the XScale core
#options	XSCALE_CACHE_WRITE_THROUGH
options		XSCALE_CACHE_WRITE_BACK
makeoptions	CPUFLAGS="-mcpu=xscale"

option	WSDISPLAY_COMPAT_USL		# VT handling
option	WSDISPLAY_COMPAT_RAWKBD		# provide raw scancodes; needed for X11
option	WSDISPLAY_DEFAULTSCREENS=2	# initial number of text consoles
option	WSDISPLAY_COMPAT_PCVT		# emulate some ioctls; needed for X11

option USBVERBOSE

config		bsd	swap generic

# The main bus device
mainbus0	at root
cpu0		at mainbus?
pxaip0		at mainbus?

pxaintc0	at pxaip?		# interrupt controller
pxagpio0	at pxaip?		# GPIO controller
pxadmac0	at pxaip?		# DMA controller
pxaost0		at pxaip? addr 0x40a00000 size 0x20

# PCMCIA/CF socket and GPIO controllers
scoop0		at pxaip?
scoop1		at pxaip?

# touch screen
zts0		at pxaip?
wsmouse*	at zts? mux 0

# keyboard
zkbd0		at pxaip?
wskbd*		at zkbd? mux 1

# USB controllers
pxaudc0		at pxaip?		# USB Device Controller
ohci0		at pxaip?		# Open Host Controller

# USB function support
usbf*		at pxaudc?		# USB logical device
cdcef*		at usbf?		# CDC ethernet function

# USB bus support
usb*		at ohci?

# USB devices
uhub*		at usb?			# USB Root Hub
uhub*		at uhub?		# USB Hub
ualea*		at uhub?		# Araneus Alea II TRNG
umodem*		at uhub?		# USB Modems/Serial
ucom*		at umodem?
uvisor*		at uhub?		# Handspring Visor
ucom*		at uvisor?
uvscom*		at uhub?		# SUNTAC Slipper U VS-10U serial
ucom*		at uvscom?
ubsa*		at uhub?		# Belkin serial adapter
ucom*		at ubsa?
uftdi*		at uhub?		# FTDI FT8U100AX serial adapter
ucom*		at uftdi?
uplcom*		at uhub?		# I/O DATA USB-RSAQ2 serial adapter
ucom*		at uplcom?
umct*		at uhub?		# MCT USB-RS232 serial adapter
ucom*		at umct?
uslcom*		at uhub?		# Silicon Laboratories CP210x serial
ucom*		at uslcom?
uark*		at uhub?		# Arkmicro ARK3116 serial
ucom*		at uark?
uipaq*		at uhub?		# iPAQ serial adapter
ucom*		at uipaq?
uchcom*		at uhub?		# WinChipHead CH341/340 serial
ucom*		at uchcom?
uaudio*		at uhub?		# USB Audio
audio*		at uaudio?
umidi*		at uhub?		# USB MIDI
midi*		at umidi?
ulpt*		at uhub?		# USB Printers
umass*		at uhub?		# USB Mass Storage devices
uhidev*		at uhub?		# Human Interface Devices
ums*		at uhidev?		# USB mouse
wsmouse*	at ums? mux 0
ukbd*		at uhidev?		# USB keyboard
wskbd*		at ukbd? mux 1
ucycom*		at uhidev?		# Cypress serial
ucom*		at ucycom?
uslhcom*	at uhidev?		# Silicon Labs CP2110 USB HID UART
ucom*		at uslhcom?
uhid*		at uhidev?		# USB generic HID support
upd*		at uhidev?		# USB Power Devices sensors
aue*		at uhub?		# ADMtek AN986 Pegasus Ethernet
atu*		at uhub?		# Atmel AT76C50x based 802.11b
axe*		at uhub?		# ASIX Electronics AX88172 USB Ethernet
axen*		at uhub?		# ASIX Electronics AX88179 USB Ethernet
cue*		at uhub?		# CATC USB-EL1201A based Ethernet
kue*		at uhub?		# Kawasaki KL5KUSB101B based Ethernet
smsc*		at uhub?		# SMSC LAN95xx Ethernet
cdce*		at uhub?		# CDC Ethernet
urndis*		at uhub?		# Remote NDIS devices
upl*		at uhub?		# Prolific PL2301/PL2302 host-to-host
ugl*		at uhub?		# Genesys Logic GL620A-USB host-to-host
udav*		at uhub?		# Davicom DM9601 based Ethernet
ural*		at uhub?		# Ralink RT2500USB
rum*		at uhub?		# Ralink RT2501USB/RT2601USB
run*		at uhub?		# Ralink RT2700U/RT2800U/RT3000U
zyd*		at uhub?		# Zydas ZD1211
url*		at uhub?		# Realtek RTL8150L based adapters
wi*		at uhub?		# WaveLAN IEEE 802.11DS
udsbr*		at uhub?		# D-Link DSB-R100 radio
radio*		at udsbr?		# USB radio
ugen*		at uhub?		# USB Generic driver
udcf*		at uhub?		# Gude Expert mouseCLOCK
umbg*		at uhub?		# Meinberg Funkuhren USB5131
uow*		at uhub?		# Maxim/Dallas DS2490 1-Wire adapter
onewire*	at uow?
utwitch*	at uhidev?		# YUREX BBU sensor

scsibus*	at scsi?
sd*		at scsibus?		# SCSI disk drives
#st*		at scsibus?		# SCSI tape drives
cd*		at scsibus?		# SCSI CD-ROM drives
#ch*		at scsibus?		# SCSI autochangers
#uk*		at scsibus?		# unknown SCSI

# integrated 16550 UARTs
options COM_PXA2X0
com0	at pxaip? addr 0x40100000 intr 22	# Full Function UART
com1	at pxaip? addr 0x40200000 intr 21	# BlueTooth UART
com2	at pxaip? addr 0x40700000 intr 20	# Standard UART (for IrDA)

# integrated PCMCIA/CF controller
pxapcic0	at pxaip?

# PCMCIA bus support
pcmcia*		at pxapcic?

# PCMCIA (CF) devices
com*		at pcmcia?		# PCMCIA modems/serial ports
wi*		at pcmcia?		# WaveLAN IEEE 802.11DS
malo*		at pcmcia?		# Marvell 88W8385
ne*		at pcmcia?		# PCMCIA based NE2000 ethernet
wdc*		at pcmcia?		# hard disk controller
#cfxga*		at pcmcia?		# VoyagerVGA frame buffer
#wsdisplay*	at cfxga?

# IDE hard drives
wd*		at wdc? flags 0x0000

# Media Independent Interface (mii) drivers
exphy*	at mii?				# 3Com internal PHYs
inphy*	at mii?				# Intel 82555 PHYs
iophy*	at mii?				# Intel 82553 PHYs
icsphy*	at mii?				# ICS 1890 PHYs
lxtphy*	at mii?				# Level1 LXT970 PHYs
nsphy*	at mii?				# NS and compatible PHYs
nsphyter* at mii?			# NS and compatible PHYs
qsphy*	at mii?				# Quality Semi QS6612 PHYs
sqphy*	at mii?				# Seeq 8x220 PHYs
rlphy* at mii?				# Realtek 8139 internal PHYs
mtdphy* at mii?				# Myson MTD972 PHYs
#dcphy*	at mii?				# Digital Clone PHYs
acphy*	at mii?				# Altima AC101 PHYs
amphy*	at mii?				# AMD 79C873 PHYs
tqphy*	at mii?				# TDK 78Q212x PHYs
bmtphy*	at mii?				# Broadcom 10/100 PHYs
#brgphy* at mii?			# Broadcom Gigabit PHYs
eephy* at mii?				# Marvell 88E1000 series PHY
#xmphy*	at mii?				# XaQti XMAC-II PHYs
nsgphy*	at mii?				# NS gigabit PHYs
urlphy*	at mii?				# Realtek RTL8150L internal PHY
rgephy* at mii?				# Realtek 8169S/8110S PHY
#ciphy* at mii?				# Cicada CS8201 10/100/1000 copper PHY
ukphy*	at mii?				# "unknown" PHYs

lcd0		at pxaip?		# LCD
wsdisplay*	at lcd? console ?
zssp0		at pxaip?		# ADC, touch screen, backlight
apm0		at pxaip?		# APM emulation

zaudio0		at pxaip?		# Zaurus I2S/I2C sound
audio*		at zaudio?
zrc0		at pxaip?		# Zaurus remote control
wskbd*		at zrc? mux 1
flash0		at pxaip?		# NAND flash memory

pxammc0		at pxaip?		# MMC/SD/SDIO controller
sdmmc*		at pxammc?		# SD/MMC bus

# USB Video
uvideo* at uhub?
video*  at uvideo?

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

# Pseudo-Devices
pseudo-device	wsmux		2	# mouse & keyboard multiplexor
pseudo-device	hotplug		1	# devices hot plugging

path: sys/arch/zaurus/conf/GENERIC