1*5457a8e2Smsaitoh /* $NetBSD: esp_mca.c,v 1.22 2016/07/14 10:19:06 msaitoh Exp $ */
24b334401Sjdolecek
34b334401Sjdolecek /*-
4a275d0a6Sjdolecek * Copyright (c) 2001 The NetBSD Foundation, Inc.
54b334401Sjdolecek * All rights reserved.
64b334401Sjdolecek *
74b334401Sjdolecek * This code is derived from software contributed to The NetBSD Foundation
8a275d0a6Sjdolecek * by Jaromir Dolecek <jdolecek@NetBSD.org>.
94b334401Sjdolecek *
104b334401Sjdolecek * Redistribution and use in source and binary forms, with or without
114b334401Sjdolecek * modification, are permitted provided that the following conditions
124b334401Sjdolecek * are met:
134b334401Sjdolecek * 1. Redistributions of source code must retain the above copyright
144b334401Sjdolecek * notice, this list of conditions and the following disclaimer.
154b334401Sjdolecek * 2. Redistributions in binary form must reproduce the above copyright
164b334401Sjdolecek * notice, this list of conditions and the following disclaimer in the
174b334401Sjdolecek * documentation and/or other materials provided with the distribution.
184b334401Sjdolecek *
194b334401Sjdolecek * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
204b334401Sjdolecek * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
214b334401Sjdolecek * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
224b334401Sjdolecek * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
234b334401Sjdolecek * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
244b334401Sjdolecek * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
254b334401Sjdolecek * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
264b334401Sjdolecek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
274b334401Sjdolecek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
284b334401Sjdolecek * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
294b334401Sjdolecek * POSSIBILITY OF SUCH DAMAGE.
304b334401Sjdolecek */
314b334401Sjdolecek
324b334401Sjdolecek /*
337a12ca98Sjdolecek * Driver for NCR 53c90, MCA version, with 86c01 DMA controller chip.
344b334401Sjdolecek *
357a12ca98Sjdolecek * Some of the information used to write this driver was taken
367a12ca98Sjdolecek * from Tymm Twillman <tymm@computer.org>'s Linux MCA NC53c90 driver,
377a12ca98Sjdolecek * in drivers/scsi/mca_53c9x.c
384b334401Sjdolecek */
394b334401Sjdolecek
40365cbd94Slukem #include <sys/cdefs.h>
41*5457a8e2Smsaitoh __KERNEL_RCSID(0, "$NetBSD: esp_mca.c,v 1.22 2016/07/14 10:19:06 msaitoh Exp $");
42365cbd94Slukem
434b334401Sjdolecek #include <sys/types.h>
444b334401Sjdolecek #include <sys/param.h>
454b334401Sjdolecek #include <sys/systm.h>
464b334401Sjdolecek #include <sys/kernel.h>
474b334401Sjdolecek #include <sys/errno.h>
484b334401Sjdolecek #include <sys/ioctl.h>
494b334401Sjdolecek #include <sys/device.h>
504b334401Sjdolecek #include <sys/buf.h>
514b334401Sjdolecek #include <sys/proc.h>
524b334401Sjdolecek #include <sys/queue.h>
534b334401Sjdolecek
544b334401Sjdolecek #include <dev/scsipi/scsi_all.h>
554b334401Sjdolecek #include <dev/scsipi/scsipi_all.h>
564b334401Sjdolecek #include <dev/scsipi/scsiconf.h>
574b334401Sjdolecek #include <dev/scsipi/scsi_message.h>
584b334401Sjdolecek
59a2a38285Sad #include <sys/bus.h>
60a2a38285Sad #include <sys/cpu.h>
614b334401Sjdolecek
624b334401Sjdolecek #include <dev/ic/ncr53c9xreg.h>
634b334401Sjdolecek #include <dev/ic/ncr53c9xvar.h>
644b334401Sjdolecek
654b334401Sjdolecek #include <dev/mca/espvar.h>
667a12ca98Sjdolecek #include <dev/mca/espreg.h>
674b334401Sjdolecek
684b334401Sjdolecek #include <dev/mca/mcavar.h>
694b334401Sjdolecek #include <dev/mca/mcareg.h>
704b334401Sjdolecek #include <dev/mca/mcadevs.h>
714b334401Sjdolecek
727a12ca98Sjdolecek #if 0
734b334401Sjdolecek #if defined(DEBUG) && !defined(NCR53C9X_DEBUG)
744b334401Sjdolecek #define NCR53C9X_DEBUG
754b334401Sjdolecek #endif
767a12ca98Sjdolecek #endif
774b334401Sjdolecek
784b334401Sjdolecek #ifdef NCR53C9X_DEBUG
797a12ca98Sjdolecek static int esp_mca_debug = 0;
804b334401Sjdolecek #define DPRINTF(x) if (esp_mca_debug) printf x;
814b334401Sjdolecek #else
824b334401Sjdolecek #define DPRINTF(x)
834b334401Sjdolecek #endif
844b334401Sjdolecek
854b334401Sjdolecek #define ESP_MCA_IOSIZE 0x20
867a12ca98Sjdolecek #define ESP_REG_OFFSET 0x10
874b334401Sjdolecek
8878a1d236Stsutsui static int esp_mca_match(device_t, cfdata_t, void *);
8978a1d236Stsutsui static void esp_mca_attach(device_t, device_t, void *);
904b334401Sjdolecek
91ea2d6ba6Schristos CFATTACH_DECL_NEW(esp_mca, sizeof(struct esp_softc),
92c9b3657cSthorpej esp_mca_match, esp_mca_attach, NULL, NULL);
934b334401Sjdolecek
944b334401Sjdolecek /*
954b334401Sjdolecek * Functions and the switch for the MI code.
964b334401Sjdolecek */
9778a1d236Stsutsui static uint8_t esp_read_reg(struct ncr53c9x_softc *, int);
9878a1d236Stsutsui static void esp_write_reg(struct ncr53c9x_softc *, int, uint8_t);
9918db93c7Sperry static int esp_dma_isintr(struct ncr53c9x_softc *);
10018db93c7Sperry static void esp_dma_reset(struct ncr53c9x_softc *);
10118db93c7Sperry static int esp_dma_intr(struct ncr53c9x_softc *);
10278a1d236Stsutsui static int esp_dma_setup(struct ncr53c9x_softc *, uint8_t **,
10318db93c7Sperry size_t *, int, size_t *);
10418db93c7Sperry static void esp_dma_go(struct ncr53c9x_softc *);
10518db93c7Sperry static void esp_dma_stop(struct ncr53c9x_softc *);
10618db93c7Sperry static int esp_dma_isactive(struct ncr53c9x_softc *);
1074b334401Sjdolecek
1084b334401Sjdolecek static struct ncr53c9x_glue esp_glue = {
1094b334401Sjdolecek esp_read_reg,
1104b334401Sjdolecek esp_write_reg,
1114b334401Sjdolecek esp_dma_isintr,
1124b334401Sjdolecek esp_dma_reset,
1134b334401Sjdolecek esp_dma_intr,
1144b334401Sjdolecek esp_dma_setup,
1154b334401Sjdolecek esp_dma_go,
1164b334401Sjdolecek esp_dma_stop,
1174b334401Sjdolecek esp_dma_isactive,
1184b334401Sjdolecek NULL, /* gl_clear_latched_intr */
1194b334401Sjdolecek };
1204b334401Sjdolecek
1214b334401Sjdolecek static int
esp_mca_match(device_t parent,cfdata_t cf,void * aux)12278a1d236Stsutsui esp_mca_match(device_t parent, cfdata_t cf, void *aux)
1234b334401Sjdolecek {
1244b334401Sjdolecek struct mca_attach_args *ma = aux;
1254b334401Sjdolecek
1264b334401Sjdolecek switch (ma->ma_id) {
1274b334401Sjdolecek case MCA_PRODUCT_NCR53C90:
1284b334401Sjdolecek return 1;
1294b334401Sjdolecek }
1304b334401Sjdolecek
1314b334401Sjdolecek return 0;
1324b334401Sjdolecek }
1334b334401Sjdolecek
1344b334401Sjdolecek static void
esp_mca_attach(device_t parent,device_t self,void * aux)13578a1d236Stsutsui esp_mca_attach(device_t parent, device_t self, void *aux)
1364b334401Sjdolecek {
137838ee1e0Sthorpej struct esp_softc *esc = device_private(self);
1384b334401Sjdolecek struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
13978a1d236Stsutsui struct mca_attach_args *ma = aux;
14078a1d236Stsutsui uint16_t iobase;
1417a12ca98Sjdolecek int scsi_id, irq, drq, error;
1424b334401Sjdolecek bus_space_handle_t ioh;
1434b334401Sjdolecek int pos2, pos3, pos5;
1444b334401Sjdolecek
14578a1d236Stsutsui static const uint16_t ncrmca_iobase[] = {
1464b334401Sjdolecek 0, 0x240, 0x340, 0x400, 0x420, 0x3240, 0x8240, 0xa240
1474b334401Sjdolecek };
1484b334401Sjdolecek
14978a1d236Stsutsui sc->sc_dev = self;
15078a1d236Stsutsui
1514b334401Sjdolecek /*
1524b334401Sjdolecek * NCR SCSI Adapter (ADF 7f4f)
1534b334401Sjdolecek *
1544b334401Sjdolecek * POS register 2: (adf pos0)
1554b334401Sjdolecek *
1564b334401Sjdolecek * 7 6 5 4 3 2 1 0
1574b334401Sjdolecek * \_/ \___/ \__ enable: 0=adapter disabled, 1=adapter enabled
1584b334401Sjdolecek * | \____ I/O base (32B): 001=0x240 010=0x340 011=0x400
1594b334401Sjdolecek * | 100=0x420 101=0x3240 110=0x8240 111=0xa240
1604b334401Sjdolecek * \__________ IRQ: 00=3 01=5 10=7 11=9
1614b334401Sjdolecek *
1624b334401Sjdolecek * POS register 3: (adf pos1)
1634b334401Sjdolecek *
1644b334401Sjdolecek * 7 6 5 4 3 2 1 0
1654b334401Sjdolecek * 1 1 1 | \_____/
1664b334401Sjdolecek * | \__ DMA level
1674b334401Sjdolecek * \_________ Fairness: 1=enabled 0=disabled
1684b334401Sjdolecek *
1694b334401Sjdolecek * POS register 5: (adf pos3)
1704b334401Sjdolecek *
1714b334401Sjdolecek * 7 6 5 4 3 2 1 0
1724b334401Sjdolecek * 1 | \___/
1734b334401Sjdolecek * | \__ Static Ram: 0xC8000-0xC87FF + XX*0x4000
1744b334401Sjdolecek * \___________ Host Adapter ID: 1=7 0=6
1754b334401Sjdolecek */
1764b334401Sjdolecek
1774b334401Sjdolecek pos2 = mca_conf_read(ma->ma_mc, ma->ma_slot, 2);
1784b334401Sjdolecek pos3 = mca_conf_read(ma->ma_mc, ma->ma_slot, 3);
1794b334401Sjdolecek pos5 = mca_conf_read(ma->ma_mc, ma->ma_slot, 5);
1804b334401Sjdolecek
1814b334401Sjdolecek iobase = ncrmca_iobase[(pos2 & 0x0e) >> 1];
1824b334401Sjdolecek irq = 3 + 2 * ((pos2 & 0x30) >> 4);
1834b334401Sjdolecek drq = (pos3 & 0x0f);
1844b334401Sjdolecek scsi_id = 6 + ((pos5 & 0x20) ? 1 : 0);
1854b334401Sjdolecek
18678a1d236Stsutsui aprint_normal(" slot %d irq %d drq %d: NCR SCSI Adapter\n",
1874b334401Sjdolecek ma->ma_slot + 1, irq, drq);
1884b334401Sjdolecek
1897a12ca98Sjdolecek /* Map the 86C01 registers */
1904b334401Sjdolecek if (bus_space_map(ma->ma_iot, iobase, ESP_MCA_IOSIZE, 0, &ioh)) {
191ea2d6ba6Schristos aprint_error_dev(sc->sc_dev, "can't map i/o space\n");
1924b334401Sjdolecek return;
1934b334401Sjdolecek }
1944b334401Sjdolecek
1954b334401Sjdolecek esc->sc_iot = ma->ma_iot;
1964b334401Sjdolecek esc->sc_ioh = ioh;
1974b334401Sjdolecek
1987a12ca98Sjdolecek /* Submap the 'esp' registers */
1997a12ca98Sjdolecek if (bus_space_subregion(ma->ma_iot, ioh, ESP_REG_OFFSET,
2007a12ca98Sjdolecek ESP_MCA_IOSIZE-ESP_REG_OFFSET, &esc->sc_esp_ioh)) {
201ea2d6ba6Schristos aprint_error_dev(sc->sc_dev, "can't subregion i/o space\n");
2027a12ca98Sjdolecek return;
2037a12ca98Sjdolecek }
2047a12ca98Sjdolecek
2054b334401Sjdolecek /* Setup DMA map */
2064b334401Sjdolecek esc->sc_dmat = ma->ma_dmat;
2074b334401Sjdolecek if ((error = mca_dmamap_create(esc->sc_dmat, MAXPHYS,
2087a12ca98Sjdolecek BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW | MCABUS_DMA_IOPORT,
2097a12ca98Sjdolecek &esc->sc_xfer, drq)) != 0){
210ea2d6ba6Schristos aprint_error_dev(sc->sc_dev,
21178a1d236Stsutsui "couldn't create DMA map - error %d\n", error);
2124b334401Sjdolecek return;
2134b334401Sjdolecek }
2144b334401Sjdolecek
2157a12ca98Sjdolecek /* MI code glue */
2164b334401Sjdolecek sc->sc_id = scsi_id;
217a1f606d3Slukem sc->sc_freq = 25; /* MHz */
2184b334401Sjdolecek
2194b334401Sjdolecek sc->sc_glue = &esp_glue;
2204b334401Sjdolecek
2217a12ca98Sjdolecek sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB; //| NCRCFG1_SLOW;
2227a12ca98Sjdolecek /* No point setting sc_cfg[2345], they won't be used */
2234b334401Sjdolecek
2247a12ca98Sjdolecek sc->sc_rev = NCR_VARIANT_NCR53C90_86C01;
2254b334401Sjdolecek sc->sc_minsync = 0;
2264b334401Sjdolecek
2274b334401Sjdolecek /* max 64KB DMA */
2284b334401Sjdolecek sc->sc_maxxfer = 64 * 1024;
2294b334401Sjdolecek
2304b334401Sjdolecek /* Establish interrupt */
2314b334401Sjdolecek esc->sc_ih = mca_intr_establish(ma->ma_mc, irq, IPL_BIO, ncr53c9x_intr,
2324b334401Sjdolecek esc);
2334b334401Sjdolecek if (esc->sc_ih == NULL) {
234ea2d6ba6Schristos aprint_error_dev(sc->sc_dev, "couldn't establish interrupt\n");
2354b334401Sjdolecek return;
2364b334401Sjdolecek }
2374b334401Sjdolecek
2384b334401Sjdolecek /*
2397a12ca98Sjdolecek * Massage the 86C01 chip - setup MCA DMA controller for DMA via
2407a12ca98Sjdolecek * the 86C01 register, and enable 86C01 interrupts.
2417a12ca98Sjdolecek */
2427a12ca98Sjdolecek mca_dma_set_ioport(drq, iobase + N86C01_PIO);
2437a12ca98Sjdolecek
2447a12ca98Sjdolecek bus_space_write_1(esc->sc_iot, esc->sc_ioh, N86C01_MODE_ENABLE,
24578a1d236Stsutsui bus_space_read_1(esc->sc_iot, esc->sc_ioh, N86C01_MODE_ENABLE) |
24678a1d236Stsutsui N86C01_INTR_ENABLE);
2477a12ca98Sjdolecek
2487a12ca98Sjdolecek /*
2494b334401Sjdolecek * Now try to attach all the sub-devices
2504b334401Sjdolecek */
2514b334401Sjdolecek sc->sc_adapter.adapt_minphys = minphys;
2524b334401Sjdolecek sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request;
2534b334401Sjdolecek
2544b334401Sjdolecek /* Do the common parts of attachment. */
255*5457a8e2Smsaitoh aprint_normal("%s", device_xname(self));
2564b334401Sjdolecek ncr53c9x_attach(sc);
2574b334401Sjdolecek }
2584b334401Sjdolecek
2594b334401Sjdolecek /*
2604b334401Sjdolecek * Glue functions.
2614b334401Sjdolecek */
2624b334401Sjdolecek
26378a1d236Stsutsui static uint8_t
esp_read_reg(struct ncr53c9x_softc * sc,int reg)26478a1d236Stsutsui esp_read_reg(struct ncr53c9x_softc *sc, int reg)
2654b334401Sjdolecek {
2664b334401Sjdolecek struct esp_softc *esc = (struct esp_softc *)sc;
2674b334401Sjdolecek
26878a1d236Stsutsui return bus_space_read_1(esc->sc_iot, esc->sc_esp_ioh, reg);
2694b334401Sjdolecek }
2704b334401Sjdolecek
2714b334401Sjdolecek static void
esp_write_reg(struct ncr53c9x_softc * sc,int reg,uint8_t val)27278a1d236Stsutsui esp_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t val)
2734b334401Sjdolecek {
2744b334401Sjdolecek struct esp_softc *esc = (struct esp_softc *)sc;
2754b334401Sjdolecek
2767a12ca98Sjdolecek bus_space_write_1(esc->sc_iot, esc->sc_esp_ioh, reg, val);
2774b334401Sjdolecek }
2784b334401Sjdolecek
2794b334401Sjdolecek static int
esp_dma_isintr(struct ncr53c9x_softc * sc)28078a1d236Stsutsui esp_dma_isintr(struct ncr53c9x_softc *sc)
2814b334401Sjdolecek {
2827a12ca98Sjdolecek struct esp_softc *esc = (struct esp_softc *)sc;
2837a12ca98Sjdolecek
2844b334401Sjdolecek DPRINTF(("[esp_dma_isintr] "));
28578a1d236Stsutsui return bus_space_read_1(esc->sc_iot, esc->sc_ioh, N86C01_STATUS) &
28678a1d236Stsutsui N86C01_IRQ_PEND;
2874b334401Sjdolecek }
2884b334401Sjdolecek
2894b334401Sjdolecek static void
esp_dma_reset(struct ncr53c9x_softc * sc)29078a1d236Stsutsui esp_dma_reset(struct ncr53c9x_softc *sc)
2914b334401Sjdolecek {
2924b334401Sjdolecek struct esp_softc *esc = (struct esp_softc *)sc;
2934b334401Sjdolecek
2944b334401Sjdolecek DPRINTF(("[esp_dma_reset] "));
2954b334401Sjdolecek
2964b334401Sjdolecek if (esc->sc_flags & ESP_XFER_LOADED) {
2974b334401Sjdolecek bus_dmamap_unload(esc->sc_dmat, esc->sc_xfer);
2984b334401Sjdolecek esc->sc_flags &= ~ESP_XFER_LOADED;
2994b334401Sjdolecek }
3007a12ca98Sjdolecek
3017a12ca98Sjdolecek if (esc->sc_flags & ESP_XFER_ACTIVE) {
3027a12ca98Sjdolecek esc->sc_flags &= ~ESP_XFER_ACTIVE;
3037a12ca98Sjdolecek mca_disk_unbusy();
3047a12ca98Sjdolecek }
3054b334401Sjdolecek }
3064b334401Sjdolecek
3074b334401Sjdolecek static int
esp_dma_intr(struct ncr53c9x_softc * sc)30878a1d236Stsutsui esp_dma_intr(struct ncr53c9x_softc *sc)
3094b334401Sjdolecek {
3104b334401Sjdolecek struct esp_softc *esc = (struct esp_softc *)sc;
31178a1d236Stsutsui
3124b334401Sjdolecek DPRINTF(("[esp_dma_intr] "));
3134b334401Sjdolecek
3144b334401Sjdolecek if ((esc->sc_flags & ESP_XFER_ACTIVE) == 0) {
31578a1d236Stsutsui printf("%s: dma_intr--inactive DMA\n",
31678a1d236Stsutsui device_xname(sc->sc_dev));
31778a1d236Stsutsui return -1;
3184b334401Sjdolecek }
3194b334401Sjdolecek
3207a12ca98Sjdolecek if ((sc->sc_espintr & NCRINTR_BS) == 0) {
3214b334401Sjdolecek esc->sc_flags &= ~ESP_XFER_ACTIVE;
3227a12ca98Sjdolecek mca_disk_unbusy();
32378a1d236Stsutsui return 0;
3247a12ca98Sjdolecek }
3257a12ca98Sjdolecek
3267a12ca98Sjdolecek sc->sc_espstat |= NCRSTAT_TC; /* XXX */
3277a12ca98Sjdolecek
3287a12ca98Sjdolecek if ((sc->sc_espstat & NCRSTAT_TC) == 0) {
32978a1d236Stsutsui printf("%s: DMA not complete?\n", device_xname(sc->sc_dev));
33078a1d236Stsutsui return 1;
3317a12ca98Sjdolecek }
3327a12ca98Sjdolecek
33378a1d236Stsutsui bus_dmamap_sync(esc->sc_dmat, esc->sc_xfer, 0, *esc->sc_xfer_len,
33478a1d236Stsutsui (esc->sc_flags & ESP_XFER_READ) ?
33578a1d236Stsutsui BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
3367a12ca98Sjdolecek
3377a12ca98Sjdolecek bus_dmamap_unload(esc->sc_dmat, esc->sc_xfer);
3387a12ca98Sjdolecek esc->sc_flags &= ~ESP_XFER_LOADED;
3397a12ca98Sjdolecek
3407a12ca98Sjdolecek *esc->sc_xfer_addr += *esc->sc_xfer_len;
3417a12ca98Sjdolecek *esc->sc_xfer_len = 0;
3427a12ca98Sjdolecek
3437a12ca98Sjdolecek esc->sc_flags &= ~ESP_XFER_ACTIVE;
3447a12ca98Sjdolecek mca_disk_unbusy();
3457a12ca98Sjdolecek
34678a1d236Stsutsui return 0;
3474b334401Sjdolecek }
3484b334401Sjdolecek
3494b334401Sjdolecek /*
3504b334401Sjdolecek * Setup DMA transfer.
3514b334401Sjdolecek */
3524b334401Sjdolecek static int
esp_dma_setup(struct ncr53c9x_softc * sc,uint8_t ** addr,size_t * len,int datain,size_t * dmasize)35378a1d236Stsutsui esp_dma_setup(struct ncr53c9x_softc *sc, uint8_t **addr, size_t *len,
35478a1d236Stsutsui int datain, size_t *dmasize)
3554b334401Sjdolecek {
3564b334401Sjdolecek struct esp_softc *esc = (struct esp_softc *)sc;
3574b334401Sjdolecek int error;
3584b334401Sjdolecek int fl;
3594b334401Sjdolecek
3604b334401Sjdolecek DPRINTF(("[esp_dma_setup] "));
3614b334401Sjdolecek
3627a12ca98Sjdolecek if (esc->sc_flags & ESP_XFER_LOADED) {
36378a1d236Stsutsui printf("%s: %s: unloading leaked xfer\n",
36478a1d236Stsutsui device_xname(sc->sc_dev), __func__);
3657a12ca98Sjdolecek bus_dmamap_unload(esc->sc_dmat, esc->sc_xfer);
3667a12ca98Sjdolecek esc->sc_flags &= ~ESP_XFER_LOADED;
3677a12ca98Sjdolecek }
3687a12ca98Sjdolecek
3694b334401Sjdolecek /* Load the buffer for DMA transfer. */
3704b334401Sjdolecek fl = (datain) ? BUS_DMA_READ : BUS_DMA_WRITE;
3714b334401Sjdolecek
3724b334401Sjdolecek if ((error = bus_dmamap_load(esc->sc_dmat, esc->sc_xfer, *addr,
3734b334401Sjdolecek *len, NULL, BUS_DMA_STREAMING|fl))) {
37478a1d236Stsutsui printf("%s: %s: unable to load DMA buffer - error %d\n",
37578a1d236Stsutsui device_xname(sc->sc_dev), __func__, error);
37678a1d236Stsutsui return error;
3774b334401Sjdolecek }
3784b334401Sjdolecek
37978a1d236Stsutsui bus_dmamap_sync(esc->sc_dmat, esc->sc_xfer, 0, *len,
38078a1d236Stsutsui (datain) ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
3814b334401Sjdolecek
3827a12ca98Sjdolecek esc->sc_flags |= ESP_XFER_LOADED | (datain ? ESP_XFER_READ : 0);
3837a12ca98Sjdolecek esc->sc_xfer_addr = addr;
3847a12ca98Sjdolecek esc->sc_xfer_len = len;
3854b334401Sjdolecek
38678a1d236Stsutsui return 0;
3874b334401Sjdolecek }
3884b334401Sjdolecek
3894b334401Sjdolecek static void
esp_dma_go(struct ncr53c9x_softc * sc)39078a1d236Stsutsui esp_dma_go(struct ncr53c9x_softc *sc)
3914b334401Sjdolecek {
3924b334401Sjdolecek struct esp_softc *esc = (struct esp_softc *)sc;
3934b334401Sjdolecek DPRINTF(("[esp_dma_go] "));
3944b334401Sjdolecek
3954b334401Sjdolecek esc->sc_flags |= ESP_XFER_ACTIVE;
3967a12ca98Sjdolecek mca_disk_busy();
3974b334401Sjdolecek }
3984b334401Sjdolecek
3994b334401Sjdolecek static void
esp_dma_stop(struct ncr53c9x_softc * sc)40078a1d236Stsutsui esp_dma_stop(struct ncr53c9x_softc *sc)
4014b334401Sjdolecek {
40278a1d236Stsutsui
4034b334401Sjdolecek DPRINTF(("[esp_dma_stop] "));
4044b334401Sjdolecek
40578a1d236Stsutsui panic("%s: stop not yet implemented", device_xname(sc->sc_dev));
4064b334401Sjdolecek }
4074b334401Sjdolecek
4084b334401Sjdolecek static int
esp_dma_isactive(struct ncr53c9x_softc * sc)40978a1d236Stsutsui esp_dma_isactive(struct ncr53c9x_softc *sc)
4104b334401Sjdolecek {
4114b334401Sjdolecek struct esp_softc *esc = (struct esp_softc *)sc;
4124b334401Sjdolecek DPRINTF(("[esp_dma_isactive] "));
4134b334401Sjdolecek
41478a1d236Stsutsui return esc->sc_flags & ESP_XFER_ACTIVE;
4154b334401Sjdolecek }
416