1 1.52 thorpej /* $NetBSD: nextdma.c,v 1.52 2023/12/20 00:40:44 thorpej Exp $ */ 2 1.1 dbj /* 3 1.1 dbj * Copyright (c) 1998 Darrin B. Jewell 4 1.1 dbj * All rights reserved. 5 1.1 dbj * 6 1.1 dbj * Redistribution and use in source and binary forms, with or without 7 1.1 dbj * modification, are permitted provided that the following conditions 8 1.1 dbj * are met: 9 1.1 dbj * 1. Redistributions of source code must retain the above copyright 10 1.1 dbj * notice, this list of conditions and the following disclaimer. 11 1.1 dbj * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 dbj * notice, this list of conditions and the following disclaimer in the 13 1.1 dbj * documentation and/or other materials provided with the distribution. 14 1.1 dbj * 15 1.1 dbj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 1.1 dbj * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 1.1 dbj * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 1.1 dbj * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 1.1 dbj * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 1.1 dbj * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 1.1 dbj * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 1.1 dbj * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 1.1 dbj * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 1.1 dbj * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 1.1 dbj */ 26 1.35 lukem 27 1.35 lukem #include <sys/cdefs.h> 28 1.52 thorpej __KERNEL_RCSID(0, "$NetBSD: nextdma.c,v 1.52 2023/12/20 00:40:44 thorpej Exp $"); 29 1.1 dbj 30 1.1 dbj #include <sys/param.h> 31 1.1 dbj #include <sys/systm.h> 32 1.51 tsutsui #include <sys/mbuf.h> 33 1.1 dbj #include <sys/syslog.h> 34 1.1 dbj #include <sys/socket.h> 35 1.1 dbj #include <sys/device.h> 36 1.1 dbj #include <sys/ioctl.h> 37 1.1 dbj #include <sys/errno.h> 38 1.1 dbj 39 1.31 mycroft #define _M68K_BUS_DMA_PRIVATE 40 1.1 dbj #include <machine/autoconf.h> 41 1.1 dbj #include <machine/cpu.h> 42 1.1 dbj #include <machine/intr.h> 43 1.5 dbj 44 1.5 dbj #include <m68k/cacheops.h> 45 1.1 dbj 46 1.1 dbj #include <next68k/next68k/isr.h> 47 1.31 mycroft #include <next68k/next68k/nextrom.h> 48 1.1 dbj 49 1.31 mycroft #include <next68k/dev/intiovar.h> 50 1.1 dbj 51 1.1 dbj #include "nextdmareg.h" 52 1.1 dbj #include "nextdmavar.h" 53 1.1 dbj 54 1.31 mycroft #include "esp.h" 55 1.31 mycroft #include "xe.h" 56 1.31 mycroft 57 1.31 mycroft #if DEBUG 58 1.1 dbj #define ND_DEBUG 59 1.1 dbj #endif 60 1.1 dbj 61 1.31 mycroft extern int turbo; 62 1.31 mycroft 63 1.40 perry #define panic __asm volatile("trap #15"); printf 64 1.30 christos 65 1.31 mycroft #define NEXTDMA_DEBUG nextdma_debug 66 1.31 mycroft /* (nsc->sc_chan->nd_intr == NEXT_I_SCSI_DMA) && nextdma_debug */ 67 1.1 dbj #if defined(ND_DEBUG) 68 1.8 dbj int nextdma_debug = 0; 69 1.30 christos #define DPRINTF(x) if (NEXTDMA_DEBUG) printf x; 70 1.49 christos int ndtrace_show = 0; 71 1.49 christos char ndtrace_buf[8192+100]; 72 1.49 christos size_t ndtrace_len = 0; 73 1.49 christos #define NDTRACEIF(x) if (10) do {x;} while (0) 74 1.1 dbj #else 75 1.1 dbj #define DPRINTF(x) 76 1.31 mycroft #define NDTRACEIF(x) 77 1.1 dbj #endif 78 1.31 mycroft #define PRINTF(x) printf x 79 1.1 dbj 80 1.49 christos void 81 1.49 christos ndtrace_printf(const char *fmt, ...) { 82 1.49 christos #ifdef ND_DEBUG 83 1.49 christos int len; 84 1.49 christos va_list ap; 85 1.49 christos 86 1.49 christos va_start(ap, fmt); 87 1.49 christos len = vsnprintf(ndtrace_buf + ndtrace_len, sizeof(ndtrace_buf) 88 1.49 christos - ndtrace_len, fmt, ap); 89 1.49 christos va_end(ap); 90 1.49 christos ndtrace_len += len; 91 1.49 christos #endif 92 1.49 christos } 93 1.49 christos 94 1.49 christos int 95 1.49 christos ndtrace_empty(void) { 96 1.49 christos #ifdef ND_DEBUG 97 1.49 christos return ndtrace_len == 0; 98 1.49 christos #else 99 1.49 christos return 1; 100 1.49 christos #endif 101 1.49 christos } 102 1.49 christos 103 1.49 christos void 104 1.49 christos ndtrace_reset(void) { 105 1.49 christos #ifdef ND_DEBUG 106 1.49 christos ndtrace_len = 0; 107 1.49 christos #endif 108 1.49 christos } 109 1.49 christos 110 1.49 christos void 111 1.49 christos ndtrace_addc(int c) { 112 1.49 christos #ifdef ND_DEBUG 113 1.49 christos if (ndtrace_len < sizeof(ndtrace_buf) - 1) { 114 1.49 christos ndtrace_buf[ndtrace_len++] = c; 115 1.49 christos ndtrace_buf[ndtrace_len] = '\0'; 116 1.49 christos } 117 1.49 christos #endif 118 1.49 christos } 119 1.49 christos 120 1.49 christos const char * 121 1.49 christos ndtrace_get(void) { 122 1.49 christos #ifdef ND_DEBUG 123 1.49 christos return ndtrace_buf; 124 1.49 christos #else 125 1.49 christos return NULL; 126 1.49 christos #endif 127 1.49 christos } 128 1.49 christos 129 1.49 christos 130 1.26 dbj #if defined(ND_DEBUG) 131 1.26 dbj int nextdma_debug_enetr_idx = 0; 132 1.26 dbj unsigned int nextdma_debug_enetr_state[100] = { 0 }; 133 1.26 dbj int nextdma_debug_scsi_idx = 0; 134 1.26 dbj unsigned int nextdma_debug_scsi_state[100] = { 0 }; 135 1.26 dbj 136 1.31 mycroft void nextdma_debug_initstate(struct nextdma_softc *); 137 1.31 mycroft void nextdma_debug_savestate(struct nextdma_softc *, unsigned int); 138 1.26 dbj void nextdma_debug_scsi_dumpstate(void); 139 1.26 dbj void nextdma_debug_enetr_dumpstate(void); 140 1.31 mycroft #endif 141 1.31 mycroft 142 1.31 mycroft 143 1.48 chs int nextdma_match(device_t, cfdata_t, void *); 144 1.48 chs void nextdma_attach(device_t, device_t, void *); 145 1.31 mycroft 146 1.37 chs void nextdmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, bus_size_t, int); 147 1.37 chs int nextdma_continue(struct nextdma_softc *); 148 1.37 chs void nextdma_rotate(struct nextdma_softc *); 149 1.31 mycroft 150 1.37 chs void nextdma_setup_cont_regs(struct nextdma_softc *); 151 1.37 chs void nextdma_setup_curr_regs(struct nextdma_softc *); 152 1.31 mycroft 153 1.31 mycroft #if NESP > 0 154 1.37 chs static int nextdma_esp_intr(void *); 155 1.31 mycroft #endif 156 1.31 mycroft #if NXE > 0 157 1.37 chs static int nextdma_enet_intr(void *); 158 1.31 mycroft #endif 159 1.31 mycroft 160 1.37 chs #define nd_bsr4(reg) \ 161 1.37 chs bus_space_read_4(nsc->sc_bst, nsc->sc_bsh, (reg)) 162 1.37 chs #define nd_bsw4(reg,val) \ 163 1.37 chs bus_space_write_4(nsc->sc_bst, nsc->sc_bsh, (reg), (val)) 164 1.26 dbj 165 1.48 chs CFATTACH_DECL_NEW(nextdma, sizeof(struct nextdma_softc), 166 1.34 thorpej nextdma_match, nextdma_attach, NULL, NULL); 167 1.31 mycroft 168 1.31 mycroft static struct nextdma_channel nextdma_channel[] = { 169 1.31 mycroft #if NESP > 0 170 1.51 tsutsui { 171 1.51 tsutsui "scsi", 172 1.51 tsutsui NEXT_P_SCSI_CSR, 173 1.51 tsutsui DD_SIZE, 174 1.51 tsutsui NEXT_I_SCSI_DMA, 175 1.51 tsutsui &nextdma_esp_intr 176 1.51 tsutsui }, 177 1.31 mycroft #endif 178 1.31 mycroft #if NXE > 0 179 1.51 tsutsui { 180 1.51 tsutsui "enetx", 181 1.51 tsutsui NEXT_P_ENETX_CSR, 182 1.51 tsutsui DD_SIZE, 183 1.51 tsutsui NEXT_I_ENETX_DMA, 184 1.51 tsutsui &nextdma_enet_intr 185 1.51 tsutsui }, 186 1.51 tsutsui { 187 1.51 tsutsui "enetr", 188 1.51 tsutsui NEXT_P_ENETR_CSR, 189 1.51 tsutsui DD_SIZE, 190 1.51 tsutsui NEXT_I_ENETR_DMA, 191 1.51 tsutsui &nextdma_enet_intr 192 1.51 tsutsui }, 193 1.31 mycroft #endif 194 1.31 mycroft }; 195 1.51 tsutsui static int nnextdma_channels = __arraycount(nextdma_channel); 196 1.31 mycroft 197 1.31 mycroft static int attached = 0; 198 1.26 dbj 199 1.31 mycroft struct nextdma_softc * 200 1.38 he nextdma_findchannel(const char *name) 201 1.26 dbj { 202 1.45 dyoung device_t dev; 203 1.45 dyoung deviter_t di; 204 1.26 dbj 205 1.45 dyoung for (dev = deviter_first(&di, DEVITER_F_ROOT_FIRST); 206 1.45 dyoung dev != NULL; 207 1.45 dyoung dev = deviter_next(&di)) { 208 1.48 chs if (strncmp(device_xname(dev), "nextdma", 7) == 0) { 209 1.45 dyoung struct nextdma_softc *nsc = device_private(dev); 210 1.45 dyoung if (strcmp(nsc->sc_chan->nd_name, name) == 0) 211 1.45 dyoung break; 212 1.45 dyoung } 213 1.45 dyoung } 214 1.45 dyoung deviter_release(&di); 215 1.45 dyoung if (dev == NULL) 216 1.45 dyoung return NULL; 217 1.45 dyoung return device_private(dev); 218 1.26 dbj } 219 1.26 dbj 220 1.31 mycroft int 221 1.48 chs nextdma_match(device_t parent, cfdata_t match, void *aux) 222 1.26 dbj { 223 1.31 mycroft struct intio_attach_args *ia = (struct intio_attach_args *)aux; 224 1.26 dbj 225 1.31 mycroft if (attached >= nnextdma_channels) 226 1.51 tsutsui return 0; 227 1.26 dbj 228 1.31 mycroft ia->ia_addr = (void *)nextdma_channel[attached].nd_base; 229 1.1 dbj 230 1.51 tsutsui return 1; 231 1.31 mycroft } 232 1.1 dbj 233 1.1 dbj void 234 1.48 chs nextdma_attach(device_t parent, device_t self, void *aux) 235 1.1 dbj { 236 1.48 chs struct nextdma_softc *nsc = device_private(self); 237 1.31 mycroft struct intio_attach_args *ia = (struct intio_attach_args *)aux; 238 1.31 mycroft 239 1.31 mycroft if (attached >= nnextdma_channels) 240 1.31 mycroft return; 241 1.31 mycroft 242 1.48 chs nsc->sc_dev = self; 243 1.31 mycroft nsc->sc_chan = &nextdma_channel[attached]; 244 1.1 dbj 245 1.31 mycroft nsc->sc_dmat = ia->ia_dmat; 246 1.31 mycroft nsc->sc_bst = ia->ia_bst; 247 1.1 dbj 248 1.31 mycroft if (bus_space_map(nsc->sc_bst, nsc->sc_chan->nd_base, 249 1.51 tsutsui nsc->sc_chan->nd_size, 0, &nsc->sc_bsh)) { 250 1.32 provos panic("%s: can't map DMA registers for channel %s", 251 1.51 tsutsui device_xname(self), nsc->sc_chan->nd_name); 252 1.1 dbj } 253 1.1 dbj 254 1.51 tsutsui nextdma_init(nsc); 255 1.30 christos 256 1.31 mycroft isrlink_autovec(nsc->sc_chan->nd_intrfunc, nsc, 257 1.51 tsutsui NEXT_I_IPL(nsc->sc_chan->nd_intr), 10, NULL); 258 1.31 mycroft INTR_ENABLE(nsc->sc_chan->nd_intr); 259 1.1 dbj 260 1.51 tsutsui printf(": channel %d (%s)\n", attached, 261 1.31 mycroft nsc->sc_chan->nd_name); 262 1.31 mycroft attached++; 263 1.1 dbj } 264 1.1 dbj 265 1.1 dbj void 266 1.37 chs nextdma_init(struct nextdma_softc *nsc) 267 1.1 dbj { 268 1.22 tv #ifdef ND_DEBUG 269 1.30 christos if (NEXTDMA_DEBUG) { 270 1.22 tv char sbuf[256]; 271 1.22 tv 272 1.43 christos snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS, 273 1.47 mrg NEXT_I_BIT(nsc->sc_chan->nd_intr)); 274 1.50 msaitoh printf("DMA init ipl (%ld) intr(%s)\n", 275 1.51 tsutsui NEXT_I_IPL(nsc->sc_chan->nd_intr), sbuf); 276 1.22 tv } 277 1.22 tv #endif 278 1.1 dbj 279 1.31 mycroft nsc->sc_stat.nd_map = NULL; 280 1.31 mycroft nsc->sc_stat.nd_idx = 0; 281 1.31 mycroft nsc->sc_stat.nd_map_cont = NULL; 282 1.31 mycroft nsc->sc_stat.nd_idx_cont = 0; 283 1.31 mycroft nsc->sc_stat.nd_exception = 0; 284 1.1 dbj 285 1.51 tsutsui nd_bsw4(DD_CSR, DMACSR_RESET | DMACSR_CLRCOMPLETE); 286 1.51 tsutsui nd_bsw4(DD_CSR, 0); 287 1.1 dbj 288 1.31 mycroft #if 01 289 1.31 mycroft nextdma_setup_curr_regs(nsc); 290 1.31 mycroft nextdma_setup_cont_regs(nsc); 291 1.31 mycroft #endif 292 1.1 dbj 293 1.20 dbj #if defined(DIAGNOSTIC) 294 1.1 dbj { 295 1.1 dbj u_long state; 296 1.31 mycroft state = nd_bsr4 (DD_CSR); 297 1.20 dbj 298 1.20 dbj #if 1 299 1.41 lukem /* mourning (a 25 MHz 68040 mono slab) appears to set BUSEXC 300 1.41 lukem * milo (a 25 MHz 68040 mono cube) didn't have this problem 301 1.31 mycroft * Darrin B. Jewell <jewell (at) mit.edu> Mon May 25 07:53:05 1998 302 1.31 mycroft */ 303 1.31 mycroft state &= (DMACSR_COMPLETE | DMACSR_SUPDATE | DMACSR_ENABLE); 304 1.20 dbj #else 305 1.51 tsutsui state &= (DMACSR_BUSEXC | DMACSR_COMPLETE | 306 1.31 mycroft DMACSR_SUPDATE | DMACSR_ENABLE); 307 1.20 dbj #endif 308 1.51 tsutsui if (state != 0) { 309 1.31 mycroft nextdma_print(nsc); 310 1.20 dbj panic("DMA did not reset"); 311 1.1 dbj } 312 1.1 dbj } 313 1.1 dbj #endif 314 1.1 dbj } 315 1.1 dbj 316 1.1 dbj void 317 1.37 chs nextdma_reset(struct nextdma_softc *nsc) 318 1.1 dbj { 319 1.1 dbj int s; 320 1.31 mycroft struct nextdma_status *stat = &nsc->sc_stat; 321 1.31 mycroft 322 1.18 dbj s = spldma(); 323 1.8 dbj 324 1.8 dbj DPRINTF(("DMA reset\n")); 325 1.8 dbj 326 1.8 dbj #if (defined(ND_DEBUG)) 327 1.51 tsutsui if (NEXTDMA_DEBUG > 1) 328 1.51 tsutsui nextdma_print(nsc); 329 1.8 dbj #endif 330 1.8 dbj 331 1.51 tsutsui nd_bsw4(DD_CSR, DMACSR_CLRCOMPLETE | DMACSR_RESET); 332 1.31 mycroft if ((stat->nd_map) || (stat->nd_map_cont)) { 333 1.31 mycroft if (stat->nd_map_cont) { 334 1.51 tsutsui DPRINTF( 335 1.51 tsutsui ("DMA: resetting with non null continue map\n")); 336 1.51 tsutsui if (nsc->sc_conf.nd_completed_cb) 337 1.51 tsutsui (*nsc->sc_conf.nd_completed_cb)( 338 1.51 tsutsui stat->nd_map_cont, nsc->sc_conf.nd_cb_arg); 339 1.51 tsutsui 340 1.31 mycroft stat->nd_map_cont = 0; 341 1.31 mycroft stat->nd_idx_cont = 0; 342 1.30 christos } 343 1.31 mycroft if (nsc->sc_conf.nd_shutdown_cb) 344 1.31 mycroft (*nsc->sc_conf.nd_shutdown_cb)(nsc->sc_conf.nd_cb_arg); 345 1.31 mycroft stat->nd_map = 0; 346 1.31 mycroft stat->nd_idx = 0; 347 1.26 dbj } 348 1.20 dbj 349 1.1 dbj splx(s); 350 1.1 dbj } 351 1.1 dbj 352 1.1 dbj /****************************************************************/ 353 1.1 dbj 354 1.1 dbj 355 1.51 tsutsui /* 356 1.51 tsutsui * Call the completed and continue callbacks to try to fill 357 1.1 dbj * in the dma continue buffers. 358 1.1 dbj */ 359 1.1 dbj void 360 1.37 chs nextdma_rotate(struct nextdma_softc *nsc) 361 1.1 dbj { 362 1.31 mycroft struct nextdma_status *stat = &nsc->sc_stat; 363 1.1 dbj 364 1.51 tsutsui NDTRACEIF(ndtrace_addc('r')); 365 1.31 mycroft DPRINTF(("DMA nextdma_rotate()\n")); 366 1.1 dbj 367 1.1 dbj /* Rotate the continue map into the current map */ 368 1.31 mycroft stat->nd_map = stat->nd_map_cont; 369 1.31 mycroft stat->nd_idx = stat->nd_idx_cont; 370 1.1 dbj 371 1.51 tsutsui if ((stat->nd_map_cont == NULL) || 372 1.31 mycroft ((++stat->nd_idx_cont >= stat->nd_map_cont->dm_nsegs))) { 373 1.51 tsutsui if (nsc->sc_conf.nd_continue_cb != NULL) { 374 1.31 mycroft stat->nd_map_cont = (*nsc->sc_conf.nd_continue_cb) 375 1.31 mycroft (nsc->sc_conf.nd_cb_arg); 376 1.51 tsutsui if (stat->nd_map_cont != NULL) { 377 1.31 mycroft stat->nd_map_cont->dm_xfer_len = 0; 378 1.26 dbj } 379 1.1 dbj } else { 380 1.31 mycroft stat->nd_map_cont = 0; 381 1.1 dbj } 382 1.31 mycroft stat->nd_idx_cont = 0; 383 1.1 dbj } 384 1.7 dbj 385 1.29 dbj #if defined(DIAGNOSTIC) && 0 386 1.31 mycroft if (stat->nd_map_cont) { 387 1.51 tsutsui if (!DMA_BEGINALIGNED( 388 1.51 tsutsui stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr)) { 389 1.31 mycroft nextdma_print(nsc); 390 1.32 provos panic("DMA request unaligned at start"); 391 1.7 dbj } 392 1.51 tsutsui if (!DMA_ENDALIGNED( 393 1.51 tsutsui stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr + 394 1.51 tsutsui stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_len)) { 395 1.31 mycroft nextdma_print(nsc); 396 1.32 provos panic("DMA request unaligned at end"); 397 1.7 dbj } 398 1.7 dbj } 399 1.7 dbj #endif 400 1.7 dbj 401 1.1 dbj } 402 1.1 dbj 403 1.1 dbj void 404 1.37 chs nextdma_setup_curr_regs(struct nextdma_softc *nsc) 405 1.1 dbj { 406 1.20 dbj bus_addr_t dd_next; 407 1.20 dbj bus_addr_t dd_limit; 408 1.20 dbj bus_addr_t dd_saved_next; 409 1.20 dbj bus_addr_t dd_saved_limit; 410 1.31 mycroft struct nextdma_status *stat = &nsc->sc_stat; 411 1.20 dbj 412 1.51 tsutsui NDTRACEIF(ndtrace_addc('C')); 413 1.31 mycroft DPRINTF(("DMA nextdma_setup_curr_regs()\n")); 414 1.1 dbj 415 1.51 tsutsui if (stat->nd_map != NULL) { 416 1.31 mycroft dd_next = stat->nd_map->dm_segs[stat->nd_idx].ds_addr; 417 1.31 mycroft dd_limit = (stat->nd_map->dm_segs[stat->nd_idx].ds_addr + 418 1.31 mycroft stat->nd_map->dm_segs[stat->nd_idx].ds_len); 419 1.15 dbj 420 1.31 mycroft if (!turbo && nsc->sc_chan->nd_intr == NEXT_I_ENETX_DMA) { 421 1.51 tsutsui /* Ethernet transmit needs secret magic */ 422 1.51 tsutsui dd_limit |= 0x80000000; 423 1.29 dbj dd_limit += 15; 424 1.20 dbj } 425 1.20 dbj } else { 426 1.31 mycroft dd_next = turbo ? 0 : 0xdeadbeef; 427 1.31 mycroft dd_limit = turbo ? 0 : 0xdeadbeef; 428 1.20 dbj } 429 1.1 dbj 430 1.20 dbj dd_saved_next = dd_next; 431 1.20 dbj dd_saved_limit = dd_limit; 432 1.1 dbj 433 1.51 tsutsui NDTRACEIF(if (stat->nd_map) { 434 1.51 tsutsui ndtrace_printf("%ld", 435 1.51 tsutsui stat->nd_map->dm_segs[stat->nd_idx].ds_len); 436 1.31 mycroft }); 437 1.30 christos 438 1.31 mycroft if (!turbo && (nsc->sc_chan->nd_intr == NEXT_I_ENETX_DMA)) { 439 1.51 tsutsui nd_bsw4(DD_NEXT_INITBUF, dd_next); 440 1.15 dbj } else { 441 1.51 tsutsui nd_bsw4(DD_NEXT, dd_next); 442 1.15 dbj } 443 1.51 tsutsui nd_bsw4(DD_LIMIT, dd_limit); 444 1.51 tsutsui if (!turbo) 445 1.51 tsutsui nd_bsw4(DD_SAVED_NEXT, dd_saved_next); 446 1.51 tsutsui if (!turbo) 447 1.51 tsutsui nd_bsw4(DD_SAVED_LIMIT, dd_saved_limit); 448 1.1 dbj 449 1.20 dbj #ifdef DIAGNOSTIC 450 1.51 tsutsui if ((nd_bsr4(DD_NEXT_INITBUF) != dd_next) 451 1.51 tsutsui || (nd_bsr4(DD_NEXT) != dd_next) 452 1.51 tsutsui || (nd_bsr4(DD_LIMIT) != dd_limit) 453 1.51 tsutsui || (!turbo && (nd_bsr4(DD_SAVED_NEXT) != dd_saved_next)) 454 1.51 tsutsui || (!turbo && (nd_bsr4(DD_SAVED_LIMIT) != dd_saved_limit)) 455 1.31 mycroft ) { 456 1.31 mycroft nextdma_print(nsc); 457 1.20 dbj panic("DMA failure writing to current regs"); 458 1.20 dbj } 459 1.7 dbj #endif 460 1.1 dbj } 461 1.1 dbj 462 1.1 dbj void 463 1.37 chs nextdma_setup_cont_regs(struct nextdma_softc *nsc) 464 1.1 dbj { 465 1.31 mycroft bus_addr_t dd_start; 466 1.31 mycroft bus_addr_t dd_stop; 467 1.31 mycroft bus_addr_t dd_saved_start; 468 1.31 mycroft bus_addr_t dd_saved_stop; 469 1.31 mycroft struct nextdma_status *stat = &nsc->sc_stat; 470 1.1 dbj 471 1.51 tsutsui NDTRACEIF(ndtrace_addc('c')); 472 1.31 mycroft DPRINTF(("DMA nextdma_setup_regs()\n")); 473 1.1 dbj 474 1.51 tsutsui if (stat->nd_map_cont != NULL) { 475 1.51 tsutsui dd_start = 476 1.51 tsutsui stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr; 477 1.51 tsutsui dd_stop = 478 1.51 tsutsui stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr + 479 1.51 tsutsui stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_len; 480 1.22 tv 481 1.31 mycroft if (!turbo && nsc->sc_chan->nd_intr == NEXT_I_ENETX_DMA) { 482 1.51 tsutsui /* Ethernet transmit needs secret magic */ 483 1.51 tsutsui dd_stop |= 0x80000000; 484 1.31 mycroft dd_stop += 15; 485 1.24 dbj } 486 1.1 dbj } else { 487 1.51 tsutsui dd_start = turbo ? nd_bsr4(DD_NEXT) : 0xdeadbee0; 488 1.31 mycroft dd_stop = turbo ? 0 : 0xdeadbee0; 489 1.1 dbj } 490 1.1 dbj 491 1.31 mycroft dd_saved_start = dd_start; 492 1.31 mycroft dd_saved_stop = dd_stop; 493 1.22 tv 494 1.51 tsutsui NDTRACEIF(if (stat->nd_map_cont != NULL) { 495 1.51 tsutsui ndtrace_printf("%ld", 496 1.51 tsutsui stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_len); 497 1.31 mycroft }); 498 1.31 mycroft 499 1.51 tsutsui nd_bsw4(DD_START, dd_start); 500 1.51 tsutsui nd_bsw4(DD_STOP, dd_stop); 501 1.51 tsutsui if (!turbo) 502 1.51 tsutsui nd_bsw4(DD_SAVED_START, dd_saved_start); 503 1.51 tsutsui if (!turbo) 504 1.51 tsutsui nd_bsw4(DD_SAVED_STOP, dd_saved_stop); 505 1.31 mycroft if (turbo && nsc->sc_chan->nd_intr == NEXT_I_ENETR_DMA) 506 1.51 tsutsui nd_bsw4(DD_STOP - 0x40, dd_start); 507 1.31 mycroft 508 1.31 mycroft #ifdef DIAGNOSTIC 509 1.51 tsutsui if ((nd_bsr4(DD_START) != dd_start) 510 1.51 tsutsui || (dd_stop && (nd_bsr4(DD_STOP) != dd_stop)) 511 1.51 tsutsui || (!turbo && (nd_bsr4(DD_SAVED_START) != dd_saved_start)) 512 1.51 tsutsui || (!turbo && (nd_bsr4(DD_SAVED_STOP) != dd_saved_stop)) 513 1.31 mycroft ) { 514 1.31 mycroft nextdma_print(nsc); 515 1.31 mycroft panic("DMA failure writing to continue regs"); 516 1.31 mycroft } 517 1.31 mycroft #endif 518 1.1 dbj } 519 1.1 dbj 520 1.1 dbj /****************************************************************/ 521 1.1 dbj 522 1.31 mycroft #if NESP > 0 523 1.31 mycroft static int 524 1.37 chs nextdma_esp_intr(void *arg) 525 1.1 dbj { 526 1.31 mycroft /* @@@ This is bogus, we can't be certain of arg's type 527 1.18 dbj * unless the interrupt is for us. For now we successfully 528 1.18 dbj * cheat because DMA interrupts are the only things invoked 529 1.18 dbj * at this interrupt level. 530 1.1 dbj */ 531 1.31 mycroft struct nextdma_softc *nsc = arg; 532 1.37 chs int esp_dma_int(void *); /* XXX */ 533 1.51 tsutsui 534 1.31 mycroft if (!INTR_OCCURRED(nsc->sc_chan->nd_intr)) 535 1.31 mycroft return 0; 536 1.31 mycroft /* Handle dma interrupts */ 537 1.1 dbj 538 1.51 tsutsui return esp_dma_int(nsc->sc_conf.nd_cb_arg); 539 1.31 mycroft } 540 1.30 christos #endif 541 1.30 christos 542 1.31 mycroft #if NXE > 0 543 1.31 mycroft static int 544 1.37 chs nextdma_enet_intr(void *arg) 545 1.31 mycroft { 546 1.51 tsutsui 547 1.51 tsutsui /* 548 1.51 tsutsui * @@@ This is bogus, we can't be certain of arg's type 549 1.31 mycroft * unless the interrupt is for us. For now we successfully 550 1.31 mycroft * cheat because DMA interrupts are the only things invoked 551 1.31 mycroft * at this interrupt level. 552 1.31 mycroft */ 553 1.31 mycroft struct nextdma_softc *nsc = arg; 554 1.31 mycroft unsigned int state; 555 1.31 mycroft bus_addr_t onext; 556 1.31 mycroft bus_addr_t olimit; 557 1.31 mycroft bus_addr_t slimit; 558 1.31 mycroft int result; 559 1.31 mycroft struct nextdma_status *stat = &nsc->sc_stat; 560 1.31 mycroft 561 1.31 mycroft if (!INTR_OCCURRED(nsc->sc_chan->nd_intr)) 562 1.31 mycroft return 0; 563 1.31 mycroft /* Handle dma interrupts */ 564 1.31 mycroft 565 1.51 tsutsui NDTRACEIF(ndtrace_addc('D')); 566 1.22 tv #ifdef ND_DEBUG 567 1.30 christos if (NEXTDMA_DEBUG) { 568 1.22 tv char sbuf[256]; 569 1.22 tv 570 1.43 christos snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS, 571 1.47 mrg NEXT_I_BIT(nsc->sc_chan->nd_intr)); 572 1.50 msaitoh printf("DMA interrupt ipl (%ld) intr(%s)\n", 573 1.51 tsutsui NEXT_I_IPL(nsc->sc_chan->nd_intr), sbuf); 574 1.22 tv } 575 1.22 tv #endif 576 1.1 dbj 577 1.7 dbj #ifdef DIAGNOSTIC 578 1.51 tsutsui if (stat->nd_map == NULL) { 579 1.31 mycroft nextdma_print(nsc); 580 1.32 provos panic("DMA missing current map in interrupt!"); 581 1.7 dbj } 582 1.7 dbj #endif 583 1.7 dbj 584 1.51 tsutsui state = nd_bsr4(DD_CSR); 585 1.26 dbj 586 1.26 dbj #if defined(ND_DEBUG) 587 1.31 mycroft nextdma_debug_savestate(nsc, state); 588 1.26 dbj #endif 589 1.26 dbj 590 1.26 dbj #ifdef DIAGNOSTIC 591 1.51 tsutsui if (/* (state & DMACSR_READ) || */ (state & DMACSR_COMPLETE) == 0) { 592 1.31 mycroft char sbuf[256]; 593 1.31 mycroft nextdma_print(nsc); 594 1.43 christos snprintb(sbuf, sizeof(sbuf), DMACSR_BITS, state); 595 1.50 msaitoh printf("DMA: state %s\n",sbuf); 596 1.32 provos panic("DMA complete not set in interrupt"); 597 1.31 mycroft } 598 1.26 dbj #endif 599 1.26 dbj 600 1.31 mycroft DPRINTF(("DMA: finishing xfer\n")); 601 1.51 tsutsui 602 1.31 mycroft onext = stat->nd_map->dm_segs[stat->nd_idx].ds_addr; 603 1.31 mycroft olimit = onext + stat->nd_map->dm_segs[stat->nd_idx].ds_len; 604 1.23 dbj 605 1.31 mycroft result = 0; 606 1.51 tsutsui if ((state & DMACSR_ENABLE) != 0) { 607 1.31 mycroft /* enable bit was set */ 608 1.31 mycroft result |= 0x01; 609 1.31 mycroft } 610 1.51 tsutsui if ((state & DMACSR_SUPDATE) != 0) { 611 1.31 mycroft /* supdate bit was set */ 612 1.31 mycroft result |= 0x02; 613 1.31 mycroft } 614 1.31 mycroft if (stat->nd_map_cont == NULL) { 615 1.31 mycroft KASSERT(stat->nd_idx+1 == stat->nd_map->dm_nsegs); 616 1.31 mycroft /* Expecting a shutdown, didn't SETSUPDATE last turn */ 617 1.31 mycroft result |= 0x04; 618 1.31 mycroft } 619 1.51 tsutsui if ((state & DMACSR_BUSEXC) != 0) { 620 1.31 mycroft /* bus exception bit was set */ 621 1.31 mycroft result |= 0x08; 622 1.31 mycroft } 623 1.31 mycroft switch (result) { 624 1.31 mycroft case 0x00: /* !BUSEXC && !expecting && !SUPDATE && !ENABLE */ 625 1.31 mycroft case 0x08: /* BUSEXC && !expecting && !SUPDATE && !ENABLE */ 626 1.31 mycroft if (turbo) { 627 1.51 tsutsui volatile u_int *limit = 628 1.51 tsutsui (volatile u_int *)IIOV(0x2000050 + 0x4000); 629 1.31 mycroft slimit = *limit; 630 1.31 mycroft } else { 631 1.51 tsutsui slimit = nd_bsr4(DD_SAVED_LIMIT); 632 1.31 mycroft } 633 1.31 mycroft break; 634 1.31 mycroft case 0x01: /* !BUSEXC && !expecting && !SUPDATE && ENABLE */ 635 1.31 mycroft case 0x09: /* BUSEXC && !expecting && !SUPDATE && ENABLE */ 636 1.31 mycroft if (turbo) { 637 1.51 tsutsui volatile u_int *limit = 638 1.51 tsutsui (volatile u_int *)IIOV(0x2000050 + 0x4000); 639 1.31 mycroft slimit = *limit; 640 1.31 mycroft } else { 641 1.51 tsutsui slimit = nd_bsr4(DD_SAVED_LIMIT); 642 1.31 mycroft } 643 1.31 mycroft break; 644 1.31 mycroft case 0x02: /* !BUSEXC && !expecting && SUPDATE && !ENABLE */ 645 1.51 tsutsui case 0x0a: /* BUSEXC && !expecting && SUPDATE && !ENABLE */ 646 1.51 tsutsui slimit = nd_bsr4(DD_NEXT); 647 1.31 mycroft break; 648 1.31 mycroft case 0x04: /* !BUSEXC && expecting && !SUPDATE && !ENABLE */ 649 1.51 tsutsui case 0x0c: /* BUSEXC && expecting && !SUPDATE && !ENABLE */ 650 1.51 tsutsui slimit = nd_bsr4(DD_LIMIT); 651 1.31 mycroft break; 652 1.31 mycroft default: 653 1.31 mycroft #ifdef DIAGNOSTIC 654 1.31 mycroft { 655 1.31 mycroft char sbuf[256]; 656 1.51 tsutsui printf("DMA: please send this output to" 657 1.51 tsutsui " port-next68k-maintainer (at) NetBSD.org:\n"); 658 1.43 christos snprintb(sbuf, sizeof(sbuf), DMACSR_BITS, state); 659 1.50 msaitoh printf("DMA: state %s\n",sbuf); 660 1.31 mycroft nextdma_print(nsc); 661 1.51 tsutsui panic("DMA: condition 0x%02x not yet documented to occur", 662 1.51 tsutsui result); 663 1.31 mycroft } 664 1.31 mycroft #endif 665 1.31 mycroft slimit = olimit; 666 1.31 mycroft break; 667 1.31 mycroft } 668 1.22 tv 669 1.31 mycroft if (!turbo && nsc->sc_chan->nd_intr == NEXT_I_ENETX_DMA) { 670 1.31 mycroft slimit &= ~0x80000000; 671 1.31 mycroft slimit -= 15; 672 1.31 mycroft } 673 1.22 tv 674 1.23 dbj #ifdef DIAGNOSTIC 675 1.51 tsutsui if ((state & DMACSR_READ) != 0) 676 1.51 tsutsui DPRINTF(("limits: 0x%08lx <= 0x%08lx <= 0x%08lx %s\n", 677 1.51 tsutsui onext, slimit, olimit, 678 1.51 tsutsui (state & DMACSR_READ) ? "read" : "write")); 679 1.51 tsutsui if (slimit < onext || slimit > olimit) { 680 1.31 mycroft char sbuf[256]; 681 1.43 christos snprintb(sbuf, sizeof(sbuf), DMACSR_BITS, state); 682 1.50 msaitoh printf("DMA: state %s\n",sbuf); 683 1.31 mycroft nextdma_print(nsc); 684 1.51 tsutsui panic("DMA: Unexpected limit register (0x%08lx) in finish_xfer", 685 1.51 tsutsui slimit); 686 1.31 mycroft } 687 1.1 dbj #endif 688 1.1 dbj 689 1.26 dbj #ifdef DIAGNOSTIC 690 1.51 tsutsui if ((state & DMACSR_ENABLE) != 0 && 691 1.51 tsutsui stat->nd_idx + 1 != stat->nd_map->dm_nsegs) { 692 1.31 mycroft if (slimit != olimit) { 693 1.31 mycroft char sbuf[256]; 694 1.43 christos snprintb(sbuf, sizeof(sbuf), DMACSR_BITS, state); 695 1.50 msaitoh printf("DMA: state %s\n",sbuf); 696 1.31 mycroft nextdma_print(nsc); 697 1.51 tsutsui panic("DMA: short limit register (0x%08lx)" 698 1.51 tsutsui " w/o finishing map.", slimit); 699 1.31 mycroft } 700 1.31 mycroft } 701 1.26 dbj #endif 702 1.26 dbj 703 1.23 dbj #if (defined(ND_DEBUG)) 704 1.51 tsutsui if (NEXTDMA_DEBUG > 2) 705 1.51 tsutsui nextdma_print(nsc); 706 1.23 dbj #endif 707 1.7 dbj 708 1.31 mycroft stat->nd_map->dm_xfer_len += slimit-onext; 709 1.31 mycroft 710 1.31 mycroft /* If we've reached the end of the current map, then inform 711 1.31 mycroft * that we've completed that map. 712 1.31 mycroft */ 713 1.51 tsutsui if (stat->nd_idx + 1 == stat->nd_map->dm_nsegs) { 714 1.51 tsutsui if (nsc->sc_conf.nd_completed_cb) 715 1.51 tsutsui (*nsc->sc_conf.nd_completed_cb)(stat->nd_map, 716 1.51 tsutsui nsc->sc_conf.nd_cb_arg); 717 1.31 mycroft } else { 718 1.31 mycroft KASSERT(stat->nd_map == stat->nd_map_cont); 719 1.31 mycroft KASSERT(stat->nd_idx+1 == stat->nd_idx_cont); 720 1.31 mycroft } 721 1.31 mycroft stat->nd_map = 0; 722 1.31 mycroft stat->nd_idx = 0; 723 1.12 dbj 724 1.31 mycroft #if (defined(ND_DEBUG)) 725 1.31 mycroft if (NEXTDMA_DEBUG) { 726 1.31 mycroft char sbuf[256]; 727 1.43 christos snprintb(sbuf, sizeof(sbuf), DMACSR_BITS, state); 728 1.51 tsutsui printf("CLNDMAP: dd->dd_csr = %s\n", sbuf); 729 1.31 mycroft } 730 1.31 mycroft #endif 731 1.51 tsutsui if ((state & DMACSR_ENABLE) != 0) { 732 1.31 mycroft u_long dmadir; /* DMACSR_SETREAD or DMACSR_SETWRITE */ 733 1.23 dbj 734 1.31 mycroft nextdma_rotate(nsc); 735 1.31 mycroft nextdma_setup_cont_regs(nsc); 736 1.51 tsutsui 737 1.51 tsutsui if ((state & DMACSR_READ) != 0) { 738 1.31 mycroft dmadir = DMACSR_SETREAD; 739 1.31 mycroft } else { 740 1.31 mycroft dmadir = DMACSR_SETWRITE; 741 1.30 christos } 742 1.22 tv 743 1.31 mycroft if (stat->nd_map_cont == NULL) { 744 1.31 mycroft KASSERT(stat->nd_idx+1 == stat->nd_map->dm_nsegs); 745 1.51 tsutsui nd_bsw4(DD_CSR, DMACSR_CLRCOMPLETE | dmadir); 746 1.51 tsutsui NDTRACEIF(ndtrace_addc('g')); 747 1.23 dbj } else { 748 1.51 tsutsui nd_bsw4(DD_CSR, 749 1.51 tsutsui DMACSR_CLRCOMPLETE | dmadir | DMACSR_SETSUPDATE); 750 1.51 tsutsui NDTRACEIF(ndtrace_addc('G')); 751 1.31 mycroft } 752 1.31 mycroft } else { 753 1.31 mycroft DPRINTF(("DMA: a shutdown occurred\n")); 754 1.51 tsutsui nd_bsw4(DD_CSR, DMACSR_CLRCOMPLETE | DMACSR_RESET); 755 1.51 tsutsui 756 1.31 mycroft /* Cleanup more incomplete transfers */ 757 1.31 mycroft /* cleanup continue map */ 758 1.31 mycroft if (stat->nd_map_cont) { 759 1.51 tsutsui DPRINTF(("DMA: shutting down with" 760 1.51 tsutsui " non null continue map\n")); 761 1.51 tsutsui if (nsc->sc_conf.nd_completed_cb != NULL) 762 1.51 tsutsui (*nsc->sc_conf.nd_completed_cb)( 763 1.51 tsutsui stat->nd_map_cont, nsc->sc_conf.nd_cb_arg); 764 1.51 tsutsui 765 1.31 mycroft stat->nd_map_cont = 0; 766 1.31 mycroft stat->nd_idx_cont = 0; 767 1.1 dbj } 768 1.51 tsutsui if (nsc->sc_conf.nd_shutdown_cb != NULL) 769 1.31 mycroft (*nsc->sc_conf.nd_shutdown_cb)(nsc->sc_conf.nd_cb_arg); 770 1.1 dbj } 771 1.51 tsutsui 772 1.22 tv #ifdef ND_DEBUG 773 1.30 christos if (NEXTDMA_DEBUG) { 774 1.22 tv char sbuf[256]; 775 1.22 tv 776 1.43 christos snprintb(sbuf, sizeof(sbuf), 777 1.43 christos NEXT_INTR_BITS, NEXT_I_BIT(nsc->sc_chan->nd_intr)); 778 1.50 msaitoh printf("DMA exiting interrupt ipl (%ld) intr(%s)\n", 779 1.51 tsutsui NEXT_I_IPL(nsc->sc_chan->nd_intr), sbuf); 780 1.22 tv } 781 1.22 tv #endif 782 1.51 tsutsui 783 1.51 tsutsui return 1; 784 1.1 dbj } 785 1.31 mycroft #endif 786 1.1 dbj 787 1.1 dbj /* 788 1.1 dbj * Check to see if dma has finished for a channel */ 789 1.1 dbj int 790 1.37 chs nextdma_finished(struct nextdma_softc *nsc) 791 1.1 dbj { 792 1.1 dbj int r; 793 1.1 dbj int s; 794 1.31 mycroft struct nextdma_status *stat = &nsc->sc_stat; 795 1.31 mycroft 796 1.31 mycroft s = spldma(); 797 1.31 mycroft r = (stat->nd_map == NULL) && (stat->nd_map_cont == NULL); 798 1.1 dbj splx(s); 799 1.31 mycroft 800 1.51 tsutsui return r; 801 1.1 dbj } 802 1.1 dbj 803 1.1 dbj void 804 1.37 chs nextdma_start(struct nextdma_softc *nsc, u_long dmadir) 805 1.1 dbj { 806 1.31 mycroft struct nextdma_status *stat = &nsc->sc_stat; 807 1.1 dbj 808 1.51 tsutsui NDTRACEIF(ndtrace_addc('n')); 809 1.1 dbj #ifdef DIAGNOSTIC 810 1.31 mycroft if (!nextdma_finished(nsc)) { 811 1.22 tv char sbuf[256]; 812 1.22 tv 813 1.43 christos snprintb(sbuf, sizeof(sbuf), 814 1.43 christos NEXT_INTR_BITS, NEXT_I_BIT(nsc->sc_chan->nd_intr)); 815 1.51 tsutsui panic("DMA trying to start before previous finished" 816 1.51 tsutsui " on intr(%s)", sbuf); 817 1.1 dbj } 818 1.1 dbj #endif 819 1.1 dbj 820 1.22 tv #ifdef ND_DEBUG 821 1.30 christos if (NEXTDMA_DEBUG) { 822 1.22 tv char sbuf[256]; 823 1.22 tv 824 1.43 christos snprintb(sbuf, sizeof(sbuf), 825 1.43 christos NEXT_INTR_BITS, NEXT_I_BIT(nsc->sc_chan->nd_intr)); 826 1.50 msaitoh printf("DMA start (%ld) intr(%s)\n", 827 1.51 tsutsui NEXT_I_IPL(nsc->sc_chan->nd_intr), sbuf); 828 1.22 tv } 829 1.22 tv #endif 830 1.1 dbj 831 1.1 dbj #ifdef DIAGNOSTIC 832 1.51 tsutsui if (stat->nd_map != NULL) { 833 1.31 mycroft nextdma_print(nsc); 834 1.32 provos panic("DMA: nextdma_start() with non null map"); 835 1.1 dbj } 836 1.51 tsutsui if (stat->nd_map_cont != NULL) { 837 1.31 mycroft nextdma_print(nsc); 838 1.32 provos panic("DMA: nextdma_start() with non null continue map"); 839 1.1 dbj } 840 1.1 dbj #endif 841 1.1 dbj 842 1.9 dbj #ifdef DIAGNOSTIC 843 1.51 tsutsui if (dmadir != DMACSR_SETREAD && dmadir != DMACSR_SETWRITE) { 844 1.51 tsutsui panic("DMA: nextdma_start(), dmadir arg must be" 845 1.51 tsutsui " DMACSR_SETREAD or DMACSR_SETWRITE"); 846 1.9 dbj } 847 1.9 dbj #endif 848 1.9 dbj 849 1.26 dbj #if defined(ND_DEBUG) 850 1.31 mycroft nextdma_debug_initstate(nsc); 851 1.26 dbj #endif 852 1.26 dbj 853 1.7 dbj /* preload both the current and the continue maps */ 854 1.31 mycroft nextdma_rotate(nsc); 855 1.1 dbj 856 1.1 dbj #ifdef DIAGNOSTIC 857 1.51 tsutsui if (stat->nd_map_cont == NULL) { 858 1.1 dbj panic("No map available in nextdma_start()"); 859 1.1 dbj } 860 1.1 dbj #endif 861 1.1 dbj 862 1.31 mycroft nextdma_rotate(nsc); 863 1.7 dbj 864 1.22 tv #ifdef ND_DEBUG 865 1.30 christos if (NEXTDMA_DEBUG) { 866 1.22 tv char sbuf[256]; 867 1.22 tv 868 1.43 christos snprintb(sbuf, sizeof(sbuf), 869 1.43 christos NEXT_INTR_BITS, NEXT_I_BIT(nsc->sc_chan->nd_intr)); 870 1.50 msaitoh printf("DMA initiating DMA %s of %d segments on intr(%s)\n", 871 1.51 tsutsui (dmadir == DMACSR_SETREAD ? "read" : "write"), 872 1.51 tsutsui stat->nd_map->dm_nsegs, sbuf); 873 1.22 tv } 874 1.22 tv #endif 875 1.1 dbj 876 1.51 tsutsui nd_bsw4(DD_CSR, (turbo ? 877 1.51 tsutsui DMACSR_INITBUFTURBO : DMACSR_INITBUF) | DMACSR_RESET | dmadir); 878 1.51 tsutsui nd_bsw4(DD_CSR, 0); 879 1.1 dbj 880 1.31 mycroft nextdma_setup_curr_regs(nsc); 881 1.31 mycroft nextdma_setup_cont_regs(nsc); 882 1.1 dbj 883 1.4 dbj #if (defined(ND_DEBUG)) 884 1.51 tsutsui if (NEXTDMA_DEBUG > 2) 885 1.51 tsutsui nextdma_print(nsc); 886 1.4 dbj #endif 887 1.1 dbj 888 1.31 mycroft if (stat->nd_map_cont == NULL) { 889 1.51 tsutsui nd_bsw4(DD_CSR, DMACSR_SETENABLE | dmadir); 890 1.20 dbj } else { 891 1.51 tsutsui nd_bsw4(DD_CSR, DMACSR_SETSUPDATE | DMACSR_SETENABLE | dmadir); 892 1.1 dbj } 893 1.1 dbj } 894 1.31 mycroft 895 1.31 mycroft /* This routine is used for debugging */ 896 1.31 mycroft void 897 1.37 chs nextdma_print(struct nextdma_softc *nsc) 898 1.31 mycroft { 899 1.31 mycroft u_long dd_csr; 900 1.31 mycroft u_long dd_next; 901 1.31 mycroft u_long dd_next_initbuf; 902 1.31 mycroft u_long dd_limit; 903 1.31 mycroft u_long dd_start; 904 1.31 mycroft u_long dd_stop; 905 1.31 mycroft u_long dd_saved_next; 906 1.31 mycroft u_long dd_saved_limit; 907 1.31 mycroft u_long dd_saved_start; 908 1.31 mycroft u_long dd_saved_stop; 909 1.31 mycroft char sbuf[256]; 910 1.31 mycroft struct nextdma_status *stat = &nsc->sc_stat; 911 1.31 mycroft 912 1.51 tsutsui /* 913 1.51 tsutsui * Read all of the registers before we print anything out, 914 1.31 mycroft * in case something changes 915 1.31 mycroft */ 916 1.51 tsutsui dd_csr = nd_bsr4(DD_CSR); 917 1.51 tsutsui dd_next = nd_bsr4(DD_NEXT); 918 1.51 tsutsui dd_next_initbuf = nd_bsr4(DD_NEXT_INITBUF); 919 1.51 tsutsui dd_limit = nd_bsr4(DD_LIMIT); 920 1.51 tsutsui dd_start = nd_bsr4(DD_START); 921 1.51 tsutsui dd_stop = nd_bsr4(DD_STOP); 922 1.51 tsutsui dd_saved_next = nd_bsr4(DD_SAVED_NEXT); 923 1.51 tsutsui dd_saved_limit = nd_bsr4(DD_SAVED_LIMIT); 924 1.51 tsutsui dd_saved_start = nd_bsr4(DD_SAVED_START); 925 1.51 tsutsui dd_saved_stop = nd_bsr4(DD_SAVED_STOP); 926 1.31 mycroft 927 1.43 christos snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS, 928 1.43 christos *(volatile u_long *)IIOV(NEXT_P_INTRSTAT)); 929 1.50 msaitoh printf("NDMAP: *intrstat = %s\n", sbuf); 930 1.31 mycroft 931 1.43 christos snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS, 932 1.43 christos *(volatile u_long *)IIOV(NEXT_P_INTRMASK)); 933 1.50 msaitoh printf("NDMAP: *intrmask = %s\n", sbuf); 934 1.31 mycroft 935 1.31 mycroft /* NDMAP is Next DMA Print (really!) */ 936 1.31 mycroft 937 1.51 tsutsui if (stat->nd_map != NULL) { 938 1.31 mycroft int i; 939 1.31 mycroft 940 1.31 mycroft printf("NDMAP: nd_map->dm_mapsize = %ld\n", 941 1.51 tsutsui stat->nd_map->dm_mapsize); 942 1.31 mycroft printf("NDMAP: nd_map->dm_nsegs = %d\n", 943 1.51 tsutsui stat->nd_map->dm_nsegs); 944 1.31 mycroft printf("NDMAP: nd_map->dm_xfer_len = %ld\n", 945 1.51 tsutsui stat->nd_map->dm_xfer_len); 946 1.31 mycroft printf("NDMAP: nd_map->dm_segs[%d].ds_addr = 0x%08lx\n", 947 1.51 tsutsui stat->nd_idx, stat->nd_map->dm_segs[stat->nd_idx].ds_addr); 948 1.31 mycroft printf("NDMAP: nd_map->dm_segs[%d].ds_len = %ld\n", 949 1.51 tsutsui stat->nd_idx, stat->nd_map->dm_segs[stat->nd_idx].ds_len); 950 1.31 mycroft 951 1.31 mycroft printf("NDMAP: Entire map;\n"); 952 1.51 tsutsui for(i = 0; i < stat->nd_map->dm_nsegs; i++) { 953 1.51 tsutsui printf("NDMAP: " 954 1.51 tsutsui "nd_map->dm_segs[%d].ds_addr = 0x%08lx\n", 955 1.51 tsutsui i, stat->nd_map->dm_segs[i].ds_addr); 956 1.31 mycroft printf("NDMAP: nd_map->dm_segs[%d].ds_len = %ld\n", 957 1.51 tsutsui i, stat->nd_map->dm_segs[i].ds_len); 958 1.31 mycroft } 959 1.31 mycroft } else { 960 1.31 mycroft printf("NDMAP: nd_map = NULL\n"); 961 1.31 mycroft } 962 1.51 tsutsui if (stat->nd_map_cont != NULL) { 963 1.31 mycroft printf("NDMAP: nd_map_cont->dm_mapsize = %ld\n", 964 1.51 tsutsui stat->nd_map_cont->dm_mapsize); 965 1.31 mycroft printf("NDMAP: nd_map_cont->dm_nsegs = %d\n", 966 1.51 tsutsui stat->nd_map_cont->dm_nsegs); 967 1.31 mycroft printf("NDMAP: nd_map_cont->dm_xfer_len = %ld\n", 968 1.51 tsutsui stat->nd_map_cont->dm_xfer_len); 969 1.31 mycroft printf("NDMAP: nd_map_cont->dm_segs[%d].ds_addr = 0x%08lx\n", 970 1.51 tsutsui stat->nd_idx_cont, 971 1.51 tsutsui stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_addr); 972 1.31 mycroft printf("NDMAP: nd_map_cont->dm_segs[%d].ds_len = %ld\n", 973 1.51 tsutsui stat->nd_idx_cont, 974 1.51 tsutsui stat->nd_map_cont->dm_segs[stat->nd_idx_cont].ds_len); 975 1.31 mycroft if (stat->nd_map_cont != stat->nd_map) { 976 1.31 mycroft int i; 977 1.31 mycroft printf("NDMAP: Entire map;\n"); 978 1.31 mycroft for(i=0;i<stat->nd_map_cont->dm_nsegs;i++) { 979 1.51 tsutsui printf("NDMAP: " 980 1.51 tsutsui "nd_map_cont->dm_segs[%d].ds_addr" 981 1.51 tsutsui " = 0x%08lx\n", 982 1.51 tsutsui i, stat->nd_map_cont->dm_segs[i].ds_addr); 983 1.51 tsutsui printf("NDMAP: " 984 1.51 tsutsui "nd_map_cont->dm_segs[%d].ds_len = %ld\n", 985 1.51 tsutsui i, stat->nd_map_cont->dm_segs[i].ds_len); 986 1.31 mycroft } 987 1.31 mycroft } 988 1.31 mycroft } else { 989 1.31 mycroft printf("NDMAP: nd_map_cont = NULL\n"); 990 1.31 mycroft } 991 1.31 mycroft 992 1.43 christos snprintb(sbuf, sizeof(sbuf), DMACSR_BITS, dd_csr); 993 1.50 msaitoh printf("NDMAP: dd->dd_csr = %s\n", sbuf); 994 1.31 mycroft 995 1.31 mycroft printf("NDMAP: dd->dd_saved_next = 0x%08lx\n", dd_saved_next); 996 1.31 mycroft printf("NDMAP: dd->dd_saved_limit = 0x%08lx\n", dd_saved_limit); 997 1.31 mycroft printf("NDMAP: dd->dd_saved_start = 0x%08lx\n", dd_saved_start); 998 1.31 mycroft printf("NDMAP: dd->dd_saved_stop = 0x%08lx\n", dd_saved_stop); 999 1.31 mycroft printf("NDMAP: dd->dd_next = 0x%08lx\n", dd_next); 1000 1.31 mycroft printf("NDMAP: dd->dd_next_initbuf = 0x%08lx\n", dd_next_initbuf); 1001 1.31 mycroft printf("NDMAP: dd->dd_limit = 0x%08lx\n", dd_limit); 1002 1.31 mycroft printf("NDMAP: dd->dd_start = 0x%08lx\n", dd_start); 1003 1.31 mycroft printf("NDMAP: dd->dd_stop = 0x%08lx\n", dd_stop); 1004 1.31 mycroft 1005 1.43 christos snprintb(sbuf, sizeof(sbuf), NEXT_INTR_BITS, 1006 1.47 mrg NEXT_I_BIT(nsc->sc_chan->nd_intr)); 1007 1.50 msaitoh printf("NDMAP: interrupt ipl (%ld) intr(%s)\n", 1008 1.51 tsutsui NEXT_I_IPL(nsc->sc_chan->nd_intr), sbuf); 1009 1.31 mycroft } 1010 1.31 mycroft 1011 1.31 mycroft #if defined(ND_DEBUG) 1012 1.31 mycroft void 1013 1.31 mycroft nextdma_debug_initstate(struct nextdma_softc *nsc) 1014 1.31 mycroft { 1015 1.31 mycroft switch(nsc->sc_chan->nd_intr) { 1016 1.31 mycroft case NEXT_I_ENETR_DMA: 1017 1.51 tsutsui memset(nextdma_debug_enetr_state, 0, 1018 1.51 tsutsui sizeof(nextdma_debug_enetr_state)); 1019 1.31 mycroft break; 1020 1.31 mycroft case NEXT_I_SCSI_DMA: 1021 1.51 tsutsui memset(nextdma_debug_scsi_state, 0, 1022 1.51 tsutsui sizeof(nextdma_debug_scsi_state)); 1023 1.31 mycroft break; 1024 1.31 mycroft } 1025 1.31 mycroft } 1026 1.31 mycroft 1027 1.31 mycroft void 1028 1.31 mycroft nextdma_debug_savestate(struct nextdma_softc *nsc, unsigned int state) 1029 1.31 mycroft { 1030 1.51 tsutsui 1031 1.31 mycroft switch(nsc->sc_chan->nd_intr) { 1032 1.31 mycroft case NEXT_I_ENETR_DMA: 1033 1.31 mycroft nextdma_debug_enetr_state[nextdma_debug_enetr_idx++] = state; 1034 1.51 tsutsui nextdma_debug_enetr_idx %= 1035 1.51 tsutsui (sizeof(nextdma_debug_enetr_state) / sizeof(unsigned int)); 1036 1.31 mycroft break; 1037 1.31 mycroft case NEXT_I_SCSI_DMA: 1038 1.31 mycroft nextdma_debug_scsi_state[nextdma_debug_scsi_idx++] = state; 1039 1.51 tsutsui nextdma_debug_scsi_idx %= 1040 1.51 tsutsui (sizeof(nextdma_debug_scsi_state) / sizeof(unsigned int)); 1041 1.31 mycroft break; 1042 1.31 mycroft } 1043 1.31 mycroft } 1044 1.31 mycroft 1045 1.31 mycroft void 1046 1.31 mycroft nextdma_debug_enetr_dumpstate(void) 1047 1.31 mycroft { 1048 1.31 mycroft int i; 1049 1.31 mycroft int s; 1050 1.31 mycroft s = spldma(); 1051 1.31 mycroft i = nextdma_debug_enetr_idx; 1052 1.31 mycroft do { 1053 1.31 mycroft char sbuf[256]; 1054 1.31 mycroft if (nextdma_debug_enetr_state[i]) { 1055 1.51 tsutsui snprintb(sbuf, sizeof(sbuf), DMACSR_BITS, 1056 1.51 tsutsui nextdma_debug_enetr_state[i]); 1057 1.51 tsutsui printf("DMA: 0x%02x state %s\n", i, sbuf); 1058 1.31 mycroft } 1059 1.31 mycroft i++; 1060 1.51 tsutsui i %= (sizeof(nextdma_debug_enetr_state) / sizeof(unsigned int)); 1061 1.31 mycroft } while (i != nextdma_debug_enetr_idx); 1062 1.31 mycroft splx(s); 1063 1.31 mycroft } 1064 1.31 mycroft 1065 1.31 mycroft void 1066 1.31 mycroft nextdma_debug_scsi_dumpstate(void) 1067 1.31 mycroft { 1068 1.31 mycroft int i; 1069 1.31 mycroft int s; 1070 1.31 mycroft s = spldma(); 1071 1.31 mycroft i = nextdma_debug_scsi_idx; 1072 1.31 mycroft do { 1073 1.31 mycroft char sbuf[256]; 1074 1.31 mycroft if (nextdma_debug_scsi_state[i]) { 1075 1.51 tsutsui snprintb(sbuf, sizeof(sbuf), DMACSR_BITS, 1076 1.51 tsutsui nextdma_debug_scsi_state[i]); 1077 1.51 tsutsui printf("DMA: 0x%02x state %s\n", i, sbuf); 1078 1.31 mycroft } 1079 1.31 mycroft i++; 1080 1.51 tsutsui i %= (sizeof(nextdma_debug_scsi_state) / sizeof(unsigned int)); 1081 1.31 mycroft } while (i != nextdma_debug_scsi_idx); 1082 1.31 mycroft splx(s); 1083 1.31 mycroft } 1084 1.31 mycroft #endif 1085