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