Expand on how VMEbus master addressing modes are specified, to better

deal with dynamic address modifier generation based on the CPU's
function code pins.

Also implement VMEbus slave mode for mvme147. (Not yet 100% working.)
This commit is contained in:
scw 2000-08-20 21:51:31 +00:00
parent a86d1f4891
commit 3cac59ee4f
8 changed files with 151 additions and 64 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: mvmebus.c,v 1.2 2000/08/20 17:07:41 scw Exp $ */
/* $NetBSD: mvmebus.c,v 1.3 2000/08/20 21:51:31 scw Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@ -68,7 +68,7 @@ static const char *mvmebus_mod_string(vme_addr_t, vme_size_t,
static int mvmebus_dmamap_load_common(struct mvmebus_softc *, bus_dmamap_t);
static vme_am_t mvmebus_am_cap[] = {
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,
@ -79,9 +79,6 @@ static vme_am_t mvmebus_am_cap[] = {
MVMEBUS_AM_CAP_BLK | MVMEBUS_AM_CAP_SUPER
};
#define MVMEBUS_AM2CAP(am) (mvmebus_am_cap[((am) & \
(VME_AM_MODEMASK | VME_AM_PRIVMASK))])
void
mvmebus_attach(sc)
struct mvmebus_softc *sc;
@ -183,6 +180,7 @@ mvmebus_map(vsc, vmeaddr, len, am, datasize, swap, tag, handle, resc)
struct mvmebus_mapresc *mr;
struct mvmebus_range *vr;
vme_addr_t end;
vme_am_t cap, as;
paddr_t paddr;
int rv, i;
@ -190,20 +188,19 @@ mvmebus_map(vsc, vmeaddr, len, am, datasize, swap, tag, handle, resc)
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; i++, vr++) {
for (i = 0; i < sc->sc_nmasters && paddr == 0; i++, vr++) {
if (vr->vr_am == MVMEBUS_AM_DISABLED)
continue;
if (am != vr->vr_am || datasize > vr->vr_datasize)
continue;
if (vmeaddr >= vr->vr_vmestart && end < vr->vr_vmeend) {
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);
break;
}
}
if (paddr == 0)
return (ENOMEM);
@ -428,18 +425,21 @@ mvmebus_dmamap_create(vsc, len, am, datasize, swap, nsegs,
struct mvmebus_softc *sc = vsc;
struct mvmebus_dmamap *vmap;
struct mvmebus_range *vr;
vme_am_t cap, am2;
vme_am_t cap, as;
int i, rv;
cap = MVMEBUS_AM2CAP(am);
am2 = am & VME_AM_ADRSIZEMASK;
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 (am2 == (vr->vr_am & VME_AM_ADRSIZEMASK) &&
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;
@ -514,6 +514,9 @@ mvmebus_dmamap_load_common(sc, map)
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
@ -716,6 +719,9 @@ mvmebus_dmamem_alloc(vsc, len, am, datasize, swap, segs, nsegs, rsegs, flags)
* 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 (am == (vr->vr_am & VME_AM_ADRSIZEMASK) &&
cap == (vr->vr_am & cap) && datasize <= vr->vr_datasize &&
len <= (vr->vr_vmeend - vr->vr_vmestart))
@ -732,11 +738,6 @@ mvmebus_dmamem_alloc(vsc, len, am, datasize, swap, segs, nsegs, rsegs, flags)
high = vr->vr_locstart + (vr->vr_vmeend - vr->vr_vmestart) + 1;
bound = (bus_size_t) vr->vr_mask + 1;
#ifdef DEBUG
printf("mvmebus_dmamem_alloc: high=0x%08lx,low=0x%08lx,bound=0x%08lx\n",
high, low, bound);
#endif
/*
* Allocate physical memory.
*
@ -849,6 +850,7 @@ mvmebus_mod_string(addr, len, am, ds)
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,");

View File

@ -1,4 +1,4 @@
/* $NetBSD: mvmebus.h,v 1.2 2000/08/20 17:07:41 scw Exp $ */
/* $NetBSD: mvmebus.h,v 1.3 2000/08/20 21:51:31 scw Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@ -67,6 +67,9 @@ struct mvmebus_range {
#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
@ -149,4 +152,6 @@ 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[];
#endif /* _MVMEBUS_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: pcc.c,v 1.13 2000/03/18 22:33:03 scw Exp $ */
/* $NetBSD: pcc.c,v 1.14 2000/08/20 21:51:31 scw Exp $ */
/*-
* Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
@ -74,6 +74,7 @@
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/kcore.h>
#include <machine/cpu.h>
#include <machine/bus.h>
@ -137,8 +138,13 @@ static int pcc_vec2intctrl[] = {
PCCREG_SOFT2_INTR_CTRL /* PCCV_SOFT2 */
};
extern phys_ram_seg_t mem_clusters[];
struct pcc_softc *sys_pcc;
/* The base address of the MVME147 from the VMEbus */
bus_addr_t pcc_slave_base_addr;
/* ARGSUSED */
int
pccmatch(parent, cf, args)
@ -194,6 +200,14 @@ pccattach(parent, self, args)
reg = pcc_reg_read(sc, PCCREG_GENERAL_CONTROL) | PCC_GENCR_IEN;
pcc_reg_write(sc, PCCREG_GENERAL_CONTROL, reg);
/*
* Calculate the board's VMEbus slave base address, for the
* benefit of the VMEchip driver.
* (Weird that this register is in the PCC ...)
*/
reg = pcc_reg_read(sc, PCCREG_SLAVE_BASE_ADDR) & PCC_SLAVE_BASE_MASK;
pcc_slave_base_addr = (bus_addr_t)reg * mem_clusters[0].size;
/*
* Attach configured children.
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: pccreg.h,v 1.6 2000/03/18 22:33:03 scw Exp $ */
/* $NetBSD: pccreg.h,v 1.7 2000/08/20 21:51:31 scw Exp $ */
/*
*
@ -185,4 +185,9 @@
#define PCC_GENCR_IEN 0x10 /* global interrupt enable */
/*
* slave base address register
*/
#define PCC_SLAVE_BASE_MASK (0x01fu)
#endif /* __MVME68K_PCCREG_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: pccvar.h,v 1.5 2000/03/18 22:33:04 scw Exp $ */
/* $NetBSD: pccvar.h,v 1.6 2000/08/20 21:51:31 scw Exp $ */
/*-
* Copyright (c) 1996, 1999 The NetBSD Foundation, Inc.
@ -62,6 +62,7 @@ struct pcc_softc {
};
extern struct pcc_softc *sys_pcc;
extern bus_addr_t pcc_slave_base_addr;
void pccintr_establish __P((int, int (*)(void *), int, void *));
void pccintr_disestablish __P((int));

View File

@ -1,4 +1,4 @@
/* $NetBSD: vme_pcc.c,v 1.10 2000/08/13 17:00:52 scw Exp $ */
/* $NetBSD: vme_pcc.c,v 1.11 2000/08/20 21:51:31 scw Exp $ */
/*-
* Copyright (c) 1996-2000 The NetBSD Foundation, Inc.
@ -83,35 +83,45 @@ void vme_pcc_intr_disestablish(void *, int, int, int);
static struct mvmebus_range vme_pcc_masters[] = {
{VME_AM_MBO | VME_AM_A24 | VME_AM_DATA | VME_AM_SUPER,
VME_D32 | VME_D16,
{VME_AM_A24 |
MVMEBUS_AM_CAP_DATA | MVMEBUS_AM_CAP_PROG |
MVMEBUS_AM_CAP_SUPER | MVMEBUS_AM_CAP_USER,
VME_D32 | VME_D16 | VME_D8,
VME1_A24D32_LOC_START,
VME1_A24_MASK,
VME1_A24D32_START,
VME1_A24D32_END},
{VME_AM_MBO | VME_AM_A32 | VME_AM_DATA | VME_AM_SUPER,
VME_D32 | VME_D16,
{VME_AM_A32 |
MVMEBUS_AM_CAP_DATA | MVMEBUS_AM_CAP_PROG |
MVMEBUS_AM_CAP_SUPER | MVMEBUS_AM_CAP_USER,
VME_D32 | VME_D16 | VME_D8,
VME1_A32D32_LOC_START,
VME1_A32_MASK,
VME1_A32D32_START,
VME1_A32D32_END},
{VME_AM_MBO | VME_AM_A24 | VME_AM_DATA | VME_AM_SUPER,
VME_D16,
{VME_AM_A24 |
MVMEBUS_AM_CAP_DATA | MVMEBUS_AM_CAP_PROG |
MVMEBUS_AM_CAP_SUPER | MVMEBUS_AM_CAP_USER,
VME_D16 | VME_D8,
VME1_A24D16_LOC_START,
VME1_A24_MASK,
VME1_A24D16_START,
VME1_A24D16_END},
{VME_AM_MBO | VME_AM_A32 | VME_AM_DATA | VME_AM_SUPER,
{VME_AM_A32 |
MVMEBUS_AM_CAP_DATA | MVMEBUS_AM_CAP_PROG |
MVMEBUS_AM_CAP_SUPER | MVMEBUS_AM_CAP_USER,
VME_D16 | VME_D8,
VME1_A32D16_LOC_START,
VME1_A32_MASK,
VME1_A32D16_START,
VME1_A32D16_END},
{VME_AM_MBO | VME_AM_A16 | VME_AM_DATA | VME_AM_SUPER,
{VME_AM_A16 |
MVMEBUS_AM_CAP_DATA |
MVMEBUS_AM_CAP_SUPER | MVMEBUS_AM_CAP_USER,
VME_D16 | VME_D8,
VME1_A16D16_LOC_START,
VME1_A16_MASK,
@ -150,6 +160,7 @@ vme_pcc_attach(parent, self, aux)
{
struct pcc_attach_args *pa;
struct vme_pcc_softc *sc;
vme_am_t am;
u_int8_t reg;
sc = (struct vme_pcc_softc *) self;
@ -181,18 +192,63 @@ vme_pcc_attach(parent, self, aux)
(vme_addr_t) (mem_clusters[0].size - 0x01000000);
}
vme_pcc_attached = 1;
am = 0;
reg = vme1_reg_read(sc, VME1REG_SLADDRMOD);
if ((reg & VME1_SLMOD_DATA) != 0)
am |= MVMEBUS_AM_CAP_DATA;
if ((reg & VME1_SLMOD_PRGRM) != 0)
am |= MVMEBUS_AM_CAP_PROG;
if ((reg & VME1_SLMOD_SUPER) != 0)
am |= MVMEBUS_AM_CAP_SUPER;
if ((reg & VME1_SLMOD_USER) != 0)
am |= MVMEBUS_AM_CAP_USER;
if ((reg & VME1_SLMOD_BLOCK) != 0)
am |= MVMEBUS_AM_CAP_BLK;
#ifdef notyet
if ((reg & VME1_SLMOD_SHORT) != 0) {
sc->sc_slave[VME1_SLAVE_A16].vr_am = am | VME_AM_A16;
sc->sc_slave[VME1_SLAVE_A16].vr_mask = 0xffffu;
} else
#endif
sc->sc_slave[VME1_SLAVE_A16].vr_am = MVMEBUS_AM_DISABLED;
if (pcc_slave_base_addr < 0x01000000u && (reg & VME1_SLMOD_STND) != 0) {
sc->sc_slave[VME1_SLAVE_A24].vr_am = am | VME_AM_A24;
sc->sc_slave[VME1_SLAVE_A24].vr_datasize = VME_D32 |
VME_D16 | VME_D8;
sc->sc_slave[VME1_SLAVE_A24].vr_mask = 0xffffffu;
sc->sc_slave[VME1_SLAVE_A24].vr_locstart = 0;
sc->sc_slave[VME1_SLAVE_A24].vr_vmestart = pcc_slave_base_addr;
sc->sc_slave[VME1_SLAVE_A24].vr_vmeend = (pcc_slave_base_addr +
mem_clusters[0].size - 1) & 0x00ffffffu;
} else
sc->sc_slave[VME1_SLAVE_A24].vr_am = MVMEBUS_AM_DISABLED;
if ((reg & VME1_SLMOD_EXTED) != 0) {
sc->sc_slave[VME1_SLAVE_A32].vr_am = am | VME_AM_A32;
sc->sc_slave[VME1_SLAVE_A32].vr_datasize = VME_D32 |
VME_D16 | VME_D8;
sc->sc_slave[VME1_SLAVE_A32].vr_mask = 0xffffffffu;
sc->sc_slave[VME1_SLAVE_A32].vr_locstart = 0;
sc->sc_slave[VME1_SLAVE_A32].vr_vmestart = pcc_slave_base_addr;
sc->sc_slave[VME1_SLAVE_A32].vr_vmeend =
pcc_slave_base_addr + mem_clusters[0].size - 1;
} else
sc->sc_slave[VME1_SLAVE_A32].vr_am = MVMEBUS_AM_DISABLED;
/* Attach to the mvme68k common VMEbus front-end */
sc->sc_mvmebus.sc_dmat = pa->pa_dmat;
sc->sc_mvmebus.sc_chip = sc;
sc->sc_mvmebus.sc_nmasters = VME1_NMASTERS;
sc->sc_mvmebus.sc_masters = &vme_pcc_masters[0];
sc->sc_mvmebus.sc_nslaves = 0;
sc->sc_mvmebus.sc_slaves = NULL;
sc->sc_mvmebus.sc_nslaves = VME1_NSLAVES;
sc->sc_mvmebus.sc_slaves = &sc->sc_slave[0];
sc->sc_mvmebus.sc_intr_establish = vme_pcc_intr_establish;
sc->sc_mvmebus.sc_intr_disestablish = vme_pcc_intr_disestablish;
vme_pcc_attached = 1;
mvmebus_attach(&sc->sc_mvmebus);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: vme_pccvar.h,v 1.4 2000/08/13 17:00:52 scw Exp $ */
/* $NetBSD: vme_pccvar.h,v 1.5 2000/08/20 21:51:32 scw Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -39,10 +39,16 @@
#ifndef _MVME68K_VME_PCCVAR_H
#define _MVME68K_VME_PCCVAR_H
#define VME1_SLAVE_A32 0
#define VME1_SLAVE_A24 1
#define VME1_SLAVE_A16 2
#define VME1_NSLAVES 3
struct vme_pcc_softc {
struct mvmebus_softc sc_mvmebus;
bus_space_tag_t sc_bust;
bus_space_handle_t sc_bush;
struct mvmebus_range sc_slave[VME1_NSLAVES];
};
#endif /* __MVME68K_VME_PCCVAR_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: vme_two.c,v 1.6 2000/08/20 17:07:42 scw Exp $ */
/* $NetBSD: vme_two.c,v 1.7 2000/08/20 21:51:32 scw Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -197,19 +197,19 @@ vmetwo_attach(parent, self, aux)
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_MBO | VME_AM_A16 | VME_AM_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 |= VME_AM_SUPER;
sc->sc_master[0].vr_am |= MVMEBUS_AM_CAP_SUPER;
else
sc->sc_master[0].vr_am |= VME_AM_USER;
sc->sc_master[0].vr_am |= MVMEBUS_AM_CAP_USER;
/* As is the datasize */
if (reg & VME2_IO_CONTROL_I1D16)
sc->sc_master[0].vr_datasize = VME_D16;
else
sc->sc_master[0].vr_datasize = VME_D32 | VME_D16;
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;
@ -220,27 +220,27 @@ vmetwo_attach(parent, self, aux)
if (reg & VME2_IO_CONTROL_I2EN) {
/* These two ranges are fixed to A24D16 and A32D16 */
sc->sc_master[1].vr_am = VME_AM_MBO | VME_AM_A24;
sc->sc_master[1].vr_am = VME_AM_A24;
sc->sc_master[1].vr_datasize = VME_D16;
sc->sc_master[2].vr_am = VME_AM_MBO | VME_AM_A32;
sc->sc_master[2].vr_am = VME_AM_A32;
sc->sc_master[2].vr_datasize = VME_D16;
/* However, SUPER/USER is selectable */
if (reg & VME2_IO_CONTROL_I2SU) {
sc->sc_master[1].vr_am |= VME_AM_SUPER;
sc->sc_master[2].vr_am |= VME_AM_SUPER;
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 |= VME_AM_USER;
sc->sc_master[2].vr_am |= VME_AM_USER;
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 |= VME_AM_PRG;
sc->sc_master[2].vr_am |= VME_AM_PRG;
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 |= VME_AM_DATA;
sc->sc_master[2].vr_am |= VME_AM_DATA;
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;
@ -313,8 +313,14 @@ vmetwo_master_range(sc, range, vr)
*/
attr = vme2_lcsr_read(sc, VME2LCSR_MASTER_ATTR);
attr >>= VME2_MASTER_ATTR_AM_SHIFT(range);
vr->vr_am = VME_AM_MBO | (attr & VME2_MASTER_ATTR_AM_MASK);
/*
* Fix up the datasizes available through this range
*/
vr->vr_datasize = (attr & VME2_MASTER_ATTR_D16) ? VME_D16 : 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:
@ -330,14 +336,6 @@ vmetwo_master_range(sc, range, vr)
break;
}
/*
* Fix up the datasizes available through this range
*/
if (attr & VME2_MASTER_ATTR_D16)
vr->vr_datasize = VME_D16;
else
vr->vr_datasize = VME_D32 | VME_D16;
/*
* XXX
* It would be nice if users of the MI VMEbus code could pass down
@ -405,11 +403,11 @@ vmetwo_slave_range(sc, range, am, vr)
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 | VME_AM_MBO;
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 | VME_AM_MBO;
vr->vr_am = VME_AM_A24;
vr->vr_mask = 0x00ffffffu;
} else {
/* The range is not enabled */