/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Tohru Nishimura.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Set up glue for MI code early; we use some of it here.
*/
sc->sc_dev = self;
sc->sc_glue = &asc_ioasic_glue;
asc->sc_bst = isc->sc_bst;
asc->sc_bsh = isc->sc_bsh;
if (bus_space_subregion(asc->sc_bst, asc->sc_bsh,
IOASIC_SLOT_12_START, 0x100, &asc->sc_scsi_bsh)) {
aprint_error(": failed to map device registers\n");
return;
}
asc->sc_dmat = isc->sc_dmat;
if (bus_dmamap_create(asc->sc_dmat, PAGE_SIZE * 2,
2, PAGE_SIZE, PAGE_SIZE, BUS_DMA_NOWAIT,
&asc->sc_dmamap)) {
aprint_error(": failed to create DMA map\n");
return;
}
/*
* XXX More of this should be in ncr53c9x_attach(), but
* XXX should we really poke around the chip that much in
* XXX the MI code? Think about this more...
*/
/*
* XXX minsync and maxxfer _should_ be set up in MI code,
* XXX but it appears to have some dependency on what sort
* XXX of DMA we're hooked up to, etc.
*/
/*
* This is the value used to start sync negotiations
* Note that the NCR register "SYNCTP" is programmed
* in "clocks per byte", and has a minimum value of 4.
* The SCSI period used in negotiation is one-fourth
* of the time (in nanoseconds) needed to transfer one byte.
* Since the chip's clock is given in MHz, we have the following
* formula: 4 * period = (1000 / freq) * 4
*/
sc->sc_minsync = (1000 / sc->sc_freq) * 5 / 4 ;
sc->sc_maxxfer = 64 * 1024;
/* Do the common parts of attachment. */
sc->sc_adapter.adapt_minphys = minphys;
sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request;
ncr53c9x_attach(sc);
}
ssr = bus_space_read_4(asc->sc_bst, asc->sc_bsh, IOASIC_CSR);
if (asc->sc_flags & ASC_ISPULLUP)
ssr |= IOASIC_CSR_SCSI_DIR;
else {
/* ULTRIX does in this way */
ssr &= ~IOASIC_CSR_SCSI_DIR;
bus_space_write_4(asc->sc_bst, asc->sc_bsh, IOASIC_CSR, ssr);
ssr = bus_space_read_4(asc->sc_bst, asc->sc_bsh, IOASIC_CSR);
}
ssr |= IOASIC_CSR_DMAEN_SCSI;
bus_space_write_4(asc->sc_bst, asc->sc_bsh, IOASIC_CSR, ssr);
asc->sc_flags |= ASC_DMAACTIVE;
}
#define IOASIC_ASC_ERRORS \
(IOASIC_INTR_SCSI_PTR_LOAD|IOASIC_INTR_SCSI_OVRUN|IOASIC_INTR_SCSI_READ_E)
/*
* When doing polled I/O, the SCSI bits in the interrupt register won't
* get cleared by the interrupt processing. This will cause the DMA
* address registers to not load on the next DMA transfer.
* Check for these bits here, and clear them if needed.
*/
intr = bus_space_read_4(asc->sc_bst, asc->sc_bsh, IOASIC_INTR);
if ((intr & IOASIC_ASC_ERRORS) != 0) {
intr &= ~IOASIC_ASC_ERRORS;
bus_space_write_4(asc->sc_bst, asc->sc_bsh, IOASIC_INTR, intr);
}
/* DMA has stopped */
ssr = bus_space_read_4(asc->sc_bst, asc->sc_bsh, IOASIC_CSR);
ssr &= ~IOASIC_CSR_DMAEN_SCSI;
bus_space_write_4(asc->sc_bst, asc->sc_bsh, IOASIC_CSR, ssr);