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