/* $NetBSD: uda.c,v 1.64 2022/05/22 11:27:35 andvar Exp $ */
/*
* Copyright (c) 1988 Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Chris Torek.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)uda.c 7.32 (Berkeley) 2/13/91
*/
/*
* Copyright (c) 1996 Ludd, University of Lule}, Sweden.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)uda.c 7.32 (Berkeley) 2/13/91
*/
/*
* More driver definitions, for generic MSCP code.
*/
struct mscp_ctlr uda_mscp_ctlr = {
udactlrdone,
udago,
udasaerror,
};
int
udaprint(void *aux, const char *name)
{
if (name)
aprint_normal("%s: mscpbus", name);
return UNCONF;
}
/*
* Poke at a supposed UDA50 to see if it is there.
*/
int
udamatch(device_t parent, cfdata_t cf, void *aux)
{
struct uba_attach_args *ua = aux;
struct uba_softc *uh = device_private(parent);
struct mscp_softc mi; /* Nice hack */
int tries;
/*
* Initialise the controller (partially). The UDA50 programmer's
* manual states that if initialisation fails, it should be retried
* at least once, but after a second failure the port should be
* considered `down'; it also mentions that the controller should
* initialise within ten seconds. Or so I hear; I have not seen
* this manual myself.
*/
tries = 0;
again:
/*
* Fill in the uba_unit struct, so we can communicate with the uba.
*/
sc->sc_unit.uu_dev = self; /* Backpointer to softc */
sc->sc_unit.uu_ready = udaready;/* go routine called from adapter */
sc->sc_unit.uu_keepbdp = vax_cputype == VAX_750 ? 1 : 0;
/*
* Map the communication area and command and
* response packets into Unibus space.
*/
sc->sc_ui.ui_size = sizeof(struct mscp_pack);
if ((error = ubmemalloc(sc->sc_uh, &sc->sc_ui, UBA_CANTWAIT)))
return printf("ubmemalloc failed: %d\n", error);
/*
* The only thing that differ UDA's and Tape ctlr's is
* their vcid. Because there are no way to determine which
* ctlr type it is, we check what is generated and later
* set the correct vcid.
*/
ma.ma_type = (device_is_a(self, "mtc") ? MSCPBUS_TAPE : MSCPBUS_DISK);
/*
* Start a transfer if there are free resources available, otherwise
* let it go in udaready, forget it for now.
* Called from mscp routines.
*/
void
udago(device_t dv, struct mscp_xi *mxi)
{
struct uda_softc *sc = device_private(dv);
struct uba_unit *uu;
struct buf *bp = mxi->mxi_bp;
int err;
/*
* If we already have transfers queued, don't try to load
* the map again.
*/
if (sc->sc_inq == 0) {
err = bus_dmamap_load(sc->sc_dmat, mxi->mxi_dmam,
bp->b_data, bp->b_bcount,
(bp->b_flags & B_PHYS ? bp->b_proc : 0), BUS_DMA_NOWAIT);
if (err == 0) {
mscp_dgo(sc->sc_softc, mxi);
return;
}
}
uu = malloc(sizeof(struct uba_unit), M_DEVBUF, M_NOWAIT|M_ZERO);
if (uu == NULL)
panic("udago: no mem");
uu->uu_ready = udaready;
uu->uu_dev = dv;
uu->uu_ref = mxi;
uba_enqueue(uu);
sc->sc_inq++;
}
/*
* Called if we have been blocked for resources, and resources
* have been freed again. Return 1 if we could start all
* transfers again, 0 if we still are waiting.
* Called from uba resource free routines.
*/
int
udaready(struct uba_unit *uu)
{
struct uda_softc *sc = device_private(uu->uu_dev);
struct mscp_xi *mxi = uu->uu_ref;
struct buf *bp = mxi->mxi_bp;
int err;
/*
* If the error bit was set in the controller status register, gripe,
* then (optionally) reset the controller and requeue pending transfers.
*/
void
udasaerror(device_t dev, int doreset)
{
struct uda_softc *sc = device_private(dev);
int code = bus_space_read_2(sc->sc_iot, sc->sc_sah, 0);
const struct saerr *e;
if ((code & MP_ERR) == 0)
return;
for (e = saerr; e->code; e++)
if (e->code == code)
break;
aprint_error_dev(sc->sc_dev, "controller error, sa=0%o (%s%s)\n",
code, e->desc + 1, *e->desc == 'E' ? " error" : "");
#if 0 /* XXX we just avoid panic when autoconfig non-existent KFQSA devices */
if (doreset) {
mscp_requeue(sc->sc_softc);
/* (void) udainit(sc); XXX */
}
#endif
}
/*
* Interrupt routine. Depending on the state of the controller,
* continue initialisation, or acknowledge command and response
* interrupts, and process responses.
*/
static void
udaintr(void *arg)
{
struct uda_softc *sc = arg;
/* ctlr fatal error */
if (bus_space_read_2(sc->sc_iot, sc->sc_sah, 0) & MP_ERR) {
udasaerror(sc->sc_dev, 1);
return;
}
/*
* Handle buffer purge requests.
* XXX - should be done in bus_dma_sync().
*/
#ifdef notyet
if (ud->mp_ca.ca_bdp) {
if (sc->sc_uh->uh_ubapurge)
(*sc->sc_uh->uh_ubapurge)(sc->sc_uh,
ud->mp_ca.ca_bdp);
/* signal purge complete */
bus_space_write_2(sc->sc_iot, sc->sc_sah, 0, 0);
}
#endif
mscp_intr(sc->sc_softc);
}
/*
* A Unibus reset has occurred on UBA uban. Reinitialise the controller(s)
* on that Unibus, and requeue outstanding I/O.
*/
static void
udareset(device_t dev)
{
struct uda_softc *sc = device_private(dev);
/*
* Our BDP (if any) is gone; our command (if any) is
* flushed; the device is no longer mapped; and the
* UDA50 is not yet initialised.
*/
if (sc->sc_unit.uu_bdp) {
/* printf("<%d>", UBAI_BDP(sc->sc_unit.uu_bdp)); */
sc->sc_unit.uu_bdp = 0;
}
/* reset queues and requeue pending transfers */
mscp_requeue(sc->sc_softc);
/*
* If it fails to initialise we will notice later and
* try again (and again...). Do not call udastart()
* here; it will be done after the controller finishes
* initialisation.
*/
/* XXX if (udainit(sc)) */
printf(" (hung)");
}