/*
* Copyright (c) 1999
* Matthias Drochner. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
int
b3_617_init(struct b3_617_softc *sc)
{
unsigned int i;
if (b3_617_reset(sc))
return (-1);
/* all maps invalid */
for (i = MR_PCI_VME; i < MR_PCI_VME + MR_PCI_VME_SIZE; i += 4)
write_mapmem(sc, i, MR_RAM_INVALID);
for (i = MR_VME_PCI; i < MR_VME_PCI + MR_VME_PCI_SIZE; i += 4)
write_mapmem(sc, i, MR_RAM_INVALID);
for (i = MR_DMA_PCI; i < MR_DMA_PCI + MR_DMA_PCI_SIZE; i += 4)
write_mapmem(sc, i, MR_RAM_INVALID);
/*
* init int handler queue,
* enable interrupts if PCI interrupt available
*/
TAILQ_INIT(&(sc->intrhdls));
sc->strayintrs = 0;
if (sc->sc_ih)
write_csr_byte(sc, LOC_INT_CTRL, LIC_INT_ENABLE);
/* no error ints */
write_csr_byte(sc, REM_CMD2, 0); /* enables VME IRQ */
return (0);
}
#ifdef notyet /* for detach */
void
b3_617_halt(struct b3_617_softc *sc)
{
/*
* because detach code checks for existence of children,
* all resources (mappings, VME IRQs, DMA requests)
* should be deallocated at this point
*/
for (ih = sc->intrhdls.tqh_first; ih;
ih = ih->ih_next.tqe_next) {
if ((ih->ih_level == level) &&
((ih->ih_vector == -1) ||
(ih->ih_vector == vector))) {
int s, res;
/*
* We should raise the interrupt level
* to ih->ih_prior here. How to do this
* machine-independently?
* To be safe, raise to the maximum.
*/
s = splhigh();
found |= (res = (*(ih->ih_fun))(ih->ih_arg));
splx(s);
if (res)
ih->ih_count++;
if (res == 1)
break;
}
}
if (!found)
sc->strayintrs++;
}
}
/* first mapped address */
vmebase = vmeaddr & ~(VME_PAGESIZE - 1);
/* base of last mapped page */
vmeend = (vmeaddr + len - 1) & ~(VME_PAGESIZE - 1);
/* bytes in scatter table required */
maplen = ((vmeend - vmebase) / VME_PAGESIZE + 1) * 4;
if (vmem_alloc(sc->vme_arena, maplen, VM_BESTFIT | VM_NOSLEEP, &first))
return (ENOMEM);
/*
* set up adapter mapping registers
*/
mapreg = (am << MR_AMOD_SHIFT) | MR_FC_RRAM | swap;
for (i = first, va = vmebase;
i < first + maplen;
i += 4, va += VME_PAGESIZE) {
write_mapmem(sc, i, mapreg | va);
#ifdef BIT3DEBUG
printf("mapreg@%lx=%x\n", i, read_mapmem(sc, i));
#endif
}
#ifdef DIAGNOSTIC
if (va != vmeend + VME_PAGESIZE)
panic("b3_617_map_pci_vme: botch");
#endif
/*
* map needed range in PCI space
*/
pcibase = sc->vmepbase + (first - MR_PCI_VME) / 4 * VME_PAGESIZE
+ (vmeaddr & (VME_PAGESIZE - 1));
if ((res = bus_space_map(sc->sc_vmet, pcibase, len, 0, handle))) {
for (i = first; i < first + maplen; i += 4)
write_mapmem(sc, i, MR_RAM_INVALID);
vmem_free(sc->vme_arena, first, maplen);
return (res);
}
*tag = sc->sc_vmet;
/*
* save all data needed for later unmapping
*/
r = kmem_alloc(sizeof(*r), KM_SLEEP);
r->handle = *handle;
r->len = len;
r->firstpage = first;
r->maplen = maplen;
*resc = r;
return (0);
}
int
b3_617_map_vmeint(void *vsc, int level, int vector, vme_intr_handle_t *handlep)
{
if (!sc->sc_ih) {
printf("%s: b3_617_map_vmeint: no IRQ\n",
device_xname(sc->sc_dev));
return (ENXIO);
}
/*
* We should check whether the interface can pass this interrupt
* level at all, but we don't know much about the jumper setting.
*/
*handlep = (void *)(long)((level << 8) | vector); /* XXX */
return (0);
}
void *
b3_617_establish_vmeint(void *vsc, vme_intr_handle_t handle, int prior, int (*func)(void *), void *arg)
{
struct b3_617_vmeintrhand *ih;
long lv;
int s;