Separate out devices common to many Motorola mvme boards (68k, 88k and ppc)
in preparation for future mvmeppc and mvme88k ports. This needs a bit if tidying up to make it trully shareable, which will happen as the new mvme ports are added.
This commit is contained in:
parent
acb4381e27
commit
08bde987bb
352
sys/dev/mvme/if_ie_mvme.c
Normal file
352
sys/dev/mvme/if_ie_mvme.c
Normal file
@ -0,0 +1,352 @@
|
||||
/* $NetBSD: if_ie_mvme.c,v 1.1 2002/02/12 20:38:43 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford.
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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/mbuf.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/if_ether.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <uvm/uvm_extern.h>
|
||||
|
||||
#include <machine/autoconf.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/ic/i82586reg.h>
|
||||
#include <dev/ic/i82586var.h>
|
||||
|
||||
#include <dev/mvme/if_iereg.h>
|
||||
#include <dev/mvme/pcctwovar.h>
|
||||
#include <dev/mvme/pcctworeg.h>
|
||||
|
||||
|
||||
int ie_pcctwo_match __P((struct device *, struct cfdata *, void *));
|
||||
void ie_pcctwo_attach __P((struct device *, struct device *, void *));
|
||||
|
||||
struct ie_pcctwo_softc {
|
||||
struct ie_softc ps_ie;
|
||||
bus_space_tag_t ps_bust;
|
||||
bus_space_handle_t ps_bush;
|
||||
struct evcnt ps_evcnt;
|
||||
};
|
||||
|
||||
struct cfattach ie_pcctwo_ca = {
|
||||
sizeof(struct ie_pcctwo_softc), ie_pcctwo_match, ie_pcctwo_attach
|
||||
};
|
||||
|
||||
extern struct cfdriver ie_cd;
|
||||
|
||||
|
||||
/* Functions required by the i82586 MI driver */
|
||||
static void ie_reset __P((struct ie_softc *, int));
|
||||
static int ie_intrhook __P((struct ie_softc *, int));
|
||||
static void ie_hwinit __P((struct ie_softc *));
|
||||
static void ie_atten __P((struct ie_softc *, int));
|
||||
|
||||
static void ie_copyin __P((struct ie_softc *, void *, int, size_t));
|
||||
static void ie_copyout __P((struct ie_softc *, const void *, int, size_t));
|
||||
|
||||
static u_int16_t ie_read_16 __P((struct ie_softc *, int));
|
||||
static void ie_write_16 __P((struct ie_softc *, int, u_int16_t));
|
||||
static void ie_write_24 __P((struct ie_softc *, int, int));
|
||||
|
||||
/*
|
||||
* i82596 Support Routines for MVME1[67][27] and MVME187 Boards
|
||||
*/
|
||||
static void
|
||||
ie_reset(sc, why)
|
||||
struct ie_softc *sc;
|
||||
int why;
|
||||
{
|
||||
struct ie_pcctwo_softc *ps;
|
||||
u_int32_t scp_addr;
|
||||
|
||||
ps = (struct ie_pcctwo_softc *) sc;
|
||||
|
||||
switch (why) {
|
||||
case CHIP_PROBE:
|
||||
case CARD_RESET:
|
||||
bus_space_write_2(ps->ps_bust, ps->ps_bush, IE_MPUREG_UPPER,
|
||||
IE_PORT_RESET);
|
||||
bus_space_write_2(ps->ps_bust, ps->ps_bush, IE_MPUREG_LOWER, 0);
|
||||
delay(1000);
|
||||
|
||||
/*
|
||||
* Set the BUSY and BUS_USE bytes here, since the MI code
|
||||
* incorrectly assumes it can use byte addressing to set it.
|
||||
* (due to wrong-endianess of the chip)
|
||||
*/
|
||||
ie_write_16(sc, IE_ISCP_BUSY(sc->iscp), 1);
|
||||
ie_write_16(sc, IE_SCP_BUS_USE(sc->scp), IE_BUS_USE);
|
||||
|
||||
scp_addr = sc->scp + (u_int) sc->sc_iobase;
|
||||
scp_addr |= IE_PORT_ALT_SCP;
|
||||
|
||||
bus_space_write_2(ps->ps_bust, ps->ps_bush, IE_MPUREG_UPPER,
|
||||
scp_addr & 0xffff);
|
||||
bus_space_write_2(ps->ps_bust, ps->ps_bush, IE_MPUREG_LOWER,
|
||||
(scp_addr >> 16) & 0xffff);
|
||||
delay(1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
ie_intrhook(sc, when)
|
||||
struct ie_softc *sc;
|
||||
int when;
|
||||
{
|
||||
struct ie_pcctwo_softc *ps;
|
||||
u_int8_t reg;
|
||||
|
||||
ps = (struct ie_pcctwo_softc *) sc;
|
||||
|
||||
if (when == INTR_EXIT) {
|
||||
reg = pcc2_reg_read(sys_pcctwo, PCC2REG_ETH_ICSR);
|
||||
reg |= PCCTWO_ICR_ICLR;
|
||||
pcc2_reg_write(sys_pcctwo, PCC2REG_ETH_ICSR, reg);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
ie_hwinit(sc)
|
||||
struct ie_softc *sc;
|
||||
{
|
||||
u_int8_t reg;
|
||||
|
||||
reg = pcc2_reg_read(sys_pcctwo, PCC2REG_ETH_ICSR);
|
||||
reg |= PCCTWO_ICR_IEN | PCCTWO_ICR_ICLR;
|
||||
pcc2_reg_write(sys_pcctwo, PCC2REG_ETH_ICSR, reg);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
ie_atten(sc, reason)
|
||||
struct ie_softc *sc;
|
||||
int reason;
|
||||
{
|
||||
struct ie_pcctwo_softc *ps;
|
||||
|
||||
ps = (struct ie_pcctwo_softc *) sc;
|
||||
bus_space_write_4(ps->ps_bust, ps->ps_bush, IE_MPUREG_CA, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
ie_copyin(sc, dst, offset, size)
|
||||
struct ie_softc *sc;
|
||||
void *dst;
|
||||
int offset;
|
||||
size_t size;
|
||||
{
|
||||
if (size == 0) /* This *can* happen! */
|
||||
return;
|
||||
|
||||
#if 0
|
||||
bus_space_read_region_1(sc->bt, sc->bh, offset, dst, size);
|
||||
#else
|
||||
/* A minor optimisation ;-) */
|
||||
memcpy(dst, (void *) ((u_long) sc->bh + (u_long) offset), size);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
ie_copyout(sc, src, offset, size)
|
||||
struct ie_softc *sc;
|
||||
const void *src;
|
||||
int offset;
|
||||
size_t size;
|
||||
{
|
||||
if (size == 0) /* This *can* happen! */
|
||||
return;
|
||||
|
||||
#if 0
|
||||
bus_space_write_region_1(sc->bt, sc->bh, offset, src, size);
|
||||
#else
|
||||
/* A minor optimisation ;-) */
|
||||
memcpy((void *) ((u_long) sc->bh + (u_long) offset), src, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
static u_int16_t
|
||||
ie_read_16(sc, offset)
|
||||
struct ie_softc *sc;
|
||||
int offset;
|
||||
{
|
||||
|
||||
return (bus_space_read_2(sc->bt, sc->bh, offset));
|
||||
}
|
||||
|
||||
static void
|
||||
ie_write_16(sc, offset, value)
|
||||
struct ie_softc *sc;
|
||||
int offset;
|
||||
u_int16_t value;
|
||||
{
|
||||
|
||||
bus_space_write_2(sc->bt, sc->bh, offset, value);
|
||||
}
|
||||
|
||||
static void
|
||||
ie_write_24(sc, offset, addr)
|
||||
struct ie_softc *sc;
|
||||
int offset;
|
||||
int addr;
|
||||
{
|
||||
|
||||
addr += (int) sc->sc_iobase;
|
||||
|
||||
bus_space_write_2(sc->bt, sc->bh, offset, addr & 0xffff);
|
||||
bus_space_write_2(sc->bt, sc->bh, offset + 2, (addr >> 16) & 0x00ff);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
ie_pcctwo_match(parent, cf, args)
|
||||
struct device *parent;
|
||||
struct cfdata *cf;
|
||||
void *args;
|
||||
{
|
||||
struct pcctwo_attach_args *pa;
|
||||
|
||||
pa = args;
|
||||
|
||||
if (strcmp(pa->pa_name, ie_cd.cd_name))
|
||||
return (0);
|
||||
|
||||
pa->pa_ipl = cf->pcctwocf_ipl;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
ie_pcctwo_attach(parent, self, args)
|
||||
struct device *parent;
|
||||
struct device *self;
|
||||
void *args;
|
||||
{
|
||||
struct pcctwo_attach_args *pa;
|
||||
struct ie_pcctwo_softc *ps;
|
||||
struct ie_softc *sc;
|
||||
bus_dma_segment_t seg;
|
||||
int rseg;
|
||||
|
||||
pa = (struct pcctwo_attach_args *) args;
|
||||
ps = (struct ie_pcctwo_softc *) self;
|
||||
sc = (struct ie_softc *) self;
|
||||
|
||||
/* Map the MPU controller registers in PCCTWO space */
|
||||
ps->ps_bust = pa->pa_bust;
|
||||
bus_space_map(pa->pa_bust, pa->pa_offset, IE_MPUREG_SIZE,
|
||||
0, &ps->ps_bush);
|
||||
|
||||
/* Get contiguous DMA-able memory for the IE chip */
|
||||
if (bus_dmamem_alloc(pa->pa_dmat, ether_data_buff_size, NBPG, 0,
|
||||
&seg, 1, &rseg,
|
||||
BUS_DMA_NOWAIT | BUS_DMA_ONBOARD_RAM | BUS_DMA_24BIT) != 0) {
|
||||
printf("%s: Failed to allocate ether buffer\n", self->dv_xname);
|
||||
return;
|
||||
}
|
||||
if (bus_dmamem_map(pa->pa_dmat, &seg, rseg, ether_data_buff_size,
|
||||
(caddr_t *) & sc->sc_maddr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) {
|
||||
printf("%s: Failed to map ether buffer\n", self->dv_xname);
|
||||
bus_dmamem_free(pa->pa_dmat, &seg, rseg);
|
||||
return;
|
||||
}
|
||||
sc->bt = pa->pa_bust;
|
||||
sc->bh = (bus_space_handle_t) sc->sc_maddr; /* XXXSCW Better way? */
|
||||
sc->sc_iobase = (void *) seg.ds_addr;
|
||||
sc->sc_msize = ether_data_buff_size;
|
||||
memset(sc->sc_maddr, 0, ether_data_buff_size);
|
||||
|
||||
sc->hwreset = ie_reset;
|
||||
sc->hwinit = ie_hwinit;
|
||||
sc->chan_attn = ie_atten;
|
||||
sc->intrhook = ie_intrhook;
|
||||
sc->memcopyin = ie_copyin;
|
||||
sc->memcopyout = ie_copyout;
|
||||
sc->ie_bus_barrier = NULL;
|
||||
sc->ie_bus_read16 = ie_read_16;
|
||||
sc->ie_bus_write16 = ie_write_16;
|
||||
sc->ie_bus_write24 = ie_write_24;
|
||||
sc->sc_mediachange = NULL;
|
||||
sc->sc_mediastatus = NULL;
|
||||
|
||||
sc->scp = 0;
|
||||
sc->iscp = sc->scp + ((IE_SCP_SZ + 15) & ~15);
|
||||
sc->scb = sc->iscp + IE_ISCP_SZ;
|
||||
sc->buf_area = sc->scb + IE_SCB_SZ;
|
||||
sc->buf_area_sz = sc->sc_msize - (sc->buf_area - sc->scp);
|
||||
|
||||
/*
|
||||
* BUS_USE -> Interrupt Active High (edge-triggered),
|
||||
* Lock function enabled,
|
||||
* Internal bus throttle timer triggering,
|
||||
* 82586 operating mode.
|
||||
*/
|
||||
ie_write_16(sc, IE_SCP_BUS_USE(sc->scp), IE_BUS_USE);
|
||||
ie_write_24(sc, IE_SCP_ISCP(sc->scp), sc->iscp);
|
||||
ie_write_16(sc, IE_ISCP_SCB(sc->iscp), sc->scb);
|
||||
ie_write_24(sc, IE_ISCP_BASE(sc->iscp), sc->scp);
|
||||
|
||||
/* This has the side-effect of resetting the chip */
|
||||
i82586_proberam(sc);
|
||||
|
||||
/* Attach the MI back-end */
|
||||
i82586_attach(sc, "onboard", mvme_ea, NULL, 0, 0);
|
||||
|
||||
/* Register the event counter */
|
||||
evcnt_attach_dynamic(&ps->ps_evcnt, EVCNT_TYPE_INTR,
|
||||
pcctwointr_evcnt(pa->pa_ipl), "ether", sc->sc_dev.dv_xname);
|
||||
|
||||
/* Finally, hook the hardware interrupt */
|
||||
pcctwointr_establish(PCCTWOV_LANC_IRQ, i82586_intr, pa->pa_ipl, sc,
|
||||
&ps->ps_evcnt);
|
||||
}
|
64
sys/dev/mvme/if_iereg.h
Normal file
64
sys/dev/mvme/if_iereg.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* $NetBSD: if_iereg.h,v 1.1 2002/02/12 20:38:43 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford.
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Definitions for the MPU Port and Channel Attention registers
|
||||
* of the onboard i82596 Ethernet controller on MVME68K and MVME88K boards.
|
||||
*/
|
||||
#ifndef __mvme_if_iereg_h
|
||||
#define __mvme_if_iereg_h
|
||||
|
||||
#define IE_MPUREG_UPPER 0x00 /* Upper Command Word */
|
||||
#define IE_MPUREG_LOWER 0x02 /* Lower Command Word */
|
||||
#define IE_MPUREG_CA 0x04 /* Channel Attention. Dummy Rd or Wr */
|
||||
|
||||
#define IE_MPUREG_SIZE 0x08
|
||||
|
||||
/*
|
||||
* BUS_USE -> Interrupt Active High (edge-triggered),
|
||||
* Lock function enabled,
|
||||
* Internal bus throttle timer triggering,
|
||||
* 82586 operating mode.
|
||||
*/
|
||||
#define IE_BUS_USE (IE_SYSBUS_596_INTHIGH | \
|
||||
IE_SYSBUS_596_LOCK | \
|
||||
IE_SYSBUS_596_TRGINT | \
|
||||
IE_SYSBUS_596_82586 | \
|
||||
IE_SYSBUS_596_RSVD_SET)
|
||||
|
||||
#endif /* __mvme_if_iereg_h */
|
396
sys/dev/mvme/lpt_mvme.c
Normal file
396
sys/dev/mvme/lpt_mvme.c
Normal file
@ -0,0 +1,396 @@
|
||||
/* $NetBSD: lpt_mvme.c,v 1.1 2002/02/12 20:38:44 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford.
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1993, 1994 Charles M. Hannum.
|
||||
* Copyright (c) 1990 William F. Jolitz, TeleMuse
|
||||
* 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 software is a component of "386BSD" developed by
|
||||
* William F. Jolitz, TeleMuse.
|
||||
* 4. Neither the name of the developer nor the name "386BSD"
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
|
||||
* AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
|
||||
* SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
|
||||
* THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
|
||||
* NOT MAKE USE OF THIS WORK.
|
||||
*
|
||||
* FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
|
||||
* BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN
|
||||
* REFERENCES SUCH AS THE "PORTING UNIX TO THE 386" SERIES
|
||||
* (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING
|
||||
* JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND
|
||||
* LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE
|
||||
* ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS
|
||||
* OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``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 DEVELOPER 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Device Driver for an MVME68K/MVME88K board's parallel printer port
|
||||
* This driver attaches above the board-specific back-end.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/syslog.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/mvme/lptvar.h>
|
||||
|
||||
|
||||
#define TIMEOUT hz*16 /* wait up to 16 seconds for a ready */
|
||||
#define STEP hz/4
|
||||
|
||||
#define LPTPRI (PZERO+8)
|
||||
#define LPT_BSIZE 1024
|
||||
|
||||
#if !defined(DEBUG) || !defined(notdef)
|
||||
#define LPRINTF(a)
|
||||
#else
|
||||
#define LPRINTF if (lptdebug) printf a
|
||||
int lptdebug = 1;
|
||||
#endif
|
||||
|
||||
/* {b,c}devsw[] function prototypes */
|
||||
dev_type_open(lptopen);
|
||||
dev_type_close(lptclose);
|
||||
dev_type_write(lptwrite);
|
||||
dev_type_ioctl(lptioctl);
|
||||
|
||||
|
||||
#define LPTUNIT(s) (minor(s) & 0x0f)
|
||||
#define LPTFLAGS(s) (minor(s) & 0xf0)
|
||||
|
||||
static void lpt_wakeup __P((void *arg));
|
||||
static int pushbytes __P((struct lpt_softc *));
|
||||
|
||||
extern struct cfdriver lpt_cd;
|
||||
|
||||
|
||||
void
|
||||
lpt_attach_subr(sc)
|
||||
struct lpt_softc *sc;
|
||||
{
|
||||
|
||||
sc->sc_state = 0;
|
||||
callout_init(&sc->sc_wakeup_ch);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the printer, then wait until it's selected and not busy.
|
||||
*/
|
||||
int
|
||||
lptopen(dev, flag, mode, p)
|
||||
dev_t dev;
|
||||
int flag;
|
||||
int mode;
|
||||
struct proc *p;
|
||||
{
|
||||
int unit;
|
||||
u_char flags;
|
||||
struct lpt_softc *sc;
|
||||
int error;
|
||||
int spin;
|
||||
|
||||
unit = LPTUNIT(dev);
|
||||
flags = LPTFLAGS(dev);
|
||||
|
||||
if (unit >= lpt_cd.cd_ndevs)
|
||||
return (ENXIO);
|
||||
sc = lpt_cd.cd_devs[unit];
|
||||
if (!sc)
|
||||
return (ENXIO);
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (sc->sc_state)
|
||||
printf("%s: stat=0x%x not zero\n", sc->sc_dev.dv_xname,
|
||||
sc->sc_state);
|
||||
#endif
|
||||
|
||||
if (sc->sc_state)
|
||||
return (EBUSY);
|
||||
|
||||
sc->sc_state = LPT_INIT;
|
||||
sc->sc_flags = flags;
|
||||
LPRINTF(("%s: open: flags=0x%x\n", sc->sc_dev.dv_xname, flags));
|
||||
|
||||
if ((flags & LPT_NOPRIME) == 0) {
|
||||
/* assert Input Prime for 100 usec to start up printer */
|
||||
(sc->sc_funcs->lf_iprime) (sc);
|
||||
}
|
||||
|
||||
/* select fast or slow strobe depending on minor device number */
|
||||
if (flags & LPT_FAST_STROBE)
|
||||
(sc->sc_funcs->lf_speed) (sc, LPT_STROBE_FAST);
|
||||
else
|
||||
(sc->sc_funcs->lf_speed) (sc, LPT_STROBE_SLOW);
|
||||
|
||||
/* wait till ready (printer running diagnostics) */
|
||||
for (spin = 0; (sc->sc_funcs->lf_notrdy) (sc, 1); spin += STEP) {
|
||||
if (spin >= TIMEOUT) {
|
||||
sc->sc_state = 0;
|
||||
return (EBUSY);
|
||||
}
|
||||
/* wait 1/4 second, give up if we get a signal */
|
||||
error = tsleep((caddr_t) sc, LPTPRI | PCATCH, "lptopen", STEP);
|
||||
if (error != EWOULDBLOCK) {
|
||||
sc->sc_state = 0;
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
|
||||
sc->sc_inbuf = geteblk(LPT_BSIZE);
|
||||
sc->sc_count = 0;
|
||||
sc->sc_state = LPT_OPEN;
|
||||
|
||||
if ((sc->sc_flags & LPT_NOINTR) == 0)
|
||||
lpt_wakeup(sc);
|
||||
|
||||
(sc->sc_funcs->lf_open) (sc, sc->sc_flags & LPT_NOINTR);
|
||||
|
||||
LPRINTF(("%s: opened\n", sc->sc_dev.dv_xname));
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
lpt_wakeup(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct lpt_softc *sc;
|
||||
int s;
|
||||
|
||||
sc = arg;
|
||||
|
||||
s = spltty();
|
||||
lpt_intr(sc);
|
||||
splx(s);
|
||||
|
||||
callout_reset(&sc->sc_wakeup_ch, STEP, lpt_wakeup, sc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close the device, and free the local line buffer.
|
||||
*/
|
||||
int
|
||||
lptclose(dev, flag, mode, p)
|
||||
dev_t dev;
|
||||
int flag;
|
||||
int mode;
|
||||
struct proc *p;
|
||||
{
|
||||
struct lpt_softc *sc;
|
||||
int unit;
|
||||
|
||||
unit = LPTUNIT(dev);
|
||||
sc = lpt_cd.cd_devs[unit];
|
||||
|
||||
if (sc->sc_count)
|
||||
(void) pushbytes(sc);
|
||||
|
||||
if ((sc->sc_flags & LPT_NOINTR) == 0)
|
||||
callout_stop(&sc->sc_wakeup_ch);
|
||||
|
||||
(sc->sc_funcs->lf_close) (sc);
|
||||
|
||||
sc->sc_state = 0;
|
||||
brelse(sc->sc_inbuf);
|
||||
|
||||
LPRINTF(("%s: closed\n", sc->sc_dev.dv_xname));
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pushbytes(sc)
|
||||
struct lpt_softc *sc;
|
||||
{
|
||||
int s, error, spin, tic;
|
||||
|
||||
if (sc->sc_flags & LPT_NOINTR) {
|
||||
while (sc->sc_count > 0) {
|
||||
spin = 0;
|
||||
while ((sc->sc_funcs->lf_notrdy) (sc, 0)) {
|
||||
if (++spin < sc->sc_spinmax)
|
||||
continue;
|
||||
tic = 0;
|
||||
/* adapt busy-wait algorithm */
|
||||
sc->sc_spinmax++;
|
||||
while ((sc->sc_funcs->lf_notrdy) (sc, 1)) {
|
||||
/* exponential backoff */
|
||||
tic = tic + tic + 1;
|
||||
if (tic > TIMEOUT)
|
||||
tic = TIMEOUT;
|
||||
error = tsleep((caddr_t) sc,
|
||||
LPTPRI | PCATCH, "lptpsh", tic);
|
||||
if (error != EWOULDBLOCK)
|
||||
return (error);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
(sc->sc_funcs->lf_wrdata) (sc, *sc->sc_cp++);
|
||||
sc->sc_count--;
|
||||
|
||||
/* adapt busy-wait algorithm */
|
||||
if (spin * 2 + 16 < sc->sc_spinmax)
|
||||
sc->sc_spinmax--;
|
||||
}
|
||||
} else {
|
||||
while (sc->sc_count > 0) {
|
||||
/* if the printer is ready for a char, give it one */
|
||||
if ((sc->sc_state & LPT_OBUSY) == 0) {
|
||||
LPRINTF(("%s: write %d\n", sc->sc_dev.dv_xname,
|
||||
sc->sc_count));
|
||||
s = spltty();
|
||||
(void) lpt_intr(sc);
|
||||
splx(s);
|
||||
}
|
||||
error = tsleep((caddr_t) sc, LPTPRI | PCATCH,
|
||||
"lptwrite2", 0);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a line from user space to a local buffer, then call putc to get the
|
||||
* chars moved to the output queue.
|
||||
*/
|
||||
int
|
||||
lptwrite(dev, uio, flags)
|
||||
dev_t dev;
|
||||
struct uio *uio;
|
||||
int flags;
|
||||
{
|
||||
struct lpt_softc *sc;
|
||||
size_t n;
|
||||
int error;
|
||||
|
||||
sc = lpt_cd.cd_devs[LPTUNIT(dev)];
|
||||
error = 0;
|
||||
|
||||
while ((n = min(LPT_BSIZE, uio->uio_resid)) != 0) {
|
||||
uiomove(sc->sc_cp = sc->sc_inbuf->b_data, n, uio);
|
||||
sc->sc_count = n;
|
||||
error = pushbytes(sc);
|
||||
if (error) {
|
||||
/*
|
||||
* Return accurate residual if interrupted or timed
|
||||
* out.
|
||||
*/
|
||||
uio->uio_resid += sc->sc_count;
|
||||
sc->sc_count = 0;
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle printer interrupts which occur when the printer is ready to accept
|
||||
* another char.
|
||||
*/
|
||||
int
|
||||
lpt_intr(sc)
|
||||
struct lpt_softc *sc;
|
||||
{
|
||||
|
||||
if (sc->sc_count) {
|
||||
/* send char */
|
||||
(sc->sc_funcs->lf_wrdata) (sc, *sc->sc_cp++);
|
||||
sc->sc_count--;
|
||||
sc->sc_state |= LPT_OBUSY;
|
||||
} else
|
||||
sc->sc_state &= ~LPT_OBUSY;
|
||||
|
||||
if (sc->sc_count == 0) {
|
||||
/* none, wake up the top half to get more */
|
||||
wakeup((caddr_t) sc);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
lptioctl(dev, cmd, data, flag, p)
|
||||
dev_t dev;
|
||||
u_long cmd;
|
||||
caddr_t data;
|
||||
int flag;
|
||||
struct proc *p;
|
||||
{
|
||||
|
||||
return (ENODEV);
|
||||
}
|
294
sys/dev/mvme/lpt_pcctwo.c
Normal file
294
sys/dev/mvme/lpt_pcctwo.c
Normal file
@ -0,0 +1,294 @@
|
||||
/* $NetBSD: lpt_pcctwo.c,v 1.1 2002/02/12 20:38:44 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford.
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Device Driver back-end for the PCCChip2's parallel printer port
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/syslog.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/mvme/lptvar.h>
|
||||
#include <dev/mvme/pcctworeg.h>
|
||||
#include <dev/mvme/pcctwovar.h>
|
||||
|
||||
/*
|
||||
* Autoconfig stuff
|
||||
*/
|
||||
int lpt_pcctwo_match __P((struct device *, struct cfdata *, void *));
|
||||
void lpt_pcctwo_attach __P((struct device *, struct device *, void *));
|
||||
|
||||
struct cfattach lpt_pcctwo_ca = {
|
||||
sizeof(struct lpt_softc), lpt_pcctwo_match, lpt_pcctwo_attach
|
||||
};
|
||||
|
||||
extern struct cfdriver lpt_cd;
|
||||
|
||||
|
||||
int lpt_pcctwo_intr __P((void *));
|
||||
void lpt_pcctwo_open __P((struct lpt_softc *, int));
|
||||
void lpt_pcctwo_close __P((struct lpt_softc *));
|
||||
void lpt_pcctwo_iprime __P((struct lpt_softc *));
|
||||
void lpt_pcctwo_speed __P((struct lpt_softc *, int));
|
||||
int lpt_pcctwo_notrdy __P((struct lpt_softc *, int));
|
||||
void lpt_pcctwo_wr_data __P((struct lpt_softc *, u_char));
|
||||
|
||||
struct lpt_funcs lpt_pcctwo_funcs = {
|
||||
lpt_pcctwo_open,
|
||||
lpt_pcctwo_close,
|
||||
lpt_pcctwo_iprime,
|
||||
lpt_pcctwo_speed,
|
||||
lpt_pcctwo_notrdy,
|
||||
lpt_pcctwo_wr_data
|
||||
};
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
lpt_pcctwo_match(parent, cf, args)
|
||||
struct device *parent;
|
||||
struct cfdata *cf;
|
||||
void *args;
|
||||
{
|
||||
struct pcctwo_attach_args *pa;
|
||||
|
||||
pa = args;
|
||||
|
||||
if (strcmp(pa->pa_name, lpt_cd.cd_name))
|
||||
return (0);
|
||||
|
||||
#ifdef MVME68K
|
||||
if (machineid != MVME_167 && machineid != MVME_177)
|
||||
return (0);
|
||||
#endif
|
||||
|
||||
#ifdef MVME88K
|
||||
if (machineid != MVME_187)
|
||||
return (0);
|
||||
#endif
|
||||
|
||||
pa->pa_ipl = cf->pcctwocf_ipl;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
lpt_pcctwo_attach(parent, self, args)
|
||||
struct device *parent;
|
||||
struct device *self;
|
||||
void *args;
|
||||
{
|
||||
struct pcctwo_attach_args *pa;
|
||||
struct lpt_softc *sc;
|
||||
|
||||
pa = (struct pcctwo_attach_args *) args;
|
||||
sc = (struct lpt_softc *) self;
|
||||
|
||||
/* The printer registers are part of the PCCChip2's own registers. */
|
||||
sc->sc_bust = pa->pa_bust;
|
||||
bus_space_map(pa->pa_bust, pa->pa_offset, PCC2REG_SIZE, 0,
|
||||
&sc->sc_bush);
|
||||
|
||||
sc->sc_ipl = pa->pa_ipl & PCCTWO_ICR_LEVEL_MASK;
|
||||
sc->sc_laststatus = 0;
|
||||
sc->sc_funcs = &lpt_pcctwo_funcs;
|
||||
|
||||
printf(": PCCchip2 Parallel Printer\n");
|
||||
|
||||
/*
|
||||
* Disable interrupts until device is opened
|
||||
*/
|
||||
pcc2_reg_write(sc, PCC2REG_PRT_ACK_ICSR, 0);
|
||||
pcc2_reg_write(sc, PCC2REG_PRT_FAULT_ICSR, 0);
|
||||
pcc2_reg_write(sc, PCC2REG_PRT_SEL_ICSR, 0);
|
||||
pcc2_reg_write(sc, PCC2REG_PRT_PE_ICSR, 0);
|
||||
pcc2_reg_write(sc, PCC2REG_PRT_BUSY_ICSR, 0);
|
||||
pcc2_reg_write(sc, PCC2REG_PRT_CONTROL, 0);
|
||||
|
||||
/*
|
||||
* Main attachment code
|
||||
*/
|
||||
lpt_attach_subr(sc);
|
||||
|
||||
/* Register the event counter */
|
||||
evcnt_attach_dynamic(&sc->sc_evcnt, EVCNT_TYPE_INTR,
|
||||
pcctwointr_evcnt(sc->sc_ipl), "printer", sc->sc_dev.dv_xname);
|
||||
|
||||
/*
|
||||
* Hook into the printer interrupt
|
||||
*/
|
||||
pcctwointr_establish(PCCTWOV_PRT_ACK, lpt_pcctwo_intr, sc->sc_ipl, sc,
|
||||
&sc->sc_evcnt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle printer interrupts
|
||||
*/
|
||||
int
|
||||
lpt_pcctwo_intr(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct lpt_softc *sc;
|
||||
int i;
|
||||
|
||||
sc = (struct lpt_softc *) arg;
|
||||
|
||||
/* is printer online and ready for output */
|
||||
if (lpt_pcctwo_notrdy(sc, 0) || lpt_pcctwo_notrdy(sc, 1))
|
||||
return (0);
|
||||
|
||||
i = lpt_intr(sc);
|
||||
|
||||
if (pcc2_reg_read(sc, PCC2REG_PRT_INPUT_STATUS) & PCCTWO_PRT_IN_SR_PINT)
|
||||
pcc2_reg_write(sc, PCC2REG_PRT_ACK_ICSR,
|
||||
sc->sc_icr | PCCTWO_ICR_ICLR);
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
void
|
||||
lpt_pcctwo_open(sc, int_ena)
|
||||
struct lpt_softc *sc;
|
||||
int int_ena;
|
||||
{
|
||||
int sps;
|
||||
|
||||
pcc2_reg_write(sc, PCC2REG_PRT_ACK_ICSR,
|
||||
PCCTWO_ICR_ICLR | PCCTWO_ICR_EDGE);
|
||||
|
||||
pcc2_reg_write(sc, PCC2REG_PRT_CONTROL,
|
||||
pcc2_reg_read(sc, PCC2REG_PRT_CONTROL) | PCCTWO_PRT_CTRL_DOEN);
|
||||
|
||||
if (int_ena == 0) {
|
||||
sps = splhigh();
|
||||
sc->sc_icr = sc->sc_ipl | PCCTWO_ICR_EDGE;
|
||||
pcc2_reg_write(sc, PCC2REG_PRT_ACK_ICSR, sc->sc_icr);
|
||||
splx(sps);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lpt_pcctwo_close(sc)
|
||||
struct lpt_softc *sc;
|
||||
{
|
||||
|
||||
pcc2_reg_write(sc, PCC2REG_PRT_ACK_ICSR,
|
||||
PCCTWO_ICR_ICLR | PCCTWO_ICR_EDGE);
|
||||
pcc2_reg_write(sc, PCC2REG_PRT_CONTROL, 0);
|
||||
}
|
||||
|
||||
void
|
||||
lpt_pcctwo_iprime(sc)
|
||||
struct lpt_softc *sc;
|
||||
{
|
||||
|
||||
pcc2_reg_write(sc, PCC2REG_PRT_CONTROL,
|
||||
pcc2_reg_read(sc, PCC2REG_PRT_CONTROL) | PCCTWO_PRT_CTRL_INP);
|
||||
|
||||
delay(100);
|
||||
|
||||
pcc2_reg_write(sc, PCC2REG_PRT_CONTROL,
|
||||
pcc2_reg_read(sc, PCC2REG_PRT_CONTROL) & ~PCCTWO_PRT_CTRL_INP);
|
||||
|
||||
delay(100);
|
||||
}
|
||||
|
||||
void
|
||||
lpt_pcctwo_speed(sc, speed)
|
||||
struct lpt_softc *sc;
|
||||
int speed;
|
||||
{
|
||||
u_int8_t reg;
|
||||
|
||||
reg = pcc2_reg_read(sc, PCC2REG_PRT_CONTROL);
|
||||
|
||||
if (speed == LPT_STROBE_FAST)
|
||||
reg |= PCCTWO_PRT_CTRL_FAST;
|
||||
else
|
||||
reg &= ~PCCTWO_PRT_CTRL_FAST;
|
||||
|
||||
pcc2_reg_write(sc, PCC2REG_PRT_CONTROL, reg);
|
||||
}
|
||||
|
||||
int
|
||||
lpt_pcctwo_notrdy(sc, err)
|
||||
struct lpt_softc *sc;
|
||||
int err;
|
||||
{
|
||||
u_int8_t status;
|
||||
u_int8_t new;
|
||||
|
||||
#define LPS_INVERT (PCCTWO_PRT_IN_SR_SEL)
|
||||
#define LPS_MASK (PCCTWO_PRT_IN_SR_SEL | PCCTWO_PRT_IN_SR_FLT | \
|
||||
PCCTWO_PRT_IN_SR_BSY | PCCTWO_PRT_IN_SR_PE)
|
||||
|
||||
status = pcc2_reg_read(sc, PCC2REG_PRT_INPUT_STATUS) ^ LPS_INVERT;
|
||||
status &= LPS_MASK;
|
||||
|
||||
if (err) {
|
||||
new = status & ~sc->sc_laststatus;
|
||||
sc->sc_laststatus = status;
|
||||
|
||||
if (new & PCCTWO_PRT_IN_SR_SEL)
|
||||
log(LOG_NOTICE, "%s: offline\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
else if (new & PCCTWO_PRT_IN_SR_PE)
|
||||
log(LOG_NOTICE, "%s: out of paper\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
else if (new & PCCTWO_PRT_IN_SR_FLT)
|
||||
log(LOG_NOTICE, "%s: output error\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
void
|
||||
lpt_pcctwo_wr_data(sc, data)
|
||||
struct lpt_softc *sc;
|
||||
u_char data;
|
||||
{
|
||||
|
||||
pcc2_reg_write16(sc, PCC2REG_PRT_DATA, (u_int16_t) data);
|
||||
}
|
95
sys/dev/mvme/lptvar.h
Normal file
95
sys/dev/mvme/lptvar.h
Normal file
@ -0,0 +1,95 @@
|
||||
/* $NetBSD: lptvar.h,v 1.1 2002/02/12 20:38:45 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford.
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Common front-end for mvme68k/mvme88k parallel printer ports
|
||||
*/
|
||||
|
||||
#ifndef __mvme_lptvar_h
|
||||
#define __mvme_lptvar_h
|
||||
|
||||
#include <sys/callout.h>
|
||||
|
||||
struct lpt_funcs;
|
||||
|
||||
|
||||
struct lpt_softc {
|
||||
struct device sc_dev;
|
||||
struct callout sc_wakeup_ch;
|
||||
struct lpt_funcs *sc_funcs;
|
||||
void *sc_arg;
|
||||
size_t sc_count;
|
||||
struct buf *sc_inbuf;
|
||||
u_char *sc_cp;
|
||||
int sc_spinmax;
|
||||
u_char sc_state;
|
||||
#define LPT_OPEN 0x01 /* device is open */
|
||||
#define LPT_OBUSY 0x02 /* printer is busy doing output */
|
||||
#define LPT_INIT 0x04 /* waiting to initialize for open */
|
||||
u_char sc_flags;
|
||||
#define LPT_FAST_STROBE 0x10 /* Select 1.6uS strobe pulse */
|
||||
#define LPT_AUTOLF 0x20 /* automatic LF on CR */
|
||||
#define LPT_NOPRIME 0x40 /* don't prime on open */
|
||||
#define LPT_NOINTR 0x80 /* do not use interrupt */
|
||||
|
||||
/* Back-end specific stuff */
|
||||
bus_space_tag_t sc_bust;
|
||||
bus_space_handle_t sc_bush;
|
||||
int sc_ipl;
|
||||
u_char sc_icr;
|
||||
u_char sc_laststatus;
|
||||
struct evcnt sc_evcnt;
|
||||
};
|
||||
|
||||
|
||||
struct lpt_funcs {
|
||||
void (*lf_open) __P((struct lpt_softc *, int));
|
||||
void (*lf_close) __P((struct lpt_softc *));
|
||||
void (*lf_iprime) __P((struct lpt_softc *));
|
||||
void (*lf_speed) __P((struct lpt_softc *, int));
|
||||
int (*lf_notrdy) __P((struct lpt_softc *, int));
|
||||
void (*lf_wrdata) __P((struct lpt_softc *, u_char));
|
||||
};
|
||||
|
||||
#define LPT_STROBE_FAST 0
|
||||
#define LPT_STROBE_SLOW 1
|
||||
|
||||
extern void lpt_attach_subr __P((struct lpt_softc *));
|
||||
extern int lpt_intr __P((struct lpt_softc *));
|
||||
|
||||
#endif /* __mvme_lptvar_h */
|
640
sys/dev/mvme/memc.c
Normal file
640
sys/dev/mvme/memc.c
Normal file
@ -0,0 +1,640 @@
|
||||
/* $NetBSD: memc.c,v 1.1 2002/02/12 20:38:46 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford.
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Support for the MEMECC and MEMC40 memory controllers on MVME68K
|
||||
* and MVME88K boards.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/mvme/memcvar.h>
|
||||
#include <dev/mvme/memcreg.h>
|
||||
#include <dev/mvme/pcctwovar.h>
|
||||
#include <dev/mvme/pcctworeg.h>
|
||||
|
||||
#include <dev/vme/vmevar.h>
|
||||
#include <dev/mvme/mvmebus.h>
|
||||
#include <dev/mvme/vme_twovar.h>
|
||||
#include <dev/mvme/vme_tworeg.h>
|
||||
|
||||
|
||||
static struct memc_softc *memc_softcs[MEMC_NDEVS];
|
||||
static int memc_softc_count;
|
||||
|
||||
static void memc040_attach(struct memc_softc *);
|
||||
static void memecc_attach(struct memc_softc *);
|
||||
static void memc_hook_error_intr(struct memc_softc *, int (*)(void *));
|
||||
|
||||
static int memecc_err_intr(void *);
|
||||
static void memecc_log_error(struct memc_softc *, u_int8_t, int, int);
|
||||
|
||||
#define MEMECC_SCRUBBER_PERIOD 86400 /* ~24 hours */
|
||||
|
||||
/*
|
||||
* The following stuff is used to decode the ECC syndrome code so
|
||||
* that we can figure out exactly which address/bit needed to be
|
||||
* corrected.
|
||||
*/
|
||||
#define MEMECC_SYN_BIT_MASK 0x0fu
|
||||
#define MEMECC_SYN_BANK_A (0x00u << 4)
|
||||
#define MEMECC_SYN_BANK_B (0x01u << 4)
|
||||
#define MEMECC_SYN_BANK_C (0x02u << 4)
|
||||
#define MEMECC_SYN_BANK_D (0x03u << 4)
|
||||
#define MEMECC_SYN_BANK_SHIFT 4
|
||||
#define MEMECC_SYN_BANK_MASK 0x03u
|
||||
#define MEMECC_SYN_CHECKBIT_ERR 0x80u
|
||||
#define MEMECC_SYN_INVALID 0xffu
|
||||
|
||||
static u_int8_t memc_syn_decode[256] = {
|
||||
MEMECC_SYN_INVALID, /* 0x00 */
|
||||
MEMECC_SYN_CHECKBIT_ERR | 0, /* 0x01: Checkbit 0 */
|
||||
MEMECC_SYN_CHECKBIT_ERR | 1, /* 0x02: Checkbit 1 */
|
||||
MEMECC_SYN_INVALID, /* 0x03 */
|
||||
MEMECC_SYN_CHECKBIT_ERR | 2, /* 0x04: Checkbit 2 */
|
||||
MEMECC_SYN_INVALID, /* 0x05 */
|
||||
MEMECC_SYN_INVALID, /* 0x06 */
|
||||
MEMECC_SYN_BANK_C | 10, /* 0x07: Bank C 10/26 */
|
||||
MEMECC_SYN_CHECKBIT_ERR | 3, /* 0x08: Checkbit 3 */
|
||||
MEMECC_SYN_INVALID, /* 0x09 */
|
||||
MEMECC_SYN_INVALID, /* 0x0a */
|
||||
MEMECC_SYN_BANK_C | 13, /* 0x0b: Bank C 13/29 */
|
||||
MEMECC_SYN_INVALID, /* 0x0c */
|
||||
MEMECC_SYN_BANK_D | 1, /* 0x0d: Bank D 1/17 */
|
||||
MEMECC_SYN_BANK_D | 2, /* 0x0e: Bank D 2/18 */
|
||||
MEMECC_SYN_INVALID, /* 0x0f */
|
||||
MEMECC_SYN_CHECKBIT_ERR | 4, /* 0x10: Checkbit 4 */
|
||||
MEMECC_SYN_INVALID, /* 0x11 */
|
||||
MEMECC_SYN_INVALID, /* 0x12 */
|
||||
MEMECC_SYN_BANK_C | 14, /* 0x13: Bank C 14/30 */
|
||||
MEMECC_SYN_INVALID, /* 0x14 */
|
||||
MEMECC_SYN_BANK_D | 4, /* 0x15: Bank D 4/20 */
|
||||
MEMECC_SYN_BANK_D | 5, /* 0x16: Bank D 5/21 */
|
||||
MEMECC_SYN_INVALID, /* 0x17 */
|
||||
MEMECC_SYN_INVALID, /* 0x18 */
|
||||
MEMECC_SYN_BANK_D | 8, /* 0x19: Bank D 8/24 */
|
||||
MEMECC_SYN_BANK_D | 9, /* 0x1a: Bank D 9/25 */
|
||||
MEMECC_SYN_INVALID, /* 0x1b */
|
||||
MEMECC_SYN_BANK_D | 10, /* 0x1c: Bank D 10/26 */
|
||||
MEMECC_SYN_INVALID, /* 0x1d */
|
||||
MEMECC_SYN_INVALID, /* 0x1e */
|
||||
MEMECC_SYN_INVALID, /* 0x1f */
|
||||
MEMECC_SYN_CHECKBIT_ERR | 5, /* 0x20: Checkbit 5 */
|
||||
MEMECC_SYN_INVALID, /* 0x21 */
|
||||
MEMECC_SYN_INVALID, /* 0x22 */
|
||||
MEMECC_SYN_BANK_C | 0, /* 0x23: Bank C 0/16 */
|
||||
MEMECC_SYN_INVALID, /* 0x24 */
|
||||
MEMECC_SYN_BANK_D | 7, /* 0x25: Bank D 7/23 */
|
||||
MEMECC_SYN_BANK_D | 6, /* 0x26: Bank D 6/22 */
|
||||
MEMECC_SYN_INVALID, /* 0x27 */
|
||||
MEMECC_SYN_INVALID, /* 0x28 */
|
||||
MEMECC_SYN_BANK_A | 15, /* 0x29: Bank A 15/31 */
|
||||
MEMECC_SYN_BANK_D | 12, /* 0x2a: Bank D 12/28 */
|
||||
MEMECC_SYN_INVALID, /* 0x2b */
|
||||
MEMECC_SYN_BANK_D | 13, /* 0x2c: Bank D 13/29 */
|
||||
MEMECC_SYN_INVALID, /* 0x2d */
|
||||
MEMECC_SYN_INVALID, /* 0x2e */
|
||||
MEMECC_SYN_INVALID, /* 0x2f */
|
||||
MEMECC_SYN_INVALID, /* 0x30 */
|
||||
MEMECC_SYN_BANK_A | 14, /* 0x31: Bank A 14/30 */
|
||||
MEMECC_SYN_BANK_A | 0, /* 0x32: Bank A 0/16 */
|
||||
MEMECC_SYN_INVALID, /* 0x33 */
|
||||
MEMECC_SYN_BANK_A | 1, /* 0x34: Bank A 1/17 */
|
||||
MEMECC_SYN_INVALID, /* 0x35 */
|
||||
MEMECC_SYN_INVALID, /* 0x36 */
|
||||
MEMECC_SYN_INVALID, /* 0x37 */
|
||||
MEMECC_SYN_BANK_A | 2, /* 0x38: Bank A 2/18 */
|
||||
MEMECC_SYN_INVALID, /* 0x39 */
|
||||
MEMECC_SYN_INVALID, /* 0x3a */
|
||||
MEMECC_SYN_INVALID, /* 0x3b */
|
||||
MEMECC_SYN_INVALID, /* 0x3c */
|
||||
MEMECC_SYN_BANK_C | 3, /* 0x3d: Bank C 3/19 */
|
||||
MEMECC_SYN_INVALID, /* 0x3e */
|
||||
MEMECC_SYN_INVALID, /* 0x3f */
|
||||
MEMECC_SYN_CHECKBIT_ERR | 6, /* 0x40: Checkbit 6 */
|
||||
MEMECC_SYN_INVALID, /* 0x41 */
|
||||
MEMECC_SYN_INVALID, /* 0x42 */
|
||||
MEMECC_SYN_BANK_C | 1, /* 0x43: Bank C 1/17 */
|
||||
MEMECC_SYN_INVALID, /* 0x44 */
|
||||
MEMECC_SYN_BANK_C | 4, /* 0x45: Bank C 4/20 */
|
||||
MEMECC_SYN_BANK_C | 8, /* 0x46: Bank C 8/24 */
|
||||
MEMECC_SYN_INVALID, /* 0x47 */
|
||||
MEMECC_SYN_INVALID, /* 0x48 */
|
||||
MEMECC_SYN_BANK_C | 7, /* 0x49: Bank C 7/23 */
|
||||
MEMECC_SYN_BANK_D | 15, /* 0x4a: Bank D 15/31 */
|
||||
MEMECC_SYN_INVALID, /* 0x4b */
|
||||
MEMECC_SYN_BANK_D | 14, /* 0x4c: Bank D 14/30 */
|
||||
MEMECC_SYN_INVALID, /* 0x4d */
|
||||
MEMECC_SYN_INVALID, /* 0x4e */
|
||||
MEMECC_SYN_BANK_B | 3, /* 0x4f: Bank B 3/19 */
|
||||
MEMECC_SYN_INVALID, /* 0x50 */
|
||||
MEMECC_SYN_BANK_B | 4, /* 0x51: Bank B 4/20 */
|
||||
MEMECC_SYN_BANK_B | 7, /* 0x52: Bank B 7/23 */
|
||||
MEMECC_SYN_INVALID, /* 0x53 */
|
||||
MEMECC_SYN_BANK_A | 4, /* 0x54: Bank A 4/20 */
|
||||
MEMECC_SYN_INVALID, /* 0x55 */
|
||||
MEMECC_SYN_INVALID, /* 0x56 */
|
||||
MEMECC_SYN_INVALID, /* 0x57 */
|
||||
MEMECC_SYN_BANK_A | 5, /* 0x58: Bank A 5/21 */
|
||||
MEMECC_SYN_INVALID, /* 0x59 */
|
||||
MEMECC_SYN_INVALID, /* 0x5a */
|
||||
MEMECC_SYN_INVALID, /* 0x5b */
|
||||
MEMECC_SYN_INVALID, /* 0x5c */
|
||||
MEMECC_SYN_INVALID, /* 0x5d */
|
||||
MEMECC_SYN_INVALID, /* 0x5e */
|
||||
MEMECC_SYN_INVALID, /* 0x5f */
|
||||
MEMECC_SYN_INVALID, /* 0x60 */
|
||||
MEMECC_SYN_BANK_B | 5, /* 0x61: Bank B 5/21 */
|
||||
MEMECC_SYN_BANK_B | 6, /* 0x62: Bank B 6/22 */
|
||||
MEMECC_SYN_INVALID, /* 0x63 */
|
||||
MEMECC_SYN_BANK_A | 8, /* 0x64: Bank A 8/24 */
|
||||
MEMECC_SYN_INVALID, /* 0x65 */
|
||||
MEMECC_SYN_INVALID, /* 0x66 */
|
||||
MEMECC_SYN_INVALID, /* 0x67 */
|
||||
MEMECC_SYN_BANK_A | 9, /* 0x68: Bank A 9/25 */
|
||||
MEMECC_SYN_INVALID, /* 0x69 */
|
||||
MEMECC_SYN_INVALID, /* 0x6a */
|
||||
MEMECC_SYN_INVALID, /* 0x6b */
|
||||
MEMECC_SYN_INVALID, /* 0x6c */
|
||||
MEMECC_SYN_INVALID, /* 0x6d */
|
||||
MEMECC_SYN_INVALID, /* 0x6e */
|
||||
MEMECC_SYN_INVALID, /* 0x6f */
|
||||
MEMECC_SYN_BANK_A | 10, /* 0x70: Bank A 10/26 */
|
||||
MEMECC_SYN_INVALID, /* 0x71 */
|
||||
MEMECC_SYN_INVALID, /* 0x72 */
|
||||
MEMECC_SYN_INVALID, /* 0x73 */
|
||||
MEMECC_SYN_INVALID, /* 0x74 */
|
||||
MEMECC_SYN_INVALID, /* 0x75 */
|
||||
MEMECC_SYN_INVALID, /* 0x76 */
|
||||
MEMECC_SYN_INVALID, /* 0x77 */
|
||||
MEMECC_SYN_INVALID, /* 0x78 */
|
||||
MEMECC_SYN_INVALID, /* 0x79 */
|
||||
MEMECC_SYN_BANK_C | 11, /* 0x7a: Bank C 11/27 */
|
||||
MEMECC_SYN_INVALID, /* 0x7b */
|
||||
MEMECC_SYN_INVALID, /* 0x7c */
|
||||
MEMECC_SYN_INVALID, /* 0x7d */
|
||||
MEMECC_SYN_INVALID, /* 0x7e */
|
||||
MEMECC_SYN_INVALID, /* 0x7f */
|
||||
MEMECC_SYN_CHECKBIT_ERR | 7, /* 0x80: Checkbit 7 */
|
||||
MEMECC_SYN_INVALID, /* 0x81 */
|
||||
MEMECC_SYN_INVALID, /* 0x82 */
|
||||
MEMECC_SYN_BANK_C | 2, /* 0x83: Bank C 2/18 */
|
||||
MEMECC_SYN_INVALID, /* 0x84 */
|
||||
MEMECC_SYN_BANK_C | 5, /* 0x85: Bank C 5/21 */
|
||||
MEMECC_SYN_BANK_C | 9, /* 0x86: Bank C 9/25 */
|
||||
MEMECC_SYN_INVALID, /* 0x87 */
|
||||
MEMECC_SYN_INVALID, /* 0x88 */
|
||||
MEMECC_SYN_BANK_C | 6, /* 0x89: Bank C 6/22 */
|
||||
MEMECC_SYN_BANK_C | 12, /* 0x8a: Bank C 12/28 */
|
||||
MEMECC_SYN_INVALID, /* 0x8b */
|
||||
MEMECC_SYN_BANK_D | 0, /* 0x8c: Bank D 0/16 */
|
||||
MEMECC_SYN_INVALID, /* 0x8d */
|
||||
MEMECC_SYN_INVALID, /* 0x8e */
|
||||
MEMECC_SYN_INVALID, /* 0x8f */
|
||||
MEMECC_SYN_INVALID, /* 0x90 */
|
||||
MEMECC_SYN_BANK_B | 8, /* 0x91: Bank B 8/24 */
|
||||
MEMECC_SYN_BANK_C | 15, /* 0x92: Bank C 15/31 */
|
||||
MEMECC_SYN_INVALID, /* 0x93 */
|
||||
MEMECC_SYN_BANK_A | 7, /* 0x94: Bank A 7/23 */
|
||||
MEMECC_SYN_INVALID, /* 0x95 */
|
||||
MEMECC_SYN_INVALID, /* 0x96 */
|
||||
MEMECC_SYN_INVALID, /* 0x97 */
|
||||
MEMECC_SYN_BANK_A | 6, /* 0x98: Bank A 6/22 */
|
||||
MEMECC_SYN_INVALID, /* 0x99 */
|
||||
MEMECC_SYN_INVALID, /* 0x9a */
|
||||
MEMECC_SYN_INVALID, /* 0x9b */
|
||||
MEMECC_SYN_INVALID, /* 0x9c */
|
||||
MEMECC_SYN_INVALID, /* 0x9d */
|
||||
MEMECC_SYN_BANK_B | 11, /* 0x9e: Bank B 11/27 */
|
||||
MEMECC_SYN_INVALID, /* 0x9f */
|
||||
MEMECC_SYN_INVALID, /* 0xa0 */
|
||||
MEMECC_SYN_BANK_B | 9, /* 0xa1: Bank B 9/25 */
|
||||
MEMECC_SYN_BANK_B | 12, /* 0xa2: Bank B 12/28 */
|
||||
MEMECC_SYN_INVALID, /* 0xa3 */
|
||||
MEMECC_SYN_BANK_B | 15, /* 0xa4: Bank B 15/31 */
|
||||
MEMECC_SYN_INVALID, /* 0xa5 */
|
||||
MEMECC_SYN_INVALID, /* 0xa6 */
|
||||
MEMECC_SYN_BANK_A | 11, /* 0xa7: Bank A 11/27 */
|
||||
MEMECC_SYN_BANK_A | 12, /* 0xa8: Bank A 12/28 */
|
||||
MEMECC_SYN_INVALID, /* 0xa9 */
|
||||
MEMECC_SYN_INVALID, /* 0xaa */
|
||||
MEMECC_SYN_INVALID, /* 0xab */
|
||||
MEMECC_SYN_INVALID, /* 0xac */
|
||||
MEMECC_SYN_INVALID, /* 0xad */
|
||||
MEMECC_SYN_INVALID, /* 0xae */
|
||||
MEMECC_SYN_INVALID, /* 0xaf */
|
||||
MEMECC_SYN_BANK_A | 13, /* 0xb0: Bank A 13/29 */
|
||||
MEMECC_SYN_INVALID, /* 0xb1 */
|
||||
MEMECC_SYN_INVALID, /* 0xb2 */
|
||||
MEMECC_SYN_INVALID, /* 0xb3 */
|
||||
MEMECC_SYN_INVALID, /* 0xb4 */
|
||||
MEMECC_SYN_INVALID, /* 0xb5 */
|
||||
MEMECC_SYN_INVALID, /* 0xb6 */
|
||||
MEMECC_SYN_INVALID, /* 0xb7 */
|
||||
MEMECC_SYN_INVALID, /* 0xb8 */
|
||||
MEMECC_SYN_INVALID, /* 0xb9 */
|
||||
MEMECC_SYN_INVALID, /* 0xba */
|
||||
MEMECC_SYN_INVALID, /* 0xbb */
|
||||
MEMECC_SYN_INVALID, /* 0xbc */
|
||||
MEMECC_SYN_INVALID, /* 0xbd */
|
||||
MEMECC_SYN_INVALID, /* 0xbe */
|
||||
MEMECC_SYN_INVALID, /* 0xbf */
|
||||
MEMECC_SYN_INVALID, /* 0xc0 */
|
||||
MEMECC_SYN_BANK_B | 10, /* 0xc1: Bank B 10/26 */
|
||||
MEMECC_SYN_BANK_B | 13, /* 0xc2: Bank B 13/29 */
|
||||
MEMECC_SYN_INVALID, /* 0xc3 */
|
||||
MEMECC_SYN_BANK_B | 14, /* 0xc4: Bank B 14/30 */
|
||||
MEMECC_SYN_INVALID, /* 0xc5 */
|
||||
MEMECC_SYN_INVALID, /* 0xc6 */
|
||||
MEMECC_SYN_INVALID, /* 0xc7 */
|
||||
MEMECC_SYN_BANK_B | 0, /* 0xc8: Bank B 0/16 */
|
||||
MEMECC_SYN_INVALID, /* 0xc9 */
|
||||
MEMECC_SYN_INVALID, /* 0xca */
|
||||
MEMECC_SYN_INVALID, /* 0xcb */
|
||||
MEMECC_SYN_INVALID, /* 0xcc */
|
||||
MEMECC_SYN_INVALID, /* 0xcd */
|
||||
MEMECC_SYN_INVALID, /* 0xce */
|
||||
MEMECC_SYN_INVALID, /* 0xcf */
|
||||
MEMECC_SYN_BANK_B | 1, /* 0xd0: Bank B 1/17 */
|
||||
MEMECC_SYN_INVALID, /* 0xd1 */
|
||||
MEMECC_SYN_INVALID, /* 0xd2 */
|
||||
MEMECC_SYN_BANK_A | 3, /* 0xd3: Bank A 3/19 */
|
||||
MEMECC_SYN_INVALID, /* 0xd4 */
|
||||
MEMECC_SYN_INVALID, /* 0xd5 */
|
||||
MEMECC_SYN_INVALID, /* 0xd6 */
|
||||
MEMECC_SYN_INVALID, /* 0xd7 */
|
||||
MEMECC_SYN_INVALID, /* 0xd8 */
|
||||
MEMECC_SYN_INVALID, /* 0xd9 */
|
||||
MEMECC_SYN_INVALID, /* 0xda */
|
||||
MEMECC_SYN_INVALID, /* 0xdb */
|
||||
MEMECC_SYN_INVALID, /* 0xdc */
|
||||
MEMECC_SYN_INVALID, /* 0xdd */
|
||||
MEMECC_SYN_INVALID, /* 0xde */
|
||||
MEMECC_SYN_INVALID, /* 0xdf */
|
||||
MEMECC_SYN_BANK_B | 2, /* 0xe0: Bank B 2/18 */
|
||||
MEMECC_SYN_INVALID, /* 0xe1 */
|
||||
MEMECC_SYN_INVALID, /* 0xe2 */
|
||||
MEMECC_SYN_INVALID, /* 0xe3 */
|
||||
MEMECC_SYN_INVALID, /* 0xe4 */
|
||||
MEMECC_SYN_INVALID, /* 0xe5 */
|
||||
MEMECC_SYN_INVALID, /* 0xe6 */
|
||||
MEMECC_SYN_INVALID, /* 0xe7 */
|
||||
MEMECC_SYN_INVALID, /* 0xe8 */
|
||||
MEMECC_SYN_BANK_D | 11, /* 0xe9: Bank D 11/27 */
|
||||
MEMECC_SYN_INVALID, /* 0xea */
|
||||
MEMECC_SYN_INVALID, /* 0xeb */
|
||||
MEMECC_SYN_INVALID, /* 0xec */
|
||||
MEMECC_SYN_INVALID, /* 0xed */
|
||||
MEMECC_SYN_INVALID, /* 0xee */
|
||||
MEMECC_SYN_INVALID, /* 0xef */
|
||||
MEMECC_SYN_INVALID, /* 0xf0 */
|
||||
MEMECC_SYN_INVALID, /* 0xf1 */
|
||||
MEMECC_SYN_INVALID, /* 0xf2 */
|
||||
MEMECC_SYN_INVALID, /* 0xf3 */
|
||||
MEMECC_SYN_BANK_D | 3, /* 0xf4: Bank D 3/19 */
|
||||
MEMECC_SYN_INVALID, /* 0xf5 */
|
||||
MEMECC_SYN_INVALID, /* 0xf6 */
|
||||
MEMECC_SYN_INVALID, /* 0xf7 */
|
||||
MEMECC_SYN_INVALID, /* 0xf8 */
|
||||
MEMECC_SYN_INVALID, /* 0xf9 */
|
||||
MEMECC_SYN_INVALID, /* 0xfa */
|
||||
MEMECC_SYN_INVALID, /* 0xfb */
|
||||
MEMECC_SYN_INVALID, /* 0xfc */
|
||||
MEMECC_SYN_INVALID, /* 0xfd */
|
||||
MEMECC_SYN_INVALID, /* 0xfe */
|
||||
MEMECC_SYN_INVALID /* 0xff */
|
||||
};
|
||||
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
memc_init(sc)
|
||||
struct memc_softc *sc;
|
||||
{
|
||||
u_int8_t chipid;
|
||||
u_int8_t memcfg;
|
||||
|
||||
if (memc_softc_count == MEMC_NDEVS)
|
||||
panic("memc_attach: too many memc devices!");
|
||||
|
||||
memc_softcs[memc_softc_count++] = sc;
|
||||
|
||||
chipid = memc_reg_read(sc, MEMC_REG_CHIP_ID);
|
||||
memcfg = memc_reg_read(sc, MEMC_REG_MEMORY_CONFIG);
|
||||
|
||||
printf(": %dMB %s Memory Controller Chip (Rev %d)\n",
|
||||
MEMC_MEMORY_CONFIG_2_MB(memcfg),
|
||||
(chipid == MEMC_CHIP_ID_MEMC040) ? "Parity" : "ECC",
|
||||
memc_reg_read(sc, MEMC_REG_CHIP_REVISION));
|
||||
|
||||
printf("%s: Base Address: 0x%x, ", sc->sc_dev.dv_xname,
|
||||
MEMC_BASE_ADDRESS(memc_reg_read(sc, MEMC_REG_BASE_ADDRESS_HI),
|
||||
memc_reg_read(sc, MEMC_REG_BASE_ADDRESS_LO)));
|
||||
|
||||
printf("Fast RAM Read %sabled\n", (memc_reg_read(sc,
|
||||
MEMC_REG_MEMORY_CONFIG) & MEMC_MEMORY_CONFIG_FSTRD) ?
|
||||
"En" : "Dis");
|
||||
|
||||
switch (chipid) {
|
||||
case MEMC_CHIP_ID_MEMC040:
|
||||
memc040_attach(sc);
|
||||
break;
|
||||
case MEMC_CHIP_ID_MEMECC:
|
||||
memecc_attach(sc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
memc040_attach(struct memc_softc *sc)
|
||||
{
|
||||
|
||||
/* XXX: TBD */
|
||||
}
|
||||
|
||||
static void
|
||||
memecc_attach(struct memc_softc *sc)
|
||||
{
|
||||
u_int8_t rv;
|
||||
|
||||
/*
|
||||
* First, disable bus-error and interrupts on ECC errors.
|
||||
* Also switch off SWAIT to enhance performance.
|
||||
*/
|
||||
rv = memc_reg_read(sc, MEMECC_REG_DRAM_CONTROL);
|
||||
rv &= ~(MEMECC_DRAM_CONTROL_NCEBEN |
|
||||
MEMECC_DRAM_CONTROL_NCEIEN |
|
||||
MEMECC_DRAM_CONTROL_SWAIT);
|
||||
rv |= MEMECC_DRAM_CONTROL_RAMEN;
|
||||
memc_reg_write(sc, MEMECC_REG_DRAM_CONTROL, rv);
|
||||
rv = memc_reg_read(sc, MEMECC_REG_SCRUB_CONTROL);
|
||||
rv &= ~(MEMECC_SCRUB_CONTROL_SCRBEN | MEMECC_SCRUB_CONTROL_SBEIEN);
|
||||
memc_reg_write(sc, MEMECC_REG_SCRUB_CONTROL, rv);
|
||||
|
||||
/*
|
||||
* Ensure error correction is enabled
|
||||
*/
|
||||
rv = memc_reg_read(sc, MEMECC_REG_DATA_CONTROL);
|
||||
rv &= ~MEMECC_DATA_CONTROL_DERC;
|
||||
memc_reg_write(sc, MEMECC_REG_DATA_CONTROL, rv);
|
||||
|
||||
/*
|
||||
* Clear any error currently in the logs
|
||||
*/
|
||||
rv = memc_reg_read(sc, MEMECC_REG_ERROR_LOGGER);
|
||||
#ifdef DIAGNOSTIC
|
||||
if ((rv & MEMECC_ERROR_LOGGER_MASK) != 0)
|
||||
memecc_log_error(sc, rv, 0, 0);
|
||||
#endif
|
||||
memc_reg_write(sc, MEMECC_REG_ERROR_LOGGER,
|
||||
MEMECC_ERROR_LOGGER_ERRLOG);
|
||||
|
||||
rv = memc_reg_read(sc, MEMECC_REG_ERROR_LOGGER + 2);
|
||||
#ifdef DIAGNOSTIC
|
||||
if ((rv & MEMECC_ERROR_LOGGER_MASK) != 0)
|
||||
memecc_log_error(sc, rv, 2, 0);
|
||||
#endif
|
||||
memc_reg_write(sc, MEMECC_REG_ERROR_LOGGER + 2,
|
||||
MEMECC_ERROR_LOGGER_ERRLOG);
|
||||
|
||||
/*
|
||||
* Now hook the ECC error interrupt
|
||||
*/
|
||||
if (memc_softc_count == 1)
|
||||
memc_hook_error_intr(sc, memecc_err_intr);
|
||||
|
||||
/*
|
||||
* Enable bus-error and interrupt on uncorrectable ECC
|
||||
*/
|
||||
rv = memc_reg_read(sc, MEMECC_REG_DRAM_CONTROL);
|
||||
rv |= MEMECC_DRAM_CONTROL_NCEBEN | MEMECC_DRAM_CONTROL_NCEIEN;
|
||||
memc_reg_write(sc, MEMECC_REG_DRAM_CONTROL, rv);
|
||||
|
||||
/*
|
||||
* Set up the scrubber to run roughly once every 24 hours
|
||||
* with minimal impact on the local bus. With these on/off
|
||||
* time settings, a scrub of a 32MB DRAM board will take
|
||||
* roughly half a minute.
|
||||
*/
|
||||
memc_reg_write(sc, MEMECC_REG_SCRUB_PERIOD_HI,
|
||||
MEMECC_SCRUB_PERIOD_HI(MEMECC_SCRUBBER_PERIOD));
|
||||
memc_reg_write(sc, MEMECC_REG_SCRUB_PERIOD_LO,
|
||||
MEMECC_SCRUB_PERIOD_LO(MEMECC_SCRUBBER_PERIOD));
|
||||
memc_reg_write(sc, MEMECC_REG_SCRUB_TIME_ONOFF,
|
||||
MEMECC_SCRUB_TIME_ON_1 | MEMECC_SCRUB_TIME_OFF_16);
|
||||
|
||||
/*
|
||||
* Start the scrubber, and enable interrupts on Correctable errors
|
||||
*/
|
||||
memc_reg_write(sc, MEMECC_REG_SCRUB_CONTROL,
|
||||
memc_reg_read(sc, MEMECC_REG_SCRUB_CONTROL) |
|
||||
MEMECC_SCRUB_CONTROL_SCRBEN | MEMECC_SCRUB_CONTROL_SBEIEN);
|
||||
|
||||
printf("%s: Logging ECC errors at ipl %d\n", sc->sc_dev.dv_xname,
|
||||
MEMC_IRQ_LEVEL);
|
||||
}
|
||||
|
||||
static void
|
||||
memc_hook_error_intr(struct memc_softc *sc, int (*func)(void *))
|
||||
{
|
||||
|
||||
#if 0
|
||||
evcnt_attach_dynamic(&sc->sc_evcnt, EVCNT_TYPE_INTR,
|
||||
(*sc->sc_isrevcnt)(sc->sc_isrcookie, MEMC_IRQ_LEVEL),
|
||||
"memory", "ecc errors");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* On boards without a VMEChip2, the interrupt is routed
|
||||
* via the MCChip (mvme162/mvme172).
|
||||
*/
|
||||
if (vmetwo_not_present)
|
||||
pcctwointr_establish(MCCHIPV_PARITY_ERR, func, MEMC_IRQ_LEVEL,
|
||||
sc, &sc->sc_evcnt);
|
||||
else
|
||||
vmetwo_local_intr_establish(MEMC_IRQ_LEVEL,
|
||||
VME2_VEC_PARITY_ERROR, func, sc, &sc->sc_evcnt);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
memecc_err_intr(void *arg)
|
||||
{
|
||||
struct memc_softc *sc;
|
||||
u_int8_t rv;
|
||||
int i, j, cnt = 0;
|
||||
|
||||
/*
|
||||
* For each memory controller we found ...
|
||||
*/
|
||||
for (i = 0; i < memc_softc_count; i++) {
|
||||
sc = memc_softcs[i];
|
||||
|
||||
/*
|
||||
* There are two error loggers per controller, the registers of
|
||||
* the 2nd are offset from the 1st by 2 bytes.
|
||||
*/
|
||||
for (j = 0; j <= 2; j += 2) {
|
||||
rv = memc_reg_read(sc, MEMECC_REG_ERROR_LOGGER + j);
|
||||
if ((rv & MEMECC_ERROR_LOGGER_MASK) != 0) {
|
||||
memecc_log_error(sc, rv, j, 1);
|
||||
memc_reg_write(sc, MEMECC_REG_ERROR_LOGGER + j,
|
||||
MEMECC_ERROR_LOGGER_ERRLOG);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (cnt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Log an ECC error to the console.
|
||||
* Note: Since this usually runs at an elevated ipl (above clock), we
|
||||
* should probably schedule a soft interrupt to log the error details.
|
||||
* (But only for errors where we would not normally panic.)
|
||||
*/
|
||||
static void
|
||||
memecc_log_error(struct memc_softc *sc, u_int8_t errlog, int off, int mbepanic)
|
||||
{
|
||||
u_int32_t addr;
|
||||
u_int8_t rv, syndrome;
|
||||
const char *bm = "CPU";
|
||||
const char *rdwr;
|
||||
const char *etype;
|
||||
char syntext[32];
|
||||
|
||||
/*
|
||||
* Get the address associated with the error.
|
||||
*/
|
||||
rv = memc_reg_read(sc, MEMECC_REG_ERROR_ADDRESS_HIHI + off);
|
||||
addr = (u_int32_t)rv;
|
||||
rv = memc_reg_read(sc, MEMECC_REG_ERROR_ADDRESS_HI + off);
|
||||
addr = (addr << 8) | (u_int32_t)rv;
|
||||
rv = memc_reg_read(sc, MEMECC_REG_ERROR_ADDRESS_MID + off);
|
||||
addr = (addr << 8) | (u_int32_t)rv;
|
||||
rv = memc_reg_read(sc, MEMECC_REG_ERROR_ADDRESS_LO + off);
|
||||
addr = (addr << 8) | (u_int32_t)rv;
|
||||
|
||||
/*
|
||||
* And the Syndrome bits
|
||||
*/
|
||||
syndrome = memc_reg_read(sc, MEMECC_REG_ERROR_SYNDROME + off);
|
||||
|
||||
rdwr = ((errlog & MEMECC_ERROR_LOGGER_ERD) != 0) ? " read" : " write";
|
||||
|
||||
if ((errlog & MEMECC_ERROR_LOGGER_EALT) != 0)
|
||||
bm = "Peripheral Device";
|
||||
else
|
||||
if ((errlog & MEMECC_ERROR_LOGGER_ESCRB) != 0) {
|
||||
bm = "Scrubber";
|
||||
rdwr = "";
|
||||
}
|
||||
|
||||
if ((errlog & MEMECC_ERROR_LOGGER_SBE) != 0) {
|
||||
int syncode, bank, bitnum;
|
||||
|
||||
etype = "Correctable";
|
||||
syncode = memc_syn_decode[syndrome];
|
||||
bitnum = (syncode & MEMECC_SYN_BIT_MASK) + (off ? 16 : 0);
|
||||
bank = (syncode >> MEMECC_SYN_BANK_SHIFT) &MEMECC_SYN_BANK_MASK;
|
||||
|
||||
if (syncode == MEMECC_SYN_INVALID)
|
||||
strcpy(syntext, "Invalid!");
|
||||
else
|
||||
if ((syncode & MEMECC_SYN_CHECKBIT_ERR) != 0)
|
||||
sprintf(syntext, "Checkbit#%d", bitnum);
|
||||
else {
|
||||
addr |= (u_int32_t) (bank << 2);
|
||||
sprintf(syntext, "DRAM Bank %c, Bit#%d",
|
||||
'A' + bank, bitnum);
|
||||
}
|
||||
} else if ((errlog & MEMECC_ERROR_LOGGER_MBE) != 0)
|
||||
etype = "Uncorrectable";
|
||||
else
|
||||
etype = "Spurious";
|
||||
|
||||
printf("%s: %s error on %s%s access to 0x%08x.\n",
|
||||
sc->sc_dev.dv_xname, etype, bm, rdwr, addr);
|
||||
|
||||
if ((errlog & MEMECC_ERROR_LOGGER_SBE) != 0)
|
||||
printf("%s: ECC Syndrome 0x%02x (%s)\n", sc->sc_dev.dv_xname,
|
||||
syndrome, syntext);
|
||||
|
||||
/*
|
||||
* If an uncorrectable error was detected by an alternate
|
||||
* bus master or the scrubber, panic immediately.
|
||||
* We can't rely on the contents of memory at this point.
|
||||
*
|
||||
* Uncorrectable errors detected when the CPU was accessing
|
||||
* DRAM will cause the CPU to take a bus error trap. Depending
|
||||
* on whether the error was in kernel or user mode, the system
|
||||
* with either panic or kill the affected process. Basically,
|
||||
* we don't have to deal with it here.
|
||||
*
|
||||
* XXX: I'm not sure whether it's our responsibility to
|
||||
* perform some dummy writes to the offending address in this
|
||||
* case to re-generate a good ECC. Note that we'd have to write
|
||||
* an entire block of 4 words since we can only narrow down the
|
||||
* faulty address for correctable errors...
|
||||
*/
|
||||
if (mbepanic && (errlog & MEMECC_ERROR_LOGGER_MBE) &&
|
||||
(errlog & (MEMECC_ERROR_LOGGER_ESCRB|MEMECC_ERROR_LOGGER_EALT))) {
|
||||
/*
|
||||
* Ensure we don't get a Bus Error while panicing...
|
||||
*/
|
||||
rv = memc_reg_read(sc, MEMECC_REG_DRAM_CONTROL + off);
|
||||
rv &= ~(MEMECC_DRAM_CONTROL_NCEBEN |
|
||||
MEMECC_DRAM_CONTROL_NCEIEN);
|
||||
memc_reg_write(sc, MEMECC_REG_DRAM_CONTROL + off, rv);
|
||||
rv = memc_reg_read(sc, MEMECC_REG_SCRUB_CONTROL + off);
|
||||
rv &= ~(MEMECC_SCRUB_CONTROL_SBEIEN |
|
||||
MEMECC_SCRUB_CONTROL_SCRBEN);
|
||||
memc_reg_write(sc, MEMECC_REG_SCRUB_CONTROL + off, rv);
|
||||
|
||||
panic("%s: Halting system to preserve data integrity.",
|
||||
sc->sc_dev.dv_xname);
|
||||
}
|
||||
}
|
177
sys/dev/mvme/memcreg.h
Normal file
177
sys/dev/mvme/memcreg.h
Normal file
@ -0,0 +1,177 @@
|
||||
/* $NetBSD: memcreg.h,v 1.1 2002/02/12 20:38:46 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford.
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Register definitions for the MEMECC and MEMC040 devices.
|
||||
*/
|
||||
#ifndef _MVME_MEMCREG_H
|
||||
#define _MVME_MEMCREG_H
|
||||
|
||||
/*
|
||||
* Size, in bytes, of the memory controller's register set
|
||||
* (Actually, the MEMC040's register set is only 0x20 bytes in size, but
|
||||
* we go with the larger of the two).
|
||||
*/
|
||||
#define MEMC_REGSIZE 0x80
|
||||
|
||||
/* Both memory controllers share some registers in common */
|
||||
#define MEMC_REG_CHIP_ID 0x00
|
||||
#define MEMC_CHIP_ID_MEMC040 0x80 /* It's a MEMC040 */
|
||||
#define MEMC_CHIP_ID_MEMECC 0x81 /* It's a MEMECC */
|
||||
|
||||
/* Revision of the ASIC */
|
||||
#define MEMC_REG_CHIP_REVISION 0x04
|
||||
|
||||
/* Configuration of the memory block controlled by this ASIC */
|
||||
#define MEMC_REG_MEMORY_CONFIG 0x08
|
||||
#define MEMC_MEMORY_CONFIG_2_BYTES(x) (0x400000 << ((x) & 0x07))
|
||||
#define MEMC_MEMORY_CONFIG_2_MB(x) (4 << ((x) & 0x07))
|
||||
#define MEMC040_MEMORY_CONFIG_EXTPEN (1u << 3) /* External parity enabled */
|
||||
#define MEMC040_MEMORY_CONFIG_WPB (1u << 4) /* Write Per Bit mode */
|
||||
#define MEMC_MEMORY_CONFIG_FSTRD (1u << 5) /* Fast RAM Read enabled */
|
||||
|
||||
/* Where, in the cpu's address space, does this memory appear? */
|
||||
#define MEMC_REG_BASE_ADDRESS_HI 0x14
|
||||
#define MEMC_REG_BASE_ADDRESS_LO 0x18
|
||||
#define MEMC_BASE_ADDRESS(hi,lo) (((hi) << 24) | (((lo) & 0xc0) << 22))
|
||||
|
||||
/* Tells the memory controller what the board's Bus Clock frequency is */
|
||||
#define MEMC_REG_BUS_CLOCK 0x1c
|
||||
|
||||
|
||||
/* Register offsets and definitions for the Parity Memory Controller */
|
||||
#define MEMC040_REG_ALT_STATUS 0x0c /* Not used */
|
||||
#define MEMC040_REG_ALT_CONTROL 0x10 /* Not used */
|
||||
|
||||
/* Memory Control Register */
|
||||
#define MEMC040_REG_RAM_CONTROL 0x18
|
||||
#define MEMC040_RAM_CONTROL_RAMEN (1u << 0)
|
||||
#define MEMC040_RAM_CONTROL_PAREN (1u << 1)
|
||||
#define MEMC040_RAM_CONTROL_PARINT (1u << 2)
|
||||
#define MEMC040_RAM_CONTROL_WWP (1u << 3)
|
||||
#define MEMC040_RAM_CONTROL_SWAIT (1u << 4)
|
||||
#define MEMC040_RAM_CONTROL_DMCTL (1u << 5)
|
||||
|
||||
|
||||
/* Register offsets and definitions for the ECC Memory Controller */
|
||||
#define MEMECC_REG_DRAM_CONTROL 0x18
|
||||
#define MEMECC_DRAM_CONTROL_RAMEN (1u << 0)
|
||||
#define MEMECC_DRAM_CONTROL_NCEBEN (1u << 1)
|
||||
#define MEMECC_DRAM_CONTROL_NCEIEN (1u << 2)
|
||||
#define MEMECC_DRAM_CONTROL_RWB3 (1u << 3)
|
||||
#define MEMECC_DRAM_CONTROL_SWAIT (1u << 4)
|
||||
#define MEMECC_DRAM_CONTROL_RWB5 (1u << 5)
|
||||
#define MEMECC_DRAM_CONTROL_BAD22 (1u << 6)
|
||||
#define MEMECC_DRAM_CONTROL_BAD23 (1u << 7)
|
||||
|
||||
#define MEMECC_REG_DATA_CONTROL 0x20
|
||||
#define MEMECC_DATA_CONTROL_RWCKB (1u << 3)
|
||||
#define MEMECC_DATA_CONTROL_ZFILL (1u << 4)
|
||||
#define MEMECC_DATA_CONTROL_DERC (1u << 5)
|
||||
|
||||
#define MEMECC_REG_SCRUB_CONTROL 0x24
|
||||
#define MEMECC_SCRUB_CONTROL_IDIS (1u << 0)
|
||||
#define MEMECC_SCRUB_CONTROL_SBEIEN (1u << 1)
|
||||
#define MEMECC_SCRUB_CONTROL_SCRBEN (1u << 3)
|
||||
#define MEMECC_SCRUB_CONTROL_SCRB (1u << 4)
|
||||
#define MEMECC_SCRUB_CONTROL_HITDIS (1u << 5)
|
||||
#define MEMECC_SCRUB_CONTROL_RADATA (1u << 6)
|
||||
#define MEMECC_SCRUB_CONTROL_RACODE (1u << 7)
|
||||
|
||||
#define MEMECC_REG_SCRUB_PERIOD_HI 0x28
|
||||
#define MEMECC_SCRUB_PERIOD_HI(secs) (((secs) / 2) >> 8)
|
||||
#define MEMECC_REG_SCRUB_PERIOD_LO 0x2c
|
||||
#define MEMECC_SCRUB_PERIOD_LO(secs) (((secs) / 2) & 0xffu)
|
||||
|
||||
#define MEMECC_REG_CHIP_PRESCALE 0x30
|
||||
|
||||
#define MEMECC_REG_SCRUB_TIME_ONOFF 0x34
|
||||
#define MEMECC_SCRUB_TIME_ONOFF_MASK 0x07u
|
||||
#define MEMECC_SCRUB_TIME_OFF_0 0u
|
||||
#define MEMECC_SCRUB_TIME_OFF_16 1u
|
||||
#define MEMECC_SCRUB_TIME_OFF_32 2u
|
||||
#define MEMECC_SCRUB_TIME_OFF_64 3u
|
||||
#define MEMECC_SCRUB_TIME_OFF_128 4u
|
||||
#define MEMECC_SCRUB_TIME_OFF_256 5u
|
||||
#define MEMECC_SCRUB_TIME_OFF_512 6u
|
||||
#define MEMECC_SCRUB_TIME_OFF_NEVER 7u
|
||||
#define MEMECC_SCRUB_TIME_ON_1 (0u << 3)
|
||||
#define MEMECC_SCRUB_TIME_ON_16 (1u << 3)
|
||||
#define MEMECC_SCRUB_TIME_ON_32 (2u << 3)
|
||||
#define MEMECC_SCRUB_TIME_ON_64 (3u << 3)
|
||||
#define MEMECC_SCRUB_TIME_ON_128 (4u << 3)
|
||||
#define MEMECC_SCRUB_TIME_ON_256 (5u << 3)
|
||||
#define MEMECC_SCRUB_TIME_ON_512 (6u << 3)
|
||||
#define MEMECC_SCRUB_TIME_ON_ALWAYS (7u << 3)
|
||||
#define MEMECC_SCRUB_TIME_SRDIS (1u << 7)
|
||||
|
||||
#define MEMECC_REG_SCRUB_PRESCALE_HI 0x38
|
||||
#define MEMECC_REG_SCRUB_PRESCALE_MID 0x3c
|
||||
#define MEMECC_REG_SCRUB_PRESCALE_LO 0x40
|
||||
|
||||
#define MEMECC_REG_SCRUB_TIMER_HI 0x44
|
||||
#define MEMECC_REG_SCRUB_TIMER_LO 0x48
|
||||
|
||||
#define MEMECC_REG_SCRUB_ADDR_CNTR_HIHI 0x4c
|
||||
#define MEMECC_REG_SCRUB_ADDR_CNTR_HI 0x50
|
||||
#define MEMECC_REG_SCRUB_ADDR_CNTR_MID 0x54
|
||||
#define MEMECC_REG_SCRUB_ADDR_CNTR_LO 0x58
|
||||
|
||||
#define MEMECC_REG_ERROR_LOGGER 0x5c
|
||||
#define MEMECC_ERROR_LOGGER_MASK 0x7fu
|
||||
#define MEMECC_ERROR_LOGGER_SBE (1u << 0)
|
||||
#define MEMECC_ERROR_LOGGER_MBE (1u << 1)
|
||||
#define MEMECC_ERROR_LOGGER_EALT (1u << 3)
|
||||
#define MEMECC_ERROR_LOGGER_ERA (1u << 4)
|
||||
#define MEMECC_ERROR_LOGGER_ESCRB (1u << 5)
|
||||
#define MEMECC_ERROR_LOGGER_ERD (1u << 6)
|
||||
#define MEMECC_ERROR_LOGGER_ERRLOG (1u << 7)
|
||||
|
||||
#define MEMECC_REG_ERROR_ADDRESS_HIHI 0x60
|
||||
#define MEMECC_REG_ERROR_ADDRESS_HI 0x64
|
||||
#define MEMECC_REG_ERROR_ADDRESS_MID 0x68
|
||||
#define MEMECC_REG_ERROR_ADDRESS_LO 0x6c
|
||||
|
||||
#define MEMECC_REG_ERROR_SYNDROME 0x70
|
||||
|
||||
#define MEMECC_REG_DEFAULTS1 0x74
|
||||
#define MEMECC_REG_DEFAULTS2 0x78
|
||||
|
||||
#define MEMECC_REG_SDRAM_CONFIG 0x7c
|
||||
|
||||
#endif /* _MVME_MEMCREG_H */
|
69
sys/dev/mvme/memcvar.h
Normal file
69
sys/dev/mvme/memcvar.h
Normal file
@ -0,0 +1,69 @@
|
||||
/* $NetBSD: memcvar.h,v 1.1 2002/02/12 20:38:46 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford.
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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.
|
||||
*/
|
||||
|
||||
#ifndef _MVME_MEMCVAR_H
|
||||
#define _MVME_MEMCVAR_H
|
||||
|
||||
struct memc_softc {
|
||||
struct device sc_dev;
|
||||
bus_space_tag_t sc_bust;
|
||||
bus_space_handle_t sc_bush;
|
||||
struct evcnt sc_evcnt;
|
||||
};
|
||||
|
||||
#define MEMC_NDEVS 2
|
||||
|
||||
#define memc_reg_read(sc, off) \
|
||||
bus_space_read_1((sc)->sc_bust, (sc)->sc_bush, (off))
|
||||
#define memc_reg_write(sc, off, v) \
|
||||
bus_space_write_1((sc)->sc_bust, (sc)->sc_bush, (off), (v))
|
||||
|
||||
/*
|
||||
* Some tweakable parameters. Mind you, I don't recommend changing
|
||||
* the ipl...
|
||||
* XXX: This should probably be ipl 7
|
||||
*/
|
||||
#ifdef MVME68K
|
||||
#define MEMC_IRQ_LEVEL 6
|
||||
#else
|
||||
#error Define irq level for memory contoller
|
||||
#endif
|
||||
|
||||
extern void memc_init(struct memc_softc *);
|
||||
|
||||
#endif /* _MVME_MEMCREG_H */
|
961
sys/dev/mvme/mvmebus.c
Normal file
961
sys/dev/mvme/mvmebus.c
Normal file
@ -0,0 +1,961 @@
|
||||
/* $NetBSD: mvmebus.c,v 1.1 2002/02/12 20:38:47 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford.
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kcore.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/vme/vmereg.h>
|
||||
#include <dev/vme/vmevar.h>
|
||||
|
||||
#include <dev/mvme/mvmebus.h>
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
int mvmebus_dummy_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
|
||||
bus_size_t, int, bus_dmamap_t *);
|
||||
void mvmebus_dummy_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
|
||||
int mvmebus_dummy_dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t,
|
||||
bus_size_t, bus_dma_segment_t *, int, int *, int);
|
||||
void mvmebus_dummy_dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char *mvmebus_mod_string(vme_addr_t, vme_size_t,
|
||||
vme_am_t, vme_datasize_t);
|
||||
#endif
|
||||
|
||||
static void mvmebus_offboard_ram(struct mvmebus_softc *);
|
||||
static int mvmebus_dmamap_load_common(struct mvmebus_softc *, bus_dmamap_t);
|
||||
|
||||
vme_am_t _mvmebus_am_cap[] = {
|
||||
MVMEBUS_AM_CAP_BLKD64 | MVMEBUS_AM_CAP_USER,
|
||||
MVMEBUS_AM_CAP_DATA | MVMEBUS_AM_CAP_USER,
|
||||
MVMEBUS_AM_CAP_PROG | MVMEBUS_AM_CAP_USER,
|
||||
MVMEBUS_AM_CAP_BLK | MVMEBUS_AM_CAP_USER,
|
||||
MVMEBUS_AM_CAP_BLKD64 | MVMEBUS_AM_CAP_SUPER,
|
||||
MVMEBUS_AM_CAP_DATA | MVMEBUS_AM_CAP_SUPER,
|
||||
MVMEBUS_AM_CAP_PROG | MVMEBUS_AM_CAP_SUPER,
|
||||
MVMEBUS_AM_CAP_BLK | MVMEBUS_AM_CAP_SUPER
|
||||
};
|
||||
|
||||
const char *mvmebus_irq_name[] = {
|
||||
"vmeirq0", "vmeirq1", "vmeirq2", "vmeirq3",
|
||||
"vmeirq4", "vmeirq5", "vmeirq6", "vmeirq7"
|
||||
};
|
||||
|
||||
extern phys_ram_seg_t mem_clusters[0];
|
||||
extern int mem_cluster_cnt;
|
||||
|
||||
|
||||
static void
|
||||
mvmebus_offboard_ram(sc)
|
||||
struct mvmebus_softc *sc;
|
||||
{
|
||||
struct mvmebus_range *svr, *mvr;
|
||||
vme_addr_t start, end, size;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* If we have any offboard RAM (i.e. a VMEbus RAM board) then
|
||||
* we need to record its details since it's effectively another
|
||||
* VMEbus slave image as far as we're concerned.
|
||||
* The chip-specific backend will have reserved sc->sc_slaves[0]
|
||||
* for exactly this purpose.
|
||||
*/
|
||||
svr = sc->sc_slaves;
|
||||
if (mem_cluster_cnt < 2) {
|
||||
svr->vr_am = MVMEBUS_AM_DISABLED;
|
||||
return;
|
||||
}
|
||||
|
||||
start = mem_clusters[1].start;
|
||||
size = mem_clusters[1].size - 1;
|
||||
end = start + size;
|
||||
|
||||
/*
|
||||
* Figure out which VMEbus master image the RAM is
|
||||
* visible through. This will tell us the address
|
||||
* modifier and datasizes it uses, as well as allowing
|
||||
* us to calculate its `real' VMEbus address.
|
||||
*
|
||||
* XXX FIXME: This is broken if the RAM is mapped through
|
||||
* a translated address space. For example, on mvme167 it's
|
||||
* perfectly legal to set up the following A32 mapping:
|
||||
*
|
||||
* vr_locaddr == 0x80000000
|
||||
* vr_vmestart == 0x10000000
|
||||
* vr_vmeend == 0x10ffffff
|
||||
*
|
||||
* In this case, RAM at VMEbus address 0x10800000 will appear at local
|
||||
* address 0x80800000, but we need to set the slave vr_vmestart to
|
||||
* 0x10800000.
|
||||
*/
|
||||
for (i = 0, mvr = sc->sc_masters; i < sc->sc_nmasters; i++, mvr++) {
|
||||
vme_addr_t vstart = mvr->vr_locstart + mvr->vr_vmestart;
|
||||
|
||||
if (start >= vstart &&
|
||||
end <= vstart + (mvr->vr_vmeend - mvr->vr_vmestart))
|
||||
break;
|
||||
}
|
||||
if (i == sc->sc_nmasters) {
|
||||
svr->vr_am = MVMEBUS_AM_DISABLED;
|
||||
#ifdef DEBUG
|
||||
printf("%s: No VMEbus master mapping for offboard RAM!\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
svr->vr_locstart = start;
|
||||
svr->vr_vmestart = start & mvr->vr_mask;
|
||||
svr->vr_vmeend = svr->vr_vmestart + size;
|
||||
svr->vr_datasize = mvr->vr_datasize;
|
||||
svr->vr_mask = mvr->vr_mask;
|
||||
svr->vr_am = mvr->vr_am & VME_AM_ADRSIZEMASK;
|
||||
svr->vr_am |= MVMEBUS_AM_CAP_DATA | MVMEBUS_AM_CAP_PROG |
|
||||
MVMEBUS_AM_CAP_SUPER | MVMEBUS_AM_CAP_USER;
|
||||
}
|
||||
|
||||
void
|
||||
mvmebus_attach(sc)
|
||||
struct mvmebus_softc *sc;
|
||||
{
|
||||
struct vmebus_attach_args vaa;
|
||||
int i;
|
||||
|
||||
/* Zap the IRQ reference counts */
|
||||
for (i = 0; i < 8; i++)
|
||||
sc->sc_irqref[i] = 0;
|
||||
|
||||
/* If there's offboard RAM, get its VMEbus slave attributes */
|
||||
mvmebus_offboard_ram(sc);
|
||||
|
||||
#ifdef DEBUG
|
||||
for (i = 0; i < sc->sc_nmasters; i++) {
|
||||
struct mvmebus_range *vr = &sc->sc_masters[i];
|
||||
if (vr->vr_am == MVMEBUS_AM_DISABLED) {
|
||||
printf("%s: Master#%d: disabled\n",
|
||||
sc->sc_dev.dv_xname, i);
|
||||
continue;
|
||||
}
|
||||
printf("%s: Master#%d: 0x%08lx -> %s\n",
|
||||
sc->sc_dev.dv_xname, i,
|
||||
vr->vr_locstart + (vr->vr_vmestart & vr->vr_mask),
|
||||
mvmebus_mod_string(vr->vr_vmestart,
|
||||
(vr->vr_vmeend - vr->vr_vmestart) + 1,
|
||||
vr->vr_am, vr->vr_datasize));
|
||||
}
|
||||
|
||||
for (i = 0; i < sc->sc_nslaves; i++) {
|
||||
struct mvmebus_range *vr = &sc->sc_slaves[i];
|
||||
if (vr->vr_am == MVMEBUS_AM_DISABLED) {
|
||||
printf("%s: Slave#%d: disabled\n",
|
||||
sc->sc_dev.dv_xname, i);
|
||||
continue;
|
||||
}
|
||||
printf("%s: Slave#%d: 0x%08lx -> %s\n",
|
||||
sc->sc_dev.dv_xname, i, vr->vr_locstart,
|
||||
mvmebus_mod_string(vr->vr_vmestart,
|
||||
(vr->vr_vmeend - vr->vr_vmestart) + 1,
|
||||
vr->vr_am, vr->vr_datasize));
|
||||
}
|
||||
#endif
|
||||
|
||||
sc->sc_vct.cookie = sc;
|
||||
sc->sc_vct.vct_probe = mvmebus_probe;
|
||||
sc->sc_vct.vct_map = mvmebus_map;
|
||||
sc->sc_vct.vct_unmap = mvmebus_unmap;
|
||||
sc->sc_vct.vct_int_map = mvmebus_intmap;
|
||||
sc->sc_vct.vct_int_evcnt = mvmebus_intr_evcnt;
|
||||
sc->sc_vct.vct_int_establish = mvmebus_intr_establish;
|
||||
sc->sc_vct.vct_int_disestablish = mvmebus_intr_disestablish;
|
||||
sc->sc_vct.vct_dmamap_create = mvmebus_dmamap_create;
|
||||
sc->sc_vct.vct_dmamap_destroy = mvmebus_dmamap_destroy;
|
||||
sc->sc_vct.vct_dmamem_alloc = mvmebus_dmamem_alloc;
|
||||
sc->sc_vct.vct_dmamem_free = mvmebus_dmamem_free;
|
||||
|
||||
sc->sc_mvmedmat._cookie = sc;
|
||||
sc->sc_mvmedmat._dmamap_load = mvmebus_dmamap_load;
|
||||
sc->sc_mvmedmat._dmamap_load_mbuf = mvmebus_dmamap_load_mbuf;
|
||||
sc->sc_mvmedmat._dmamap_load_uio = mvmebus_dmamap_load_uio;
|
||||
sc->sc_mvmedmat._dmamap_load_raw = mvmebus_dmamap_load_raw;
|
||||
sc->sc_mvmedmat._dmamap_unload = mvmebus_dmamap_unload;
|
||||
sc->sc_mvmedmat._dmamap_sync = mvmebus_dmamap_sync;
|
||||
sc->sc_mvmedmat._dmamem_map = mvmebus_dmamem_map;
|
||||
sc->sc_mvmedmat._dmamem_unmap = mvmebus_dmamem_unmap;
|
||||
sc->sc_mvmedmat._dmamem_mmap = mvmebus_dmamem_mmap;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
sc->sc_mvmedmat._dmamap_create = mvmebus_dummy_dmamap_create;
|
||||
sc->sc_mvmedmat._dmamap_destroy = mvmebus_dummy_dmamap_destroy;
|
||||
sc->sc_mvmedmat._dmamem_alloc = mvmebus_dummy_dmamem_alloc;
|
||||
sc->sc_mvmedmat._dmamem_free = mvmebus_dummy_dmamem_free;
|
||||
#else
|
||||
sc->sc_mvmedmat._dmamap_create = NULL;
|
||||
sc->sc_mvmedmat._dmamap_destroy = NULL;
|
||||
sc->sc_mvmedmat._dmamem_alloc = NULL;
|
||||
sc->sc_mvmedmat._dmamem_free = NULL;
|
||||
#endif
|
||||
|
||||
vaa.va_vct = &sc->sc_vct;
|
||||
vaa.va_bdt = &sc->sc_mvmedmat;
|
||||
vaa.va_slaveconfig = NULL;
|
||||
|
||||
config_found(&sc->sc_dev, &vaa, 0);
|
||||
}
|
||||
|
||||
int
|
||||
mvmebus_map(vsc, vmeaddr, len, am, datasize, swap, tag, handle, resc)
|
||||
void *vsc;
|
||||
vme_addr_t vmeaddr;
|
||||
vme_size_t len;
|
||||
vme_am_t am;
|
||||
vme_datasize_t datasize;
|
||||
vme_swap_t swap;
|
||||
bus_space_tag_t *tag;
|
||||
bus_space_handle_t *handle;
|
||||
vme_mapresc_t *resc;
|
||||
{
|
||||
struct mvmebus_softc *sc;
|
||||
struct mvmebus_mapresc *mr;
|
||||
struct mvmebus_range *vr;
|
||||
vme_addr_t end;
|
||||
vme_am_t cap, as;
|
||||
paddr_t paddr;
|
||||
int rv, i;
|
||||
|
||||
sc = vsc;
|
||||
end = (vmeaddr + len) - 1;
|
||||
paddr = 0;
|
||||
vr = sc->sc_masters;
|
||||
cap = MVMEBUS_AM2CAP(am);
|
||||
as = am & VME_AM_ADRSIZEMASK;
|
||||
|
||||
for (i = 0; i < sc->sc_nmasters && paddr == 0; i++, vr++) {
|
||||
if (vr->vr_am == MVMEBUS_AM_DISABLED)
|
||||
continue;
|
||||
|
||||
if (cap == (vr->vr_am & cap) &&
|
||||
as == (vr->vr_am & VME_AM_ADRSIZEMASK) &&
|
||||
datasize <= vr->vr_datasize &&
|
||||
vmeaddr >= vr->vr_vmestart && end < vr->vr_vmeend)
|
||||
paddr = vr->vr_locstart + (vmeaddr & vr->vr_mask);
|
||||
}
|
||||
if (paddr == 0)
|
||||
return (ENOMEM);
|
||||
|
||||
rv = bus_space_map(sc->sc_bust, paddr, len, 0, handle);
|
||||
if (rv != 0)
|
||||
return (rv);
|
||||
|
||||
/* Allocate space for the resource tag */
|
||||
if ((mr = malloc(sizeof(*mr), M_DEVBUF, M_NOWAIT)) == NULL) {
|
||||
bus_space_unmap(sc->sc_bust, *handle, len);
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
/* Record the range's details */
|
||||
mr->mr_am = am;
|
||||
mr->mr_datasize = datasize;
|
||||
mr->mr_addr = vmeaddr;
|
||||
mr->mr_size = len;
|
||||
mr->mr_handle = *handle;
|
||||
mr->mr_range = i;
|
||||
|
||||
*tag = sc->sc_bust;
|
||||
*resc = (vme_mapresc_t *) mr;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
mvmebus_unmap(vsc, resc)
|
||||
void *vsc;
|
||||
vme_mapresc_t resc;
|
||||
{
|
||||
struct mvmebus_softc *sc = vsc;
|
||||
struct mvmebus_mapresc *mr = (struct mvmebus_mapresc *) resc;
|
||||
|
||||
bus_space_unmap(sc->sc_bust, mr->mr_handle, mr->mr_size);
|
||||
|
||||
free(mr, M_DEVBUF);
|
||||
}
|
||||
|
||||
int
|
||||
mvmebus_probe(vsc, vmeaddr, len, am, datasize, callback, arg)
|
||||
void *vsc;
|
||||
vme_addr_t vmeaddr;
|
||||
vme_size_t len;
|
||||
vme_am_t am;
|
||||
vme_datasize_t datasize;
|
||||
int (*callback)(void *, bus_space_tag_t, bus_space_handle_t);
|
||||
void *arg;
|
||||
{
|
||||
bus_space_tag_t tag;
|
||||
bus_space_handle_t handle;
|
||||
vme_mapresc_t resc;
|
||||
vme_size_t offs;
|
||||
int rv;
|
||||
|
||||
/* Get a temporary mapping to the VMEbus range */
|
||||
rv = mvmebus_map(vsc, vmeaddr, len, am, datasize, 0,
|
||||
&tag, &handle, &resc);
|
||||
if (rv)
|
||||
return (rv);
|
||||
|
||||
if (callback)
|
||||
rv = (*callback) (arg, tag, handle);
|
||||
else
|
||||
for (offs = 0; offs < len && rv == 0;) {
|
||||
switch (datasize) {
|
||||
case VME_D8:
|
||||
rv = bus_space_peek_1(tag, handle, offs, NULL);
|
||||
offs += 1;
|
||||
break;
|
||||
|
||||
case VME_D16:
|
||||
rv = bus_space_peek_2(tag, handle, offs, NULL);
|
||||
offs += 2;
|
||||
break;
|
||||
|
||||
case VME_D32:
|
||||
rv = bus_space_peek_4(tag, handle, offs, NULL);
|
||||
offs += 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mvmebus_unmap(vsc, resc);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
mvmebus_intmap(vsc, level, vector, handlep)
|
||||
void *vsc;
|
||||
int level, vector;
|
||||
vme_intr_handle_t *handlep;
|
||||
{
|
||||
|
||||
if (level < 1 || level > 7 || vector < 0x80 || vector > 0xff)
|
||||
return (EINVAL);
|
||||
|
||||
/* This is rather gross */
|
||||
*handlep = (void *) (int) ((level << 8) | vector);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
const struct evcnt *
|
||||
mvmebus_intr_evcnt(vsc, handle)
|
||||
void *vsc;
|
||||
vme_intr_handle_t handle;
|
||||
{
|
||||
struct mvmebus_softc *sc = vsc;
|
||||
|
||||
return (&sc->sc_evcnt[(((int) handle) >> 8) - 1]);
|
||||
}
|
||||
|
||||
void *
|
||||
mvmebus_intr_establish(vsc, handle, prior, func, arg)
|
||||
void *vsc;
|
||||
vme_intr_handle_t handle;
|
||||
int prior;
|
||||
int (*func)(void *);
|
||||
void *arg;
|
||||
{
|
||||
struct mvmebus_softc *sc;
|
||||
int level, vector, first;
|
||||
|
||||
sc = vsc;
|
||||
|
||||
/* Extract the interrupt's level and vector */
|
||||
level = ((int) handle) >> 8;
|
||||
vector = ((int) handle) & 0xff;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (vector < 0 || vector > 0xff) {
|
||||
printf("%s: Illegal vector offset: 0x%x\n",
|
||||
sc->sc_dev.dv_xname, vector);
|
||||
panic("mvmebus_intr_establish");
|
||||
}
|
||||
if (level < 1 || level > 7) {
|
||||
printf("%s: Illegal interrupt level: %d\n",
|
||||
sc->sc_dev.dv_xname, level);
|
||||
panic("mvmebus_intr_establish");
|
||||
}
|
||||
#endif
|
||||
|
||||
first = (sc->sc_irqref[level]++ == 0);
|
||||
|
||||
(*sc->sc_intr_establish)(sc->sc_chip, prior, level, vector, first,
|
||||
func, arg, &sc->sc_evcnt[level - 1]);
|
||||
|
||||
return ((void *) handle);
|
||||
}
|
||||
|
||||
void
|
||||
mvmebus_intr_disestablish(vsc, handle)
|
||||
void *vsc;
|
||||
vme_intr_handle_t handle;
|
||||
{
|
||||
struct mvmebus_softc *sc;
|
||||
int level, vector, last;
|
||||
|
||||
sc = vsc;
|
||||
|
||||
/* Extract the interrupt's level and vector */
|
||||
level = ((int) handle) >> 8;
|
||||
vector = ((int) handle) & 0xff;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (vector < 0 || vector > 0xff) {
|
||||
printf("%s: Illegal vector offset: 0x%x\n",
|
||||
sc->sc_dev.dv_xname, vector);
|
||||
panic("mvmebus_intr_disestablish");
|
||||
}
|
||||
if (level < 1 || level > 7) {
|
||||
printf("%s: Illegal interrupt level: %d\n",
|
||||
sc->sc_dev.dv_xname, level);
|
||||
panic("mvmebus_intr_disestablish");
|
||||
}
|
||||
if (sc->sc_irqref[level] == 0) {
|
||||
printf("%s: VMEirq#%d: Reference count already zero!\n",
|
||||
sc->sc_dev.dv_xname, level);
|
||||
panic("mvmebus_intr_disestablish");
|
||||
}
|
||||
#endif
|
||||
|
||||
last = (--(sc->sc_irqref[level]) == 0);
|
||||
|
||||
(*sc->sc_intr_disestablish)(sc->sc_chip, level, vector, last,
|
||||
&sc->sc_evcnt[level - 1]);
|
||||
}
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
/* ARGSUSED */
|
||||
int
|
||||
mvmebus_dummy_dmamap_create(t, size, nsegs, maxsegsz, boundary, flags, dmamp)
|
||||
bus_dma_tag_t t;
|
||||
bus_size_t size;
|
||||
int nsegs;
|
||||
bus_size_t maxsegsz;
|
||||
bus_size_t boundary;
|
||||
int flags;
|
||||
bus_dmamap_t *dmamp;
|
||||
{
|
||||
|
||||
panic("Must use vme_dmamap_create() in place of bus_dmamap_create()");
|
||||
return (0); /* Shutup the compiler */
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
mvmebus_dummy_dmamap_destroy(t, map)
|
||||
bus_dma_tag_t t;
|
||||
bus_dmamap_t map;
|
||||
{
|
||||
|
||||
panic("Must use vme_dmamap_destroy() in place of bus_dmamap_destroy()");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
mvmebus_dmamap_create(vsc, len, am, datasize, swap, nsegs,
|
||||
segsz, bound, flags, mapp)
|
||||
void *vsc;
|
||||
vme_size_t len;
|
||||
vme_am_t am;
|
||||
vme_datasize_t datasize;
|
||||
vme_swap_t swap;
|
||||
int nsegs;
|
||||
vme_size_t segsz;
|
||||
vme_addr_t bound;
|
||||
int flags;
|
||||
bus_dmamap_t *mapp;
|
||||
{
|
||||
struct mvmebus_softc *sc = vsc;
|
||||
struct mvmebus_dmamap *vmap;
|
||||
struct mvmebus_range *vr;
|
||||
vme_am_t cap, as;
|
||||
int i, rv;
|
||||
|
||||
cap = MVMEBUS_AM2CAP(am);
|
||||
as = am & VME_AM_ADRSIZEMASK;
|
||||
|
||||
/*
|
||||
* Verify that we even stand a chance of satisfying
|
||||
* the VMEbus address space and datasize requested.
|
||||
*/
|
||||
for (i = 0, vr = sc->sc_slaves; i < sc->sc_nslaves; i++, vr++) {
|
||||
if (vr->vr_am == MVMEBUS_AM_DISABLED)
|
||||
continue;
|
||||
|
||||
if (as == (vr->vr_am & VME_AM_ADRSIZEMASK) &&
|
||||
cap == (vr->vr_am & cap) && datasize <= vr->vr_datasize &&
|
||||
len <= (vr->vr_vmeend - vr->vr_vmestart))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == sc->sc_nslaves)
|
||||
return (EINVAL);
|
||||
|
||||
if ((vmap = malloc(sizeof(*vmap), M_DMAMAP,
|
||||
(flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
|
||||
rv = bus_dmamap_create(sc->sc_dmat, len, nsegs, segsz,
|
||||
bound, flags, mapp);
|
||||
if (rv != 0) {
|
||||
free(vmap, M_DMAMAP);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
vmap->vm_am = am;
|
||||
vmap->vm_datasize = datasize;
|
||||
vmap->vm_swap = swap;
|
||||
vmap->vm_slave = vr;
|
||||
|
||||
(*mapp)->_dm_cookie = vmap;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
mvmebus_dmamap_destroy(vsc, map)
|
||||
void *vsc;
|
||||
bus_dmamap_t map;
|
||||
{
|
||||
struct mvmebus_softc *sc = vsc;
|
||||
|
||||
free(map->_dm_cookie, M_DMAMAP);
|
||||
bus_dmamap_destroy(sc->sc_dmat, map);
|
||||
}
|
||||
|
||||
static int
|
||||
mvmebus_dmamap_load_common(sc, map)
|
||||
struct mvmebus_softc *sc;
|
||||
bus_dmamap_t map;
|
||||
{
|
||||
struct mvmebus_dmamap *vmap = map->_dm_cookie;
|
||||
struct mvmebus_range *vr = vmap->vm_slave;
|
||||
bus_dma_segment_t *ds;
|
||||
vme_am_t cap, am;
|
||||
int i;
|
||||
|
||||
cap = MVMEBUS_AM2CAP(vmap->vm_am);
|
||||
am = vmap->vm_am & VME_AM_ADRSIZEMASK;
|
||||
|
||||
/*
|
||||
* Traverse the list of segments which make up this map, and
|
||||
* convert the cpu-relative addresses therein to VMEbus addresses.
|
||||
*/
|
||||
for (ds = &map->dm_segs[0]; ds < &map->dm_segs[map->dm_nsegs]; ds++) {
|
||||
/*
|
||||
* First, see if this map's slave image can access the
|
||||
* segment, otherwise we have to waste time scanning all
|
||||
* the slave images.
|
||||
*/
|
||||
vr = vmap->vm_slave;
|
||||
if (am == (vr->vr_am & VME_AM_ADRSIZEMASK) &&
|
||||
cap == (vr->vr_am & cap) &&
|
||||
vmap->vm_datasize <= vr->vr_datasize &&
|
||||
ds->_ds_cpuaddr >= vr->vr_locstart &&
|
||||
ds->ds_len <= (vr->vr_vmeend - vr->vr_vmestart))
|
||||
goto found;
|
||||
|
||||
for (i = 0, vr = sc->sc_slaves; i < sc->sc_nslaves; i++, vr++) {
|
||||
if (vr->vr_am == MVMEBUS_AM_DISABLED)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Filter out any slave images which don't have the
|
||||
* same VMEbus address modifier and datasize as
|
||||
* this DMA map, and those which don't cover the
|
||||
* physical address region containing the segment.
|
||||
*/
|
||||
if (vr != vmap->vm_slave &&
|
||||
am == (vr->vr_am & VME_AM_ADRSIZEMASK) &&
|
||||
cap == (vr->vr_am & cap) &&
|
||||
vmap->vm_datasize <= vr->vr_datasize &&
|
||||
ds->_ds_cpuaddr >= vr->vr_locstart &&
|
||||
ds->ds_len <= (vr->vr_vmeend - vr->vr_vmestart))
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Did we find an applicable slave image which covers this
|
||||
* segment?
|
||||
*/
|
||||
if (i == sc->sc_nslaves) {
|
||||
/*
|
||||
* XXX TODO:
|
||||
*
|
||||
* Bounce this segment via a bounce buffer allocated
|
||||
* from this DMA map.
|
||||
*/
|
||||
printf("mvmebus_dmamap_load_common: bounce needed!\n");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
found:
|
||||
/*
|
||||
* Generate the VMEbus address of this segment
|
||||
*/
|
||||
ds->ds_addr = (ds->_ds_cpuaddr - vr->vr_locstart) +
|
||||
vr->vr_vmestart;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
mvmebus_dmamap_load(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;
|
||||
{
|
||||
struct mvmebus_softc *sc = t->_cookie;
|
||||
int rv;
|
||||
|
||||
rv = bus_dmamap_load(sc->sc_dmat, map, buf, buflen, p, flags);
|
||||
if (rv != 0)
|
||||
return rv;
|
||||
|
||||
return mvmebus_dmamap_load_common(sc, map);
|
||||
}
|
||||
|
||||
int
|
||||
mvmebus_dmamap_load_mbuf(t, map, chain, flags)
|
||||
bus_dma_tag_t t;
|
||||
bus_dmamap_t map;
|
||||
struct mbuf *chain;
|
||||
int flags;
|
||||
{
|
||||
struct mvmebus_softc *sc = t->_cookie;
|
||||
int rv;
|
||||
|
||||
rv = bus_dmamap_load_mbuf(sc->sc_dmat, map, chain, flags);
|
||||
if (rv != 0)
|
||||
return rv;
|
||||
|
||||
return mvmebus_dmamap_load_common(sc, map);
|
||||
}
|
||||
|
||||
int
|
||||
mvmebus_dmamap_load_uio(t, map, uio, flags)
|
||||
bus_dma_tag_t t;
|
||||
bus_dmamap_t map;
|
||||
struct uio *uio;
|
||||
int flags;
|
||||
{
|
||||
struct mvmebus_softc *sc = t->_cookie;
|
||||
int rv;
|
||||
|
||||
rv = bus_dmamap_load_uio(sc->sc_dmat, map, uio, flags);
|
||||
if (rv != 0)
|
||||
return rv;
|
||||
|
||||
return mvmebus_dmamap_load_common(sc, map);
|
||||
}
|
||||
|
||||
int
|
||||
mvmebus_dmamap_load_raw(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;
|
||||
{
|
||||
struct mvmebus_softc *sc = t->_cookie;
|
||||
int rv;
|
||||
|
||||
/*
|
||||
* mvmebus_dmamem_alloc() will ensure that the physical memory
|
||||
* backing these segments is 100% accessible in at least one
|
||||
* of the board's VMEbus slave images.
|
||||
*/
|
||||
rv = bus_dmamap_load_raw(sc->sc_dmat, map, segs, nsegs, size, flags);
|
||||
if (rv != 0)
|
||||
return rv;
|
||||
|
||||
return mvmebus_dmamap_load_common(sc, map);
|
||||
}
|
||||
|
||||
void
|
||||
mvmebus_dmamap_unload(t, map)
|
||||
bus_dma_tag_t t;
|
||||
bus_dmamap_t map;
|
||||
{
|
||||
struct mvmebus_softc *sc = t->_cookie;
|
||||
|
||||
/* XXX Deal with bounce buffers */
|
||||
|
||||
bus_dmamap_unload(sc->sc_dmat, map);
|
||||
}
|
||||
|
||||
void
|
||||
mvmebus_dmamap_sync(t, map, offset, len, ops)
|
||||
bus_dma_tag_t t;
|
||||
bus_dmamap_t map;
|
||||
bus_addr_t offset;
|
||||
bus_size_t len;
|
||||
int ops;
|
||||
{
|
||||
struct mvmebus_softc *sc = t->_cookie;
|
||||
|
||||
/* XXX Bounce buffers */
|
||||
|
||||
bus_dmamap_sync(sc->sc_dmat, map, offset, len, ops);
|
||||
}
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
/* ARGSUSED */
|
||||
int
|
||||
mvmebus_dummy_dmamem_alloc(t, size, align, boundary, segs, nsegs, rsegs, flags)
|
||||
bus_dma_tag_t t;
|
||||
bus_size_t size;
|
||||
bus_size_t align;
|
||||
bus_size_t boundary;
|
||||
bus_dma_segment_t *segs;
|
||||
int nsegs;
|
||||
int *rsegs;
|
||||
int flags;
|
||||
{
|
||||
|
||||
panic("Must use vme_dmamem_alloc() in place of bus_dmamem_alloc()\n");
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
mvmebus_dummy_dmamem_free(t, segs, nsegs)
|
||||
bus_dma_tag_t t;
|
||||
bus_dma_segment_t *segs;
|
||||
int nsegs;
|
||||
{
|
||||
|
||||
panic("Must use vme_dmamem_free() in place of bus_dmamem_free()");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
mvmebus_dmamem_alloc(vsc, len, am, datasize, swap, segs, nsegs, rsegs, flags)
|
||||
void *vsc;
|
||||
vme_size_t len;
|
||||
vme_am_t am;
|
||||
vme_datasize_t datasize;
|
||||
vme_swap_t swap;
|
||||
bus_dma_segment_t *segs;
|
||||
int nsegs;
|
||||
int *rsegs;
|
||||
int flags;
|
||||
{
|
||||
extern paddr_t avail_start;
|
||||
struct mvmebus_softc *sc = vsc;
|
||||
struct mvmebus_range *vr;
|
||||
bus_addr_t low, high;
|
||||
bus_size_t bound;
|
||||
vme_am_t cap;
|
||||
int i;
|
||||
|
||||
cap = MVMEBUS_AM2CAP(am);
|
||||
am &= VME_AM_ADRSIZEMASK;
|
||||
|
||||
/*
|
||||
* Find a slave mapping in the requested VMEbus address space.
|
||||
*/
|
||||
for (i = 0, vr = sc->sc_slaves; i < sc->sc_nslaves; i++, vr++) {
|
||||
if (vr->vr_am == MVMEBUS_AM_DISABLED)
|
||||
continue;
|
||||
|
||||
if (i == 0 && (flags & BUS_DMA_ONBOARD_RAM) != 0)
|
||||
continue;
|
||||
|
||||
if (am == (vr->vr_am & VME_AM_ADRSIZEMASK) &&
|
||||
cap == (vr->vr_am & cap) && datasize <= vr->vr_datasize &&
|
||||
len <= (vr->vr_vmeend - vr->vr_vmestart))
|
||||
break;
|
||||
}
|
||||
if (i == sc->sc_nslaves)
|
||||
return (EINVAL);
|
||||
|
||||
/*
|
||||
* Set up the constraints so we can allocate physical memory which
|
||||
* is visible in the requested address space
|
||||
*/
|
||||
low = max(vr->vr_locstart, avail_start);
|
||||
high = vr->vr_locstart + (vr->vr_vmeend - vr->vr_vmestart) + 1;
|
||||
bound = (bus_size_t) vr->vr_mask + 1;
|
||||
|
||||
/*
|
||||
* Allocate physical memory.
|
||||
*
|
||||
* Note: This fills in the segments with cpu-relative physical
|
||||
* addresses. A further call to bus_dmamap_load_raw() (with a
|
||||
* dma map which specifies the same VMEbus address space and
|
||||
* constraints as the call to here) must be made. The segments
|
||||
* of the dma map will then contain VMEbus-relative physical
|
||||
* addresses of the memory allocated here.
|
||||
*/
|
||||
return _bus_dmamem_alloc_common(sc->sc_dmat, low, high,
|
||||
len, 0, bound, segs, nsegs, rsegs, flags);
|
||||
}
|
||||
|
||||
void
|
||||
mvmebus_dmamem_free(vsc, segs, nsegs)
|
||||
void *vsc;
|
||||
bus_dma_segment_t *segs;
|
||||
int nsegs;
|
||||
{
|
||||
struct mvmebus_softc *sc = vsc;
|
||||
|
||||
bus_dmamem_free(sc->sc_dmat, segs, nsegs);
|
||||
}
|
||||
|
||||
int
|
||||
mvmebus_dmamem_map(t, segs, nsegs, size, kvap, flags)
|
||||
bus_dma_tag_t t;
|
||||
bus_dma_segment_t *segs;
|
||||
int nsegs;
|
||||
size_t size;
|
||||
caddr_t *kvap;
|
||||
int flags;
|
||||
{
|
||||
struct mvmebus_softc *sc = t->_cookie;
|
||||
|
||||
return bus_dmamem_map(sc->sc_dmat, segs, nsegs, size, kvap, flags);
|
||||
}
|
||||
|
||||
void
|
||||
mvmebus_dmamem_unmap(t, kva, size)
|
||||
bus_dma_tag_t t;
|
||||
caddr_t kva;
|
||||
size_t size;
|
||||
{
|
||||
struct mvmebus_softc *sc = t->_cookie;
|
||||
|
||||
bus_dmamem_unmap(sc->sc_dmat, kva, size);
|
||||
}
|
||||
|
||||
paddr_t
|
||||
mvmebus_dmamem_mmap(t, segs, nsegs, offset, prot, flags)
|
||||
bus_dma_tag_t t;
|
||||
bus_dma_segment_t *segs;
|
||||
int nsegs;
|
||||
off_t offset;
|
||||
int prot;
|
||||
int flags;
|
||||
{
|
||||
struct mvmebus_softc *sc = t->_cookie;
|
||||
|
||||
return bus_dmamem_mmap(sc->sc_dmat, segs, nsegs, offset, prot, flags);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char *
|
||||
mvmebus_mod_string(addr, len, am, ds)
|
||||
vme_addr_t addr;
|
||||
vme_size_t len;
|
||||
vme_am_t am;
|
||||
vme_datasize_t ds;
|
||||
{
|
||||
static const char *mode[] = {"BLT64)", "DATA)", "PROG)", "BLT32)"};
|
||||
static const char *dsiz[] = {"(", "(D8,", "(D16,", "(D16-D8,",
|
||||
"(D32,", "(D32,D8,", "(D32-D16,", "(D32-D8,"};
|
||||
static char mstring[40];
|
||||
char *fmt;
|
||||
|
||||
switch (am & VME_AM_ADRSIZEMASK) {
|
||||
case VME_AM_A32:
|
||||
fmt = "A32:%08x-%08x ";
|
||||
break;
|
||||
|
||||
case VME_AM_A24:
|
||||
fmt = "A24:%06x-%06x ";
|
||||
break;
|
||||
|
||||
case VME_AM_A16:
|
||||
fmt = "A16:%04x-%04x ";
|
||||
break;
|
||||
|
||||
case VME_AM_USERDEF:
|
||||
fmt = "USR:%08x-%08x ";
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(mstring, fmt, addr, addr + len - 1);
|
||||
strcat(mstring, dsiz[ds & 0x7]);
|
||||
|
||||
if (MVMEBUS_AM_HAS_CAP(am)) {
|
||||
if (am & MVMEBUS_AM_CAP_DATA)
|
||||
strcat(mstring, "D");
|
||||
if (am & MVMEBUS_AM_CAP_PROG)
|
||||
strcat(mstring, "P");
|
||||
if (am & MVMEBUS_AM_CAP_USER)
|
||||
strcat(mstring, "U");
|
||||
if (am & MVMEBUS_AM_CAP_SUPER)
|
||||
strcat(mstring, "S");
|
||||
if (am & MVMEBUS_AM_CAP_BLK)
|
||||
strcat(mstring, "B");
|
||||
if (am & MVMEBUS_AM_CAP_BLKD64)
|
||||
strcat(mstring, "6");
|
||||
strcat(mstring, ")");
|
||||
} else {
|
||||
strcat(mstring, ((am & VME_AM_PRIVMASK) == VME_AM_USER) ?
|
||||
"USER," : "SUPER,");
|
||||
strcat(mstring, mode[am & VME_AM_MODEMASK]);
|
||||
}
|
||||
|
||||
return (mstring);
|
||||
}
|
||||
#endif
|
161
sys/dev/mvme/mvmebus.h
Normal file
161
sys/dev/mvme/mvmebus.h
Normal file
@ -0,0 +1,161 @@
|
||||
/* $NetBSD: mvmebus.h,v 1.1 2002/02/12 20:38:48 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford.
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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.
|
||||
*/
|
||||
|
||||
#ifndef _MVME_MVMEBUS_H
|
||||
#define _MVME_MVMEBUS_H
|
||||
|
||||
/*
|
||||
* VMEbus master and slave windows are described using
|
||||
* instances of this structure.
|
||||
*
|
||||
* The chip-specific code records the details of the available mappings
|
||||
* for the MVME board.
|
||||
*/
|
||||
struct mvmebus_range {
|
||||
vme_am_t vr_am; /* Address modifier (A16, A24, A32) */
|
||||
vme_datasize_t vr_datasize; /* Datasize: logical OR of D8,D16,D32 */
|
||||
paddr_t vr_locstart; /* CPU-relative address of mapping */
|
||||
paddr_t vr_mask; /* Mask to apply to this mapping */
|
||||
vme_addr_t vr_vmestart; /* VMEbus start address */
|
||||
vme_addr_t vr_vmeend; /* VMEbus end address */
|
||||
};
|
||||
|
||||
/* Assigned to vr_am to specify the mapping is not valid */
|
||||
#define MVMEBUS_AM_DISABLED ((vme_am_t)-1)
|
||||
|
||||
/* For slave mappings, these specify the slave's capabilities */
|
||||
#define MVMEBUS_AM_CAP_DATA 0x0100
|
||||
#define MVMEBUS_AM_CAP_PROG 0x0200
|
||||
#define MVMEBUS_AM_CAP_BLK 0x0400
|
||||
#define MVMEBUS_AM_CAP_BLKD64 0x0800
|
||||
#define MVMEBUS_AM_CAP_USER 0x1000
|
||||
#define MVMEBUS_AM_CAP_SUPER 0x2000
|
||||
#define MVMEBUS_AM_HAS_CAP(x) (((x) & 0x3f00) != 0)
|
||||
|
||||
#define MVMEBUS_AM2CAP(am) (_mvmebus_am_cap[((am) & \
|
||||
(VME_AM_MODEMASK | VME_AM_PRIVMASK))])
|
||||
|
||||
|
||||
/*
|
||||
* This records VMEbus-specific details of a region of bus_space_map'd
|
||||
* VMEbus address space.
|
||||
*/
|
||||
struct mvmebus_mapresc {
|
||||
bus_space_handle_t mr_handle;
|
||||
bus_addr_t mr_addr;
|
||||
bus_size_t mr_size;
|
||||
vme_am_t mr_am;
|
||||
vme_datasize_t mr_datasize;
|
||||
int mr_range;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This records the VMEbus-specific details of a region of phyisical
|
||||
* memory accessible through a VMEbus slave map.
|
||||
*/
|
||||
struct mvmebus_dmamap {
|
||||
vme_am_t vm_am;
|
||||
vme_datasize_t vm_datasize;
|
||||
vme_swap_t vm_swap;
|
||||
struct mvmebus_range *vm_slave;
|
||||
};
|
||||
|
||||
|
||||
struct mvmebus_softc {
|
||||
struct device sc_dev;
|
||||
bus_space_tag_t sc_bust;
|
||||
bus_dma_tag_t sc_dmat;
|
||||
short sc_irqref[8];
|
||||
void *sc_chip;
|
||||
int sc_nmasters;
|
||||
struct mvmebus_range *sc_masters;
|
||||
int sc_nslaves;
|
||||
struct mvmebus_range *sc_slaves;
|
||||
struct evcnt sc_evcnt[7];
|
||||
void (*sc_intr_establish)(void *, int, int, int, int,
|
||||
int (*)(void *), void *, struct evcnt *);
|
||||
void (*sc_intr_disestablish)(void *, int, int, int,
|
||||
struct evcnt *);
|
||||
struct vme_chipset_tag sc_vct;
|
||||
struct mvme68k_bus_dma_tag sc_mvmedmat;
|
||||
};
|
||||
|
||||
|
||||
void mvmebus_attach(struct mvmebus_softc *);
|
||||
int mvmebus_map(void *, vme_addr_t, vme_size_t, vme_am_t,
|
||||
vme_datasize_t, vme_swap_t, bus_space_tag_t *,
|
||||
bus_space_handle_t *, vme_mapresc_t *);
|
||||
void mvmebus_unmap(void *, vme_mapresc_t);
|
||||
int mvmebus_probe(void *, vme_addr_t, vme_size_t,
|
||||
vme_am_t, vme_datasize_t,
|
||||
int (*) (void *, bus_space_tag_t, bus_space_handle_t), void *arg);
|
||||
int mvmebus_intmap(void *, int, int, vme_intr_handle_t *);
|
||||
const struct evcnt *mvmebus_intr_evcnt(void *, vme_intr_handle_t);
|
||||
void * mvmebus_intr_establish(void *, vme_intr_handle_t, int,
|
||||
int (*) (void *), void *);
|
||||
void mvmebus_intr_disestablish(void *, vme_intr_handle_t);
|
||||
|
||||
int mvmebus_dmamap_create(void *, vme_size_t, vme_am_t, vme_datasize_t,
|
||||
vme_swap_t, int, vme_size_t, vme_addr_t, int, bus_dmamap_t *);
|
||||
void mvmebus_dmamap_destroy(void *, bus_dmamap_t);
|
||||
int mvmebus_dmamap_load(bus_dma_tag_t, bus_dmamap_t,
|
||||
void *, bus_size_t, struct proc *, int);
|
||||
int mvmebus_dmamap_load_mbuf(bus_dma_tag_t,
|
||||
bus_dmamap_t, struct mbuf *, int);
|
||||
int mvmebus_dmamap_load_uio(bus_dma_tag_t,
|
||||
bus_dmamap_t, struct uio *, int);
|
||||
int mvmebus_dmamap_load_raw(bus_dma_tag_t,
|
||||
bus_dmamap_t, bus_dma_segment_t *, int, bus_size_t, int);
|
||||
void mvmebus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
|
||||
void mvmebus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
|
||||
bus_size_t, int);
|
||||
|
||||
int mvmebus_dmamem_alloc(void *, vme_size_t, vme_am_t, vme_datasize_t,
|
||||
vme_swap_t, bus_dma_segment_t *, int, int *, int);
|
||||
void mvmebus_dmamem_free(void *, bus_dma_segment_t *, int);
|
||||
int mvmebus_dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, int,
|
||||
size_t, caddr_t *, int);
|
||||
void mvmebus_dmamem_unmap(bus_dma_tag_t, caddr_t, size_t);
|
||||
paddr_t mvmebus_dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int,
|
||||
off_t, int, int);
|
||||
|
||||
extern vme_am_t _mvmebus_am_cap[];
|
||||
extern const char *mvmebus_irq_name[];
|
||||
|
||||
#endif /* _MVME_MVMEBUS_H */
|
191
sys/dev/mvme/osiop_pcctwo.c
Normal file
191
sys/dev/mvme/osiop_pcctwo.c
Normal file
@ -0,0 +1,191 @@
|
||||
/* $NetBSD: osiop_pcctwo.c,v 1.1 2002/02/12 20:38:48 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford.
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Front-end attachment code for the ncr53c710 SCSI controller
|
||||
* on mvme68k/mvme88k boards.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <dev/scsipi/scsi_all.h>
|
||||
#include <dev/scsipi/scsipi_all.h>
|
||||
#include <dev/scsipi/scsiconf.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/autoconf.h>
|
||||
|
||||
#include <dev/ic/osiopreg.h>
|
||||
#include <dev/ic/osiopvar.h>
|
||||
|
||||
#include <dev/mvme/pcctworeg.h>
|
||||
#include <dev/mvme/pcctwovar.h>
|
||||
|
||||
|
||||
int osiop_pcctwo_match __P((struct device *, struct cfdata *, void *));
|
||||
void osiop_pcctwo_attach __P((struct device *, struct device *, void *));
|
||||
|
||||
struct osiop_pcctwo_softc {
|
||||
struct osiop_softc sc_osiop;
|
||||
struct evcnt sc_evcnt;
|
||||
};
|
||||
|
||||
struct cfattach osiop_pcctwo_ca = {
|
||||
sizeof(struct osiop_pcctwo_softc), osiop_pcctwo_match,
|
||||
osiop_pcctwo_attach
|
||||
};
|
||||
|
||||
static int osiop_pcctwo_intr __P((void *));
|
||||
|
||||
extern struct cfdriver osiop_cd;
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
osiop_pcctwo_match(parent, cf, args)
|
||||
struct device *parent;
|
||||
struct cfdata *cf;
|
||||
void *args;
|
||||
{
|
||||
struct pcctwo_attach_args *pa;
|
||||
|
||||
pa = args;
|
||||
|
||||
if (strcmp(pa->pa_name, osiop_cd.cd_name))
|
||||
return (0);
|
||||
|
||||
pa->pa_ipl = cf->pcctwocf_ipl;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
osiop_pcctwo_attach(parent, self, args)
|
||||
struct device *parent;
|
||||
struct device *self;
|
||||
void *args;
|
||||
{
|
||||
struct pcctwo_attach_args *pa;
|
||||
struct osiop_pcctwo_softc *sc;
|
||||
int clk, ctest7;
|
||||
|
||||
pa = (struct pcctwo_attach_args *) args;
|
||||
sc = (struct osiop_pcctwo_softc *) self;
|
||||
|
||||
/*
|
||||
* On the '17x the siop's clock is the same as the cpu clock.
|
||||
* On the other boards, the siop runs at twice the cpu clock.
|
||||
* Also, the 17x cannot do proper bus-snooping (the 68060 is
|
||||
* lame in this repspect) so don't enable it on that board.
|
||||
*/
|
||||
#ifdef MVME68K
|
||||
if (machineid == MVME_172 || machineid == MVME_177) {
|
||||
clk = cpuspeed;
|
||||
ctest7 = 0;
|
||||
} else {
|
||||
clk = cpuspeed * 2;
|
||||
ctest7 = OSIOP_CTEST7_SC0;
|
||||
}
|
||||
#else
|
||||
#error Set up siop clock speed for mvme187
|
||||
#endif
|
||||
|
||||
sc->sc_osiop.sc_bst = pa->pa_bust;
|
||||
sc->sc_osiop.sc_dmat = pa->pa_dmat;
|
||||
(void) bus_space_map(sc->sc_osiop.sc_bst, pa->pa_offset, OSIOP_NREGS,
|
||||
0, &sc->sc_osiop.sc_reg);
|
||||
|
||||
sc->sc_osiop.sc_clock_freq = clk;
|
||||
sc->sc_osiop.sc_ctest7 = ctest7 | OSIOP_CTEST7_TT1;
|
||||
sc->sc_osiop.sc_dcntl = OSIOP_DCNTL_EA;
|
||||
sc->sc_osiop.sc_id = 7; /* XXX: Could use NVRAM setting */
|
||||
|
||||
/* Attach main MI driver */
|
||||
osiop_attach(&sc->sc_osiop);
|
||||
|
||||
/* Register the event counter */
|
||||
evcnt_attach_dynamic(&sc->sc_evcnt, EVCNT_TYPE_INTR,
|
||||
pcctwointr_evcnt(pa->pa_ipl), "disk", sc->sc_osiop.sc_dev.dv_xname);
|
||||
|
||||
/* Hook the chip's interrupt */
|
||||
pcctwointr_establish(PCCTWOV_SCSI, osiop_pcctwo_intr, pa->pa_ipl, sc,
|
||||
&sc->sc_evcnt);
|
||||
}
|
||||
|
||||
static int
|
||||
osiop_pcctwo_intr(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct osiop_pcctwo_softc *sc = (struct osiop_pcctwo_softc *) arg;
|
||||
u_char istat;
|
||||
|
||||
/*
|
||||
* Catch any errors which can happen when the SIOP is
|
||||
* local bus master...
|
||||
*/
|
||||
istat = pcc2_reg_read(sys_pcctwo, PCC2REG_SCSI_ERR_STATUS);
|
||||
if ((istat & PCCTWO_ERR_SR_MASK) != 0) {
|
||||
printf("%s: Local bus error: 0x%02x\n",
|
||||
sc->sc_osiop.sc_dev.dv_xname, istat);
|
||||
istat |= PCCTWO_ERR_SR_SCLR;
|
||||
pcc2_reg_write(sys_pcctwo, PCC2REG_SCSI_ERR_STATUS, istat);
|
||||
}
|
||||
|
||||
/* This is potentially nasty, since the IRQ is level triggered... */
|
||||
if (sc->sc_osiop.sc_flags & OSIOP_INTSOFF)
|
||||
return (0);
|
||||
|
||||
istat = osiop_read_1(&sc->sc_osiop, OSIOP_ISTAT);
|
||||
|
||||
if ((istat & (OSIOP_ISTAT_SIP | OSIOP_ISTAT_DIP)) == 0)
|
||||
return (0);
|
||||
|
||||
/* Save interrupt details for the back-end interrupt handler */
|
||||
sc->sc_osiop.sc_sstat0 = osiop_read_1(&sc->sc_osiop, OSIOP_SSTAT0);
|
||||
sc->sc_osiop.sc_istat = istat;
|
||||
sc->sc_osiop.sc_dstat = osiop_read_1(&sc->sc_osiop, OSIOP_DSTAT);
|
||||
|
||||
/* Deal with the interrupt */
|
||||
osiop_intr(&sc->sc_osiop);
|
||||
|
||||
return (1);
|
||||
}
|
204
sys/dev/mvme/pcctwo.c
Normal file
204
sys/dev/mvme/pcctwo.c
Normal file
@ -0,0 +1,204 @@
|
||||
/* $NetBSD: pcctwo.c,v 1.1 2002/02/12 20:38:49 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford.
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PCCchip2 and MCchip Driver
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/mvme/pcctworeg.h>
|
||||
#include <dev/mvme/pcctwovar.h>
|
||||
|
||||
/*
|
||||
* Global Pointer to the PCCChip2/MCchip soft state, and chip ID
|
||||
*/
|
||||
struct pcctwo_softc *sys_pcctwo;
|
||||
|
||||
int pcctwoprint(void *, const char *);
|
||||
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
pcctwo_init(sc, pd, devoff)
|
||||
struct pcctwo_softc *sc;
|
||||
struct pcctwo_device *pd;
|
||||
int devoff;
|
||||
{
|
||||
struct pcctwo_attach_args npa;
|
||||
u_int8_t cid;
|
||||
|
||||
/*
|
||||
* Fix up the vector base for PCCChip2 Interrupts
|
||||
*/
|
||||
pcc2_reg_write(sc, PCC2REG_VECTOR_BASE, sc->sc_vecbase);
|
||||
|
||||
/*
|
||||
* Enable PCCChip2 Interrupts
|
||||
*/
|
||||
pcc2_reg_write(sc, PCC2REG_GENERAL_CONTROL,
|
||||
pcc2_reg_read(sc, PCC2REG_GENERAL_CONTROL) | PCCTWO_GEN_CTRL_MIEN);
|
||||
|
||||
/* What are we? */
|
||||
cid = pcc2_reg_read(sc, PCC2REG_CHIP_ID);
|
||||
|
||||
/*
|
||||
* Announce ourselves to the world in general
|
||||
*/
|
||||
if (cid == PCCTWO_CHIP_ID_PCC2)
|
||||
printf(": Peripheral Channel Controller (PCCchip2), Rev %d\n",
|
||||
pcc2_reg_read(sc, PCC2REG_CHIP_REVISION));
|
||||
else
|
||||
if (cid == PCCTWO_CHIP_ID_MCCHIP)
|
||||
printf(": Memory Controller ASIC (MCchip), Rev %d\n",
|
||||
pcc2_reg_read(sc, PCC2REG_CHIP_REVISION));
|
||||
|
||||
/*
|
||||
* Attach configured children.
|
||||
*/
|
||||
npa._pa_base = devoff;
|
||||
while (pd->pcc_name != NULL) {
|
||||
/*
|
||||
* Note that IPL is filled in by match function.
|
||||
*/
|
||||
npa.pa_name = pd->pcc_name;
|
||||
npa.pa_ipl = -1;
|
||||
npa.pa_dmat = sc->sc_dmat;
|
||||
npa.pa_bust = sc->sc_bust;
|
||||
npa.pa_offset = pd->pcc_offset + devoff;
|
||||
pd++;
|
||||
|
||||
/* Attach the device if configured. */
|
||||
(void) config_found(&sc->sc_dev, &npa, pcctwoprint);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
pcctwoprint(aux, cp)
|
||||
void *aux;
|
||||
const char *cp;
|
||||
{
|
||||
struct pcctwo_attach_args *pa;
|
||||
|
||||
pa = aux;
|
||||
|
||||
if (cp)
|
||||
printf("%s at %s", pa->pa_name, cp);
|
||||
|
||||
printf(" offset 0x%lx", pa->pa_offset - pa->_pa_base);
|
||||
if (pa->pa_ipl != -1)
|
||||
printf(" ipl %d", pa->pa_ipl);
|
||||
|
||||
return (UNCONF);
|
||||
}
|
||||
|
||||
/*
|
||||
* pcctwointr_establish: Establish PCCChip2 Interrupt
|
||||
*/
|
||||
void
|
||||
pcctwointr_establish(vec, hand, lvl, arg, evcnt)
|
||||
int vec;
|
||||
int (*hand) __P((void *)), lvl;
|
||||
void *arg;
|
||||
struct evcnt *evcnt;
|
||||
{
|
||||
int vec2icsr;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (vec < 0 || vec >= PCCTWOV_MAX) {
|
||||
printf("pcctwo: illegal vector offset: 0x%x\n", vec);
|
||||
panic("pcctwointr_establish");
|
||||
}
|
||||
if (lvl < 1 || lvl > 7) {
|
||||
printf("pcctwo: illegal interrupt level: %d\n", lvl);
|
||||
panic("pcctwointr_establish");
|
||||
}
|
||||
if (sys_pcctwo->sc_vec2icsr[vec] == -1) {
|
||||
printf("pcctwo: unsupported vector: %d\n", vec);
|
||||
panic("pcctwointr_establish");
|
||||
}
|
||||
#endif
|
||||
|
||||
vec2icsr = sys_pcctwo->sc_vec2icsr[vec];
|
||||
pcc2_reg_write(sys_pcctwo, VEC2ICSR_REG(vec2icsr), 0);
|
||||
|
||||
/* Hook the interrupt */
|
||||
(*sys_pcctwo->sc_isrlink)(sys_pcctwo->sc_isrcookie, hand, arg,
|
||||
lvl, vec + sys_pcctwo->sc_vecbase, evcnt);
|
||||
|
||||
/* Enable it in hardware */
|
||||
pcc2_reg_write(sys_pcctwo, VEC2ICSR_REG(vec2icsr),
|
||||
VEC2ICSR_INIT(vec2icsr) | lvl);
|
||||
}
|
||||
|
||||
void
|
||||
pcctwointr_disestablish(vec)
|
||||
int vec;
|
||||
{
|
||||
|
||||
#ifdef DEBUG
|
||||
if (vec < 0 || vec >= PCCTWOV_MAX) {
|
||||
printf("pcctwo: illegal vector offset: 0x%x\n", vec);
|
||||
panic("pcctwointr_disestablish");
|
||||
}
|
||||
if (sys_pcctwo->sc_vec2icsr[vec] == -1) {
|
||||
printf("pcctwo: unsupported vector: %d\n", vec);
|
||||
panic("pcctwointr_establish");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Disable it in hardware */
|
||||
pcc2_reg_write(sys_pcctwo, sys_pcctwo->sc_vec2icsr[vec], 0);
|
||||
|
||||
(*sys_pcctwo->sc_isrunlink)(sys_pcctwo->sc_isrcookie,
|
||||
vec + sys_pcctwo->sc_vecbase);
|
||||
}
|
||||
|
||||
struct evcnt *
|
||||
pcctwointr_evcnt(lev)
|
||||
int lev;
|
||||
{
|
||||
|
||||
return ((*sys_pcctwo->sc_isrevcnt)(sys_pcctwo->sc_isrcookie, lev));
|
||||
}
|
316
sys/dev/mvme/pcctworeg.h
Normal file
316
sys/dev/mvme/pcctworeg.h
Normal file
@ -0,0 +1,316 @@
|
||||
/* $NetBSD: pcctworeg.h,v 1.1 2002/02/12 20:38:49 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Register definitions for the PCCchip2 device, and offset to the
|
||||
* various subordinate devices which hang off it.
|
||||
*/
|
||||
#ifndef _MVME_PCCTWOREG_H
|
||||
#define _MVME_PCCTWOREG_H
|
||||
|
||||
/*
|
||||
* Offsets to the various devices which hang off the PCCChip2.
|
||||
* Note that these are offsets from the base of the PCCChip2's
|
||||
* own registers.
|
||||
*/
|
||||
#define PCCTWO_REG_OFF 0x00000 /* Offset of PCCChip2's own registers */
|
||||
#define PCCTWO_LPT_OFF 0x00000 /* Offset of parallel port registers */
|
||||
#define PCCTWO_SCC_OFF 0x03000 /* Offset of CD2401 Serial Comms chip */
|
||||
#define PCCTWO_IE_OFF 0x04000 /* Offset of 82596 LAN controller */
|
||||
#define PCCTWO_NCRSC_OFF 0x05000 /* Offset of NCR53C710 SCSI chip */
|
||||
|
||||
/*
|
||||
* The two devices on mvme1[67]2's MCchip
|
||||
*/
|
||||
#define MCCHIP_ZS0_OFF 0x03000
|
||||
#define MCCHIP_ZS1_OFF 0x03800
|
||||
|
||||
/*
|
||||
* This is needed to figure out the boot device.
|
||||
* (The physical address of the boot device's registers are passed in
|
||||
* from the Boot ROM)
|
||||
*/
|
||||
#define PCCTWO_PADDR(off) ((void *)(0xfff42000u + (off)))
|
||||
|
||||
|
||||
/*
|
||||
* The layout of the PCCchip2's Registers.
|
||||
* Each one is 8-bits wide, unless otherwise indicated.
|
||||
*/
|
||||
#define PCC2REG_CHIP_ID 0x00 /* Chip ID */
|
||||
#define PCC2REG_CHIP_REVISION 0x01 /* Chip Revision */
|
||||
#define PCC2REG_GENERAL_CONTROL 0x02 /* General Control */
|
||||
#define PCC2REG_VECTOR_BASE 0x03 /* Vector Base */
|
||||
#define PCC2REG_TIMER1_COMPARE 0x04 /* Tick Timer 1 Compare (32-bit) */
|
||||
#define PCC2REG_TIMER1_COUNTER 0x08 /* Tick Timer 1 Counter (32-bit) */
|
||||
#define PCC2REG_TIMER2_COMPARE 0x0c /* Tick Timer 2 Compare (32-bit) */
|
||||
#define PCC2REG_TIMER2_COUNTER 0x10 /* Tick Timer 2 Counter (32-bit) */
|
||||
#define PCC2REG_PRESCALE_COUNT 0x14 /* Prescaler Count */
|
||||
#define PCC2REG_PRESCALE_ADJUST 0x15 /* Prescaler Clock Adjust */
|
||||
#define PCC2REG_TIMER2_CONTROL 0x16 /* Tick Timer 2 Control */
|
||||
#define PCC2REG_TIMER1_CONTROL 0x17 /* Tick Timer 1 Control */
|
||||
#define PCC2REG_GPIO_ICSR 0x18 /* GP Input Interrupt Control */
|
||||
#define PCC2REG_GPIO_CONTROL 0x19 /* GP Input/Output Control */
|
||||
#define PCC2REG_TIMER2_ICSR 0x1a /* Tick Timer 2 Interrupt Control */
|
||||
#define PCC2REG_TIMER1_ICSR 0x1b /* Tick Timer 1 Interrupt Control */
|
||||
#define PCC2REG_SCC_ERR_STATUS 0x1c /* SCC Error Status */
|
||||
#define PCC2REG_SCC_MODEM_ICSR 0x1d /* SCC Modem Interrupt Control */
|
||||
#define PCC2REG_SCC_TX_ICSR 0x1e /* SCC Transmit Interrupt Control */
|
||||
#define PCC2REG_SCC_RX_ICSR 0x1f /* SCC Receive Interrupt Control */
|
||||
#define PCC2REG_SCC_MODEM_PIACK 0x23 /* SCC Modem PIACK */
|
||||
#define PCC2REG_SCC_TX_PIACK 0x25 /* SCC Transmit PIACK */
|
||||
#define PCC2REG_SCC_RX_PIACK 0x27 /* SCC Receive PIACK */
|
||||
#define PCC2REG_ETH_ERR_STATUS 0x28 /* LANC Error Status */
|
||||
#define PCC2REG_ETH_ICSR 0x2a /* LANC Interrupt Control */
|
||||
#define PCC2REG_ETH_BERR_STATUS 0x2b /* LANC Bus Error Interrupt Ctrl */
|
||||
#define PCC2REG_SCSI_ERR_STATUS 0x2c /* SCSI Error Status */
|
||||
#define PCC2REG_SCSI_ICSR 0x2f /* SCSI Interrupt Control */
|
||||
#define PCC2REG_PRT_ACK_ICSR 0x30 /* Printer ACK Interrupt Control */
|
||||
#define PCC2REG_PRT_FAULT_ICSR 0x31 /* Printer FAULT Interrupt Ctrl */
|
||||
#define PCC2REG_PRT_SEL_ICSR 0x32 /* Printer SEL Interrupt Control */
|
||||
#define PCC2REG_PRT_PE_ICSR 0x33 /* Printer PE Interrupt Control */
|
||||
#define PCC2REG_PRT_BUSY_ICSR 0x34 /* Printer BUSY Interrupt Control */
|
||||
#define PCC2REG_PRT_INPUT_STATUS 0x36 /* Printer Input Status */
|
||||
#define PCC2REG_PRT_CONTROL 0x37 /* Printer Port Control */
|
||||
#define PCC2REG_CHIP_SPEED 0x38 /* Chip Speed (16-bit) */
|
||||
#define PCC2REG_PRT_DATA 0x3a /* Printer Data (16-bit) */
|
||||
#define PCC2REG_IRQ_LEVEL 0x3e /* Interrupt Priority Level */
|
||||
#define PCC2REG_IRQ_MASK 0x3f /* Interrupt Mask */
|
||||
|
||||
/*
|
||||
* Additions to the registers for the MCChip. Some of these overlap with
|
||||
* the PCCchip2's registers, but only where hardware is not present, eg.
|
||||
* the printer registers.
|
||||
*/
|
||||
#define MCCHIPREG_TIMER4_ICSR 0x18 /* Tick timer 4 interrupt control */
|
||||
#define MCCHIPREG_TIMER3_ICSR 0x19 /* Tick timer 4 interrupt control */
|
||||
#define MCCHIPREG_PARERR_ICSR 0x1c /* Parity error interrupt control */
|
||||
#define MCCHIPREG_SCC_ICSR 0x1d /* ZS-85230 interrupt control */
|
||||
#define MCCHIPREG_TIMER4_CTRL 0x1e /* Tick timer 4 control */
|
||||
#define MCCHIPREG_TIMER3_CTRL 0x1f /* Tick timer 3 control */
|
||||
#define MCCHIPREG_DRAM_BAR 0x20 /* DRAM Base Address (16-bits) */
|
||||
#define MCCHIPREG_SRAM_BAR 0x22 /* SRAM Base Address (16-bits) */
|
||||
#define MCCHIPREG_DRAM_SIZE 0x24 /* DRAM Size */
|
||||
#define MCCHIPREG_RAM_OPTIONS 0x25 /* DRAM/SRAM Options */
|
||||
#define MCCHIPREG_SRAM_SIZE 0x26 /* SRAM Size */
|
||||
#define MCCHIPREG_GP_INPUTS 0x2d /* General Purpose Inputs */
|
||||
#define MCCHIPREG_162_VERSION 0x2e /* MVME162-LX Series Version */
|
||||
#define MCCHIPREG_TIMER3_COMP 0x30 /* Tick Timer 3 Compare (32-bit) */
|
||||
#define MCCHIPREG_TIMER3_CNTR 0x34 /* Tick Timer 3 Counter (32-bit) */
|
||||
#define MCCHIPREG_TIMER4_COMP 0x38 /* Tick Timer 4 Compare (32-bit) */
|
||||
#define MCCHIPREG_TIMER4_CNTR 0x3c /* Tick Timer 4 Counter (32-bit) */
|
||||
#define MCCHIPREG_BUS_CLOCK 0x40 /* Bus Clock */
|
||||
#define MCCHIPREG_EPROM_TIMING 0x41 /* EPROM Access Time Control */
|
||||
#define MCCHIPREG_FLASH_TIMING 0x42 /* FLASH Access Time Control */
|
||||
#define MCCHIPREG_ABORT_ICSR 0x43 /* ABORT Switch Interrupt Control */
|
||||
#define MCCHIPREG_RESET_CONTROL 0x44 /* Reset Switch Control */
|
||||
#define MCCHIPREG_WDOG_CONTROL 0x45 /* Watchdog Timer Control */
|
||||
#define MCCHIPREG_TIMEBASE_SEL 0x46 /* Access & Watchdog Timebase Select */
|
||||
#define MCCHIPREG_DRAM_CONTROL 0x48 /* Parity DRAM Control */
|
||||
#define MCCHIPREG_MPU_STATUS 0x4a /* MPU Status */
|
||||
#define MCCHIPREG_PRESCALER 0x4c /* Prescaler Count Register (32-bits) */
|
||||
|
||||
/*
|
||||
* PCCchip2's register size is 0x40. MCchip's is 0x50. Plump for the latter.
|
||||
*/
|
||||
#define PCC2REG_SIZE 0x50
|
||||
|
||||
/*
|
||||
* Convenience macroes for accessing the PCCChip2's registers
|
||||
* through bus_space.
|
||||
*/
|
||||
#define pcc2_reg_read(sc,r) \
|
||||
bus_space_read_1((sc)->sc_bust, (sc)->sc_bush, (r))
|
||||
#define pcc2_reg_read16(sc,r) \
|
||||
bus_space_read_2((sc)->sc_bust, (sc)->sc_bush, (r))
|
||||
#define pcc2_reg_read32(sc,r) \
|
||||
bus_space_read_4((sc)->sc_bust, (sc)->sc_bush, (r))
|
||||
#define pcc2_reg_write(sc,r,v) \
|
||||
bus_space_write_1((sc)->sc_bust, (sc)->sc_bush, (r), (v))
|
||||
#define pcc2_reg_write16(sc,r,v) \
|
||||
bus_space_write_2((sc)->sc_bust, (sc)->sc_bush, (r), (v))
|
||||
#define pcc2_reg_write32(sc,r,v) \
|
||||
bus_space_write_4((sc)->sc_bust, (sc)->sc_bush, (r), (v))
|
||||
|
||||
/*
|
||||
* We use the interrupt vector bases suggested in the Motorola Docs...
|
||||
* The first is written to the PCCChip2 for interrupt sources under
|
||||
* its control. The second is written to the CD2401's Local Interrupt
|
||||
* Vector Register. Thus, we don't use the Auto-Vector facilities
|
||||
* for the CD2401, as recommended in the PCCChip2 Programmer's Guide.
|
||||
* The third is used as a base for the ZS85230 serial chips on mvme162.
|
||||
*/
|
||||
#define PCCTWO_VECBASE 0x50
|
||||
#define PCCTWO_SCC_VECBASE 0x5c
|
||||
#define MCCHIP_ZS_VECBASE 0x5c
|
||||
|
||||
/*
|
||||
* PCCchip2 Vector Encoding (Offsets from PCCTWO_VECBASE)
|
||||
* The order 0x0 -> 0xf also indicates priority, with 0x0 lowest.
|
||||
*/
|
||||
#define PCCTWOV_PRT_BUSY 0x0 /* Printer Port 'BSY' */
|
||||
#define PCCTWOV_PRT_PE 0x1 /* Printer Port 'PE' (Paper Empty) */
|
||||
#define PCCTWOV_PRT_SELECT 0x2 /* Printer Port 'SELECT' */
|
||||
#define PCCTWOV_PRT_FAULT 0x3 /* Printer Port 'FAULT' */
|
||||
#define PCCTWOV_PRT_ACK 0x4 /* Printer Port 'ACK' */
|
||||
#define PCCTWOV_SCSI 0x5 /* SCSI Interrupt */
|
||||
#define PCCTWOV_LANC_ERR 0x6 /* LAN Controller Error */
|
||||
#define PCCTWOV_LANC_IRQ 0x7 /* LAN Controller Interrupt */
|
||||
#define PCCTWOV_TIMER2 0x8 /* Tick Timer 2 Interrupt */
|
||||
#define PCCTWOV_TIMER1 0x9 /* Tick Timer 1 Interrupt */
|
||||
#define PCCTWOV_GPIO 0xa /* General Purpose Input Interrupt */
|
||||
#define PCCTWOV_SCC_RX_EXCEP 0xc /* SCC Receive Exception */
|
||||
#define PCCTWOV_SCC_MODEM 0xd /* SCC Modem (Non-Auto-vector mode) */
|
||||
#define PCCTWOV_SCC_TX 0xe /* SCC Tx (Non-Auto-vector mode) */
|
||||
#define PCCTWOV_SCC_RX 0xf /* SCC Rx (Non-Auto-vector mode) */
|
||||
#define PCCTWOV_MAX 16
|
||||
|
||||
/*
|
||||
* MCchip-specific Vector Encoding (Offsets from PCCTWO_VECBASE)
|
||||
*/
|
||||
#define MCCHIPV_TIMER4 0x3 /* Tick Timer 4 Interrupt */
|
||||
#define MCCHIPV_TIMER3 0x4 /* Tick Timer 3 Interrupt */
|
||||
#define MCCHIPV_PARITY_ERR 0xb /* Parity DRAM Error Exception */
|
||||
#define MCCHIPV_ZS0 0xc /* First ZS85230 Interrupt Vector */
|
||||
#define MCCHIPV_ZS1 0xc /* Second ZS85230 Interrupt Vector */
|
||||
#define MCCHIPV_ABORT 0xe /* Abort Switch */
|
||||
|
||||
/*
|
||||
* How to identify the PCCchip2 from an MCchip
|
||||
*/
|
||||
#define PCCTWO_CHIP_ID_PCC2 0x20
|
||||
#define PCCTWO_CHIP_ID_MCCHIP 0x84
|
||||
|
||||
|
||||
/*
|
||||
* Bit Values for the General Control Register (PCC2REG_GENERAL_CONTROL)
|
||||
*/
|
||||
#define PCCTWO_GEN_CTRL_FAST (1u<<0) /* BBRAM Speed Control */
|
||||
#define PCCTWO_GEN_CTRL_MIEN (1u<<1) /* Master Interrupt Enable */
|
||||
#define PCCTWO_GEN_CTRL_C040 (1u<<2) /* Set when CPU is mc68k family */
|
||||
#define PCCTWO_GEN_CTRL_DR0 (1u<<3) /* Download ROM at 0 (mvme166 only) */
|
||||
|
||||
|
||||
/*
|
||||
* Calculate the Prescaler Adjust value for a given
|
||||
* value of BCLK in MHz. (PCC2REG_PRESCALE_ADJUST)
|
||||
*/
|
||||
#define PCCTWO_PRES_ADJ(mhz) (256 - (mhz))
|
||||
|
||||
|
||||
/*
|
||||
* Calculate the Tick Timer Compare register value for
|
||||
* a given number of micro-seconds. With the PCCChip2,
|
||||
* this is simple since the Tick Counters already have
|
||||
* a 1uS period. (PCC2REG_TIMER[12]_COMPARE)
|
||||
*/
|
||||
#define PCCTWO_US2LIM(us) (us)
|
||||
#define PCCTWO_LIM2US(lim) (lim)
|
||||
|
||||
/*
|
||||
* The Tick Timer Control Registers (PCC2REG_TIMER[12]_CONTROL)
|
||||
*/
|
||||
#define PCCTWO_TT_CTRL_CEN (1u<<0) /* Counter Enable */
|
||||
#define PCCTWO_TT_CTRL_COC (1u<<1) /* Clear On Compare */
|
||||
#define PCCTWO_TT_CTRL_COVF (1u<<2) /* Clear Overflow Counter */
|
||||
#define PCCTWO_TT_CTRL_OVF(r) ((r)>>4)/* Value of the Overflow Counter */
|
||||
|
||||
|
||||
/*
|
||||
* All the Interrupt Control Registers (PCC2REG_*_ICSR) on the PCCChip2
|
||||
* mostly share the same basic layout. These are defined as follows:
|
||||
*/
|
||||
#define PCCTWO_ICR_LEVEL_MASK 0x7 /* Mask for the interrupt level */
|
||||
#define PCCTWO_ICR_ICLR (1u<<3) /* Clear Int. (edge-sensitive mode) */
|
||||
#define PCCTWO_ICR_AVEC (1u<<3) /* Enable Auto-Vector Mode */
|
||||
#define PCCTWO_ICR_IEN (1u<<4) /* Interrupt Enable */
|
||||
#define PCCTWO_ICR_INT (1u<<5) /* Interrupt Active */
|
||||
#define PCCTWO_ICR_LEVEL (0u<<6) /* Level Triggered */
|
||||
#define PCCTWO_ICR_EDGE (1u<<6) /* Edge Triggered */
|
||||
#define PCCTWO_ICR_RISE_HIGH (0u<<7) /* Polarity: Rising Edge or Hi Level */
|
||||
#define PCCTWO_ICR_FALL_LOW (1u<<7) /* Polarity: Falling Edge or Lo Level */
|
||||
#define PCCTWO_ICR_SC_RD(r) ((r)>>6)/* Get Snoop Control Bits */
|
||||
#define PCCTWO_ICR_SC_WR(r) ((r)<<6)/* Write Snoop Control Bits */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Most of the Error Status Registers (PCC2REG_*_ERR_STATUS) mostly
|
||||
* follow the same layout. These error registers are used when a
|
||||
* device (eg. SCC, LANC) is mastering the PCCChip2's local bus (for
|
||||
* example, performing a DMA) and some error occurs. The bits are
|
||||
* defined as follows:
|
||||
*/
|
||||
#define PCCTWO_ERR_SR_SCLR (1u<<0) /* Clear Error Status */
|
||||
#define PCCTWO_ERR_SR_LTO (1u<<1) /* Local Bus Timeout */
|
||||
#define PCCTWO_ERR_SR_EXT (1u<<2) /* External (VMEbus) Error */
|
||||
#define PCCTWO_ERR_SR_PRTY (1u<<3) /* DRAM Parity Error */
|
||||
#define PCCTWO_ERR_SR_RTRY (1u<<4) /* Retry Required */
|
||||
#define PCCTWO_ERR_SR_MASK 0x0Eu
|
||||
|
||||
|
||||
/*
|
||||
* General Purpose Input/Output Pin Control Register
|
||||
* (PCC2REG_GPIO_CONTROL)
|
||||
*/
|
||||
#define PCCTWO_GPIO_CTRL_GPO (1u<<0) /* Controls the GP Output Pin */
|
||||
#define PCCTWO_GPIO_CTRL_GPOE (1u<<1) /* General Purpose Output Enable */
|
||||
#define PCCTWO_GPIO_CTRL_GPI (1u<<3) /* The current state of the GP Input */
|
||||
|
||||
|
||||
/*
|
||||
* Printer Input Status Register (PCC2REG_PRT_INPUT_STATUS)
|
||||
*/
|
||||
#define PCCTWO_PRT_IN_SR_BSY (1u<<0) /* State of printer's BSY Input */
|
||||
#define PCCTWO_PRT_IN_SR_PE (1u<<1) /* State of printer's PE Input */
|
||||
#define PCCTWO_PRT_IN_SR_SEL (1u<<2) /* State of printer's SELECT Input */
|
||||
#define PCCTWO_PRT_IN_SR_FLT (1u<<3) /* State of printer's FAULT Input */
|
||||
#define PCCTWO_PRT_IN_SR_ACK (1u<<4) /* State of printer's ACK Input */
|
||||
#define PCCTWO_PRT_IN_SR_PINT (1u<<7) /* Printer Interrupt Status */
|
||||
|
||||
|
||||
/*
|
||||
* Printer Port Control Register (PCC2REG_PRT_CONTROL)
|
||||
*/
|
||||
#define PCCTWO_PRT_CTRL_MAN (1u<<0) /* Manual Strobe Control */
|
||||
#define PCCTWO_PRT_CTRL_FAST (1u<<1) /* Fast Auto Strobe */
|
||||
#define PCCTWO_PRT_CTRL_STB (1u<<2) /* Strobe Pin, in manual control mode */
|
||||
#define PCCTWO_PRT_CTRL_INP (1u<<3) /* Printer Input Prime */
|
||||
#define PCCTWO_PRT_CTRL_DOEN (1u<<4) /* Printer Data Output Enable */
|
||||
|
||||
#endif /* _MVME_PCCTWOREG_H */
|
103
sys/dev/mvme/pcctwovar.h
Normal file
103
sys/dev/mvme/pcctwovar.h
Normal file
@ -0,0 +1,103 @@
|
||||
/* $NetBSD: pcctwovar.h,v 1.1 2002/02/12 20:38:50 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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.
|
||||
*/
|
||||
|
||||
#ifndef _MVME_PCCTWOVAR_H
|
||||
#define _MVME_PCCTWOVAR_H
|
||||
|
||||
/*
|
||||
* Structure used to attach PCC devices.
|
||||
*/
|
||||
struct pcctwo_attach_args {
|
||||
const char *pa_name; /* name of device */
|
||||
int pa_ipl; /* interrupt level */
|
||||
bus_dma_tag_t pa_dmat; /* DMA tag */
|
||||
bus_space_tag_t pa_bust; /* Bus tag */
|
||||
bus_addr_t pa_offset; /* Offset with 'Bus tag' bus space */
|
||||
|
||||
bus_addr_t _pa_base;
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure used to describe a device for autoconfiguration purposes.
|
||||
*/
|
||||
struct pcctwo_device {
|
||||
char *pcc_name; /* name of device (e.g. "clock") */
|
||||
bus_addr_t pcc_offset; /* offset from PCC2 base */
|
||||
};
|
||||
|
||||
/*
|
||||
* Macroes to make life easy when converting vector offset to interrupt
|
||||
* control register, and how to initialise the ICSR.
|
||||
*/
|
||||
#define VEC2ICSR(r,v) ((r) | (((v) | PCCTWO_ICR_IEN) << 8))
|
||||
#define VEC2ICSR_REG(x) ((x) & 0xff)
|
||||
#define VEC2ICSR_INIT(x) ((x) >> 8)
|
||||
|
||||
/* Shorthand for locators. */
|
||||
#include "locators.h"
|
||||
#define pcctwocf_ipl cf_loc[PCCTWOCF_IPL]
|
||||
|
||||
/*
|
||||
* PCCChip2 driver's soft state structure
|
||||
*/
|
||||
struct pcctwo_softc {
|
||||
struct device sc_dev;
|
||||
bus_space_tag_t sc_bust; /* PCCChip2's register tag */
|
||||
bus_space_handle_t sc_bush; /* PCCChip2's register handle */
|
||||
bus_dma_tag_t sc_dmat; /* PCCChip2's dma tag (unused)*/
|
||||
int *sc_vec2icsr; /* Translate vector to ICSR */
|
||||
int sc_vecbase;
|
||||
void *sc_isrcookie;
|
||||
void (*sc_isrlink)(void *, int (*)(void *), void *,
|
||||
int, int, struct evcnt *);
|
||||
void (*sc_isrunlink)(void *, int);
|
||||
struct evcnt * (*sc_isrevcnt)(void *, int);
|
||||
#if defined(MVME162) || defined(MVME172)
|
||||
struct evcnt sc_evcnt;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct pcctwo_softc *sys_pcctwo;
|
||||
|
||||
extern void pcctwo_init(struct pcctwo_softc *, struct pcctwo_device *, int);
|
||||
extern struct evcnt *pcctwointr_evcnt(int);
|
||||
extern void pcctwointr_establish(int, int (*)(void *), int, void *,
|
||||
struct evcnt *);
|
||||
extern void pcctwointr_disestablish(int);
|
||||
|
||||
#endif /* _MVME_PCCTWOVAR_H */
|
353
sys/dev/mvme/vme_two.c
Normal file
353
sys/dev/mvme/vme_two.c
Normal file
@ -0,0 +1,353 @@
|
||||
/* $NetBSD: vme_two.c,v 1.1 2002/02/12 20:38:50 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford.
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* VME support specific to the VMEchip2 found on all high-end MVME boards
|
||||
*/
|
||||
|
||||
#include "vmetwo.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/vme/vmereg.h>
|
||||
#include <dev/vme/vmevar.h>
|
||||
|
||||
#include <dev/mvme/mvmebus.h>
|
||||
#include <dev/mvme/vme_tworeg.h>
|
||||
#include <dev/mvme/vme_twovar.h>
|
||||
|
||||
void vmetwo_master_range(struct vmetwo_softc *, int, struct mvmebus_range *);
|
||||
void vmetwo_slave_range(struct vmetwo_softc *, int, vme_am_t,
|
||||
struct mvmebus_range *);
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
vmetwo_init(sc)
|
||||
struct vmetwo_softc *sc;
|
||||
{
|
||||
u_int32_t reg;
|
||||
int i;
|
||||
|
||||
/* Initialise stuff for the common mvmebus front-end */
|
||||
sc->sc_mvmebus.sc_chip = sc;
|
||||
sc->sc_mvmebus.sc_nmasters = VME2_NMASTERS;
|
||||
sc->sc_mvmebus.sc_masters = &sc->sc_master[0];
|
||||
sc->sc_mvmebus.sc_nslaves = VME2_NSLAVES;
|
||||
sc->sc_mvmebus.sc_slaves = &sc->sc_slave[0];
|
||||
sc->sc_mvmebus.sc_intr_establish = vmetwo_intr_establish;
|
||||
sc->sc_mvmebus.sc_intr_disestablish = vmetwo_intr_disestablish;
|
||||
|
||||
/* Initialise interrupts */
|
||||
vmetwo_intr_init(sc);
|
||||
|
||||
reg = vme2_lcsr_read(sc, VME2LCSR_BOARD_CONTROL);
|
||||
printf(": Type 2 VMEchip, scon jumper %s\n",
|
||||
(reg & VME2_BOARD_CONTROL_SCON) ? "enabled" : "disabled");
|
||||
|
||||
/*
|
||||
* Figure out what bits of the VMEbus we can access.
|
||||
* First record the `fixed' maps (if they're enabled)
|
||||
*/
|
||||
reg = vme2_lcsr_read(sc, VME2LCSR_IO_CONTROL);
|
||||
if (reg & VME2_IO_CONTROL_I1EN) {
|
||||
/* This range is fixed to A16, DATA */
|
||||
sc->sc_master[0].vr_am = VME_AM_A16 | MVMEBUS_AM_CAP_DATA;
|
||||
|
||||
/* However, SUPER/USER is selectable... */
|
||||
if (reg & VME2_IO_CONTROL_I1SU)
|
||||
sc->sc_master[0].vr_am |= MVMEBUS_AM_CAP_SUPER;
|
||||
else
|
||||
sc->sc_master[0].vr_am |= MVMEBUS_AM_CAP_USER;
|
||||
|
||||
/* As is the datasize */
|
||||
sc->sc_master[0].vr_datasize = VME_D32 | VME_D16 | VME_D8;
|
||||
if (reg & VME2_IO_CONTROL_I1D16)
|
||||
sc->sc_master[0].vr_datasize &= ~VME_D32;
|
||||
|
||||
sc->sc_master[0].vr_locstart = VME2_IO0_LOCAL_START;
|
||||
sc->sc_master[0].vr_mask = VME2_IO0_MASK;
|
||||
sc->sc_master[0].vr_vmestart = VME2_IO0_VME_START;
|
||||
sc->sc_master[0].vr_vmeend = VME2_IO0_VME_END;
|
||||
} else
|
||||
sc->sc_master[0].vr_am = MVMEBUS_AM_DISABLED;
|
||||
|
||||
if (reg & VME2_IO_CONTROL_I2EN) {
|
||||
/* These two ranges are fixed to A24D16 and A32D16 */
|
||||
sc->sc_master[1].vr_am = VME_AM_A24;
|
||||
sc->sc_master[1].vr_datasize = VME_D16 | VME_D8;
|
||||
sc->sc_master[2].vr_am = VME_AM_A32;
|
||||
sc->sc_master[2].vr_datasize = VME_D16 | VME_D8;
|
||||
|
||||
/* However, SUPER/USER is selectable */
|
||||
if (reg & VME2_IO_CONTROL_I2SU) {
|
||||
sc->sc_master[1].vr_am |= MVMEBUS_AM_CAP_SUPER;
|
||||
sc->sc_master[2].vr_am |= MVMEBUS_AM_CAP_SUPER;
|
||||
} else {
|
||||
sc->sc_master[1].vr_am |= MVMEBUS_AM_CAP_USER;
|
||||
sc->sc_master[2].vr_am |= MVMEBUS_AM_CAP_USER;
|
||||
}
|
||||
|
||||
/* As is PROGRAM/DATA */
|
||||
if (reg & VME2_IO_CONTROL_I2PD) {
|
||||
sc->sc_master[1].vr_am |= MVMEBUS_AM_CAP_PROG;
|
||||
sc->sc_master[2].vr_am |= MVMEBUS_AM_CAP_PROG;
|
||||
} else {
|
||||
sc->sc_master[1].vr_am |= MVMEBUS_AM_CAP_DATA;
|
||||
sc->sc_master[2].vr_am |= MVMEBUS_AM_CAP_DATA;
|
||||
}
|
||||
|
||||
sc->sc_master[1].vr_locstart = VME2_IO1_LOCAL_START;
|
||||
sc->sc_master[1].vr_mask = VME2_IO1_MASK;
|
||||
sc->sc_master[1].vr_vmestart = VME2_IO1_VME_START;
|
||||
sc->sc_master[1].vr_vmeend = VME2_IO1_VME_END;
|
||||
|
||||
sc->sc_master[2].vr_locstart = VME2_IO2_LOCAL_START;
|
||||
sc->sc_master[2].vr_mask = VME2_IO2_MASK;
|
||||
sc->sc_master[2].vr_vmestart = VME2_IO2_VME_START;
|
||||
sc->sc_master[2].vr_vmeend = VME2_IO2_VME_END;
|
||||
} else {
|
||||
sc->sc_master[1].vr_am = MVMEBUS_AM_DISABLED;
|
||||
sc->sc_master[2].vr_am = MVMEBUS_AM_DISABLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now read the progammable maps
|
||||
*/
|
||||
for (i = 0; i < VME2_MASTER_WINDOWS; i++)
|
||||
vmetwo_master_range(sc, i,
|
||||
&(sc->sc_master[i + VME2_MASTER_PROG_START]));
|
||||
|
||||
/* XXX: No A16 slave yet :XXX */
|
||||
sc->sc_slave[VME2_SLAVE_A16].vr_am = MVMEBUS_AM_DISABLED;
|
||||
|
||||
for (i = 0; i < VME2_SLAVE_WINDOWS; i++) {
|
||||
vmetwo_slave_range(sc, i, VME_AM_A32,
|
||||
&sc->sc_slave[i + VME2_SLAVE_PROG_START]);
|
||||
vmetwo_slave_range(sc, i, VME_AM_A24,
|
||||
&sc->sc_slave[i + VME2_SLAVE_PROG_START + 2]);
|
||||
}
|
||||
|
||||
mvmebus_attach(&sc->sc_mvmebus);
|
||||
}
|
||||
|
||||
void
|
||||
vmetwo_master_range(sc, range, vr)
|
||||
struct vmetwo_softc *sc;
|
||||
int range;
|
||||
struct mvmebus_range *vr;
|
||||
{
|
||||
u_int32_t start, end, attr;
|
||||
u_int32_t reg;
|
||||
|
||||
/*
|
||||
* First, check if the range is actually enabled...
|
||||
*/
|
||||
reg = vme2_lcsr_read(sc, VME2LCSR_MASTER_ENABLE);
|
||||
if ((reg & VME2_MASTER_ENABLE(range)) == 0) {
|
||||
vr->vr_am = MVMEBUS_AM_DISABLED;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch and record the range's attributes
|
||||
*/
|
||||
attr = vme2_lcsr_read(sc, VME2LCSR_MASTER_ATTR);
|
||||
attr >>= VME2_MASTER_ATTR_AM_SHIFT(range);
|
||||
|
||||
/*
|
||||
* Fix up the datasizes available through this range
|
||||
*/
|
||||
vr->vr_datasize = VME_D32 | VME_D16 | VME_D8;
|
||||
if (attr & VME2_MASTER_ATTR_D16)
|
||||
vr->vr_datasize &= ~VME_D32;
|
||||
attr &= VME2_MASTER_ATTR_AM_MASK;
|
||||
|
||||
vr->vr_am = (attr & VME_AM_ADRSIZEMASK) | MVMEBUS_AM2CAP(attr);
|
||||
switch (vr->vr_am & VME_AM_ADRSIZEMASK) {
|
||||
case VME_AM_A32:
|
||||
default:
|
||||
vr->vr_mask = 0xffffffffu;
|
||||
break;
|
||||
|
||||
case VME_AM_A24:
|
||||
vr->vr_mask = 0x00ffffffu;
|
||||
break;
|
||||
|
||||
case VME_AM_A16:
|
||||
vr->vr_mask = 0x0000ffffu;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* It would be nice if users of the MI VMEbus code could pass down
|
||||
* whether they can tolerate Write-Posting to their device(s).
|
||||
* XXX
|
||||
*/
|
||||
|
||||
/*
|
||||
* Fetch the local-bus start and end addresses for the range
|
||||
*/
|
||||
reg = vme2_lcsr_read(sc, VME2LCSR_MASTER_ADDRESS(range));
|
||||
start = (reg & VME2_MAST_ADDRESS_START_MASK);
|
||||
start <<= VME2_MAST_ADDRESS_START_SHIFT;
|
||||
end = (reg & VME2_MAST_ADDRESS_END_MASK);
|
||||
end <<= VME2_MAST_ADDRESS_END_SHIFT;
|
||||
|
||||
/*
|
||||
* Local->VMEbus map '4' has optional translation bits, so
|
||||
* the VMEbus start and end addresses may need to be adjusted.
|
||||
*/
|
||||
if (range == 3 && (reg = vme2_lcsr_read(sc, VME2LCSR_MAST4_TRANS))!=0) {
|
||||
uint32_t addr, sel, len = end - start;
|
||||
|
||||
vr->vr_locstart = start;
|
||||
|
||||
reg = vme2_lcsr_read(sc, VME2LCSR_MAST4_TRANS);
|
||||
reg &= VME2_MAST4_TRANS_SELECT_MASK;
|
||||
sel = reg << VME2_MAST4_TRANS_SELECT_SHIFT;
|
||||
|
||||
reg = vme2_lcsr_read(sc, VME2LCSR_MAST4_TRANS);
|
||||
reg &= VME2_MAST4_TRANS_ADDRESS_MASK;
|
||||
addr = reg << VME2_MAST4_TRANS_ADDRESS_SHIFT;
|
||||
|
||||
start = (addr & sel) | (start & (~sel));
|
||||
end = start + len;
|
||||
vr->vr_mask &= len - 1;
|
||||
} else
|
||||
vr->vr_locstart = 0;
|
||||
|
||||
/* XXX Deal with overlap of onboard RAM address space */
|
||||
/* XXX Then again, 167-Bug warns about this at setup time ... */
|
||||
|
||||
/*
|
||||
* Fixup the addresses this range corresponds to
|
||||
*/
|
||||
vr->vr_vmestart = start;
|
||||
vr->vr_vmeend = end - 1;
|
||||
}
|
||||
|
||||
void
|
||||
vmetwo_slave_range(sc, range, am, vr)
|
||||
struct vmetwo_softc *sc;
|
||||
int range;
|
||||
vme_am_t am;
|
||||
struct mvmebus_range *vr;
|
||||
{
|
||||
u_int32_t reg;
|
||||
|
||||
/*
|
||||
* First, check if the range is actually enabled.
|
||||
* Note that bit 1 of `range' is used to indicte if we're
|
||||
* looking for an A24 range (set) or an A32 range (clear).
|
||||
*/
|
||||
reg = vme2_lcsr_read(sc, VME2LCSR_SLAVE_CTRL);
|
||||
|
||||
if (am == VME_AM_A32 && (reg & VME2_SLAVE_AMSEL_A32(range))) {
|
||||
vr->vr_am = VME_AM_A32;
|
||||
vr->vr_mask = 0xffffffffu;
|
||||
} else
|
||||
if (am == VME_AM_A24 && (reg & VME2_SLAVE_AMSEL_A24(range))) {
|
||||
vr->vr_am = VME_AM_A24;
|
||||
vr->vr_mask = 0x00ffffffu;
|
||||
} else {
|
||||
/* The range is not enabled */
|
||||
vr->vr_am = MVMEBUS_AM_DISABLED;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((reg & VME2_SLAVE_AMSEL_DAT(range)) != 0)
|
||||
vr->vr_am |= MVMEBUS_AM_CAP_DATA;
|
||||
|
||||
if ((reg & VME2_SLAVE_AMSEL_PGM(range)) != 0)
|
||||
vr->vr_am |= MVMEBUS_AM_CAP_PROG;
|
||||
|
||||
if ((reg & VME2_SLAVE_AMSEL_USR(range)) != 0)
|
||||
vr->vr_am |= MVMEBUS_AM_CAP_USER;
|
||||
|
||||
if ((reg & VME2_SLAVE_AMSEL_SUP(range)) != 0)
|
||||
vr->vr_am |= MVMEBUS_AM_CAP_SUPER;
|
||||
|
||||
if ((reg & VME2_SLAVE_AMSEL_BLK(range)) != 0)
|
||||
vr->vr_am |= MVMEBUS_AM_CAP_BLK;
|
||||
|
||||
if ((reg & VME2_SLAVE_AMSEL_BLKD64(range)) != 0)
|
||||
vr->vr_am |= MVMEBUS_AM_CAP_BLKD64;
|
||||
|
||||
vr->vr_datasize = VME_D32 | VME_D16 | VME_D8;
|
||||
|
||||
/*
|
||||
* Record the VMEbus start and end addresses of the slave image
|
||||
*/
|
||||
reg = vme2_lcsr_read(sc, VME2LCSR_SLAVE_ADDRESS(range));
|
||||
vr->vr_vmestart = reg & VME2_SLAVE_ADDRESS_START_MASK;
|
||||
vr->vr_vmestart <<= VME2_SLAVE_ADDRESS_START_SHIFT;
|
||||
vr->vr_vmestart &= vr->vr_mask;
|
||||
vr->vr_vmeend = reg & VME2_SLAVE_ADDRESS_END_MASK;
|
||||
vr->vr_vmeend <<= VME2_SLAVE_ADDRESS_END_SHIFT;
|
||||
vr->vr_vmeend &= vr->vr_mask;
|
||||
vr->vr_vmeend |= 0xffffu;
|
||||
|
||||
/*
|
||||
* Now figure out the local-bus address
|
||||
*/
|
||||
reg = vme2_lcsr_read(sc, VME2LCSR_SLAVE_CTRL);
|
||||
if ((reg & VME2_SLAVE_CTRL_ADDER(range)) != 0) {
|
||||
reg = vme2_lcsr_read(sc, VME2LCSR_SLAVE_TRANS(range));
|
||||
reg &= VME2_SLAVE_TRANS_ADDRESS_MASK;
|
||||
reg <<= VME2_SLAVE_TRANS_ADDRESS_SHIFT;
|
||||
vr->vr_locstart = vr->vr_vmestart + reg;
|
||||
} else {
|
||||
u_int32_t sel, addr;
|
||||
|
||||
reg = vme2_lcsr_read(sc, VME2LCSR_SLAVE_TRANS(range));
|
||||
sel = reg & VME2_SLAVE_TRANS_SELECT_MASK;
|
||||
sel <<= VME2_SLAVE_TRANS_SELECT_SHIFT;
|
||||
addr = reg & VME2_SLAVE_TRANS_ADDRESS_MASK;
|
||||
addr <<= VME2_SLAVE_TRANS_ADDRESS_SHIFT;
|
||||
|
||||
vr->vr_locstart = addr & sel;
|
||||
vr->vr_locstart |= vr->vr_vmestart & (~sel);
|
||||
}
|
||||
}
|
429
sys/dev/mvme/vme_two_isr.c
Normal file
429
sys/dev/mvme/vme_two_isr.c
Normal file
@ -0,0 +1,429 @@
|
||||
/* $NetBSD: vme_two_isr.c,v 1.1 2002/02/12 20:38:51 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford.
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Split off from vme_two.c specifically to deal with hardware assisted
|
||||
* soft interrupts when the user hasn't specified `vmetwo0' in the
|
||||
* kernel config file (mvme1[67]2 only).
|
||||
*/
|
||||
|
||||
#include "vmetwo.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/vme/vmereg.h>
|
||||
#include <dev/vme/vmevar.h>
|
||||
|
||||
#include <dev/mvme/mvmebus.h>
|
||||
#include <dev/mvme/vme_tworeg.h>
|
||||
#include <dev/mvme/vme_twovar.h>
|
||||
|
||||
/*
|
||||
* Non-zero if there is no VMEChip2 on this board.
|
||||
*/
|
||||
int vmetwo_not_present;
|
||||
|
||||
/*
|
||||
* Array of interrupt handlers registered with us for the non-VMEbus
|
||||
* vectored interrupts. Eg. ABORT Switch, SYSFAIL etc.
|
||||
*
|
||||
* We can't just install a caller's handler directly, since these
|
||||
* interrupts have to be manually cleared, so we have a trampoline
|
||||
* which does the clearing automatically.
|
||||
*/
|
||||
static struct vme_two_handler {
|
||||
int (*isr_hand) __P((void *));
|
||||
void *isr_arg;
|
||||
} vme_two_handlers[(VME2_VECTOR_LOCAL_MAX - VME2_VECTOR_LOCAL_MIN) + 1];
|
||||
|
||||
#define VMETWO_HANDLERS_SZ (sizeof(vme_two_handlers) / \
|
||||
sizeof(struct vme_two_handler))
|
||||
|
||||
static int vmetwo_local_isr_trampoline(void *);
|
||||
static void vmetwo_softintr_assert(void);
|
||||
|
||||
static struct vmetwo_softc *vmetwo_sc;
|
||||
|
||||
int
|
||||
vmetwo_probe(bus_space_tag_t bt, bus_addr_t offset)
|
||||
{
|
||||
bus_space_handle_t bh;
|
||||
|
||||
bus_space_map(bt, offset + VME2REG_LCSR_OFFSET, VME2LCSR_SIZE, 0, &bh);
|
||||
|
||||
if (bus_space_peek_4(bt, bh, VME2LCSR_MISC_STATUS, NULL) != 0) {
|
||||
#if defined(MVME162) || defined(MVME172)
|
||||
#if defined(MVME167) || defined(MVME177)
|
||||
if (machineid == MVME_162 || machineid == MVME_172)
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* No VMEChip2 on mvme162/172 is not too big a
|
||||
* deal; we can fall back on timer4 in the
|
||||
* mcchip for h/w assisted soft interrupts...
|
||||
*/
|
||||
extern void pcctwosoftintrinit(void);
|
||||
bus_space_unmap(bt, bh, VME2LCSR_SIZE);
|
||||
vmetwo_not_present = 1;
|
||||
pcctwosoftintrinit();
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
#if defined(MVME167) || defined(MVME177) || defined(MVME88K)
|
||||
/*
|
||||
* No VMEChip2 on mvme167/177, however, is a Big Deal.
|
||||
* In fact, it means the hardware's shot since the
|
||||
* VMEChip2 is not a `build-option' on those boards.
|
||||
*/
|
||||
panic("VMEChip2 not responding! Faulty board?");
|
||||
/* NOTREACHED */
|
||||
#endif
|
||||
#if defined(MVMEPPC)
|
||||
/*
|
||||
* No VMEChip2 on mvmeppc is no big deal.
|
||||
*/
|
||||
bus_space_unmap(bt, bh, VME2LCSR_SIZE);
|
||||
vmetwo_not_present = 1;
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
#if NVMETWO == 0
|
||||
else {
|
||||
/*
|
||||
* The kernel config file has no `vmetwo0' device, but
|
||||
* there is a VMEChip2 on the board. Fix up things
|
||||
* just enough to hook VMEChip2 local interrupts.
|
||||
*/
|
||||
struct vmetwo_softc *sc;
|
||||
|
||||
/* XXX Should check sc != NULL here... */
|
||||
MALLOC(sc, struct vmetwo_softc *, sizeof(*sc), M_DEVBUF,
|
||||
M_NOWAIT);
|
||||
|
||||
sc->sc_mvmebus.sc_bust = bt;
|
||||
sc->sc_lcrh = bh;
|
||||
vmetwo_intr_init(sc);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
bus_space_unmap(bt, bh, VME2LCSR_SIZE);
|
||||
return (1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
vmetwo_intr_init(struct vmetwo_softc *sc)
|
||||
{
|
||||
u_int32_t reg;
|
||||
int i;
|
||||
|
||||
vmetwo_sc = sc;
|
||||
|
||||
/* Clear out the ISR handler array */
|
||||
for (i = 0; i < VMETWO_HANDLERS_SZ; i++)
|
||||
vme_two_handlers[i].isr_hand = NULL;
|
||||
|
||||
/*
|
||||
* Initialize the chip.
|
||||
* Firstly, disable all VMEChip2 Interrupts
|
||||
*/
|
||||
reg = vme2_lcsr_read(sc, VME2LCSR_MISC_STATUS) & ~VME2_MISC_STATUS_MIEN;
|
||||
vme2_lcsr_write(sc, VME2LCSR_MISC_STATUS, reg);
|
||||
vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_ENABLE, 0);
|
||||
vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_CLEAR,
|
||||
VME2_LOCAL_INTERRUPT_CLEAR_ALL);
|
||||
|
||||
/* Zap all the IRQ level registers */
|
||||
for (i = 0; i < VME2_NUM_IL_REGS; i++)
|
||||
vme2_lcsr_write(sc, VME2LCSR_INTERRUPT_LEVEL_BASE + (i * 4), 0);
|
||||
|
||||
/* Disable the tick timers */
|
||||
reg = vme2_lcsr_read(sc, VME2LCSR_TIMER_CONTROL);
|
||||
reg &= ~VME2_TIMER_CONTROL_EN(0);
|
||||
reg &= ~VME2_TIMER_CONTROL_EN(1);
|
||||
vme2_lcsr_write(sc, VME2LCSR_TIMER_CONTROL, reg);
|
||||
|
||||
/* Set the VMEChip2's vector base register to the required value */
|
||||
reg = vme2_lcsr_read(sc, VME2LCSR_VECTOR_BASE);
|
||||
reg &= ~VME2_VECTOR_BASE_MASK;
|
||||
reg |= VME2_VECTOR_BASE_REG_VALUE;
|
||||
vme2_lcsr_write(sc, VME2LCSR_VECTOR_BASE, reg);
|
||||
|
||||
/* Set the Master Interrupt Enable bit now */
|
||||
reg = vme2_lcsr_read(sc, VME2LCSR_MISC_STATUS) | VME2_MISC_STATUS_MIEN;
|
||||
vme2_lcsr_write(sc, VME2LCSR_MISC_STATUS, reg);
|
||||
|
||||
#if defined(MVME167) || defined(MVME177)
|
||||
#if defined(MVME162) || defined(MVME172)
|
||||
if (machineid != MVME_162 && machineid != MVME_172)
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* Let the NMI handler deal with level 7 ABORT switch
|
||||
* interrupts
|
||||
*/
|
||||
vmetwo_intr_establish(sc, 7, 7, VME2_VEC_ABORT, 1,
|
||||
nmihand, NULL, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Setup hardware assisted soft interrupts */
|
||||
vmetwo_intr_establish(sc, 1, 1, VME2_VEC_SOFT0, 1,
|
||||
(int (*)(void *))softintr_dispatch, NULL, NULL);
|
||||
_softintr_chipset_assert = vmetwo_softintr_assert;
|
||||
}
|
||||
|
||||
static int
|
||||
vmetwo_local_isr_trampoline(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct vme_two_handler *isr;
|
||||
int vec;
|
||||
|
||||
vec = (int) arg; /* 0x08 <= vec <= 0x1f */
|
||||
|
||||
/* Clear the interrupt source */
|
||||
vme2_lcsr_write(vmetwo_sc, VME2LCSR_LOCAL_INTERRUPT_CLEAR,
|
||||
VME2_LOCAL_INTERRUPT(vec));
|
||||
|
||||
isr = &vme_two_handlers[vec - VME2_VECTOR_LOCAL_OFFSET];
|
||||
if (isr->isr_hand)
|
||||
(void) (*isr->isr_hand) (isr->isr_arg);
|
||||
else
|
||||
printf("vmetwo: Spurious local interrupt, vector 0x%x\n", vec);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
vmetwo_local_intr_establish(pri, vec, hand, arg, evcnt)
|
||||
int pri, vec;
|
||||
int (*hand)(void *);
|
||||
void *arg;
|
||||
struct evcnt *evcnt;
|
||||
{
|
||||
|
||||
vmetwo_intr_establish(vmetwo_sc, pri, pri, vec, 1, hand, arg, evcnt);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
vmetwo_intr_establish(csc, prior, lvl, vec, first, hand, arg, evcnt)
|
||||
void *csc;
|
||||
int prior, lvl, vec, first;
|
||||
int (*hand)(void *);
|
||||
void *arg;
|
||||
struct evcnt *evcnt;
|
||||
{
|
||||
struct vmetwo_softc *sc = csc;
|
||||
u_int32_t reg;
|
||||
int bitoff;
|
||||
int iloffset, ilshift;
|
||||
int s;
|
||||
|
||||
s = splhigh();
|
||||
|
||||
#if NVMETWO > 0
|
||||
/*
|
||||
* Sort out interrupts generated locally by the VMEChip2 from
|
||||
* those generated by VMEbus devices...
|
||||
*/
|
||||
if (vec >= VME2_VECTOR_LOCAL_MIN && vec <= VME2_VECTOR_LOCAL_MAX) {
|
||||
#endif
|
||||
/*
|
||||
* Local interrupts need to be bounced through some
|
||||
* trampoline code which acknowledges/clears them.
|
||||
*/
|
||||
vme_two_handlers[vec - VME2_VECTOR_LOCAL_MIN].isr_hand = hand;
|
||||
vme_two_handlers[vec - VME2_VECTOR_LOCAL_MIN].isr_arg = arg;
|
||||
hand = vmetwo_local_isr_trampoline;
|
||||
arg = (void *) (vec - VME2_VECTOR_BASE);
|
||||
|
||||
/*
|
||||
* Interrupt enable/clear bit offset is 0x08 - 0x1f
|
||||
*/
|
||||
bitoff = vec - VME2_VECTOR_BASE;
|
||||
#if NVMETWO > 0
|
||||
first = 1; /* Force the interrupt to be enabled */
|
||||
} else {
|
||||
/*
|
||||
* Interrupts originating from the VMEbus are
|
||||
* controlled by an offset of 0x00 - 0x07
|
||||
*/
|
||||
bitoff = lvl - 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Hook the interrupt */
|
||||
(*sc->sc_isrlink)(sc->sc_isrcookie, hand, arg, prior, vec, evcnt);
|
||||
|
||||
/*
|
||||
* Do we need to tell the VMEChip2 to let the interrupt through?
|
||||
* (This is always true for locally-generated interrupts, but only
|
||||
* needs doing once for each VMEbus interrupt level which is hooked)
|
||||
*/
|
||||
#if NVMETWO > 0
|
||||
if (first) {
|
||||
if (evcnt)
|
||||
evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
|
||||
(*sc->sc_isrevcnt)(sc->sc_isrcookie, prior),
|
||||
sc->sc_mvmebus.sc_dev.dv_xname,
|
||||
mvmebus_irq_name[lvl]);
|
||||
#endif
|
||||
iloffset = VME2_ILOFFSET_FROM_VECTOR(bitoff) +
|
||||
VME2LCSR_INTERRUPT_LEVEL_BASE;
|
||||
ilshift = VME2_ILSHIFT_FROM_VECTOR(bitoff);
|
||||
|
||||
/* Program the specified interrupt to signal at 'prior' */
|
||||
reg = vme2_lcsr_read(sc, iloffset);
|
||||
reg &= ~(VME2_INTERRUPT_LEVEL_MASK << ilshift);
|
||||
reg |= (prior << ilshift);
|
||||
vme2_lcsr_write(sc, iloffset, reg);
|
||||
|
||||
/* Clear it */
|
||||
vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_CLEAR,
|
||||
VME2_LOCAL_INTERRUPT(bitoff));
|
||||
|
||||
/* Enable it. */
|
||||
reg = vme2_lcsr_read(sc, VME2LCSR_LOCAL_INTERRUPT_ENABLE);
|
||||
reg |= VME2_LOCAL_INTERRUPT(bitoff);
|
||||
vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_ENABLE, reg);
|
||||
#if NVMETWO > 0
|
||||
}
|
||||
#ifdef DIAGNOSTIC
|
||||
else {
|
||||
/* Verify the interrupt priority is the same */
|
||||
iloffset = VME2_ILOFFSET_FROM_VECTOR(bitoff) +
|
||||
VME2LCSR_INTERRUPT_LEVEL_BASE;
|
||||
ilshift = VME2_ILSHIFT_FROM_VECTOR(bitoff);
|
||||
|
||||
reg = vme2_lcsr_read(sc, iloffset);
|
||||
reg &= (VME2_INTERRUPT_LEVEL_MASK << ilshift);
|
||||
|
||||
if ((prior << ilshift) != reg)
|
||||
panic("vmetwo_intr_establish: priority mismatch!");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
splx(s);
|
||||
}
|
||||
|
||||
void
|
||||
vmetwo_intr_disestablish(csc, lvl, vec, last, evcnt)
|
||||
void *csc;
|
||||
int lvl, vec, last;
|
||||
struct evcnt *evcnt;
|
||||
{
|
||||
struct vmetwo_softc *sc = csc;
|
||||
u_int32_t reg;
|
||||
int iloffset, ilshift;
|
||||
int bitoff;
|
||||
int s;
|
||||
|
||||
s = splhigh();
|
||||
|
||||
#if NVMETWO > 0
|
||||
/*
|
||||
* Sort out interrupts generated locally by the VMEChip2 from
|
||||
* those generated by VMEbus devices...
|
||||
*/
|
||||
if (vec >= VME2_VECTOR_LOCAL_MIN && vec <= VME2_VECTOR_LOCAL_MAX) {
|
||||
#endif
|
||||
/*
|
||||
* Interrupt enable/clear bit offset is 0x08 - 0x1f
|
||||
*/
|
||||
bitoff = vec - VME2_VECTOR_BASE;
|
||||
vme_two_handlers[vec - VME2_VECTOR_LOCAL_MIN].isr_hand = NULL;
|
||||
last = 1; /* Force the interrupt to be cleared */
|
||||
#if NVMETWO > 0
|
||||
} else {
|
||||
/*
|
||||
* Interrupts originating from the VMEbus are
|
||||
* controlled by an offset of 0x00 - 0x07
|
||||
*/
|
||||
bitoff = lvl - 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Do we need to tell the VMEChip2 to block the interrupt?
|
||||
* (This is always true for locally-generated interrupts, but only
|
||||
* needs doing once when the last VMEbus handler for any given level
|
||||
* has been unhooked.)
|
||||
*/
|
||||
if (last) {
|
||||
iloffset = VME2_ILOFFSET_FROM_VECTOR(bitoff) +
|
||||
VME2LCSR_INTERRUPT_LEVEL_BASE;
|
||||
ilshift = VME2_ILSHIFT_FROM_VECTOR(bitoff);
|
||||
|
||||
/* Disable it. */
|
||||
reg = vme2_lcsr_read(sc, VME2LCSR_LOCAL_INTERRUPT_ENABLE);
|
||||
reg &= ~VME2_LOCAL_INTERRUPT(bitoff);
|
||||
vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_ENABLE, reg);
|
||||
|
||||
/* Set the interrupt's level to zero */
|
||||
reg = vme2_lcsr_read(sc, iloffset);
|
||||
reg &= ~(VME2_INTERRUPT_LEVEL_MASK << ilshift);
|
||||
vme2_lcsr_write(sc, iloffset, reg);
|
||||
|
||||
/* Clear it */
|
||||
vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_CLEAR,
|
||||
VME2_LOCAL_INTERRUPT(vec));
|
||||
|
||||
if (evcnt)
|
||||
evcnt_detach(evcnt);
|
||||
}
|
||||
/* Un-hook it */
|
||||
(*sc->sc_isrunlink)(sc->sc_isrcookie, vec);
|
||||
|
||||
splx(s);
|
||||
}
|
||||
|
||||
static void
|
||||
vmetwo_softintr_assert(void)
|
||||
{
|
||||
|
||||
vme2_lcsr_write(vmetwo_sc, VME2LCSR_SOFTINT_SET, VME2_SOFTINT_SET(0));
|
||||
}
|
526
sys/dev/mvme/vme_tworeg.h
Normal file
526
sys/dev/mvme/vme_tworeg.h
Normal file
@ -0,0 +1,526 @@
|
||||
/* $NetBSD: vme_tworeg.h,v 1.1 2002/02/12 20:38:51 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford.
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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.
|
||||
*/
|
||||
|
||||
#ifndef _MVME_VME_TWOREG_H
|
||||
#define _MVME_VME_TWOREG_H
|
||||
|
||||
/*
|
||||
* Where the VMEchip2's registers live relative to the start
|
||||
* of the VMEChip2's register space.
|
||||
*/
|
||||
#define VME2REG_LCSR_OFFSET 0x0000
|
||||
#define VME2REG_GCSR_OFFSET 0x0100
|
||||
|
||||
|
||||
/*
|
||||
* Register map of the Type 2 VMEchip found on many MVME boards.
|
||||
* Note: Only responds to D32 accesses.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Slave window configuration registers
|
||||
*/
|
||||
#define VME2_SLAVE_WINDOWS 2
|
||||
#define VME2LCSR_SLAVE_ADDRESS(x) (0x00 + ((x) * 4))
|
||||
#define VME2_SLAVE_ADDRESS_START_SHIFT 16
|
||||
#define VME2_SLAVE_ADDRESS_START_MASK (0x0000ffffu)
|
||||
#define VME2_SLAVE_ADDRESS_END_SHIFT 0
|
||||
#define VME2_SLAVE_ADDRESS_END_MASK (0xffff0000u)
|
||||
|
||||
#define VME2LCSR_SLAVE_TRANS(x) (0x08 + ((x) * 4))
|
||||
#define VME2_SLAVE_TRANS_SELECT_SHIFT 16
|
||||
#define VME2_SLAVE_TRANS_SELECT_MASK (0x0000ffffu)
|
||||
#define VME2_SLAVE_TRANS_ADDRESS_SHIFT 0
|
||||
#define VME2_SLAVE_TRANS_ADDRESS_MASK (0xffff0000u)
|
||||
|
||||
#define VME2LCSR_SLAVE_CTRL 0x10
|
||||
#define VME2_SLAVE_AMSEL_DAT(x) (1u << (0 + ((x) * 16)))
|
||||
#define VME2_SLAVE_AMSEL_PGM(x) (1u << (1 + ((x) * 16)))
|
||||
#define VME2_SLAVE_AMSEL_BLK(x) (1u << (2 + ((x) * 16)))
|
||||
#define VME2_SLAVE_AMSEL_BLKD64(x) (1u << (3 + ((x) * 16)))
|
||||
#define VME2_SLAVE_AMSEL_A24(x) (1u << (4 + ((x) * 16)))
|
||||
#define VME2_SLAVE_AMSEL_A32(x) (1u << (5 + ((x) * 16)))
|
||||
#define VME2_SLAVE_AMSEL_USR(x) (1u << (6 + ((x) * 16)))
|
||||
#define VME2_SLAVE_AMSEL_SUP(x) (1u << (7 + ((x) * 16)))
|
||||
#define VME2_SLAVE_CTRL_WP(x) (1u << (8 + ((x) * 16)))
|
||||
#define VME2_SLAVE_CTRL_SNOOP_INHIBIT(x) (0u << (9 + ((x) * 16)))
|
||||
#define VME2_SLAVE_CTRL_SNOOP_WRSINK(x) (1u << (9 + ((x) * 16)))
|
||||
#define VME2_SLAVE_CTRL_SNOOP_WRINVAL(x) (2u << (9 + ((x) * 16)))
|
||||
#define VME2_SLAVE_CTRL_ADDER(x) (1u << (11 + ((x) * 16)))
|
||||
|
||||
/*
|
||||
* Master window address control registers
|
||||
*/
|
||||
#define VME2_MASTER_WINDOWS 4
|
||||
#define VME2LCSR_MASTER_ADDRESS(x) (0x14 + ((x) * 4))
|
||||
#define VME2_MAST_ADDRESS_START_SHIFT 16
|
||||
#define VME2_MAST_ADDRESS_START_MASK (0x0000ffffu)
|
||||
#define VME2_MAST_ADDRESS_END_SHIFT 0
|
||||
#define VME2_MAST_ADDRESS_END_MASK (0xffff0000u)
|
||||
|
||||
#define VME2LCSR_MAST4_TRANS 0x24
|
||||
#define VME2_MAST4_TRANS_SELECT_SHIFT 16
|
||||
#define VME2_MAST4_TRANS_SELECT_MASK (0x0000ffffu)
|
||||
#define VME2_MAST4_TRANS_ADDRESS_SHIFT 0
|
||||
#define VME2_MAST4_TRANS_ADDRESS_MASK (0xffff0000u)
|
||||
|
||||
/*
|
||||
* VMEbus master attribute control register
|
||||
*/
|
||||
#define VME2LCSR_MASTER_ATTR 0x28
|
||||
#define VME2_MASTER_ATTR_AM_SHIFT(x) ((x) * 8)
|
||||
#define VME2_MASTER_ATTR_AM_MASK (0x0000003fu)
|
||||
#define VME2_MASTER_ATTR_WP (1u << 6)
|
||||
#define VME2_MASTER_ATTR_D16 (1u << 7)
|
||||
|
||||
/*
|
||||
* GCSR Group/Board addresses, and
|
||||
* VMEbus Master Enable Control register, and
|
||||
* Local to VMEbus I/O Control register, and
|
||||
* ROM Control register (unused).
|
||||
*/
|
||||
#define VME2LCSR_GCSR_ADDRESS 0x2c
|
||||
#define VME2_GCSR_ADDRESS_SHIFT 16
|
||||
#define VME2_GCSR_ADDRESS_MASK (0xfff00000u)
|
||||
|
||||
#define VME2LCSR_MASTER_ENABLE 0x2c
|
||||
#define VME2_MASTER_ENABLE_MASK (0x000f0000u)
|
||||
#define VME2_MASTER_ENABLE(x) (1u << ((x) + 16))
|
||||
|
||||
#define VME2LCSR_IO_CONTROL 0x2c
|
||||
#define VME2_IO_CONTROL_SHIFT 8
|
||||
#define VME2_IO_CONTROL_MASK (0x0000ff00u)
|
||||
#define VME2_IO_CONTROL_I1SU (1u << 8)
|
||||
#define VME2_IO_CONTROL_I1WP (1u << 9)
|
||||
#define VME2_IO_CONTROL_I1D16 (1u << 10)
|
||||
#define VME2_IO_CONTROL_I1EN (1u << 11)
|
||||
#define VME2_IO_CONTROL_I2PD (1u << 12)
|
||||
#define VME2_IO_CONTROL_I2SU (1u << 13)
|
||||
#define VME2_IO_CONTROL_I2WP (1u << 14)
|
||||
#define VME2_IO_CONTROL_I2EN (1u << 15)
|
||||
|
||||
/*
|
||||
* VMEChip2 PROM Decoder, SRAM and DMA Control register
|
||||
*/
|
||||
#define VME2LCSR_PROM_SRAM_DMA_CTRL 0x30
|
||||
#define VME2_PSD_SRAMS_MASK (0x00ff0000u)
|
||||
#define VME2_PSD_SRAMS_CLKS6 (0u << 16)
|
||||
#define VME2_PSD_SRAMS_CLKS5 (1u << 16)
|
||||
#define VME2_PSD_SRAMS_CLKS4 (2u << 16)
|
||||
#define VME2_PSD_SRAMS_CLKS3 (3u << 16)
|
||||
#define VME2_PSD_TBLSC_INHIB (0u << 18)
|
||||
#define VME2_PSD_TBLSC_WRSINK (1u << 18)
|
||||
#define VME2_PSD_TBLSC_WRINV (2u << 18)
|
||||
#define VME2_PSD_ROM0 (1u << 20)
|
||||
#define VME2_PSD_WAITRMW (1u << 21)
|
||||
|
||||
/*
|
||||
* VMEbus requester control register
|
||||
*/
|
||||
#define VME2LCSR_VME_REQUESTER_CONTROL 0x30
|
||||
#define VME2_VMEREQ_CTRL_MASK (0x0000ff00u)
|
||||
#define VME2_VMEREQ_CTRL_LVREQL_MASK (0x00000300u)
|
||||
#define VME2_VMEREQ_CTRL_LVREQL(x) ((u_int)(x) << 8)
|
||||
#define VME2_VMEREQ_CTRL_LVRWD (1u << 10)
|
||||
#define VME2_VMEREQ_CTRL_LVFAIR (1u << 11)
|
||||
#define VME2_VMEREQ_CTRL_DWB (1u << 13)
|
||||
#define VME2_VMEREQ_CTRL_DHB (1u << 14)
|
||||
#define VME2_VMEREQ_CTRL_ROBN (1u << 15)
|
||||
|
||||
/*
|
||||
* DMAC control register
|
||||
*/
|
||||
#define VME2LCSR_DMAC_CONTROL1 0x30
|
||||
#define VME2_DMAC_CTRL1_MASK (0x000000ffu)
|
||||
#define VME2_DMAC_CTRL1_DREQL_MASK (0x00000003u)
|
||||
#define VME2_DMAC_CTRL1_DREQL(x) ((u_int)(x) << 0)
|
||||
#define VME2_DMAC_CTRL1_DRELM_MASK (0x0000000cu)
|
||||
#define VME2_DMAC_CTRL1_DRELM(x) ((u_int)(x) << 2)
|
||||
#define VME2_DMAC_CTRL1_DFAIR (1u << 4)
|
||||
#define VME2_DMAC_CTRL1_DTBL (1u << 5)
|
||||
#define VME2_DMAC_CTRL1_DEN (1u << 6)
|
||||
#define VME2_DMAC_CTRL1_DHALT (1u << 7)
|
||||
|
||||
/*
|
||||
* DMA Control register #2
|
||||
*/
|
||||
#define VME2LCSR_DMAC_CONTROL2 0x34
|
||||
#define VME2_DMAC_CTRL2_MASK (0x0000ffffu)
|
||||
#define VME2_DMAC_CTRL2_SHIFT 0
|
||||
#define VME2_DMAC_CTRL2_AM_MASK (0x0000003fu)
|
||||
#define VME2_DMAC_CTRL2_BLK_D32 (1u << 6)
|
||||
#define VME2_DMAC_CTRL2_BLK_D64 (3u << 6)
|
||||
#define VME2_DMAC_CTRL2_D16 (1u << 8)
|
||||
#define VME2_DMAC_CTRL2_TVME (1u << 9)
|
||||
#define VME2_DMAC_CTRL2_LINC (1u << 10)
|
||||
#define VME2_DMAC_CTRL2_VINC (1u << 11)
|
||||
#define VME2_DMAC_CTRL2_SNOOP_INHIB (0u << 13)
|
||||
#define VME2_DMAC_CTRL2_SNOOP_WRSNK (1u << 13)
|
||||
#define VME2_DMAC_CTRL2_SNOOP_WRINV (2u << 13)
|
||||
#define VME2_DMAC_CTRL2_INTE (1u << 15)
|
||||
|
||||
/*
|
||||
* DMA Controller Local Bus and VMEbus Addresses, Byte
|
||||
* Counter and Table Address Counter registers
|
||||
*/
|
||||
#define VME2LCSR_DMAC_LOCAL_ADDRESS 0x38
|
||||
#define VME2LCSR_DMAC_VME_ADDRESS 0x3c
|
||||
#define VME2LCSR_DMAC_BYTE_COUNTER 0x40
|
||||
#define VME2LCSR_DMAC_TABLE_ADDRESS 0x44
|
||||
|
||||
/*
|
||||
* VMEbus Interrupter Control register
|
||||
*/
|
||||
#define VME2LCSR_INTERRUPT_CONTROL 0x48
|
||||
#define VME2_INT_CTRL_MASK (0xff000000u)
|
||||
#define VME2_INT_CTRL_SHIFT 24
|
||||
#define VME2_INT_CTRL_IRQL_MASK (0x07000000u)
|
||||
#define VME2_INT_CTRL_IRQS (1u << 27)
|
||||
#define VME2_INT_CTRL_IRQC (1u << 28)
|
||||
#define VME2_INT_CTRL_IRQ1S_INT (0u << 29)
|
||||
#define VME2_INT_CTRL_IRQ1S_TICK1 (1u << 29)
|
||||
#define VME2_INT_CTRL_IRQ1S_TICK2 (3u << 29)
|
||||
|
||||
/*
|
||||
* VMEbus Interrupt Vector register
|
||||
*/
|
||||
#define VME2LCSR_INTERRUPT_VECTOR 0x48
|
||||
#define VME2_INTERRUPT_VECTOR_MASK (0x00ff0000u)
|
||||
#define VME2_INTERRUPT_VECTOR_SHIFT 16
|
||||
|
||||
/*
|
||||
* MPU Status register
|
||||
*/
|
||||
#define VME2LCSR_MPU_STATUS 0x48
|
||||
#define VME2_MPU_STATUS_MLOB (1u << 0)
|
||||
#define VME2_MPU_STATUS_MLPE (1u << 1)
|
||||
#define VME2_MPU_STATUS_MLBE (1u << 2)
|
||||
#define VME2_MPU_STATUS_MCLR (1u << 3)
|
||||
|
||||
/*
|
||||
* DMA Interrupt Count register
|
||||
*/
|
||||
#define VME2LCSR_DMAC_INTERRUPT_CONTROL 0x48
|
||||
#define VME2_DMAC_INT_COUNT_MASK (0x0000f000u)
|
||||
#define VME2_DMAC_INT_COUNT_SHIFT 12
|
||||
|
||||
/*
|
||||
* DMA Controller Status register
|
||||
*/
|
||||
#define VME2LCSR_DMAC_STATUS 0x48
|
||||
#define VME2_DMAC_STATUS_DONE (1u << 0)
|
||||
#define VME2_DMAC_STATUS_VME (1u << 1)
|
||||
#define VME2_DMAC_STATUS_TBL (1u << 2)
|
||||
#define VME2_DMAC_STATUS_DLTO (1u << 3)
|
||||
#define VME2_DMAC_STATUS_DLOB (1u << 4)
|
||||
#define VME2_DMAC_STATUS_DLPE (1u << 5)
|
||||
#define VME2_DMAC_STATUS_DLBE (1u << 6)
|
||||
#define VME2_DMAC_STATUS_MLTO (1u << 7)
|
||||
|
||||
|
||||
/*
|
||||
* VMEbus Arbiter Time-out register
|
||||
*/
|
||||
#define VME2LCSR_VME_ARB_TIMEOUT 0x4c
|
||||
#define VME2_VME_ARB_TIMEOUT_ENAB (1u << 24)
|
||||
|
||||
/*
|
||||
* DMA Controller Timers and VMEbus Global Time-out Control registers
|
||||
*/
|
||||
#define VME2LCSR_DMAC_TIME_ONOFF 0x4c
|
||||
#define VME2_DMAC_TIME_ON_MASK (0x001c0000u)
|
||||
#define VME2_DMAC_TIME_ON_16US (0u << 18)
|
||||
#define VME2_DMAC_TIME_ON_32US (1u << 18)
|
||||
#define VME2_DMAC_TIME_ON_64US (2u << 18)
|
||||
#define VME2_DMAC_TIME_ON_128US (3u << 18)
|
||||
#define VME2_DMAC_TIME_ON_256US (4u << 18)
|
||||
#define VME2_DMAC_TIME_ON_512US (5u << 18)
|
||||
#define VME2_DMAC_TIME_ON_1024US (6u << 18)
|
||||
#define VME2_DMAC_TIME_ON_DONE (7u << 18)
|
||||
#define VME2_DMAC_TIME_OFF_MASK (0x00e00000u)
|
||||
#define VME2_DMAC_TIME_OFF_0US (0u << 21)
|
||||
#define VME2_DMAC_TIME_OFF_16US (1u << 21)
|
||||
#define VME2_DMAC_TIME_OFF_32US (2u << 21)
|
||||
#define VME2_DMAC_TIME_OFF_64US (3u << 21)
|
||||
#define VME2_DMAC_TIME_OFF_128US (4u << 21)
|
||||
#define VME2_DMAC_TIME_OFF_256US (5u << 21)
|
||||
#define VME2_DMAC_TIME_OFF_512US (6u << 21)
|
||||
#define VME2_DMAC_TIME_OFF_1024US (7u << 21)
|
||||
#define VME2_VME_GLOBAL_TO_MASK (0x00030000u)
|
||||
#define VME2_VME_GLOBAL_TO_8US (0u << 16)
|
||||
#define VME2_VME_GLOBAL_TO_16US (1u << 16)
|
||||
#define VME2_VME_GLOBAL_TO_256US (2u << 16)
|
||||
#define VME2_VME_GLOBAL_TO_DISABLE (3u << 16)
|
||||
|
||||
/*
|
||||
* VME Access, Local Bus and Watchdog Time-out Control register
|
||||
*/
|
||||
#define VME2LCSR_VME_ACCESS_TIMEOUT 0x4c
|
||||
#define VME2_VME_ACCESS_TIMEOUT_MASK (0x0000c000u)
|
||||
#define VME2_VME_ACCESS_TIMEOUT_64US (0u << 14)
|
||||
#define VME2_VME_ACCESS_TIMEOUT_1MS (1u << 14)
|
||||
#define VME2_VME_ACCESS_TIMEOUT_32MS (2u << 14)
|
||||
#define VME2_VME_ACCESS_TIMEOUT_DISABLE (3u << 14)
|
||||
|
||||
#define VME2LCSR_LOCAL_BUS_TIMEOUT 0x4c
|
||||
#define VME2_LOCAL_BUS_TIMEOUT_MASK (0x00003000u)
|
||||
#define VME2_LOCAL_BUS_TIMEOUT_64US (0u << 12)
|
||||
#define VME2_LOCAL_BUS_TIMEOUT_1MS (1u << 12)
|
||||
#define VME2_LOCAL_BUS_TIMEOUT_32MS (2u << 12)
|
||||
#define VME2_LOCAL_BUS_TIMEOUT_DISABLE (3u << 12)
|
||||
|
||||
#define VME2LCSR_WATCHDOG_TIMEOUT 0x4c
|
||||
#define VME2_WATCHDOG_TIMEOUT_MASK (0x00000f00u)
|
||||
#define VME2_WATCHDOG_TIMEOUT_512US (0u << 8)
|
||||
#define VME2_WATCHDOG_TIMEOUT_1MS (1u << 8)
|
||||
#define VME2_WATCHDOG_TIMEOUT_2MS (2u << 8)
|
||||
#define VME2_WATCHDOG_TIMEOUT_4MS (3u << 8)
|
||||
#define VME2_WATCHDOG_TIMEOUT_8MS (4u << 8)
|
||||
#define VME2_WATCHDOG_TIMEOUT_16MS (5u << 8)
|
||||
#define VME2_WATCHDOG_TIMEOUT_32MS (6u << 8)
|
||||
#define VME2_WATCHDOG_TIMEOUT_64MS (7u << 8)
|
||||
#define VME2_WATCHDOG_TIMEOUT_128MS (8u << 8)
|
||||
#define VME2_WATCHDOG_TIMEOUT_256MS (9u << 8)
|
||||
#define VME2_WATCHDOG_TIMEOUT_512MS (10u << 8)
|
||||
#define VME2_WATCHDOG_TIMEOUT_1S (11u << 8)
|
||||
#define VME2_WATCHDOG_TIMEOUT_4S (12u << 8)
|
||||
#define VME2_WATCHDOG_TIMEOUT_16S (13u << 8)
|
||||
#define VME2_WATCHDOG_TIMEOUT_32S (14u << 8)
|
||||
#define VME2_WATCHDOG_TIMEOUT_64S (15u << 8)
|
||||
|
||||
/*
|
||||
* Prescaler Control register
|
||||
*/
|
||||
#define VME2LCSR_PRESCALER_CONTROL 0x4c
|
||||
#define VME2_PRESCALER_MASK (0x000000ffu)
|
||||
#define VME2_PRESCALER_SHIFT 0
|
||||
#define VME2_PRESCALER_CTRL(c) (256 - (c))
|
||||
|
||||
/*
|
||||
* Tick Timer registers
|
||||
*/
|
||||
#define VME2LCSR_TIMER_COMPARE(x) (0x50 + ((x) * 8))
|
||||
#define VME2LCSR_TIMER_COUNTER(x) (0x54 + ((x) * 8))
|
||||
|
||||
|
||||
/*
|
||||
* Board Control register
|
||||
*/
|
||||
#define VME2LCSR_BOARD_CONTROL 0x60
|
||||
#define VME2_BOARD_CONTROL_RSWE (1u << 24)
|
||||
#define VME2_BOARD_CONTROL_BDFLO (1u << 25)
|
||||
#define VME2_BOARD_CONTROL_CPURS (1u << 26)
|
||||
#define VME2_BOARD_CONTROL_PURS (1u << 27)
|
||||
#define VME2_BOARD_CONTROL_BRFLI (1u << 28)
|
||||
#define VME2_BOARD_CONTROL_SFFL (1u << 29)
|
||||
#define VME2_BOARD_CONTROL_SCON (1u << 30)
|
||||
|
||||
/*
|
||||
* Watchdog Timer Control register
|
||||
*/
|
||||
#define VME2LCSR_WATCHDOG_TIMER_CONTROL 0x60
|
||||
#define VME2_WATCHDOG_TCONTROL_WDEN (1u << 16)
|
||||
#define VME2_WATCHDOG_TCONTTRL_WDRSE (1u << 17)
|
||||
#define VME2_WATCHDOG_TCONTTRL_WDSL (1u << 18)
|
||||
#define VME2_WATCHDOG_TCONTTRL_WDBFE (1u << 19)
|
||||
#define VME2_WATCHDOG_TCONTTRL_WDTO (1u << 20)
|
||||
#define VME2_WATCHDOG_TCONTTRL_WDCC (1u << 21)
|
||||
#define VME2_WATCHDOG_TCONTTRL_WDCS (1u << 22)
|
||||
#define VME2_WATCHDOG_TCONTTRL_SRST (1u << 23)
|
||||
|
||||
/*
|
||||
* Tick Timer Control registers
|
||||
*/
|
||||
#define VME2LCSR_TIMER_CONTROL 0x60
|
||||
#define VME2_TIMER_CONTROL_EN(x) (1u << (0 + ((x) * 8)))
|
||||
#define VME2_TIMER_CONTROL_COC(x) (1u << (1 + ((x) * 8)))
|
||||
#define VME2_TIMER_CONTROL_COF(x) (1u << (2 + ((x) * 8)))
|
||||
#define VME2_TIMER_CONTROL_OVF_SHIFT(x) (4 + ((x) * 8))
|
||||
#define VME2_TIMER_CONTROL_OVF_MASK(x) (0x000000f0u << (4 + ((x) * 8)))
|
||||
|
||||
/*
|
||||
* Prescaler Counter register
|
||||
*/
|
||||
#define VME2LCSR_PRESCALER_COUNTER 0x64
|
||||
|
||||
/*
|
||||
* Local Bus Interrupter Status/Enable/Clear registers
|
||||
*/
|
||||
#define VME2LCSR_LOCAL_INTERRUPT_STATUS 0x68
|
||||
#define VME2LCSR_LOCAL_INTERRUPT_ENABLE 0x6c
|
||||
#define VME2LCSR_LOCAL_INTERRUPT_CLEAR 0x74
|
||||
#define VME2_LOCAL_INTERRUPT(x) (1u << (x))
|
||||
#define VME2_LOCAL_INTERRUPT_VME(x) (1u << ((x) - 1))
|
||||
#define VME2_LOCAL_INTERRUPT_SWINT(x) (1u << ((x) + 8))
|
||||
#define VME2_LOCAL_INTERRUPT_LM(x) (1u << ((x) + 16))
|
||||
#define VME2_LOCAL_INTERRUPT_SIG(x) (1u << ((x) + 18))
|
||||
#define VME2_LOCAL_INTERRUPT_DMAC (1u << 22)
|
||||
#define VME2_LOCAL_INTERRUPT_VIA (1u << 23)
|
||||
#define VME2_LOCAL_INTERRUPT_TIC(x) (1u << ((x) + 24))
|
||||
#define VME2_LOCAL_INTERRUPT_VI1E (1u << 26)
|
||||
#define VME2_LOCAL_INTERRUPT_PE (1u << 27)
|
||||
#define VME2_LOCAL_INTERRUPT_MWP (1u << 28)
|
||||
#define VME2_LOCAL_INTERRUPT_SYSF (1u << 29)
|
||||
#define VME2_LOCAL_INTERRUPT_ABORT (1u << 30)
|
||||
#define VME2_LOCAL_INTERRUPT_ACFAIL (1u << 31)
|
||||
#define VME2_LOCAL_INTERRUPT_CLEAR_ALL (0xffffff00u)
|
||||
|
||||
/*
|
||||
* Software Interrupt Set register
|
||||
*/
|
||||
#define VME2LCSR_SOFTINT_SET 0x70
|
||||
#define VME2_SOFTINT_SET(x) (1u << ((x) + 8))
|
||||
|
||||
/*
|
||||
* Interrupt Level registers
|
||||
*/
|
||||
#define VME2LCSR_INTERRUPT_LEVEL_BASE 0x78
|
||||
#define VME2_NUM_IL_REGS 4
|
||||
#define VME2_ILOFFSET_FROM_VECTOR(v) (((((VME2_NUM_IL_REGS*8)-1)-(v))/8)<<2)
|
||||
#define VME2_ILSHIFT_FROM_VECTOR(v) (((v) & 7) * 4)
|
||||
#define VME2_INTERRUPT_LEVEL_MASK (0x0fu)
|
||||
|
||||
/*
|
||||
* Vector Base register
|
||||
*/
|
||||
#define VME2LCSR_VECTOR_BASE 0x88
|
||||
#define VME2_VECTOR_BASE_MASK (0xff000000u)
|
||||
#define VME2_VECTOR_BASE_REG_VALUE (0x76000000u)
|
||||
#define VME2_VECTOR_BASE (0x60u)
|
||||
#define VME2_VECTOR_LOCAL_OFFSET (0x08u)
|
||||
#define VME2_VECTOR_LOCAL_MIN (VME2_VECTOR_BASE + 0x08u)
|
||||
#define VME2_VECTOR_LOCAL_MAX (VME2_VECTOR_BASE + 0x1fu)
|
||||
#define VME2_VEC_SOFT0 (VME2_VECTOR_BASE + 0x08u)
|
||||
#define VME2_VEC_SOFT1 (VME2_VECTOR_BASE + 0x09u)
|
||||
#define VME2_VEC_SOFT2 (VME2_VECTOR_BASE + 0x0au)
|
||||
#define VME2_VEC_SOFT3 (VME2_VECTOR_BASE + 0x0bu)
|
||||
#define VME2_VEC_SOFT4 (VME2_VECTOR_BASE + 0x0cu)
|
||||
#define VME2_VEC_SOFT5 (VME2_VECTOR_BASE + 0x0du)
|
||||
#define VME2_VEC_SOFT6 (VME2_VECTOR_BASE + 0x0eu)
|
||||
#define VME2_VEC_SOFT7 (VME2_VECTOR_BASE + 0x0fu)
|
||||
#define VME2_VEC_GCSRLM0 (VME2_VECTOR_BASE + 0x10u)
|
||||
#define VME2_VEC_GCSRLM1 (VME2_VECTOR_BASE + 0x11u)
|
||||
#define VME2_VEC_GCSRSIG0 (VME2_VECTOR_BASE + 0x12u)
|
||||
#define VME2_VEC_GCSRSIG1 (VME2_VECTOR_BASE + 0x13u)
|
||||
#define VME2_VEC_GCSRSIG2 (VME2_VECTOR_BASE + 0x14u)
|
||||
#define VME2_VEC_GCSRSIG3 (VME2_VECTOR_BASE + 0x15u)
|
||||
#define VME2_VEC_DMAC (VME2_VECTOR_BASE + 0x16u)
|
||||
#define VME2_VEC_VIA (VME2_VECTOR_BASE + 0x17u)
|
||||
#define VME2_VEC_TT1 (VME2_VECTOR_BASE + 0x18u)
|
||||
#define VME2_VEC_TT2 (VME2_VECTOR_BASE + 0x19u)
|
||||
#define VME2_VEC_IRQ1 (VME2_VECTOR_BASE + 0x1au)
|
||||
#define VME2_VEC_PARITY_ERROR (VME2_VECTOR_BASE + 0x1bu)
|
||||
#define VME2_VEC_MWP_ERROR (VME2_VECTOR_BASE + 0x1cu)
|
||||
#define VME2_VEC_SYSFAIL (VME2_VECTOR_BASE + 0x1du)
|
||||
#define VME2_VEC_ABORT (VME2_VECTOR_BASE + 0x1eu)
|
||||
#define VME2_VEC_ACFAIL (VME2_VECTOR_BASE + 0x1fu)
|
||||
|
||||
/*
|
||||
* I/O Control register #1
|
||||
*/
|
||||
#define VME2LCSR_GPIO_DIRECTION 0x88
|
||||
#define VME2_GPIO_DIRECTION_OUT(x) (1u << ((x) + 16))
|
||||
|
||||
/*
|
||||
* Misc. Status register
|
||||
*/
|
||||
#define VME2LCSR_MISC_STATUS 0x88
|
||||
#define VME2_MISC_STATUS_ABRTL (1u << 20)
|
||||
#define VME2_MISC_STATUS_ACFL (1u << 21)
|
||||
#define VME2_MISC_STATUS_SYSFL (1u << 22)
|
||||
#define VME2_MISC_STATUS_MIEN (1u << 23)
|
||||
|
||||
/*
|
||||
* GPIO Status register
|
||||
*/
|
||||
#define VME2LCSR_GPIO_STATUS 0x88
|
||||
#define VME2_GPIO_STATUS(x) (1u << ((x) + 8))
|
||||
|
||||
/*
|
||||
* GPIO Control register #2
|
||||
*/
|
||||
#define VME2LCSR_GPIO_CONTROL 0x88
|
||||
#define VME2_GPIO_CONTROL_SET(x) (1u << ((x) + 12))
|
||||
|
||||
/*
|
||||
* General purpose input registers
|
||||
*/
|
||||
#define VME2LCSR_GP_INPUTS 0x88
|
||||
#define VME2_GP_INPUT(x) (1u << (x))
|
||||
|
||||
/*
|
||||
* Miscellaneous Control register
|
||||
*/
|
||||
#define VME2LCSR_MISC_CONTROL 0x8c
|
||||
#define VME2_MISC_CONTROL_DISBGN (1u << 0)
|
||||
#define VME2_MISC_CONTROL_ENINT (1u << 1)
|
||||
#define VME2_MISC_CONTROL_DISBSYT (1u << 2)
|
||||
#define VME2_MISC_CONTROL_NOELBBSY (1u << 3)
|
||||
#define VME2_MISC_CONTROL_DISMST (1u << 4)
|
||||
#define VME2_MISC_CONTROL_DISSRAM (1u << 5)
|
||||
#define VME2_MISC_CONTROL_REVEROM (1u << 6)
|
||||
#define VME2_MISC_CONTROL_MPIRQEN (1u << 7)
|
||||
|
||||
#define VME2LCSR_SIZE 0x90
|
||||
|
||||
|
||||
#define vme2_lcsr_read(s,r) \
|
||||
bus_space_read_4((s)->sc_mvmebus.sc_bust, (s)->sc_lcrh, (r))
|
||||
#define vme2_lcsr_write(s,r,v) \
|
||||
bus_space_write_4((s)->sc_mvmebus.sc_bust, (s)->sc_lcrh, (r), (v))
|
||||
|
||||
|
||||
/*
|
||||
* Locations of the three fixed VMEbus I/O ranges
|
||||
*/
|
||||
#define VME2_IO0_LOCAL_START (0xffff0000u)
|
||||
#define VME2_IO0_MASK (0x0000ffffu)
|
||||
#define VME2_IO0_VME_START (0x00000000u)
|
||||
#define VME2_IO0_VME_END (0x0000ffffu)
|
||||
|
||||
#define VME2_IO1_LOCAL_START (0xf0000000u)
|
||||
#define VME2_IO1_MASK (0x00ffffffu)
|
||||
#define VME2_IO1_VME_START (0x00000000u)
|
||||
#define VME2_IO1_VME_END (0x00ffffffu)
|
||||
|
||||
#define VME2_IO2_LOCAL_START (0x00000000u)
|
||||
#define VME2_IO2_MASK (0xffffffffu)
|
||||
#define VME2_IO2_VME_START (0xf1000000u) /* Maybe starts@ 0x0? */
|
||||
#define VME2_IO2_VME_END (0xff7fffffu)
|
||||
|
||||
#endif /* _MVME_VME_TWOREG_H */
|
79
sys/dev/mvme/vme_twovar.h
Normal file
79
sys/dev/mvme/vme_twovar.h
Normal file
@ -0,0 +1,79 @@
|
||||
/* $NetBSD: vme_twovar.h,v 1.1 2002/02/12 20:38:52 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Steve C. Woodford.
|
||||
*
|
||||
* 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 the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation 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 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.
|
||||
*/
|
||||
|
||||
#ifndef _MVME_VME_TWOVAR_H
|
||||
#define _MVME_VME_TWOVAR_H
|
||||
|
||||
#define VME2_MASTER_FIXED_A16 0
|
||||
#define VME2_MASTER_FIXED_A24 1
|
||||
#define VME2_MASTER_FIXED_A32 2
|
||||
#define VME2_MASTER_PROG_START 3
|
||||
#define VME2_SLAVE_OFFBOARD_RAM 0
|
||||
#define VME2_SLAVE_PROG_START 1
|
||||
#define VME2_SLAVE_A16 (VME2_SLAVE_PROG_START+(VME2_SLAVE_WINDOWS*2))
|
||||
|
||||
#define VME2_NMASTERS (VME2_MASTER_PROG_START + VME2_MASTER_WINDOWS)
|
||||
#define VME2_NSLAVES (VME2_SLAVE_A16 + 1)
|
||||
|
||||
struct vmetwo_softc {
|
||||
struct mvmebus_softc sc_mvmebus;
|
||||
bus_space_handle_t sc_lcrh;
|
||||
bus_space_handle_t sc_gcrh;
|
||||
void *sc_isrcookie;
|
||||
void (*sc_isrlink)(void *, int (*)(void *),
|
||||
void *, int, int, struct evcnt *);
|
||||
void (*sc_isrunlink)(void *, int);
|
||||
struct evcnt * (*sc_isrevcnt)(void *, int);
|
||||
#if NVMETWO > 0
|
||||
struct mvmebus_range sc_master[VME2_NMASTERS];
|
||||
struct mvmebus_range sc_slave[VME2_NSLAVES];
|
||||
#endif
|
||||
};
|
||||
|
||||
extern int vmetwo_not_present;
|
||||
|
||||
void vmetwo_init(struct vmetwo_softc *);
|
||||
int vmetwo_probe(bus_space_tag_t, bus_addr_t);
|
||||
void vmetwo_intr_init(struct vmetwo_softc *);
|
||||
void vmetwo_intr_establish(void *, int, int, int, int,
|
||||
int (*)(void *), void *, struct evcnt *);
|
||||
void vmetwo_intr_disestablish(void *, int, int, int, struct evcnt *);
|
||||
void vmetwo_local_intr_establish(int, int,
|
||||
int (*)(void *), void *, struct evcnt *);
|
||||
|
||||
#endif /* _MVME_VME_TWOVAR_H */
|
Loading…
x
Reference in New Issue
Block a user