1 1.67 tsutsui /* $NetBSD: esp.c,v 1.67 2023/02/03 23:17:49 tsutsui Exp $ */ 2 1.1 dbj 3 1.1 dbj /*- 4 1.5 mycroft * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 5 1.1 dbj * All rights reserved. 6 1.1 dbj * 7 1.1 dbj * This code is derived from software contributed to The NetBSD Foundation 8 1.6 mycroft * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace 9 1.6 mycroft * Simulation Facility, NASA Ames Research Center. 10 1.1 dbj * 11 1.1 dbj * Redistribution and use in source and binary forms, with or without 12 1.1 dbj * modification, are permitted provided that the following conditions 13 1.1 dbj * are met: 14 1.1 dbj * 1. Redistributions of source code must retain the above copyright 15 1.1 dbj * notice, this list of conditions and the following disclaimer. 16 1.1 dbj * 2. Redistributions in binary form must reproduce the above copyright 17 1.1 dbj * notice, this list of conditions and the following disclaimer in the 18 1.1 dbj * documentation and/or other materials provided with the distribution. 19 1.1 dbj * 20 1.1 dbj * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.1 dbj * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.1 dbj * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.1 dbj * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.1 dbj * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.1 dbj * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.1 dbj * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.1 dbj * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.1 dbj * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.1 dbj * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.1 dbj * POSSIBILITY OF SUCH DAMAGE. 31 1.1 dbj */ 32 1.1 dbj 33 1.1 dbj /* 34 1.1 dbj * Copyright (c) 1994 Peter Galbavy 35 1.1 dbj * All rights reserved. 36 1.1 dbj * 37 1.1 dbj * Redistribution and use in source and binary forms, with or without 38 1.1 dbj * modification, are permitted provided that the following conditions 39 1.1 dbj * are met: 40 1.1 dbj * 1. Redistributions of source code must retain the above copyright 41 1.1 dbj * notice, this list of conditions and the following disclaimer. 42 1.1 dbj * 2. Redistributions in binary form must reproduce the above copyright 43 1.1 dbj * notice, this list of conditions and the following disclaimer in the 44 1.1 dbj * documentation and/or other materials provided with the distribution. 45 1.1 dbj * 3. All advertising materials mentioning features or use of this software 46 1.1 dbj * must display the following acknowledgement: 47 1.1 dbj * This product includes software developed by Peter Galbavy 48 1.1 dbj * 4. The name of the author may not be used to endorse or promote products 49 1.1 dbj * derived from this software without specific prior written permission. 50 1.1 dbj * 51 1.1 dbj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 52 1.1 dbj * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 53 1.1 dbj * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 54 1.1 dbj * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 55 1.1 dbj * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 56 1.1 dbj * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 57 1.1 dbj * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 1.1 dbj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 59 1.1 dbj * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 60 1.1 dbj * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 61 1.1 dbj * POSSIBILITY OF SUCH DAMAGE. 62 1.1 dbj */ 63 1.1 dbj 64 1.1 dbj /* 65 1.1 dbj * Based on aic6360 by Jarle Greipsland 66 1.1 dbj * 67 1.1 dbj * Acknowledgements: Many of the algorithms used in this driver are 68 1.1 dbj * inspired by the work of Julian Elischer (julian (at) tfs.com) and 69 1.1 dbj * Charles Hannum (mycroft (at) duality.gnu.ai.mit.edu). Thanks a million! 70 1.1 dbj */ 71 1.1 dbj 72 1.1 dbj /* 73 1.1 dbj * Grabbed from the sparc port at revision 1.73 for the NeXT. 74 1.47 keihan * Darrin B. Jewell <dbj (at) NetBSD.org> Sat Jul 4 15:41:32 1998 75 1.1 dbj */ 76 1.45 lukem 77 1.45 lukem #include <sys/cdefs.h> 78 1.67 tsutsui __KERNEL_RCSID(0, "$NetBSD: esp.c,v 1.67 2023/02/03 23:17:49 tsutsui Exp $"); 79 1.1 dbj 80 1.1 dbj #include <sys/types.h> 81 1.1 dbj #include <sys/param.h> 82 1.1 dbj #include <sys/systm.h> 83 1.1 dbj #include <sys/kernel.h> 84 1.1 dbj #include <sys/errno.h> 85 1.1 dbj #include <sys/ioctl.h> 86 1.1 dbj #include <sys/device.h> 87 1.1 dbj #include <sys/buf.h> 88 1.1 dbj #include <sys/proc.h> 89 1.1 dbj #include <sys/queue.h> 90 1.1 dbj 91 1.43 thorpej #include <uvm/uvm_extern.h> 92 1.43 thorpej 93 1.1 dbj #include <dev/scsipi/scsi_all.h> 94 1.1 dbj #include <dev/scsipi/scsipi_all.h> 95 1.1 dbj #include <dev/scsipi/scsiconf.h> 96 1.1 dbj #include <dev/scsipi/scsi_message.h> 97 1.1 dbj 98 1.1 dbj #include <machine/bus.h> 99 1.1 dbj #include <machine/autoconf.h> 100 1.1 dbj #include <machine/cpu.h> 101 1.1 dbj 102 1.1 dbj #include <dev/ic/ncr53c9xreg.h> 103 1.1 dbj #include <dev/ic/ncr53c9xvar.h> 104 1.1 dbj 105 1.1 dbj #include <next68k/next68k/isr.h> 106 1.1 dbj 107 1.38 mycroft #include <next68k/dev/intiovar.h> 108 1.1 dbj #include <next68k/dev/nextdmareg.h> 109 1.1 dbj #include <next68k/dev/nextdmavar.h> 110 1.1 dbj 111 1.38 mycroft #include <next68k/dev/espreg.h> 112 1.38 mycroft #include <next68k/dev/espvar.h> 113 1.1 dbj 114 1.20 dbj #ifdef DEBUG 115 1.39 mycroft #undef ESP_DEBUG 116 1.4 dbj #endif 117 1.4 dbj 118 1.4 dbj #ifdef ESP_DEBUG 119 1.10 dbj int esp_debug = 0; 120 1.10 dbj #define DPRINTF(x) if (esp_debug) printf x; 121 1.61 christos #define NDTRACEIF(x) if (10) do {x;} while (0) 122 1.4 dbj #else 123 1.4 dbj #define DPRINTF(x) 124 1.38 mycroft #define NDTRACEIF(x) 125 1.4 dbj #endif 126 1.37 christos #define PRINTF(x) printf x; 127 1.4 dbj 128 1.4 dbj 129 1.67 tsutsui static int espmatch_intio(device_t, cfdata_t, void *); 130 1.67 tsutsui static void espattach_intio(device_t, device_t, void *); 131 1.1 dbj 132 1.2 dbj /* DMA callbacks */ 133 1.67 tsutsui static bus_dmamap_t esp_dmacb_continue(void *); 134 1.67 tsutsui static void esp_dmacb_completed(bus_dmamap_t, void *); 135 1.67 tsutsui static void esp_dmacb_shutdown(void *); 136 1.2 dbj 137 1.66 tsutsui static void findchannel_defer(device_t); 138 1.38 mycroft 139 1.20 dbj #ifdef ESP_DEBUG 140 1.20 dbj char esp_dma_dump[5*1024] = ""; 141 1.20 dbj struct ncr53c9x_softc *esp_debug_sc = 0; 142 1.49 chs void esp_dma_store(struct ncr53c9x_softc *); 143 1.49 chs void esp_dma_print(struct ncr53c9x_softc *); 144 1.22 dbj int esp_dma_nest = 0; 145 1.61 christos int esptraceshow; 146 1.20 dbj #endif 147 1.20 dbj 148 1.20 dbj 149 1.1 dbj /* Linkup to the rest of the kernel */ 150 1.55 tsutsui CFATTACH_DECL_NEW(esp, sizeof(struct esp_softc), 151 1.42 thorpej espmatch_intio, espattach_intio, NULL, NULL); 152 1.1 dbj 153 1.38 mycroft static int attached = 0; 154 1.38 mycroft 155 1.1 dbj /* 156 1.1 dbj * Functions and the switch for the MI code. 157 1.1 dbj */ 158 1.67 tsutsui static uint8_t esp_read_reg(struct ncr53c9x_softc *, int); 159 1.67 tsutsui static void esp_write_reg(struct ncr53c9x_softc *, int, uint8_t); 160 1.67 tsutsui static int esp_dma_isintr(struct ncr53c9x_softc *); 161 1.67 tsutsui static void esp_dma_reset(struct ncr53c9x_softc *); 162 1.67 tsutsui static int esp_dma_intr(struct ncr53c9x_softc *); 163 1.67 tsutsui static int esp_dma_setup(struct ncr53c9x_softc *, uint8_t **, size_t *, int, 164 1.67 tsutsui size_t *); 165 1.67 tsutsui static void esp_dma_go(struct ncr53c9x_softc *); 166 1.67 tsutsui static void esp_dma_stop(struct ncr53c9x_softc *); 167 1.67 tsutsui static int esp_dma_isactive(struct ncr53c9x_softc *); 168 1.1 dbj 169 1.67 tsutsui static int doze(volatile int); 170 1.67 tsutsui 171 1.67 tsutsui static struct ncr53c9x_glue esp_glue = { 172 1.66 tsutsui .gl_read_reg = esp_read_reg, 173 1.66 tsutsui .gl_write_reg = esp_write_reg, 174 1.66 tsutsui .gl_dma_isintr = esp_dma_isintr, 175 1.66 tsutsui .gl_dma_reset = esp_dma_reset, 176 1.66 tsutsui .gl_dma_intr = esp_dma_intr, 177 1.66 tsutsui .gl_dma_setup = esp_dma_setup, 178 1.66 tsutsui .gl_dma_go = esp_dma_go, 179 1.66 tsutsui .gl_dma_stop = esp_dma_stop, 180 1.66 tsutsui .gl_dma_isactive = esp_dma_isactive, 181 1.66 tsutsui .gl_clear_latched_intr = NULL 182 1.1 dbj }; 183 1.1 dbj 184 1.66 tsutsui #define nd_bsr4(reg) \ 185 1.66 tsutsui bus_space_read_4(nsc->sc_bst, nsc->sc_bsh, (reg)) 186 1.66 tsutsui #define nd_bsw4(reg, val) \ 187 1.66 tsutsui bus_space_write_4(nsc->sc_bst, nsc->sc_bsh, (reg), (val)) 188 1.66 tsutsui 189 1.11 dbj #ifdef ESP_DEBUG 190 1.50 christos #define XCHR(x) hexdigits[(x) & 0xf] 191 1.11 dbj static void 192 1.11 dbj esp_hex_dump(unsigned char *pkt, size_t len) 193 1.11 dbj { 194 1.11 dbj size_t i, j; 195 1.11 dbj 196 1.31 dbj printf("00000000 "); 197 1.55 tsutsui for(i = 0; i < len; i++) { 198 1.66 tsutsui printf("%c%c ", XCHR(pkt[i] >> 4), XCHR(pkt[i])); 199 1.55 tsutsui if ((i + 1) % 16 == 8) { 200 1.24 dbj printf(" "); 201 1.24 dbj } 202 1.55 tsutsui if ((i + 1) % 16 == 0) { 203 1.24 dbj printf(" %c", '|'); 204 1.55 tsutsui for(j = 0; j < 16; j++) { 205 1.66 tsutsui printf("%c", pkt[i - 15 + j] >= 32 && 206 1.66 tsutsui pkt[i - 15 + j] < 127 ? 207 1.66 tsutsui pkt[i - 15 + j] : '.'); 208 1.24 dbj } 209 1.66 tsutsui printf("%c\n%c%c%c%c%c%c%c%c ", '|', 210 1.66 tsutsui XCHR((i + 1) >> 28), XCHR((i + 1) >> 24), 211 1.66 tsutsui XCHR((i + 1) >> 20), XCHR((i + 1) >> 16), 212 1.66 tsutsui XCHR((i + 1) >> 12), XCHR((i + 1) >> 8), 213 1.66 tsutsui XCHR((i + 1) >> 4), XCHR(i + 1)); 214 1.11 dbj } 215 1.11 dbj } 216 1.11 dbj printf("\n"); 217 1.11 dbj } 218 1.11 dbj #endif 219 1.11 dbj 220 1.67 tsutsui static int 221 1.55 tsutsui espmatch_intio(device_t parent, cfdata_t cf, void *aux) 222 1.1 dbj { 223 1.55 tsutsui struct intio_attach_args *ia = aux; 224 1.38 mycroft 225 1.38 mycroft if (attached) 226 1.55 tsutsui return 0; 227 1.38 mycroft 228 1.38 mycroft ia->ia_addr = (void *)NEXT_P_SCSI; 229 1.1 dbj 230 1.55 tsutsui return 1; 231 1.1 dbj } 232 1.1 dbj 233 1.38 mycroft static void 234 1.60 chs findchannel_defer(device_t self) 235 1.38 mycroft { 236 1.55 tsutsui struct esp_softc *esc = device_private(self); 237 1.38 mycroft struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 238 1.38 mycroft int error; 239 1.38 mycroft 240 1.66 tsutsui if (esc->sc_dma == NULL) { 241 1.55 tsutsui aprint_normal("%s", device_xname(sc->sc_dev)); 242 1.55 tsutsui esc->sc_dma = nextdma_findchannel("scsi"); 243 1.66 tsutsui if (esc->sc_dma == NULL) 244 1.55 tsutsui panic("%s: can't find DMA channel", 245 1.55 tsutsui device_xname(sc->sc_dev)); 246 1.38 mycroft } 247 1.38 mycroft 248 1.55 tsutsui nextdma_setconf(esc->sc_dma, shutdown_cb, &esp_dmacb_shutdown); 249 1.55 tsutsui nextdma_setconf(esc->sc_dma, continue_cb, &esp_dmacb_continue); 250 1.55 tsutsui nextdma_setconf(esc->sc_dma, completed_cb, &esp_dmacb_completed); 251 1.55 tsutsui nextdma_setconf(esc->sc_dma, cb_arg, sc); 252 1.38 mycroft 253 1.38 mycroft error = bus_dmamap_create(esc->sc_dma->sc_dmat, 254 1.66 tsutsui sc->sc_maxxfer, sc->sc_maxxfer / PAGE_SIZE + 1, sc->sc_maxxfer, 255 1.66 tsutsui 0, BUS_DMA_ALLOCNOW, &esc->sc_main_dmamap); 256 1.66 tsutsui if (error != 0) { 257 1.38 mycroft panic("%s: can't create main i/o DMA map, error = %d", 258 1.66 tsutsui device_xname(sc->sc_dev), error); 259 1.38 mycroft } 260 1.38 mycroft 261 1.38 mycroft error = bus_dmamap_create(esc->sc_dma->sc_dmat, 262 1.66 tsutsui ESP_DMA_TAILBUFSIZE, 1, ESP_DMA_TAILBUFSIZE, 263 1.66 tsutsui 0, BUS_DMA_ALLOCNOW, &esc->sc_tail_dmamap); 264 1.66 tsutsui if (error != 0) { 265 1.38 mycroft panic("%s: can't create tail i/o DMA map, error = %d", 266 1.66 tsutsui device_xname(sc->sc_dev), error); 267 1.38 mycroft } 268 1.66 tsutsui 269 1.38 mycroft #if 0 270 1.44 wiz /* Turn on target selection using the `DMA' method */ 271 1.38 mycroft sc->sc_features |= NCR_F_DMASELECT; 272 1.38 mycroft #endif 273 1.38 mycroft 274 1.38 mycroft /* Do the common parts of attachment. */ 275 1.38 mycroft sc->sc_adapter.adapt_minphys = minphys; 276 1.38 mycroft sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request; 277 1.38 mycroft ncr53c9x_attach(sc); 278 1.38 mycroft 279 1.38 mycroft /* Establish interrupt channel */ 280 1.38 mycroft isrlink_autovec(ncr53c9x_intr, sc, NEXT_I_IPL(NEXT_I_SCSI), 0, NULL); 281 1.38 mycroft INTR_ENABLE(NEXT_I_SCSI); 282 1.38 mycroft 283 1.38 mycroft /* register interrupt stats */ 284 1.38 mycroft evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL, 285 1.66 tsutsui device_xname(sc->sc_dev), "intr"); 286 1.38 mycroft 287 1.55 tsutsui aprint_normal_dev(sc->sc_dev, "using DMA channel %s\n", 288 1.60 chs device_xname(esc->sc_dma->sc_dev)); 289 1.38 mycroft } 290 1.38 mycroft 291 1.67 tsutsui static void 292 1.55 tsutsui espattach_intio(device_t parent, device_t self, void *aux) 293 1.1 dbj { 294 1.55 tsutsui struct esp_softc *esc = device_private(self); 295 1.1 dbj struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 296 1.55 tsutsui struct intio_attach_args *ia = aux; 297 1.55 tsutsui 298 1.55 tsutsui sc->sc_dev = self; 299 1.1 dbj 300 1.20 dbj #ifdef ESP_DEBUG 301 1.20 dbj esp_debug_sc = sc; 302 1.20 dbj #endif 303 1.20 dbj 304 1.38 mycroft esc->sc_bst = ia->ia_bst; 305 1.66 tsutsui if (bus_space_map(esc->sc_bst, NEXT_P_SCSI, 306 1.66 tsutsui ESP_DEVICE_SIZE, 0, &esc->sc_bsh)) { 307 1.55 tsutsui aprint_normal("\n"); 308 1.55 tsutsui panic("%s: can't map ncr53c90 registers", 309 1.66 tsutsui device_xname(self)); 310 1.1 dbj } 311 1.1 dbj 312 1.1 dbj sc->sc_id = 7; 313 1.52 lukem sc->sc_freq = 20; /* MHz */ 314 1.1 dbj 315 1.1 dbj /* 316 1.1 dbj * Set up glue for MI code early; we use some of it here. 317 1.1 dbj */ 318 1.1 dbj sc->sc_glue = &esp_glue; 319 1.1 dbj 320 1.1 dbj /* 321 1.1 dbj * XXX More of this should be in ncr53c9x_attach(), but 322 1.1 dbj * XXX should we really poke around the chip that much in 323 1.1 dbj * XXX the MI code? Think about this more... 324 1.1 dbj */ 325 1.1 dbj 326 1.1 dbj /* 327 1.1 dbj * It is necessary to try to load the 2nd config register here, 328 1.1 dbj * to find out what rev the esp chip is, else the ncr53c9x_reset 329 1.1 dbj * will not set up the defaults correctly. 330 1.1 dbj */ 331 1.1 dbj sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB; 332 1.1 dbj sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE; 333 1.1 dbj sc->sc_cfg3 = NCRCFG3_CDB; 334 1.1 dbj NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 335 1.1 dbj 336 1.1 dbj if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) != 337 1.1 dbj (NCRCFG2_SCSI2 | NCRCFG2_RPE)) { 338 1.1 dbj sc->sc_rev = NCR_VARIANT_ESP100; 339 1.1 dbj } else { 340 1.1 dbj sc->sc_cfg2 = NCRCFG2_SCSI2; 341 1.1 dbj NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 342 1.1 dbj sc->sc_cfg3 = 0; 343 1.1 dbj NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 344 1.1 dbj sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK); 345 1.1 dbj NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 346 1.1 dbj if (NCR_READ_REG(sc, NCR_CFG3) != 347 1.1 dbj (NCRCFG3_CDB | NCRCFG3_FCLK)) { 348 1.1 dbj sc->sc_rev = NCR_VARIANT_ESP100A; 349 1.1 dbj } else { 350 1.1 dbj /* NCRCFG2_FE enables > 64K transfers */ 351 1.1 dbj sc->sc_cfg2 |= NCRCFG2_FE; 352 1.1 dbj sc->sc_cfg3 = 0; 353 1.1 dbj NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 354 1.1 dbj sc->sc_rev = NCR_VARIANT_ESP200; 355 1.1 dbj } 356 1.1 dbj } 357 1.1 dbj 358 1.1 dbj /* 359 1.1 dbj * XXX minsync and maxxfer _should_ be set up in MI code, 360 1.1 dbj * XXX but it appears to have some dependency on what sort 361 1.1 dbj * XXX of DMA we're hooked up to, etc. 362 1.1 dbj */ 363 1.1 dbj 364 1.1 dbj /* 365 1.1 dbj * This is the value used to start sync negotiations 366 1.1 dbj * Note that the NCR register "SYNCTP" is programmed 367 1.1 dbj * in "clocks per byte", and has a minimum value of 4. 368 1.1 dbj * The SCSI period used in negotiation is one-fourth 369 1.1 dbj * of the time (in nanoseconds) needed to transfer one byte. 370 1.1 dbj * Since the chip's clock is given in MHz, we have the following 371 1.1 dbj * formula: 4 * period = (1000 / freq) * 4 372 1.1 dbj */ 373 1.39 mycroft sc->sc_minsync = /* 1000 / sc->sc_freq */ 0; 374 1.1 dbj 375 1.1 dbj /* 376 1.1 dbj * Alas, we must now modify the value a bit, because it's 377 1.66 tsutsui * only valid when can switch on FASTCLK and FASTSCSI bits 378 1.66 tsutsui * in config register 3... 379 1.1 dbj */ 380 1.1 dbj switch (sc->sc_rev) { 381 1.1 dbj case NCR_VARIANT_ESP100: 382 1.1 dbj sc->sc_maxxfer = 64 * 1024; 383 1.1 dbj sc->sc_minsync = 0; /* No synch on old chip? */ 384 1.1 dbj break; 385 1.1 dbj 386 1.1 dbj case NCR_VARIANT_ESP100A: 387 1.1 dbj sc->sc_maxxfer = 64 * 1024; 388 1.1 dbj /* Min clocks/byte is 5 */ 389 1.39 mycroft sc->sc_minsync = /* ncr53c9x_cpb2stp(sc, 5) */ 0; 390 1.1 dbj break; 391 1.1 dbj 392 1.1 dbj case NCR_VARIANT_ESP200: 393 1.1 dbj sc->sc_maxxfer = 16 * 1024 * 1024; 394 1.1 dbj /* XXX - do actually set FAST* bits */ 395 1.1 dbj break; 396 1.1 dbj } 397 1.1 dbj 398 1.3 dbj /* @@@ Some ESP_DCTL bits probably need setting */ 399 1.66 tsutsui NCR_WRITE_REG(sc, ESP_DCTL, 400 1.55 tsutsui ESPDCTL_16MHZ | ESPDCTL_INTENB | ESPDCTL_RESET); 401 1.3 dbj DELAY(10); 402 1.66 tsutsui DPRINTF(("esp dctl is 0x%02x\n", NCR_READ_REG(sc,ESP_DCTL))); 403 1.37 christos NCR_WRITE_REG(sc, ESP_DCTL, ESPDCTL_16MHZ | ESPDCTL_INTENB); 404 1.3 dbj DELAY(10); 405 1.66 tsutsui DPRINTF(("esp dctl is 0x%02x\n", NCR_READ_REG(sc, ESP_DCTL))); 406 1.3 dbj 407 1.66 tsutsui esc->sc_dma = nextdma_findchannel("scsi"); 408 1.66 tsutsui if (esc->sc_dma != NULL) { 409 1.55 tsutsui findchannel_defer(self); 410 1.38 mycroft } else { 411 1.55 tsutsui aprint_normal("\n"); 412 1.55 tsutsui config_defer(self, findchannel_defer); 413 1.3 dbj } 414 1.1 dbj 415 1.38 mycroft attached = 1; 416 1.1 dbj } 417 1.1 dbj 418 1.1 dbj /* 419 1.1 dbj * Glue functions. 420 1.1 dbj */ 421 1.1 dbj 422 1.67 tsutsui static uint8_t 423 1.49 chs esp_read_reg(struct ncr53c9x_softc *sc, int reg) 424 1.1 dbj { 425 1.1 dbj struct esp_softc *esc = (struct esp_softc *)sc; 426 1.1 dbj 427 1.55 tsutsui return bus_space_read_1(esc->sc_bst, esc->sc_bsh, reg); 428 1.1 dbj } 429 1.1 dbj 430 1.67 tsutsui static void 431 1.55 tsutsui esp_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t val) 432 1.1 dbj { 433 1.1 dbj struct esp_softc *esc = (struct esp_softc *)sc; 434 1.1 dbj 435 1.1 dbj bus_space_write_1(esc->sc_bst, esc->sc_bsh, reg, val); 436 1.1 dbj } 437 1.1 dbj 438 1.55 tsutsui volatile uint32_t save1; 439 1.37 christos 440 1.37 christos #define xADDR 0x0211a000 441 1.67 tsutsui static int 442 1.49 chs doze(volatile int c) 443 1.37 christos { 444 1.66 tsutsui #if 0 445 1.66 tsutsui static int tmp1; 446 1.66 tsutsui #endif 447 1.55 tsutsui uint32_t tmp1; 448 1.55 tsutsui volatile uint8_t tmp2; 449 1.55 tsutsui volatile uint8_t *reg = (volatile uint8_t *)IIOV(xADDR); 450 1.55 tsutsui 451 1.55 tsutsui if (c > 244) 452 1.55 tsutsui return 0; 453 1.55 tsutsui if (c == 0) 454 1.55 tsutsui return 0; 455 1.66 tsutsui #if 0 456 1.66 tsutsui ((*(volatile u_long *)IIOV(NEXT_P_INTRMASK)) &= (~NEXT_I_BIT(x))); 457 1.66 tsutsui #endif 458 1.37 christos (*reg) = 0; 459 1.37 christos (*reg) = 0; 460 1.37 christos do { 461 1.37 christos save1 = (*reg); 462 1.37 christos tmp2 = *(reg + 3); 463 1.37 christos tmp1 = tmp2; 464 1.37 christos } while (tmp1 <= c); 465 1.55 tsutsui return 0; 466 1.37 christos } 467 1.37 christos 468 1.67 tsutsui static int 469 1.49 chs esp_dma_isintr(struct ncr53c9x_softc *sc) 470 1.1 dbj { 471 1.4 dbj struct esp_softc *esc = (struct esp_softc *)sc; 472 1.55 tsutsui 473 1.37 christos if (INTR_OCCURRED(NEXT_I_SCSI)) { 474 1.66 tsutsui NDTRACEIF(ndtrace_addc('i')); 475 1.55 tsutsui NCR_WRITE_REG(sc, ESP_DCTL, 476 1.55 tsutsui ESPDCTL_16MHZ | ESPDCTL_INTENB | 477 1.55 tsutsui (esc->sc_datain ? ESPDCTL_DMARD : 0)); 478 1.55 tsutsui return 1; 479 1.37 christos } else { 480 1.55 tsutsui return 0; 481 1.37 christos } 482 1.37 christos } 483 1.37 christos 484 1.67 tsutsui static int 485 1.49 chs esp_dma_intr(struct ncr53c9x_softc *sc) 486 1.37 christos { 487 1.37 christos struct esp_softc *esc = (struct esp_softc *)sc; 488 1.38 mycroft struct nextdma_softc *nsc = esc->sc_dma; 489 1.38 mycroft struct nextdma_status *stat = &nsc->sc_stat; 490 1.4 dbj int r = (INTR_OCCURRED(NEXT_I_SCSI)); 491 1.37 christos int flushcount; 492 1.55 tsutsui 493 1.37 christos r = 1; 494 1.4 dbj 495 1.66 tsutsui NDTRACEIF(ndtrace_addc('I')); 496 1.4 dbj if (r) { 497 1.66 tsutsui #if 0 498 1.66 tsutsui printf("esp_dma_isintr start\n"); 499 1.66 tsutsui #endif 500 1.20 dbj { 501 1.37 christos int s = spldma(); 502 1.38 mycroft void *ndmap = stat->nd_map; 503 1.38 mycroft int ndidx = stat->nd_idx; 504 1.37 christos splx(s); 505 1.20 dbj 506 1.23 dbj flushcount = 0; 507 1.23 dbj 508 1.22 dbj #ifdef ESP_DEBUG 509 1.66 tsutsui #if 0 510 1.66 tsutsui esp_dma_nest++; 511 1.66 tsutsui #endif 512 1.28 tv 513 1.28 tv if (esp_debug) { 514 1.28 tv char sbuf[256]; 515 1.28 tv 516 1.66 tsutsui snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS, 517 1.57 christos (*(volatile u_long *)IIOV(NEXT_P_INTRSTAT))); 518 1.66 tsutsui 519 1.64 msaitoh printf("esp_dma_isintr = %s\n", sbuf); 520 1.28 tv } 521 1.22 dbj #endif 522 1.22 dbj 523 1.65 tsutsui mutex_exit(&sc->sc_lock); /* for nextdma intr */ 524 1.55 tsutsui while (!nextdma_finished(nsc)) { 525 1.66 tsutsui NDTRACEIF(ndtrace_addc('w')); 526 1.66 tsutsui NDTRACEIF( 527 1.61 christos ndtrace_printf("f%dm%dl%dw", 528 1.55 tsutsui NCR_READ_REG(sc, NCR_FFLAG) & 529 1.55 tsutsui NCRFIFO_FF, 530 1.55 tsutsui NCR_READ_REG((sc), NCR_TCM), 531 1.55 tsutsui NCR_READ_REG((sc), NCR_TCL)); 532 1.55 tsutsui ); 533 1.37 christos if (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF) 534 1.55 tsutsui flushcount = 5; 535 1.55 tsutsui NCR_WRITE_REG(sc, ESP_DCTL, 536 1.55 tsutsui ESPDCTL_16MHZ | ESPDCTL_INTENB | 537 1.55 tsutsui ESPDCTL_DMAMOD | 538 1.55 tsutsui (esc->sc_datain ? ESPDCTL_DMARD : 0)); 539 1.37 christos 540 1.37 christos s = spldma(); 541 1.55 tsutsui while (ndmap == stat->nd_map && 542 1.55 tsutsui ndidx == stat->nd_idx && 543 1.66 tsutsui (nd_bsr4(DD_CSR) & 0x08000000) == 0 && 544 1.37 christos ++flushcount < 5) { 545 1.37 christos splx(s); 546 1.66 tsutsui NDTRACEIF(ndtrace_addc('F')); 547 1.55 tsutsui NCR_WRITE_REG(sc, ESP_DCTL, 548 1.55 tsutsui ESPDCTL_FLUSH | ESPDCTL_16MHZ | 549 1.55 tsutsui ESPDCTL_INTENB | ESPDCTL_DMAMOD | 550 1.55 tsutsui (esc->sc_datain ? 551 1.55 tsutsui ESPDCTL_DMARD : 0)); 552 1.37 christos doze(0x32); 553 1.66 tsutsui NCR_WRITE_REG(sc, ESP_DCTL, 554 1.55 tsutsui ESPDCTL_16MHZ | ESPDCTL_INTENB | 555 1.55 tsutsui ESPDCTL_DMAMOD | 556 1.55 tsutsui (esc->sc_datain ? 557 1.55 tsutsui ESPDCTL_DMARD : 0)); 558 1.37 christos doze(0x32); 559 1.37 christos s = spldma(); 560 1.37 christos } 561 1.66 tsutsui NDTRACEIF(ndtrace_addc('0' + flushcount)); 562 1.37 christos if (flushcount > 4) { 563 1.37 christos int next; 564 1.37 christos int onext = 0; 565 1.55 tsutsui 566 1.37 christos splx(s); 567 1.55 tsutsui DPRINTF(("DMA reset\n")); 568 1.66 tsutsui while (((next = nd_bsr4(DD_NEXT)) != 569 1.55 tsutsui (nd_bsr4(DD_LIMIT) & 0x7FFFFFFF)) && 570 1.55 tsutsui onext != next) { 571 1.37 christos onext = next; 572 1.37 christos DELAY(50); 573 1.37 christos } 574 1.66 tsutsui NDTRACEIF(ndtrace_addc('R')); 575 1.55 tsutsui NCR_WRITE_REG(sc, ESP_DCTL, 576 1.55 tsutsui ESPDCTL_16MHZ | ESPDCTL_INTENB); 577 1.66 tsutsui NDTRACEIF( 578 1.61 christos ndtrace_printf( 579 1.55 tsutsui "ff:%d tcm:%d tcl:%d ", 580 1.55 tsutsui NCR_READ_REG(sc, NCR_FFLAG) 581 1.55 tsutsui & NCRFIFO_FF, 582 1.55 tsutsui NCR_READ_REG((sc), NCR_TCM), 583 1.55 tsutsui NCR_READ_REG((sc), 584 1.55 tsutsui NCR_TCL)); 585 1.38 mycroft ); 586 1.37 christos s = spldma(); 587 1.66 tsutsui nextdma_reset(nsc); 588 1.37 christos splx(s); 589 1.37 christos goto out; 590 1.20 dbj } 591 1.37 christos splx(s); 592 1.20 dbj 593 1.23 dbj #ifdef DIAGNOSTIC 594 1.37 christos if (flushcount > 4) { 595 1.66 tsutsui NDTRACEIF(ndtrace_addc('+')); 596 1.55 tsutsui printf("%s: unexpected flushcount" 597 1.55 tsutsui " %d on %s\n", 598 1.55 tsutsui device_xname(sc->sc_dev), 599 1.55 tsutsui flushcount, 600 1.55 tsutsui esc->sc_datain ? "read" : "write"); 601 1.37 christos } 602 1.23 dbj #endif 603 1.23 dbj 604 1.55 tsutsui if (!nextdma_finished(nsc)) { 605 1.66 tsutsui NDTRACEIF(ndtrace_addc('1')); 606 1.16 dbj } 607 1.37 christos flushcount = 0; 608 1.37 christos s = spldma(); 609 1.38 mycroft ndmap = stat->nd_map; 610 1.38 mycroft ndidx = stat->nd_idx; 611 1.37 christos splx(s); 612 1.37 christos 613 1.16 dbj } 614 1.55 tsutsui out: 615 1.65 tsutsui mutex_enter(&sc->sc_lock); /* for nextdma intr */ 616 1.20 dbj 617 1.22 dbj #ifdef ESP_DEBUG 618 1.66 tsutsui #if 0 619 1.66 tsutsui esp_dma_nest--; 620 1.66 tsutsui #endif 621 1.22 dbj #endif 622 1.22 dbj 623 1.13 dbj } 624 1.13 dbj 625 1.55 tsutsui doze(0x32); 626 1.55 tsutsui NCR_WRITE_REG(sc, ESP_DCTL, 627 1.55 tsutsui ESPDCTL_16MHZ | ESPDCTL_INTENB | 628 1.55 tsutsui (esc->sc_datain ? ESPDCTL_DMARD : 0)); 629 1.66 tsutsui NDTRACEIF(ndtrace_addc('b')); 630 1.37 christos 631 1.55 tsutsui while (esc->sc_datain != -1) 632 1.55 tsutsui DELAY(50); 633 1.37 christos 634 1.37 christos if (esc->sc_dmaaddr) { 635 1.37 christos bus_size_t xfer_len = 0; 636 1.37 christos int resid; 637 1.37 christos 638 1.55 tsutsui NCR_WRITE_REG(sc, ESP_DCTL, 639 1.55 tsutsui ESPDCTL_16MHZ | ESPDCTL_INTENB); 640 1.38 mycroft if (stat->nd_exception == 0) { 641 1.55 tsutsui resid = NCR_READ_REG((sc), NCR_TCL) + 642 1.55 tsutsui (NCR_READ_REG((sc), NCR_TCM) << 8); 643 1.37 christos if (resid) { 644 1.55 tsutsui resid += (NCR_READ_REG(sc, NCR_FFLAG) & 645 1.55 tsutsui NCRFIFO_FF); 646 1.38 mycroft #ifdef ESP_DEBUG 647 1.55 tsutsui if (NCR_READ_REG(sc, NCR_FFLAG) & 648 1.55 tsutsui NCRFIFO_FF) 649 1.55 tsutsui if ((NCR_READ_REG(sc, 650 1.55 tsutsui NCR_FFLAG) & NCRFIFO_FF) != 651 1.55 tsutsui 16 || 652 1.55 tsutsui NCR_READ_REG((sc), 653 1.55 tsutsui NCR_TCL) != 240) 654 1.61 christos esptraceshow++; 655 1.38 mycroft #endif 656 1.37 christos } 657 1.37 christos xfer_len = esc->sc_dmasize - resid; 658 1.37 christos } else { 659 1.37 christos #define ncr53c9x_sched_msgout(m) \ 660 1.37 christos do { \ 661 1.37 christos NCR_MISC(("ncr53c9x_sched_msgout %x %d", m, __LINE__)); \ 662 1.37 christos NCRCMD(sc, NCRCMD_SETATN); \ 663 1.37 christos sc->sc_flags |= NCR_ATN; \ 664 1.37 christos sc->sc_msgpriq |= (m); \ 665 1.37 christos } while (0) 666 1.37 christos int i; 667 1.55 tsutsui 668 1.38 mycroft xfer_len = 0; 669 1.38 mycroft if (esc->sc_begin) 670 1.38 mycroft xfer_len += esc->sc_begin_size; 671 1.38 mycroft if (esc->sc_main_dmamap) 672 1.55 tsutsui xfer_len += 673 1.55 tsutsui esc->sc_main_dmamap->dm_xfer_len; 674 1.38 mycroft if (esc->sc_tail_dmamap) 675 1.55 tsutsui xfer_len += 676 1.55 tsutsui esc->sc_tail_dmamap->dm_xfer_len; 677 1.37 christos resid = 0; 678 1.66 tsutsui printf("X\n"); 679 1.37 christos for (i = 0; i < 16; i++) { 680 1.55 tsutsui NCR_WRITE_REG(sc, ESP_DCTL, 681 1.55 tsutsui ESPDCTL_FLUSH | ESPDCTL_16MHZ | 682 1.55 tsutsui ESPDCTL_INTENB | 683 1.55 tsutsui (esc->sc_datain ? 684 1.55 tsutsui ESPDCTL_DMARD : 0)); 685 1.66 tsutsui NCR_WRITE_REG(sc, ESP_DCTL, 686 1.55 tsutsui ESPDCTL_16MHZ | ESPDCTL_INTENB | 687 1.55 tsutsui (esc->sc_datain ? 688 1.55 tsutsui ESPDCTL_DMARD : 0)); 689 1.37 christos } 690 1.37 christos #if 0 691 1.66 tsutsui printf("ff:%02x tcm:%d tcl:%d esp_dstat:%02x" 692 1.55 tsutsui " stat:%02x step: %02x intr:%02x" 693 1.55 tsutsui " new stat:%02X\n", 694 1.55 tsutsui NCR_READ_REG(sc, NCR_FFLAG), 695 1.55 tsutsui NCR_READ_REG((sc), NCR_TCM), 696 1.55 tsutsui NCR_READ_REG((sc), NCR_TCL), 697 1.55 tsutsui NCR_READ_REG(sc, ESP_DSTAT), 698 1.55 tsutsui sc->sc_espstat, sc->sc_espstep, 699 1.55 tsutsui sc->sc_espintr, 700 1.55 tsutsui NCR_READ_REG(sc, NCR_STAT)); 701 1.55 tsutsui printf("sc->sc_state: %x sc->sc_phase: %x" 702 1.55 tsutsui " sc->sc_espstep:%x sc->sc_prevphase:%x" 703 1.55 tsutsui " sc->sc_flags:%x\n", 704 1.55 tsutsui sc->sc_state, sc->sc_phase, sc->sc_espstep, 705 1.55 tsutsui sc->sc_prevphase, sc->sc_flags); 706 1.37 christos #endif 707 1.66 tsutsui #if 0 708 1.66 tsutsui sc->sc_flags &= ~NCR_ICCS; 709 1.66 tsutsui #endif 710 1.37 christos sc->sc_nexus->flags |= ECB_ABORT; 711 1.37 christos if (sc->sc_phase == MESSAGE_IN_PHASE) { 712 1.66 tsutsui #if 0 713 1.66 tsutsui ncr53c9x_sched_msgout(SEND_ABORT); 714 1.66 tsutsui #endif 715 1.37 christos ncr53c9x_abort(sc, sc->sc_nexus); 716 1.37 christos } else if (sc->sc_phase != STATUS_PHASE) { 717 1.55 tsutsui printf("ATTENTION!!! " 718 1.55 tsutsui "not message/status phase: %d\n", 719 1.55 tsutsui sc->sc_phase); 720 1.37 christos } 721 1.37 christos } 722 1.66 tsutsui 723 1.66 tsutsui NDTRACEIF(ndtrace_printf("f%dm%dl%ds%dx%dr%dS", 724 1.66 tsutsui NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF, 725 1.66 tsutsui NCR_READ_REG((sc), NCR_TCM), 726 1.66 tsutsui NCR_READ_REG((sc), NCR_TCL), 727 1.66 tsutsui esc->sc_dmasize, (int)xfer_len, resid); 728 1.55 tsutsui ); 729 1.20 dbj 730 1.55 tsutsui *esc->sc_dmaaddr += xfer_len; 731 1.54 tsutsui *esc->sc_dmalen -= xfer_len; 732 1.37 christos esc->sc_dmaaddr = 0; 733 1.37 christos esc->sc_dmalen = 0; 734 1.37 christos esc->sc_dmasize = 0; 735 1.13 dbj } 736 1.37 christos 737 1.66 tsutsui NDTRACEIF(ndtrace_addc('B')); 738 1.55 tsutsui sc->sc_espstat = NCR_READ_REG(sc, NCR_STAT) | 739 1.55 tsutsui (sc->sc_espstat & NCRSTAT_INT); 740 1.37 christos 741 1.55 tsutsui DPRINTF(("esp dctl is 0x%02x\n", NCR_READ_REG(sc, ESP_DCTL))); 742 1.66 tsutsui #if 0 743 1.66 tsutsui printf("esp_dma_isintr DONE\n"); 744 1.66 tsutsui #endif 745 1.4 dbj } 746 1.4 dbj 747 1.55 tsutsui return r; 748 1.1 dbj } 749 1.1 dbj 750 1.67 tsutsui static void 751 1.49 chs esp_dma_reset(struct ncr53c9x_softc *sc) 752 1.1 dbj { 753 1.1 dbj struct esp_softc *esc = (struct esp_softc *)sc; 754 1.3 dbj 755 1.44 wiz DPRINTF(("esp DMA reset\n")); 756 1.13 dbj 757 1.13 dbj #ifdef ESP_DEBUG 758 1.13 dbj if (esp_debug) { 759 1.28 tv char sbuf[256]; 760 1.28 tv 761 1.66 tsutsui snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS, 762 1.57 christos (*(volatile u_long *)IIOV(NEXT_P_INTRSTAT))); 763 1.64 msaitoh printf(" *intrstat = %s\n", sbuf); 764 1.28 tv 765 1.66 tsutsui snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS, 766 1.57 christos (*(volatile u_long *)IIOV(NEXT_P_INTRMASK))); 767 1.64 msaitoh printf(" *intrmask = %s\n", sbuf); 768 1.13 dbj } 769 1.13 dbj #endif 770 1.13 dbj 771 1.38 mycroft #if 0 772 1.13 dbj /* Clear the DMAMOD bit in the DCTL register: */ 773 1.55 tsutsui NCR_WRITE_REG(sc, ESP_DCTL, ESPDCTL_16MHZ | ESPDCTL_INTENB); 774 1.22 dbj DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL))); 775 1.38 mycroft #endif 776 1.13 dbj 777 1.38 mycroft nextdma_reset(esc->sc_dma); 778 1.38 mycroft nextdma_init(esc->sc_dma); 779 1.4 dbj 780 1.18 dbj esc->sc_datain = -1; 781 1.18 dbj esc->sc_dmaaddr = 0; 782 1.18 dbj esc->sc_dmalen = 0; 783 1.20 dbj esc->sc_dmasize = 0; 784 1.18 dbj 785 1.18 dbj esc->sc_loaded = 0; 786 1.18 dbj 787 1.18 dbj esc->sc_begin = 0; 788 1.18 dbj esc->sc_begin_size = 0; 789 1.13 dbj 790 1.18 dbj if (esc->sc_main_dmamap->dm_mapsize) { 791 1.38 mycroft bus_dmamap_unload(esc->sc_dma->sc_dmat, esc->sc_main_dmamap); 792 1.13 dbj } 793 1.18 dbj esc->sc_main = 0; 794 1.18 dbj esc->sc_main_size = 0; 795 1.13 dbj 796 1.18 dbj if (esc->sc_tail_dmamap->dm_mapsize) { 797 1.38 mycroft bus_dmamap_unload(esc->sc_dma->sc_dmat, esc->sc_tail_dmamap); 798 1.18 dbj } 799 1.18 dbj esc->sc_tail = 0; 800 1.18 dbj esc->sc_tail_size = 0; 801 1.1 dbj } 802 1.1 dbj 803 1.66 tsutsui /* 804 1.66 tsutsui * it appears that: 805 1.19 dbj * addr and len arguments to this need to be kept up to date 806 1.19 dbj * with the status of the transfter. 807 1.19 dbj * the dmasize of this is the actual length of the transfer 808 1.19 dbj * request, which is guaranteed to be less than maxxfer. 809 1.19 dbj * (len may be > maxxfer) 810 1.19 dbj */ 811 1.19 dbj 812 1.67 tsutsui static int 813 1.55 tsutsui esp_dma_setup(struct ncr53c9x_softc *sc, uint8_t **addr, size_t *len, 814 1.55 tsutsui int datain, size_t *dmasize) 815 1.1 dbj { 816 1.1 dbj struct esp_softc *esc = (struct esp_softc *)sc; 817 1.2 dbj 818 1.66 tsutsui NDTRACEIF(ndtrace_addc('h')); 819 1.11 dbj #ifdef DIAGNOSTIC 820 1.20 dbj #ifdef ESP_DEBUG 821 1.66 tsutsui /* 822 1.66 tsutsui * if this is a read DMA, pre-fill the buffer with 0xdeadbeef 823 1.11 dbj * to identify bogus reads 824 1.11 dbj */ 825 1.11 dbj if (datain) { 826 1.14 dbj int *v = (int *)(*addr); 827 1.11 dbj int i; 828 1.55 tsutsui for (i = 0; i < ((*len) / 4); i++) 829 1.55 tsutsui v[i] = 0xdeadbeef; 830 1.18 dbj v = (int *)(&(esc->sc_tailbuf[0])); 831 1.55 tsutsui for (i = 0; i < ((sizeof(esc->sc_tailbuf) / 4)); i++) 832 1.55 tsutsui v[i] = 0xdeafbeef; 833 1.23 dbj } else { 834 1.23 dbj int *v; 835 1.23 dbj int i; 836 1.23 dbj v = (int *)(&(esc->sc_tailbuf[0])); 837 1.55 tsutsui for (i = 0; i < ((sizeof(esc->sc_tailbuf) / 4)); i++) 838 1.55 tsutsui v[i] = 0xfeeb1eed; 839 1.11 dbj } 840 1.20 dbj #endif 841 1.11 dbj #endif 842 1.11 dbj 843 1.55 tsutsui DPRINTF(("esp_dma_setup(%p,0x%08x,0x%08x)\n", *addr, *len, *dmasize)); 844 1.11 dbj 845 1.24 dbj #if 0 846 1.66 tsutsui #ifdef DIAGNOSTIC 847 1.66 tsutsui /* 848 1.66 tsutsui * @@@ this is ok sometimes. verify that we handle it ok 849 1.66 tsutsui * and then remove this check 850 1.66 tsutsui */ 851 1.14 dbj if (*len != *dmasize) { 852 1.55 tsutsui panic("esp dmalen 0x%lx != size 0x%lx", *len, *dmasize); 853 1.11 dbj } 854 1.11 dbj #endif 855 1.24 dbj #endif 856 1.4 dbj 857 1.2 dbj #ifdef DIAGNOSTIC 858 1.3 dbj if ((esc->sc_datain != -1) || 859 1.55 tsutsui (esc->sc_main_dmamap->dm_mapsize != 0) || 860 1.55 tsutsui (esc->sc_tail_dmamap->dm_mapsize != 0) || 861 1.66 tsutsui (esc->sc_dmasize != 0)) { 862 1.40 provos panic("%s: map already loaded in esp_dma_setup" 863 1.55 tsutsui "\tdatain = %d\n\tmain_mapsize=%ld\n" 864 1.55 tsutsui "\tail_mapsize=%ld\n\tdmasize = %d", 865 1.55 tsutsui device_xname(sc->sc_dev), esc->sc_datain, 866 1.55 tsutsui esc->sc_main_dmamap->dm_mapsize, 867 1.55 tsutsui esc->sc_tail_dmamap->dm_mapsize, 868 1.55 tsutsui esc->sc_dmasize); 869 1.2 dbj } 870 1.2 dbj #endif 871 1.2 dbj 872 1.44 wiz /* we are sometimes asked to DMA zero bytes, that's easy */ 873 1.24 dbj if (*dmasize <= 0) { 874 1.55 tsutsui return 0; 875 1.20 dbj } 876 1.20 dbj 877 1.37 christos if (*dmasize > ESP_MAX_DMASIZE) 878 1.37 christos *dmasize = ESP_MAX_DMASIZE; 879 1.37 christos 880 1.14 dbj /* Save these in case we have to abort DMA */ 881 1.14 dbj esc->sc_datain = datain; 882 1.14 dbj esc->sc_dmaaddr = addr; 883 1.14 dbj esc->sc_dmalen = len; 884 1.14 dbj esc->sc_dmasize = *dmasize; 885 1.14 dbj 886 1.18 dbj esc->sc_loaded = 0; 887 1.18 dbj 888 1.23 dbj #define DMA_SCSI_ALIGNMENT 16 889 1.23 dbj #define DMA_SCSI_ALIGN(type, addr) \ 890 1.55 tsutsui ((type)(((unsigned int)(addr) + DMA_SCSI_ALIGNMENT - 1) \ 891 1.66 tsutsui & ~(DMA_SCSI_ALIGNMENT-1))) 892 1.23 dbj #define DMA_SCSI_ALIGNED(addr) \ 893 1.66 tsutsui (((unsigned int)(addr) & (DMA_SCSI_ALIGNMENT - 1)) == 0) 894 1.23 dbj 895 1.2 dbj { 896 1.18 dbj size_t slop_bgn_size; /* # bytes to be fifo'd at beginning */ 897 1.66 tsutsui size_t slop_end_size; /* # bytes to be transferred in 898 1.66 tsutsui tail buffer */ 899 1.66 tsutsui 900 1.3 dbj { 901 1.13 dbj u_long bgn = (u_long)(*esc->sc_dmaaddr); 902 1.54 tsutsui u_long end = bgn + esc->sc_dmasize; 903 1.3 dbj 904 1.55 tsutsui slop_bgn_size = 905 1.55 tsutsui DMA_SCSI_ALIGNMENT - (bgn % DMA_SCSI_ALIGNMENT); 906 1.55 tsutsui if (slop_bgn_size == DMA_SCSI_ALIGNMENT) 907 1.55 tsutsui slop_bgn_size = 0; 908 1.55 tsutsui slop_end_size = end % DMA_ENDALIGNMENT; 909 1.3 dbj } 910 1.3 dbj 911 1.66 tsutsui /* 912 1.66 tsutsui * Force a minimum slop end size. This ensures that write 913 1.55 tsutsui * requests will overrun, as required to get completion 914 1.55 tsutsui * interrupts. 915 1.23 dbj * In addition, since the tail buffer is guaranteed to be mapped 916 1.44 wiz * in a single DMA segment, the overrun won't accidentally 917 1.23 dbj * end up in its own segment. 918 1.23 dbj */ 919 1.23 dbj if (!esc->sc_datain) { 920 1.24 dbj #if 0 921 1.23 dbj slop_end_size += ESP_DMA_MAXTAIL; 922 1.24 dbj #else 923 1.24 dbj slop_end_size += 0x10; 924 1.24 dbj #endif 925 1.23 dbj } 926 1.23 dbj 927 1.66 tsutsui /* 928 1.66 tsutsui * Check to make sure we haven't counted extra slop 929 1.44 wiz * as would happen for a very short DMA buffer, also 930 1.14 dbj * for short buffers, just stuff the entire thing in the tail 931 1.14 dbj */ 932 1.18 dbj if ((slop_bgn_size+slop_end_size >= esc->sc_dmasize) 933 1.20 dbj #if 0 934 1.55 tsutsui || (esc->sc_dmasize <= ESP_DMA_MAXTAIL) 935 1.18 dbj #endif 936 1.55 tsutsui ) { 937 1.66 tsutsui slop_bgn_size = 0; 938 1.14 dbj slop_end_size = esc->sc_dmasize; 939 1.18 dbj } 940 1.14 dbj 941 1.18 dbj /* initialize the fifo buffer */ 942 1.66 tsutsui if (slop_bgn_size != 0) { 943 1.18 dbj esc->sc_begin = *esc->sc_dmaaddr; 944 1.18 dbj esc->sc_begin_size = slop_bgn_size; 945 1.18 dbj } else { 946 1.18 dbj esc->sc_begin = 0; 947 1.18 dbj esc->sc_begin_size = 0; 948 1.18 dbj } 949 1.18 dbj 950 1.66 tsutsui #if 1 951 1.18 dbj /* Load the normal DMA map */ 952 1.18 dbj { 953 1.55 tsutsui esc->sc_main = *esc->sc_dmaaddr; 954 1.55 tsutsui esc->sc_main += slop_bgn_size; 955 1.55 tsutsui esc->sc_main_size = 956 1.66 tsutsui (esc->sc_dmasize) - (slop_end_size + slop_bgn_size); 957 1.18 dbj 958 1.66 tsutsui if (esc->sc_main_size != 0) { 959 1.18 dbj int error; 960 1.37 christos 961 1.55 tsutsui if (!esc->sc_datain || 962 1.55 tsutsui DMA_ENDALIGNED(esc->sc_main_size + 963 1.55 tsutsui slop_end_size)) { 964 1.55 tsutsui KASSERT(DMA_SCSI_ALIGNMENT == 965 1.55 tsutsui DMA_ENDALIGNMENT); 966 1.55 tsutsui KASSERT(DMA_BEGINALIGNMENT == 967 1.55 tsutsui DMA_ENDALIGNMENT); 968 1.37 christos esc->sc_main_size += slop_end_size; 969 1.37 christos slop_end_size = 0; 970 1.37 christos if (!esc->sc_datain) { 971 1.55 tsutsui esc->sc_main_size = 972 1.55 tsutsui DMA_ENDALIGN(uint8_t *, 973 1.55 tsutsui esc->sc_main + 974 1.55 tsutsui esc->sc_main_size) - 975 1.55 tsutsui esc->sc_main; 976 1.37 christos } 977 1.37 christos } 978 1.37 christos 979 1.38 mycroft error = bus_dmamap_load(esc->sc_dma->sc_dmat, 980 1.55 tsutsui esc->sc_main_dmamap, 981 1.55 tsutsui esc->sc_main, esc->sc_main_size, 982 1.55 tsutsui NULL, BUS_DMA_NOWAIT); 983 1.66 tsutsui if (error != 0) { 984 1.34 dbj #ifdef ESP_DEBUG 985 1.55 tsutsui printf("%s: esc->sc_main_dmamap->" 986 1.55 tsutsui "_dm_size = %ld\n", 987 1.55 tsutsui device_xname(sc->sc_dev), 988 1.55 tsutsui esc->sc_main_dmamap->_dm_size); 989 1.55 tsutsui printf("%s: esc->sc_main_dmamap->" 990 1.55 tsutsui "_dm_segcnt = %d\n", 991 1.55 tsutsui device_xname(sc->sc_dev), 992 1.55 tsutsui esc->sc_main_dmamap->_dm_segcnt); 993 1.61 christos #ifdef notdef 994 1.55 tsutsui printf("%s: esc->sc_main_dmamap->" 995 1.55 tsutsui "_dm_maxsegsz = %ld\n", 996 1.55 tsutsui device_xname(sc->sc_dev), 997 1.55 tsutsui esc->sc_main_dmamap->_dm_maxsegsz); 998 1.61 christos #endif 999 1.55 tsutsui printf("%s: esc->sc_main_dmamap->" 1000 1.55 tsutsui "_dm_boundary = %ld\n", 1001 1.55 tsutsui device_xname(sc->sc_dev), 1002 1.55 tsutsui esc->sc_main_dmamap->_dm_boundary); 1003 1.34 dbj esp_dma_print(sc); 1004 1.34 dbj #endif 1005 1.55 tsutsui panic("%s: can't load main DMA map." 1006 1.55 tsutsui " error = %d, addr=%p, size=0x%08x", 1007 1.55 tsutsui device_xname(sc->sc_dev), 1008 1.55 tsutsui error, esc->sc_main, 1009 1.55 tsutsui esc->sc_main_size); 1010 1.18 dbj } 1011 1.55 tsutsui if (!esc->sc_datain) { 1012 1.55 tsutsui /* 1013 1.55 tsutsui * patch the DMA map for write overrun 1014 1.55 tsutsui */ 1015 1.55 tsutsui esc->sc_main_dmamap->dm_mapsize += 1016 1.55 tsutsui ESP_DMA_OVERRUN; 1017 1.55 tsutsui esc->sc_main_dmamap->dm_segs[ 1018 1.55 tsutsui esc->sc_main_dmamap->dm_nsegs - 1019 1.55 tsutsui 1].ds_len += 1020 1.37 christos ESP_DMA_OVERRUN; 1021 1.37 christos } 1022 1.23 dbj #if 0 1023 1.55 tsutsui bus_dmamap_sync(esc->sc_dma->sc_dmat, 1024 1.55 tsutsui esc->sc_main_dmamap, 1025 1.66 tsutsui 0, esc->sc_main_dmamap->dm_mapsize, 1026 1.55 tsutsui (esc->sc_datain ? BUS_DMASYNC_PREREAD : 1027 1.55 tsutsui BUS_DMASYNC_PREWRITE)); 1028 1.34 dbj esc->sc_main_dmamap->dm_xfer_len = 0; 1029 1.23 dbj #endif 1030 1.18 dbj } else { 1031 1.18 dbj esc->sc_main = 0; 1032 1.18 dbj } 1033 1.14 dbj } 1034 1.3 dbj 1035 1.18 dbj /* Load the tail DMA map */ 1036 1.66 tsutsui if (slop_end_size != 0) { 1037 1.55 tsutsui esc->sc_tail = DMA_ENDALIGN(uint8_t *, 1038 1.55 tsutsui esc->sc_tailbuf + slop_end_size) - slop_end_size; 1039 1.55 tsutsui /* 1040 1.55 tsutsui * If the beginning of the tail is not correctly 1041 1.55 tsutsui * aligned, we have no choice but to align the start, 1042 1.55 tsutsui * which might then unalign the end. 1043 1.55 tsutsui */ 1044 1.55 tsutsui esc->sc_tail = DMA_SCSI_ALIGN(uint8_t *, esc->sc_tail); 1045 1.55 tsutsui /* 1046 1.55 tsutsui * So therefore, we change the tail size to be 1047 1.55 tsutsui * end aligned again. 1048 1.18 dbj */ 1049 1.55 tsutsui esc->sc_tail_size = DMA_ENDALIGN(uint8_t *, 1050 1.55 tsutsui esc->sc_tail + slop_end_size) - esc->sc_tail; 1051 1.19 dbj 1052 1.44 wiz /* @@@ next DMA overrun lossage */ 1053 1.20 dbj if (!esc->sc_datain) { 1054 1.21 dbj esc->sc_tail_size += ESP_DMA_OVERRUN; 1055 1.20 dbj } 1056 1.20 dbj 1057 1.18 dbj { 1058 1.18 dbj int error; 1059 1.38 mycroft error = bus_dmamap_load(esc->sc_dma->sc_dmat, 1060 1.55 tsutsui esc->sc_tail_dmamap, 1061 1.66 tsutsui esc->sc_tail, esc->sc_tail_size, 1062 1.55 tsutsui NULL, BUS_DMA_NOWAIT); 1063 1.18 dbj if (error) { 1064 1.55 tsutsui panic("%s: can't load tail DMA map." 1065 1.55 tsutsui " error = %d, addr=%p, size=0x%08x", 1066 1.55 tsutsui device_xname(sc->sc_dev), error, 1067 1.55 tsutsui esc->sc_tail,esc->sc_tail_size); 1068 1.18 dbj } 1069 1.23 dbj #if 0 1070 1.55 tsutsui bus_dmamap_sync(esc->sc_dma->sc_dmat, 1071 1.55 tsutsui esc->sc_tail_dmamap, 0, 1072 1.66 tsutsui esc->sc_tail_dmamap->dm_mapsize, 1073 1.55 tsutsui (esc->sc_datain ? BUS_DMASYNC_PREREAD : 1074 1.55 tsutsui BUS_DMASYNC_PREWRITE)); 1075 1.34 dbj esc->sc_tail_dmamap->dm_xfer_len = 0; 1076 1.23 dbj #endif 1077 1.3 dbj } 1078 1.3 dbj } 1079 1.37 christos #else 1080 1.37 christos 1081 1.37 christos esc->sc_begin = *esc->sc_dmaaddr; 1082 1.55 tsutsui slop_bgn_size = DMA_SCSI_ALIGNMENT - 1083 1.55 tsutsui ((u_long)esc->sc_begin % DMA_SCSI_ALIGNMENT); 1084 1.55 tsutsui if (slop_bgn_size == DMA_SCSI_ALIGNMENT) 1085 1.55 tsutsui slop_bgn_size = 0; 1086 1.37 christos slop_end_size = esc->sc_dmasize - slop_bgn_size; 1087 1.37 christos 1088 1.37 christos if (slop_bgn_size < esc->sc_dmasize) { 1089 1.37 christos int error; 1090 1.37 christos 1091 1.37 christos esc->sc_tail = 0; 1092 1.37 christos esc->sc_tail_size = 0; 1093 1.37 christos 1094 1.37 christos esc->sc_begin_size = slop_bgn_size; 1095 1.54 tsutsui esc->sc_main = *esc->sc_dmaaddr; 1096 1.54 tsutsui esc->sc_main += slop_bgn_size; 1097 1.55 tsutsui esc->sc_main_size = DMA_ENDALIGN(uint8_t *, 1098 1.55 tsutsui esc->sc_main + esc->sc_dmasize - slop_bgn_size) - 1099 1.55 tsutsui esc->sc_main; 1100 1.37 christos 1101 1.37 christos if (!esc->sc_datain) { 1102 1.37 christos esc->sc_main_size += ESP_DMA_OVERRUN; 1103 1.37 christos } 1104 1.38 mycroft error = bus_dmamap_load(esc->sc_dma->sc_dmat, 1105 1.55 tsutsui esc->sc_main_dmamap, 1106 1.55 tsutsui esc->sc_main, esc->sc_main_size, 1107 1.55 tsutsui NULL, BUS_DMA_NOWAIT); 1108 1.37 christos if (error) { 1109 1.55 tsutsui panic("%s: can't load main DMA map." 1110 1.55 tsutsui " error = %d, addr=%p, size=0x%08x", 1111 1.55 tsutsui device_xname(sc->sc_dev), error, 1112 1.55 tsutsui esc->sc_main,esc->sc_main_size); 1113 1.37 christos } 1114 1.37 christos } else { 1115 1.37 christos esc->sc_begin = 0; 1116 1.37 christos esc->sc_begin_size = 0; 1117 1.37 christos esc->sc_main = 0; 1118 1.37 christos esc->sc_main_size = 0; 1119 1.37 christos 1120 1.37 christos #if 0 1121 1.55 tsutsui esc->sc_tail = DMA_ENDALIGN(uint8_t *, 1122 1.55 tsutsui esc->sc_tailbuf + slop_bgn_size) - slop_bgn_size; 1123 1.55 tsutsui /* 1124 1.55 tsutsui * If the beginning of the tail is not correctly 1125 1.55 tsutsui * aligned, we have no choice but to align the start, 1126 1.55 tsutsui * which might then unalign the end. 1127 1.37 christos */ 1128 1.37 christos #endif 1129 1.55 tsutsui esc->sc_tail = DMA_SCSI_ALIGN(void *, esc->sc_tailbuf); 1130 1.55 tsutsui /* 1131 1.55 tsutsui * So therefore, we change the tail size to be 1132 1.55 tsutsui * end aligned again. 1133 1.55 tsutsui */ 1134 1.55 tsutsui esc->sc_tail_size = DMA_ENDALIGN(uint8_t *, 1135 1.55 tsutsui esc->sc_tail + esc->sc_dmasize) - esc->sc_tail; 1136 1.37 christos 1137 1.44 wiz /* @@@ next DMA overrun lossage */ 1138 1.37 christos if (!esc->sc_datain) { 1139 1.37 christos esc->sc_tail_size += ESP_DMA_OVERRUN; 1140 1.37 christos } 1141 1.37 christos 1142 1.37 christos { 1143 1.37 christos int error; 1144 1.38 mycroft error = bus_dmamap_load(esc->sc_dma->sc_dmat, 1145 1.55 tsutsui esc->sc_tail_dmamap, 1146 1.55 tsutsui esc->sc_tail, esc->sc_tail_size, 1147 1.55 tsutsui NULL, BUS_DMA_NOWAIT); 1148 1.66 tsutsui if (error != 0) { 1149 1.55 tsutsui panic("%s: can't load tail DMA map." 1150 1.55 tsutsui " error = %d, addr=%p, size=0x%08x", 1151 1.55 tsutsui device_xname(sc->sc_dev), error, 1152 1.55 tsutsui esc->sc_tail, esc->sc_tail_size); 1153 1.37 christos } 1154 1.37 christos } 1155 1.37 christos } 1156 1.37 christos #endif 1157 1.37 christos 1158 1.55 tsutsui DPRINTF(("%s: setup: %8p %d %8p %d %8p %d %8p %d\n", 1159 1.55 tsutsui device_xname(sc->sc_dev), 1160 1.55 tsutsui *esc->sc_dmaaddr, esc->sc_dmasize, 1161 1.55 tsutsui esc->sc_begin, esc->sc_begin_size, 1162 1.55 tsutsui esc->sc_main, esc->sc_main_size, 1163 1.55 tsutsui esc->sc_tail, esc->sc_tail_size)); 1164 1.2 dbj } 1165 1.2 dbj 1166 1.55 tsutsui return 0; 1167 1.1 dbj } 1168 1.1 dbj 1169 1.20 dbj #ifdef ESP_DEBUG 1170 1.20 dbj /* For debugging */ 1171 1.1 dbj void 1172 1.49 chs esp_dma_store(struct ncr53c9x_softc *sc) 1173 1.1 dbj { 1174 1.1 dbj struct esp_softc *esc = (struct esp_softc *)sc; 1175 1.61 christos char *p = esp_dma_dump; 1176 1.61 christos size_t l = 0; 1177 1.61 christos size_t len = sizeof(esp_dma_dump); 1178 1.66 tsutsui 1179 1.61 christos l += snprintf(p + l, len - l, "%s: sc_datain=%d\n", 1180 1.55 tsutsui device_xname(sc->sc_dev), esc->sc_datain); 1181 1.62 christos if (l > len) 1182 1.62 christos return; 1183 1.61 christos l += snprintf(p + l, len - l, "%s: sc_loaded=0x%08x\n", 1184 1.55 tsutsui device_xname(sc->sc_dev), esc->sc_loaded); 1185 1.62 christos if (l > len) 1186 1.62 christos return; 1187 1.3 dbj 1188 1.66 tsutsui if (esc->sc_dmaaddr != 0) { 1189 1.61 christos l += snprintf(p + l, len - l, "%s: sc_dmaaddr=%p\n", 1190 1.55 tsutsui device_xname(sc->sc_dev), *esc->sc_dmaaddr); 1191 1.20 dbj } else { 1192 1.61 christos l += snprintf(p + l, len - l, "%s: sc_dmaaddr=NULL\n", 1193 1.55 tsutsui device_xname(sc->sc_dev)); 1194 1.20 dbj } 1195 1.62 christos if (l > len) 1196 1.62 christos return; 1197 1.20 dbj if (esc->sc_dmalen) { 1198 1.66 tsutsui l += snprintf(p + l, len - l, "%s: sc_dmalen=0x%08x\n", 1199 1.55 tsutsui device_xname(sc->sc_dev), *esc->sc_dmalen); 1200 1.20 dbj } else { 1201 1.61 christos l += snprintf(p + l, len - l, "%s: sc_dmalen=NULL\n", 1202 1.55 tsutsui device_xname(sc->sc_dev)); 1203 1.20 dbj } 1204 1.62 christos if (l > len) 1205 1.62 christos return; 1206 1.61 christos l += snprintf(p + l, len - l, "%s: sc_dmasize=0x%08x\n", 1207 1.55 tsutsui device_xname(sc->sc_dev), esc->sc_dmasize); 1208 1.62 christos if (l > len) 1209 1.62 christos return; 1210 1.19 dbj 1211 1.66 tsutsui l += snprintf(p + l, len - l, 1212 1.66 tsutsui "%s: sc_begin = %p, sc_begin_size = 0x%08x\n", 1213 1.63 christos device_xname(sc->sc_dev), esc->sc_begin, esc->sc_begin_size); 1214 1.62 christos if (l > len) 1215 1.62 christos return; 1216 1.66 tsutsui l += snprintf(p + l, len - l, 1217 1.66 tsutsui "%s: sc_main = %p, sc_main_size = 0x%08x\n", 1218 1.55 tsutsui device_xname(sc->sc_dev), esc->sc_main, esc->sc_main_size); 1219 1.62 christos if (l > len) 1220 1.62 christos return; 1221 1.66 tsutsui #if 0 1222 1.66 tsutsui if (esc->sc_main) 1223 1.66 tsutsui #endif 1224 1.66 tsutsui { 1225 1.19 dbj int i; 1226 1.19 dbj bus_dmamap_t map = esc->sc_main_dmamap; 1227 1.61 christos l += snprintf(p + l, len - l, "%s: sc_main_dmamap." 1228 1.55 tsutsui " mapsize = 0x%08lx, nsegs = %d\n", 1229 1.55 tsutsui device_xname(sc->sc_dev), map->dm_mapsize, map->dm_nsegs); 1230 1.62 christos if (l > len) 1231 1.62 christos return; 1232 1.55 tsutsui for(i = 0; i < map->dm_nsegs; i++) { 1233 1.61 christos l += snprintf(p + l, len - l, "%s:" 1234 1.55 tsutsui " map->dm_segs[%d].ds_addr = 0x%08lx," 1235 1.55 tsutsui " len = 0x%08lx\n", 1236 1.55 tsutsui device_xname(sc->sc_dev), 1237 1.55 tsutsui i, map->dm_segs[i].ds_addr, 1238 1.55 tsutsui map->dm_segs[i].ds_len); 1239 1.62 christos if (l > len) 1240 1.62 christos return; 1241 1.19 dbj } 1242 1.19 dbj } 1243 1.66 tsutsui l += snprintf(p + l, len - l, 1244 1.66 tsutsui "%s: sc_tail = %p, sc_tail_size = 0x%08x\n", 1245 1.55 tsutsui device_xname(sc->sc_dev), esc->sc_tail, esc->sc_tail_size); 1246 1.62 christos if (l > len) 1247 1.62 christos return; 1248 1.66 tsutsui #if 0 1249 1.66 tsutsui if (esc->sc_tail) 1250 1.66 tsutsui #endif 1251 1.66 tsutsui { 1252 1.19 dbj int i; 1253 1.19 dbj bus_dmamap_t map = esc->sc_tail_dmamap; 1254 1.61 christos l += snprintf(p + l, len - l, "%s: sc_tail_dmamap." 1255 1.55 tsutsui " mapsize = 0x%08lx, nsegs = %d\n", 1256 1.55 tsutsui device_xname(sc->sc_dev), map->dm_mapsize, map->dm_nsegs); 1257 1.62 christos if (l > len) 1258 1.62 christos return; 1259 1.55 tsutsui for (i = 0; i < map->dm_nsegs; i++) { 1260 1.61 christos l += snprintf(p + l, len - l, "%s:" 1261 1.55 tsutsui " map->dm_segs[%d].ds_addr = 0x%08lx," 1262 1.55 tsutsui " len = 0x%08lx\n", 1263 1.55 tsutsui device_xname(sc->sc_dev), 1264 1.55 tsutsui i, map->dm_segs[i].ds_addr, 1265 1.55 tsutsui map->dm_segs[i].ds_len); 1266 1.62 christos if (l > len) 1267 1.62 christos return; 1268 1.19 dbj } 1269 1.19 dbj } 1270 1.20 dbj } 1271 1.20 dbj 1272 1.20 dbj void 1273 1.49 chs esp_dma_print(struct ncr53c9x_softc *sc) 1274 1.20 dbj { 1275 1.55 tsutsui 1276 1.20 dbj esp_dma_store(sc); 1277 1.55 tsutsui printf("%s", esp_dma_dump); 1278 1.20 dbj } 1279 1.20 dbj #endif 1280 1.20 dbj 1281 1.67 tsutsui static void 1282 1.49 chs esp_dma_go(struct ncr53c9x_softc *sc) 1283 1.20 dbj { 1284 1.20 dbj struct esp_softc *esc = (struct esp_softc *)sc; 1285 1.38 mycroft struct nextdma_softc *nsc = esc->sc_dma; 1286 1.38 mycroft struct nextdma_status *stat = &nsc->sc_stat; 1287 1.66 tsutsui #if 0 1288 1.66 tsutsui int s = spldma(); 1289 1.66 tsutsui #endif 1290 1.37 christos 1291 1.38 mycroft #ifdef ESP_DEBUG 1292 1.61 christos if (!ndtrace_empty()) { 1293 1.61 christos if (esptraceshow) { 1294 1.61 christos printf("esp ndtrace: %s\n", ndtrace_get()); 1295 1.61 christos esptraceshow = 0; 1296 1.37 christos } else { 1297 1.55 tsutsui DPRINTF(("X")); 1298 1.37 christos } 1299 1.61 christos ndtrace_reset(); 1300 1.37 christos } 1301 1.38 mycroft #endif 1302 1.20 dbj 1303 1.20 dbj DPRINTF(("%s: esp_dma_go(datain = %d)\n", 1304 1.55 tsutsui device_xname(sc->sc_dev), esc->sc_datain)); 1305 1.20 dbj 1306 1.20 dbj #ifdef ESP_DEBUG 1307 1.55 tsutsui if (esp_debug) 1308 1.55 tsutsui esp_dma_print(sc); 1309 1.55 tsutsui else 1310 1.55 tsutsui esp_dma_store(sc); 1311 1.19 dbj #endif 1312 1.4 dbj 1313 1.20 dbj #ifdef ESP_DEBUG 1314 1.11 dbj { 1315 1.11 dbj int n = NCR_READ_REG(sc, NCR_FFLAG); 1316 1.20 dbj DPRINTF(("%s: fifo size = %d, seq = 0x%x\n", 1317 1.55 tsutsui device_xname(sc->sc_dev), 1318 1.55 tsutsui n & NCRFIFO_FF, (n & NCRFIFO_SS) >> 5)); 1319 1.4 dbj } 1320 1.11 dbj #endif 1321 1.4 dbj 1322 1.44 wiz /* zero length DMA transfers are boring */ 1323 1.20 dbj if (esc->sc_dmasize == 0) { 1324 1.66 tsutsui #if 0 1325 1.66 tsutsui splx(s); 1326 1.66 tsutsui #endif 1327 1.20 dbj return; 1328 1.20 dbj } 1329 1.20 dbj 1330 1.18 dbj #if defined(DIAGNOSTIC) 1331 1.55 tsutsui if ((esc->sc_begin_size == 0) && 1332 1.55 tsutsui (esc->sc_main_dmamap->dm_mapsize == 0) && 1333 1.55 tsutsui (esc->sc_tail_dmamap->dm_mapsize == 0)) { 1334 1.38 mycroft #ifdef ESP_DEBUG 1335 1.20 dbj esp_dma_print(sc); 1336 1.38 mycroft #endif 1337 1.55 tsutsui panic("%s: No DMA requested!", device_xname(sc->sc_dev)); 1338 1.18 dbj } 1339 1.18 dbj #endif 1340 1.18 dbj 1341 1.18 dbj /* Stuff the fifo with the begin buffer */ 1342 1.18 dbj if (esc->sc_datain) { 1343 1.4 dbj int i; 1344 1.23 dbj DPRINTF(("%s: FIFO read of %d bytes:", 1345 1.55 tsutsui device_xname(sc->sc_dev), esc->sc_begin_size)); 1346 1.55 tsutsui for (i = 0; i < esc->sc_begin_size; i++) { 1347 1.55 tsutsui esc->sc_begin[i] = NCR_READ_REG(sc, NCR_FIFO); 1348 1.55 tsutsui DPRINTF((" %02x", esc->sc_begin[i] & 0xff)); 1349 1.4 dbj } 1350 1.23 dbj DPRINTF(("\n")); 1351 1.4 dbj } else { 1352 1.4 dbj int i; 1353 1.23 dbj DPRINTF(("%s: FIFO write of %d bytes:", 1354 1.55 tsutsui device_xname(sc->sc_dev), esc->sc_begin_size)); 1355 1.55 tsutsui for (i = 0; i < esc->sc_begin_size; i++) { 1356 1.18 dbj NCR_WRITE_REG(sc, NCR_FIFO, esc->sc_begin[i]); 1357 1.55 tsutsui DPRINTF((" %02x",esc->sc_begin[i] & 0xff)); 1358 1.4 dbj } 1359 1.23 dbj DPRINTF(("\n")); 1360 1.11 dbj } 1361 1.4 dbj 1362 1.66 tsutsui if (esc->sc_main_dmamap->dm_mapsize != 0) { 1363 1.38 mycroft bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_main_dmamap, 1364 1.66 tsutsui 0, esc->sc_main_dmamap->dm_mapsize, 1365 1.55 tsutsui (esc->sc_datain ? 1366 1.55 tsutsui BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)); 1367 1.34 dbj esc->sc_main_dmamap->dm_xfer_len = 0; 1368 1.23 dbj } 1369 1.23 dbj 1370 1.66 tsutsui if (esc->sc_tail_dmamap->dm_mapsize != 0) { 1371 1.44 wiz /* if we are a DMA write cycle, copy the end slop */ 1372 1.37 christos if (!esc->sc_datain) { 1373 1.55 tsutsui memcpy(esc->sc_tail, *esc->sc_dmaaddr + 1374 1.55 tsutsui esc->sc_begin_size+esc->sc_main_size, 1375 1.55 tsutsui esc->sc_dmasize - 1376 1.55 tsutsui (esc->sc_begin_size + esc->sc_main_size)); 1377 1.37 christos } 1378 1.38 mycroft bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_tail_dmamap, 1379 1.66 tsutsui 0, esc->sc_tail_dmamap->dm_mapsize, 1380 1.55 tsutsui (esc->sc_datain ? 1381 1.55 tsutsui BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)); 1382 1.34 dbj esc->sc_tail_dmamap->dm_xfer_len = 0; 1383 1.23 dbj } 1384 1.23 dbj 1385 1.38 mycroft stat->nd_exception = 0; 1386 1.38 mycroft nextdma_start(nsc, (esc->sc_datain ? DMACSR_SETREAD : DMACSR_SETWRITE)); 1387 1.12 dbj 1388 1.66 tsutsui if (esc->sc_datain) { 1389 1.14 dbj NCR_WRITE_REG(sc, ESP_DCTL, 1390 1.55 tsutsui ESPDCTL_16MHZ | ESPDCTL_INTENB | ESPDCTL_DMAMOD | 1391 1.55 tsutsui ESPDCTL_DMARD); 1392 1.3 dbj } else { 1393 1.14 dbj NCR_WRITE_REG(sc, ESP_DCTL, 1394 1.55 tsutsui ESPDCTL_16MHZ | ESPDCTL_INTENB | ESPDCTL_DMAMOD); 1395 1.3 dbj } 1396 1.22 dbj DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL))); 1397 1.37 christos 1398 1.55 tsutsui NDTRACEIF( 1399 1.66 tsutsui if (esc->sc_begin_size != 0) { 1400 1.61 christos ndtrace_addc('1'); 1401 1.61 christos ndtrace_addc('A' + esc->sc_begin_size); 1402 1.55 tsutsui } 1403 1.55 tsutsui ); 1404 1.55 tsutsui NDTRACEIF( 1405 1.66 tsutsui if (esc->sc_main_size != 0) { 1406 1.61 christos ndtrace_addc('2'); 1407 1.61 christos ndtrace_addc('0' + esc->sc_main_dmamap->dm_nsegs); 1408 1.55 tsutsui } 1409 1.55 tsutsui ); 1410 1.55 tsutsui NDTRACEIF( 1411 1.66 tsutsui if (esc->sc_tail_size != 0) { 1412 1.61 christos ndtrace_addc('3'); 1413 1.61 christos ndtrace_addc('A' + esc->sc_tail_size); 1414 1.55 tsutsui } 1415 1.55 tsutsui ); 1416 1.37 christos 1417 1.66 tsutsui #if 0 1418 1.66 tsutsui splx(s); 1419 1.66 tsutsui #endif 1420 1.1 dbj } 1421 1.1 dbj 1422 1.67 tsutsui static void 1423 1.49 chs esp_dma_stop(struct ncr53c9x_softc *sc) 1424 1.1 dbj { 1425 1.34 dbj struct esp_softc *esc = (struct esp_softc *)sc; 1426 1.55 tsutsui 1427 1.38 mycroft nextdma_print(esc->sc_dma); 1428 1.38 mycroft #ifdef ESP_DEBUG 1429 1.34 dbj esp_dma_print(sc); 1430 1.38 mycroft #endif 1431 1.37 christos #if 1 1432 1.55 tsutsui panic("%s: stop not yet implemented", device_xname(sc->sc_dev)); 1433 1.37 christos #endif 1434 1.1 dbj } 1435 1.1 dbj 1436 1.67 tsutsui static int 1437 1.49 chs esp_dma_isactive(struct ncr53c9x_softc *sc) 1438 1.1 dbj { 1439 1.1 dbj struct esp_softc *esc = (struct esp_softc *)sc; 1440 1.55 tsutsui int r; 1441 1.55 tsutsui 1442 1.66 tsutsui #if 0 1443 1.66 tsutsui r = !nextdma_finished(esc->sc_dma); 1444 1.66 tsutsui #else 1445 1.66 tsutsui r = (esc->sc_dmaaddr != NULL); 1446 1.66 tsutsui #endif 1447 1.11 dbj DPRINTF(("esp_dma_isactive = %d\n",r)); 1448 1.55 tsutsui return r; 1449 1.2 dbj } 1450 1.2 dbj 1451 1.2 dbj /****************************************************************/ 1452 1.2 dbj 1453 1.66 tsutsui int esp_dma_int(void *); /* XXX: called from nextdma.c */ 1454 1.49 chs int esp_dma_int(void *arg) 1455 1.37 christos { 1456 1.66 tsutsui void nextdma_rotate(struct nextdma_softc *); /* XXX */ 1457 1.66 tsutsui void nextdma_setup_curr_regs(struct nextdma_softc *); /* XXX */ 1458 1.66 tsutsui void nextdma_setup_cont_regs(struct nextdma_softc *); /* XXX */ 1459 1.37 christos 1460 1.37 christos struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg; 1461 1.37 christos struct esp_softc *esc = (struct esp_softc *)sc; 1462 1.38 mycroft struct nextdma_softc *nsc = esc->sc_dma; 1463 1.38 mycroft struct nextdma_status *stat = &nsc->sc_stat; 1464 1.37 christos unsigned int state; 1465 1.37 christos 1466 1.66 tsutsui NDTRACEIF(ndtrace_addc('E')); 1467 1.37 christos 1468 1.66 tsutsui state = nd_bsr4(DD_CSR); 1469 1.37 christos 1470 1.37 christos #if 1 1471 1.66 tsutsui NDTRACEIF( 1472 1.55 tsutsui if (state & DMACSR_COMPLETE) 1473 1.61 christos ndtrace_addc('c'); 1474 1.55 tsutsui if (state & DMACSR_ENABLE) 1475 1.61 christos ndtrace_addc('e'); 1476 1.55 tsutsui if (state & DMACSR_BUSEXC) 1477 1.61 christos ndtrace_addc('b'); 1478 1.55 tsutsui if (state & DMACSR_READ) 1479 1.61 christos ndtrace_addc('r'); 1480 1.55 tsutsui if (state & DMACSR_SUPDATE) 1481 1.61 christos ndtrace_addc('s'); 1482 1.38 mycroft ); 1483 1.37 christos 1484 1.66 tsutsui NDTRACEIF(ndtrace_addc('E')); 1485 1.37 christos 1486 1.38 mycroft #ifdef ESP_DEBUG 1487 1.55 tsutsui if (0) 1488 1.55 tsutsui if ((state & DMACSR_BUSEXC) && (state & DMACSR_ENABLE)) 1489 1.61 christos esptraceshow++; 1490 1.55 tsutsui if (0) 1491 1.55 tsutsui if ((state & DMACSR_SUPDATE)) 1492 1.61 christos esptraceshow++; 1493 1.38 mycroft #endif 1494 1.37 christos #endif 1495 1.37 christos 1496 1.55 tsutsui if ((stat->nd_exception == 0) && 1497 1.66 tsutsui ((state & DMACSR_COMPLETE) != 0) && 1498 1.66 tsutsui ((state & DMACSR_ENABLE) != 0)) { 1499 1.55 tsutsui stat->nd_map->dm_xfer_len += 1500 1.55 tsutsui stat->nd_map->dm_segs[stat->nd_idx].ds_len; 1501 1.38 mycroft } 1502 1.37 christos 1503 1.55 tsutsui if ((stat->nd_idx + 1) == stat->nd_map->dm_nsegs) { 1504 1.66 tsutsui if (nsc->sc_conf.nd_completed_cb) 1505 1.55 tsutsui (*nsc->sc_conf.nd_completed_cb)(stat->nd_map, 1506 1.55 tsutsui nsc->sc_conf.nd_cb_arg); 1507 1.37 christos } 1508 1.38 mycroft nextdma_rotate(nsc); 1509 1.37 christos 1510 1.66 tsutsui if ((state & DMACSR_COMPLETE) != 0 && 1511 1.66 tsutsui (state & DMACSR_ENABLE) != 0) { 1512 1.37 christos #if 0 1513 1.66 tsutsui int l = nd_bsr4(DD_LIMIT) & 0x7FFFFFFF; 1514 1.66 tsutsui int s = nd_bsr4(DD_STOP); 1515 1.37 christos #endif 1516 1.66 tsutsui #if 0 1517 1.66 tsutsui nextdma_setup_cont_regs(nsc); 1518 1.66 tsutsui #endif 1519 1.66 tsutsui if (stat->nd_map_cont != NULL) { 1520 1.55 tsutsui nd_bsw4(DD_START, stat->nd_map_cont->dm_segs[ 1521 1.55 tsutsui stat->nd_idx_cont].ds_addr); 1522 1.55 tsutsui nd_bsw4(DD_STOP, (stat->nd_map_cont->dm_segs[ 1523 1.55 tsutsui stat->nd_idx_cont].ds_addr + 1524 1.55 tsutsui stat->nd_map_cont->dm_segs[ 1525 1.55 tsutsui stat->nd_idx_cont].ds_len)); 1526 1.37 christos } 1527 1.37 christos 1528 1.66 tsutsui nd_bsw4(DD_CSR, DMACSR_CLRCOMPLETE | 1529 1.55 tsutsui (state & DMACSR_READ ? DMACSR_SETREAD : DMACSR_SETWRITE) | 1530 1.55 tsutsui (stat->nd_map_cont ? DMACSR_SETSUPDATE : 0)); 1531 1.37 christos 1532 1.37 christos #if 0 1533 1.38 mycroft #ifdef ESP_DEBUG 1534 1.66 tsutsui if ((state & DMACSR_BUSEXC) != 0) { 1535 1.66 tsutsui ndtrace_printf("CE/BUSEXC: %08lX %08X %08X\n", 1536 1.55 tsutsui (stat->nd_map->dm_segs[stat->nd_idx].ds_addr + 1537 1.55 tsutsui stat->nd_map->dm_segs[stat->nd_idx].ds_len), 1538 1.55 tsutsui l, s); 1539 1.37 christos } 1540 1.37 christos #endif 1541 1.38 mycroft #endif 1542 1.37 christos } else { 1543 1.37 christos #if 0 1544 1.66 tsutsui if ((state & DMACSR_BUSEXC) != 0) { 1545 1.55 tsutsui while (nd_bsr4(DD_NEXT) != 1546 1.55 tsutsui (nd_bsr4(DD_LIMIT) & 0x7FFFFFFF)) 1547 1.55 tsutsui printf("Y"); /* DELAY(50); */ 1548 1.55 tsutsui state = nd_bsr4(DD_CSR); 1549 1.37 christos } 1550 1.37 christos #endif 1551 1.37 christos 1552 1.66 tsutsui if ((state & DMACSR_SUPDATE) == 0) { 1553 1.38 mycroft nextdma_rotate(nsc); 1554 1.37 christos } else { 1555 1.55 tsutsui nd_bsw4(DD_CSR, DMACSR_CLRCOMPLETE | 1556 1.55 tsutsui DMACSR_INITBUF | DMACSR_RESET | 1557 1.55 tsutsui (state & DMACSR_READ ? 1558 1.55 tsutsui DMACSR_SETREAD : DMACSR_SETWRITE)); 1559 1.55 tsutsui 1560 1.55 tsutsui nd_bsw4(DD_NEXT, 1561 1.55 tsutsui stat->nd_map->dm_segs[stat->nd_idx].ds_addr); 1562 1.66 tsutsui nd_bsw4(DD_LIMIT, 1563 1.55 tsutsui (stat->nd_map->dm_segs[stat->nd_idx].ds_addr + 1564 1.55 tsutsui stat->nd_map->dm_segs[stat->nd_idx].ds_len) | 1565 1.55 tsutsui 0/* x80000000 */); 1566 1.38 mycroft if (stat->nd_map_cont) { 1567 1.55 tsutsui nd_bsw4(DD_START, 1568 1.55 tsutsui stat->nd_map_cont->dm_segs[ 1569 1.55 tsutsui stat->nd_idx_cont].ds_addr); 1570 1.55 tsutsui nd_bsw4(DD_STOP, 1571 1.55 tsutsui (stat->nd_map_cont->dm_segs[ 1572 1.55 tsutsui stat->nd_idx_cont].ds_addr + 1573 1.55 tsutsui stat->nd_map_cont->dm_segs[ 1574 1.55 tsutsui stat->nd_idx_cont].ds_len) | 1575 1.55 tsutsui 0/* x80000000 */); 1576 1.37 christos } 1577 1.55 tsutsui nd_bsw4(DD_CSR, DMACSR_SETENABLE | DMACSR_CLRCOMPLETE | 1578 1.55 tsutsui (state & DMACSR_READ ? 1579 1.55 tsutsui DMACSR_SETREAD : DMACSR_SETWRITE) | 1580 1.55 tsutsui (stat->nd_map_cont ? DMACSR_SETSUPDATE : 0)); 1581 1.37 christos #if 1 1582 1.38 mycroft #ifdef ESP_DEBUG 1583 1.66 tsutsui ndtrace_printf("supdate "); 1584 1.66 tsutsui ndtrace_printf("%08X %08X %08X %08X ", 1585 1.66 tsutsui nd_bsr4(DD_NEXT), 1586 1.66 tsutsui nd_bsr4(DD_LIMIT) & 0x7FFFFFFF, 1587 1.66 tsutsui nd_bsr4(DD_START), 1588 1.66 tsutsui nd_bsr4(DD_STOP) & 0x7FFFFFFF); 1589 1.38 mycroft #endif 1590 1.37 christos #endif 1591 1.66 tsutsui stat->nd_exception++; 1592 1.55 tsutsui return 1; 1593 1.37 christos /* NCR_WRITE_REG(sc, ESP_DCTL, ctl); */ 1594 1.37 christos goto restart; 1595 1.37 christos } 1596 1.37 christos 1597 1.66 tsutsui if (stat->nd_map != NULL) { 1598 1.37 christos #if 1 1599 1.38 mycroft #ifdef ESP_DEBUG 1600 1.61 christos ndtrace_printf("%08X %08X %08X %08X ", 1601 1.66 tsutsui nd_bsr4(DD_NEXT), 1602 1.66 tsutsui nd_bsr4(DD_LIMIT) & 0x7FFFFFFF, 1603 1.66 tsutsui nd_bsr4(DD_START), 1604 1.66 tsutsui nd_bsr4(DD_STOP) & 0x7FFFFFFF); 1605 1.38 mycroft #endif 1606 1.37 christos #endif 1607 1.37 christos 1608 1.66 tsutsui #if 0 1609 1.55 tsutsui nd_bsw4(DD_CSR, DMACSR_CLRCOMPLETE | DMACSR_RESET); 1610 1.66 tsutsui 1611 1.55 tsutsui nd_bsw4(DD_CSR, 0); 1612 1.37 christos #endif 1613 1.37 christos #if 1 1614 1.37 christos /* 6/2 */ 1615 1.55 tsutsui nd_bsw4(DD_CSR, DMACSR_CLRCOMPLETE | 1616 1.55 tsutsui DMACSR_INITBUF | DMACSR_RESET | 1617 1.55 tsutsui (state & DMACSR_READ ? 1618 1.55 tsutsui DMACSR_SETREAD : DMACSR_SETWRITE)); 1619 1.66 tsutsui 1620 1.55 tsutsui /* nextdma_setup_curr_regs(nsc); */ 1621 1.55 tsutsui nd_bsw4(DD_NEXT, 1622 1.55 tsutsui stat->nd_map->dm_segs[stat->nd_idx].ds_addr); 1623 1.66 tsutsui nd_bsw4(DD_LIMIT, 1624 1.55 tsutsui (stat->nd_map->dm_segs[stat->nd_idx].ds_addr + 1625 1.55 tsutsui stat->nd_map->dm_segs[stat->nd_idx].ds_len) | 1626 1.55 tsutsui 0/* x80000000 */); 1627 1.55 tsutsui /* nextdma_setup_cont_regs(nsc); */ 1628 1.66 tsutsui if (stat->nd_map_cont != NULL) { 1629 1.55 tsutsui nd_bsw4(DD_START, 1630 1.55 tsutsui stat->nd_map_cont->dm_segs[ 1631 1.55 tsutsui stat->nd_idx_cont].ds_addr); 1632 1.55 tsutsui nd_bsw4(DD_STOP, 1633 1.55 tsutsui (stat->nd_map_cont->dm_segs[ 1634 1.55 tsutsui stat->nd_idx_cont].ds_addr + 1635 1.55 tsutsui stat->nd_map_cont->dm_segs[ 1636 1.55 tsutsui stat->nd_idx_cont].ds_len) | 1637 1.55 tsutsui 0/* x80000000 */); 1638 1.37 christos } 1639 1.66 tsutsui 1640 1.55 tsutsui nd_bsw4(DD_CSR, DMACSR_SETENABLE | 1641 1.55 tsutsui (stat->nd_map_cont ? DMACSR_SETSUPDATE : 0) | 1642 1.55 tsutsui (state & DMACSR_READ ? 1643 1.55 tsutsui DMACSR_SETREAD : DMACSR_SETWRITE)); 1644 1.38 mycroft #ifdef ESP_DEBUG 1645 1.66 tsutsui #if 0 1646 1.66 tsutsui esptraceshow++; 1647 1.38 mycroft #endif 1648 1.66 tsutsui #endif 1649 1.66 tsutsui stat->nd_exception++; 1650 1.55 tsutsui return 1; 1651 1.37 christos #endif 1652 1.66 tsutsui #if 0 1653 1.66 tsutsui NCR_WRITE_REG(sc, ESP_DCTL, ctl); 1654 1.66 tsutsui #endif 1655 1.37 christos goto restart; 1656 1.37 christos restart: 1657 1.37 christos #if 1 1658 1.38 mycroft #ifdef ESP_DEBUG 1659 1.61 christos ndtrace_printf("restart %08lX %08lX\n", 1660 1.66 tsutsui stat->nd_map->dm_segs[stat->nd_idx].ds_addr, 1661 1.55 tsutsui stat->nd_map->dm_segs[stat->nd_idx].ds_addr + 1662 1.55 tsutsui stat->nd_map->dm_segs[stat->nd_idx].ds_len); 1663 1.66 tsutsui if (stat->nd_map_cont != NULL) { 1664 1.61 christos ndtrace_printf(" %08lX %08lX\n", 1665 1.55 tsutsui stat->nd_map_cont->dm_segs[ 1666 1.55 tsutsui stat->nd_idx_cont].ds_addr, 1667 1.55 tsutsui stat->nd_map_cont->dm_segs[ 1668 1.55 tsutsui stat->nd_idx_cont].ds_addr + 1669 1.55 tsutsui stat->nd_map_cont->dm_segs[ 1670 1.55 tsutsui stat->nd_idx_cont].ds_len); 1671 1.37 christos } 1672 1.38 mycroft #endif 1673 1.37 christos #endif 1674 1.38 mycroft nextdma_print(nsc); 1675 1.55 tsutsui NCR_WRITE_REG(sc, ESP_DCTL, 1676 1.55 tsutsui ESPDCTL_16MHZ | ESPDCTL_INTENB); 1677 1.55 tsutsui printf("ff:%02x tcm:%d tcl:%d esp_dstat:%02x" 1678 1.55 tsutsui " state:%02x step: %02x intr:%02x state:%08X\n", 1679 1.55 tsutsui NCR_READ_REG(sc, NCR_FFLAG), 1680 1.55 tsutsui NCR_READ_REG((sc), NCR_TCM), 1681 1.55 tsutsui NCR_READ_REG((sc), NCR_TCL), 1682 1.55 tsutsui NCR_READ_REG(sc, ESP_DSTAT), 1683 1.55 tsutsui NCR_READ_REG(sc, NCR_STAT), 1684 1.55 tsutsui NCR_READ_REG(sc, NCR_STEP), 1685 1.55 tsutsui NCR_READ_REG(sc, NCR_INTR), state); 1686 1.38 mycroft #ifdef ESP_DEBUG 1687 1.61 christos printf("ndtrace: %s\n", ndtrace_get()); 1688 1.38 mycroft #endif 1689 1.55 tsutsui panic("%s: busexc/supdate occurred." 1690 1.55 tsutsui " Please email this output to chris (at) pin.lu.", 1691 1.55 tsutsui device_xname(sc->sc_dev)); 1692 1.38 mycroft #ifdef ESP_DEBUG 1693 1.61 christos esptraceshow++; 1694 1.38 mycroft #endif 1695 1.37 christos } else { 1696 1.55 tsutsui nd_bsw4(DD_CSR, DMACSR_CLRCOMPLETE | DMACSR_RESET); 1697 1.38 mycroft if (nsc->sc_conf.nd_shutdown_cb) 1698 1.66 tsutsui (*nsc->sc_conf.nd_shutdown_cb)( 1699 1.66 tsutsui nsc->sc_conf.nd_cb_arg); 1700 1.37 christos } 1701 1.37 christos } 1702 1.55 tsutsui return 1; 1703 1.37 christos } 1704 1.37 christos 1705 1.44 wiz /* Internal DMA callback routines */ 1706 1.67 tsutsui static bus_dmamap_t 1707 1.49 chs esp_dmacb_continue(void *arg) 1708 1.2 dbj { 1709 1.55 tsutsui struct ncr53c9x_softc *sc = arg; 1710 1.2 dbj struct esp_softc *esc = (struct esp_softc *)sc; 1711 1.2 dbj 1712 1.66 tsutsui NDTRACEIF(ndtrace_addc('x')); 1713 1.60 chs DPRINTF(("%s: DMA continue\n", device_xname(sc->sc_dev))); 1714 1.4 dbj 1715 1.2 dbj #ifdef DIAGNOSTIC 1716 1.66 tsutsui if (esc->sc_datain < 0 || esc->sc_datain > 1) { 1717 1.55 tsutsui panic("%s: map not loaded in DMA continue callback," 1718 1.55 tsutsui " datain = %d", 1719 1.55 tsutsui device_xname(sc->sc_dev), esc->sc_datain); 1720 1.2 dbj } 1721 1.2 dbj #endif 1722 1.18 dbj 1723 1.66 tsutsui if ((esc->sc_loaded & ESP_LOADED_MAIN) == 0 && 1724 1.66 tsutsui esc->sc_main_dmamap->dm_mapsize != 0) { 1725 1.55 tsutsui DPRINTF(("%s: Loading main map\n", device_xname(sc->sc_dev))); 1726 1.19 dbj #if 0 1727 1.55 tsutsui bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_main_dmamap, 1728 1.66 tsutsui 0, esc->sc_main_dmamap->dm_mapsize, 1729 1.55 tsutsui (esc->sc_datain ? 1730 1.55 tsutsui BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)); 1731 1.55 tsutsui esc->sc_main_dmamap->dm_xfer_len = 0; 1732 1.55 tsutsui #endif 1733 1.55 tsutsui esc->sc_loaded |= ESP_LOADED_MAIN; 1734 1.55 tsutsui return esc->sc_main_dmamap; 1735 1.18 dbj } 1736 1.18 dbj 1737 1.66 tsutsui if ((esc->sc_loaded & ESP_LOADED_TAIL) == 0 && 1738 1.66 tsutsui esc->sc_tail_dmamap->dm_mapsize != 0) { 1739 1.55 tsutsui DPRINTF(("%s: Loading tail map\n", device_xname(sc->sc_dev))); 1740 1.19 dbj #if 0 1741 1.55 tsutsui bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_tail_dmamap, 1742 1.66 tsutsui 0, esc->sc_tail_dmamap->dm_mapsize, 1743 1.55 tsutsui (esc->sc_datain ? 1744 1.55 tsutsui BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)); 1745 1.55 tsutsui esc->sc_tail_dmamap->dm_xfer_len = 0; 1746 1.19 dbj #endif 1747 1.55 tsutsui esc->sc_loaded |= ESP_LOADED_TAIL; 1748 1.55 tsutsui return esc->sc_tail_dmamap; 1749 1.10 dbj } 1750 1.18 dbj 1751 1.55 tsutsui DPRINTF(("%s: not loading map\n", device_xname(sc->sc_dev))); 1752 1.55 tsutsui return 0; 1753 1.2 dbj } 1754 1.2 dbj 1755 1.14 dbj 1756 1.67 tsutsui static void 1757 1.49 chs esp_dmacb_completed(bus_dmamap_t map, void *arg) 1758 1.2 dbj { 1759 1.2 dbj struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg; 1760 1.2 dbj struct esp_softc *esc = (struct esp_softc *)sc; 1761 1.2 dbj 1762 1.66 tsutsui NDTRACEIF(ndtrace_addc('X')); 1763 1.55 tsutsui DPRINTF(("%s: DMA completed\n", device_xname(sc->sc_dev))); 1764 1.4 dbj 1765 1.2 dbj #ifdef DIAGNOSTIC 1766 1.66 tsutsui if (esc->sc_datain < 0 || esc->sc_datain > 1) { 1767 1.55 tsutsui panic("%s: invalid DMA direction in completed callback," 1768 1.55 tsutsui " datain = %d", 1769 1.55 tsutsui device_xname(sc->sc_dev), esc->sc_datain); 1770 1.32 dbj } 1771 1.32 dbj #endif 1772 1.32 dbj 1773 1.34 dbj #if defined(DIAGNOSTIC) && 0 1774 1.32 dbj { 1775 1.32 dbj int i; 1776 1.55 tsutsui for(i = 0; i < map->dm_nsegs; i++) { 1777 1.33 dbj if (map->dm_xfer_len != map->dm_mapsize) { 1778 1.55 tsutsui printf("%s: map->dm_mapsize = %d\n", 1779 1.55 tsutsui device_xname(sc->sc_dev), map->dm_mapsize); 1780 1.55 tsutsui printf("%s: map->dm_nsegs = %d\n", 1781 1.55 tsutsui device_xname(sc->sc_dev), map->dm_nsegs); 1782 1.55 tsutsui printf("%s: map->dm_xfer_len = %d\n", 1783 1.55 tsutsui device_xname(sc->sc_dev), map->dm_xfer_len); 1784 1.55 tsutsui for(i = 0; i < map->dm_nsegs; i++) { 1785 1.55 tsutsui printf("%s: map->dm_segs[%d].ds_addr =" 1786 1.55 tsutsui " 0x%08lx\n", 1787 1.55 tsutsui device_xname(sc->sc_dev), i, 1788 1.55 tsutsui map->dm_segs[i].ds_addr); 1789 1.55 tsutsui printf("%s: map->dm_segs[%d].ds_len =" 1790 1.55 tsutsui " %d\n", 1791 1.55 tsutsui device_xname(sc->sc_dev), i, 1792 1.55 tsutsui map->dm_segs[i].ds_len); 1793 1.32 dbj } 1794 1.55 tsutsui panic("%s: incomplete DMA transfer", 1795 1.55 tsutsui device_xname(sc->sc_dev)); 1796 1.32 dbj } 1797 1.32 dbj } 1798 1.2 dbj } 1799 1.23 dbj #endif 1800 1.23 dbj 1801 1.23 dbj if (map == esc->sc_main_dmamap) { 1802 1.23 dbj #ifdef DIAGNOSTIC 1803 1.23 dbj if ((esc->sc_loaded & ESP_UNLOADED_MAIN) || 1804 1.55 tsutsui (esc->sc_loaded & ESP_LOADED_MAIN) == 0) { 1805 1.55 tsutsui panic("%s: unexpected completed call for main map", 1806 1.55 tsutsui device_xname(sc->sc_dev)); 1807 1.23 dbj } 1808 1.23 dbj #endif 1809 1.23 dbj esc->sc_loaded |= ESP_UNLOADED_MAIN; 1810 1.23 dbj } else if (map == esc->sc_tail_dmamap) { 1811 1.23 dbj #ifdef DIAGNOSTIC 1812 1.23 dbj if ((esc->sc_loaded & ESP_UNLOADED_TAIL) || 1813 1.55 tsutsui (esc->sc_loaded & ESP_LOADED_TAIL) == 0) { 1814 1.55 tsutsui panic("%s: unexpected completed call for tail map", 1815 1.55 tsutsui device_xname(sc->sc_dev)); 1816 1.23 dbj } 1817 1.23 dbj #endif 1818 1.23 dbj esc->sc_loaded |= ESP_UNLOADED_TAIL; 1819 1.23 dbj } 1820 1.23 dbj #ifdef DIAGNOSTIC 1821 1.23 dbj else { 1822 1.55 tsutsui panic("%s: unexpected completed map", device_xname(sc->sc_dev)); 1823 1.2 dbj } 1824 1.2 dbj #endif 1825 1.2 dbj 1826 1.23 dbj #ifdef ESP_DEBUG 1827 1.23 dbj if (esp_debug) { 1828 1.23 dbj if (map == esc->sc_main_dmamap) { 1829 1.55 tsutsui printf("%s: completed main map\n", 1830 1.55 tsutsui device_xname(sc->sc_dev)); 1831 1.23 dbj } else if (map == esc->sc_tail_dmamap) { 1832 1.55 tsutsui printf("%s: completed tail map\n", 1833 1.55 tsutsui device_xname(sc->sc_dev)); 1834 1.23 dbj } 1835 1.23 dbj } 1836 1.23 dbj #endif 1837 1.22 dbj 1838 1.22 dbj #if 0 1839 1.22 dbj if ((map == esc->sc_tail_dmamap) || 1840 1.55 tsutsui ((esc->sc_tail_size == 0) && (map == esc->sc_main_dmamap))) { 1841 1.22 dbj 1842 1.55 tsutsui /* 1843 1.55 tsutsui * Clear the DMAMOD bit in the DCTL register to give control 1844 1.22 dbj * back to the scsi chip. 1845 1.22 dbj */ 1846 1.22 dbj if (esc->sc_datain) { 1847 1.22 dbj NCR_WRITE_REG(sc, ESP_DCTL, 1848 1.55 tsutsui ESPDCTL_16MHZ | ESPDCTL_INTENB | ESPDCTL_DMARD); 1849 1.22 dbj } else { 1850 1.22 dbj NCR_WRITE_REG(sc, ESP_DCTL, 1851 1.55 tsutsui ESPDCTL_16MHZ | ESPDCTL_INTENB); 1852 1.22 dbj } 1853 1.55 tsutsui DPRINTF(("esp dctl is 0x%02x\n", NCR_READ_REG(sc, ESP_DCTL))); 1854 1.22 dbj } 1855 1.22 dbj #endif 1856 1.22 dbj 1857 1.22 dbj 1858 1.19 dbj #if 0 1859 1.38 mycroft bus_dmamap_sync(esc->sc_dma->sc_dmat, map, 1860 1.55 tsutsui 0, map->dm_mapsize, 1861 1.55 tsutsui (esc->sc_datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE)); 1862 1.19 dbj #endif 1863 1.13 dbj 1864 1.2 dbj } 1865 1.2 dbj 1866 1.67 tsutsui static void 1867 1.49 chs esp_dmacb_shutdown(void *arg) 1868 1.2 dbj { 1869 1.2 dbj struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg; 1870 1.2 dbj struct esp_softc *esc = (struct esp_softc *)sc; 1871 1.2 dbj 1872 1.61 christos NDTRACEIF (ndtrace_addc('S')); 1873 1.55 tsutsui DPRINTF(("%s: DMA shutdown\n", device_xname(sc->sc_dev))); 1874 1.4 dbj 1875 1.37 christos if (esc->sc_loaded == 0) 1876 1.37 christos return; 1877 1.37 christos 1878 1.22 dbj #if 0 1879 1.22 dbj { 1880 1.22 dbj /* Clear the DMAMOD bit in the DCTL register to give control 1881 1.22 dbj * back to the scsi chip. 1882 1.22 dbj */ 1883 1.22 dbj if (esc->sc_datain) { 1884 1.22 dbj NCR_WRITE_REG(sc, ESP_DCTL, 1885 1.55 tsutsui ESPDCTL_16MHZ | ESPDCTL_INTENB | ESPDCTL_DMARD); 1886 1.22 dbj } else { 1887 1.22 dbj NCR_WRITE_REG(sc, ESP_DCTL, 1888 1.55 tsutsui ESPDCTL_16MHZ | ESPDCTL_INTENB); 1889 1.22 dbj } 1890 1.55 tsutsui DPRINTF(("esp dctl is 0x%02x\n", NCR_READ_REG(sc, ESP_DCTL))); 1891 1.22 dbj } 1892 1.22 dbj #endif 1893 1.22 dbj 1894 1.55 tsutsui DPRINTF(("%s: esp_dma_nest == %d\n", 1895 1.55 tsutsui device_xname(sc->sc_dev), esp_dma_nest)); 1896 1.22 dbj 1897 1.13 dbj /* Stuff the end slop into fifo */ 1898 1.3 dbj 1899 1.14 dbj #ifdef ESP_DEBUG 1900 1.14 dbj if (esp_debug) { 1901 1.13 dbj int n = NCR_READ_REG(sc, NCR_FFLAG); 1902 1.55 tsutsui 1903 1.20 dbj DPRINTF(("%s: fifo size = %d, seq = 0x%x\n", 1904 1.55 tsutsui device_xname(sc->sc_dev), n & NCRFIFO_FF, 1905 1.55 tsutsui (n & NCRFIFO_SS) >> 5)); 1906 1.13 dbj } 1907 1.13 dbj #endif 1908 1.12 dbj 1909 1.66 tsutsui if (esc->sc_main_dmamap->dm_mapsize != 0) { 1910 1.55 tsutsui if (!esc->sc_datain) { 1911 1.55 tsutsui /* unpatch the DMA map for write overrun */ 1912 1.37 christos esc->sc_main_dmamap->dm_mapsize -= ESP_DMA_OVERRUN; 1913 1.55 tsutsui esc->sc_main_dmamap->dm_segs[ 1914 1.55 tsutsui esc->sc_main_dmamap->dm_nsegs - 1].ds_len -= 1915 1.55 tsutsui ESP_DMA_OVERRUN; 1916 1.37 christos } 1917 1.38 mycroft bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_main_dmamap, 1918 1.55 tsutsui 0, esc->sc_main_dmamap->dm_mapsize, 1919 1.55 tsutsui (esc->sc_datain ? 1920 1.55 tsutsui BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE)); 1921 1.38 mycroft bus_dmamap_unload(esc->sc_dma->sc_dmat, esc->sc_main_dmamap); 1922 1.66 tsutsui NDTRACEIF( 1923 1.61 christos ndtrace_printf("m%ld", 1924 1.55 tsutsui esc->sc_main_dmamap->dm_xfer_len); 1925 1.55 tsutsui ); 1926 1.22 dbj } 1927 1.22 dbj 1928 1.66 tsutsui if (esc->sc_tail_dmamap->dm_mapsize != 0) { 1929 1.38 mycroft bus_dmamap_sync(esc->sc_dma->sc_dmat, esc->sc_tail_dmamap, 1930 1.55 tsutsui 0, esc->sc_tail_dmamap->dm_mapsize, 1931 1.55 tsutsui (esc->sc_datain ? 1932 1.55 tsutsui BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE)); 1933 1.38 mycroft bus_dmamap_unload(esc->sc_dma->sc_dmat, esc->sc_tail_dmamap); 1934 1.44 wiz /* copy the tail DMA buffer data for read transfers */ 1935 1.37 christos if (esc->sc_datain) { 1936 1.55 tsutsui memcpy(*esc->sc_dmaaddr + esc->sc_begin_size + 1937 1.55 tsutsui esc->sc_main_size, esc->sc_tail, 1938 1.55 tsutsui esc->sc_dmasize - 1939 1.55 tsutsui (esc->sc_begin_size + esc->sc_main_size)); 1940 1.37 christos } 1941 1.66 tsutsui NDTRACEIF( 1942 1.61 christos ndtrace_printf("t%ld", 1943 1.55 tsutsui esc->sc_tail_dmamap->dm_xfer_len); 1944 1.55 tsutsui ); 1945 1.4 dbj } 1946 1.13 dbj 1947 1.18 dbj #ifdef ESP_DEBUG 1948 1.18 dbj if (esp_debug) { 1949 1.35 chs printf("%s: dma_shutdown: addr=%p,len=0x%08x,size=0x%08x\n", 1950 1.55 tsutsui device_xname(sc->sc_dev), 1951 1.55 tsutsui *esc->sc_dmaaddr, *esc->sc_dmalen, esc->sc_dmasize); 1952 1.24 dbj if (esp_debug > 10) { 1953 1.55 tsutsui esp_hex_dump(*(esc->sc_dmaaddr), esc->sc_dmasize); 1954 1.35 chs printf("%s: tail=%p,tailbuf=%p,tail_size=0x%08x\n", 1955 1.55 tsutsui device_xname(sc->sc_dev), 1956 1.55 tsutsui esc->sc_tail, &(esc->sc_tailbuf[0]), 1957 1.55 tsutsui esc->sc_tail_size); 1958 1.55 tsutsui esp_hex_dump(&(esc->sc_tailbuf[0]), 1959 1.55 tsutsui sizeof(esc->sc_tailbuf)); 1960 1.24 dbj } 1961 1.13 dbj } 1962 1.11 dbj #endif 1963 1.3 dbj 1964 1.18 dbj esc->sc_main = 0; 1965 1.18 dbj esc->sc_main_size = 0; 1966 1.14 dbj esc->sc_tail = 0; 1967 1.14 dbj esc->sc_tail_size = 0; 1968 1.19 dbj 1969 1.19 dbj esc->sc_datain = -1; 1970 1.66 tsutsui #if 0 1971 1.66 tsutsui esc->sc_dmaaddr = 0; 1972 1.66 tsutsui esc->sc_dmalen = 0; 1973 1.66 tsutsui esc->sc_dmasize = 0; 1974 1.66 tsutsui #endif 1975 1.19 dbj 1976 1.19 dbj esc->sc_loaded = 0; 1977 1.19 dbj 1978 1.19 dbj esc->sc_begin = 0; 1979 1.19 dbj esc->sc_begin_size = 0; 1980 1.20 dbj 1981 1.20 dbj #ifdef ESP_DEBUG 1982 1.20 dbj if (esp_debug) { 1983 1.28 tv char sbuf[256]; 1984 1.28 tv 1985 1.66 tsutsui snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS, 1986 1.57 christos (*(volatile u_long *)IIOV(NEXT_P_INTRSTAT))); 1987 1.64 msaitoh printf(" *intrstat = %s\n", sbuf); 1988 1.28 tv 1989 1.66 tsutsui snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS, 1990 1.57 christos (*(volatile u_long *)IIOV(NEXT_P_INTRMASK))); 1991 1.64 msaitoh printf(" *intrmask = %s\n", sbuf); 1992 1.20 dbj } 1993 1.20 dbj #endif 1994 1.1 dbj } 1995