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