1 /* $NetBSD: esp.c,v 1.36 2002/05/20 18:03:03 jdolecek 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/nextdmareg.h> 111 #include <next68k/dev/nextdmavar.h> 112 113 #include "espreg.h" 114 #include "espvar.h" 115 116 #ifdef DEBUG 117 #define ESP_DEBUG 118 #endif 119 120 #ifdef ESP_DEBUG 121 int esp_debug = 0; 122 #define DPRINTF(x) if (esp_debug) printf x; 123 #else 124 #define DPRINTF(x) 125 #endif 126 127 128 void espattach_intio __P((struct device *, struct device *, void *)); 129 int espmatch_intio __P((struct device *, struct cfdata *, void *)); 130 131 /* DMA callbacks */ 132 bus_dmamap_t esp_dmacb_continue __P((void *arg)); 133 void esp_dmacb_completed __P((bus_dmamap_t map, void *arg)); 134 void esp_dmacb_shutdown __P((void *arg)); 135 136 #ifdef ESP_DEBUG 137 char esp_dma_dump[5*1024] = ""; 138 struct ncr53c9x_softc *esp_debug_sc = 0; 139 void esp_dma_store __P((struct ncr53c9x_softc *sc)); 140 void esp_dma_print __P((struct ncr53c9x_softc *sc)); 141 int esp_dma_nest = 0; 142 #endif 143 144 145 /* Linkup to the rest of the kernel */ 146 struct cfattach esp_ca = { 147 sizeof(struct esp_softc), espmatch_intio, espattach_intio 148 }; 149 150 /* 151 * Functions and the switch for the MI code. 152 */ 153 u_char esp_read_reg __P((struct ncr53c9x_softc *, int)); 154 void esp_write_reg __P((struct ncr53c9x_softc *, int, u_char)); 155 int esp_dma_isintr __P((struct ncr53c9x_softc *)); 156 void esp_dma_reset __P((struct ncr53c9x_softc *)); 157 int esp_dma_intr __P((struct ncr53c9x_softc *)); 158 int esp_dma_setup __P((struct ncr53c9x_softc *, caddr_t *, 159 size_t *, int, size_t *)); 160 void esp_dma_go __P((struct ncr53c9x_softc *)); 161 void esp_dma_stop __P((struct ncr53c9x_softc *)); 162 int esp_dma_isactive __P((struct ncr53c9x_softc *)); 163 164 struct ncr53c9x_glue esp_glue = { 165 esp_read_reg, 166 esp_write_reg, 167 esp_dma_isintr, 168 esp_dma_reset, 169 esp_dma_intr, 170 esp_dma_setup, 171 esp_dma_go, 172 esp_dma_stop, 173 esp_dma_isactive, 174 NULL, /* gl_clear_latched_intr */ 175 }; 176 177 #ifdef ESP_DEBUG 178 #define XCHR(x) "0123456789abcdef"[(x) & 0xf] 179 static void 180 esp_hex_dump(unsigned char *pkt, size_t len) 181 { 182 size_t i, j; 183 184 printf("00000000 "); 185 for(i=0; i<len; i++) { 186 printf("%c%c ", XCHR(pkt[i]>>4), XCHR(pkt[i])); 187 if ((i+1) % 16 == 8) { 188 printf(" "); 189 } 190 if ((i+1) % 16 == 0) { 191 printf(" %c", '|'); 192 for(j=0; j<16; j++) { 193 printf("%c", pkt[i-15+j]>=32 && pkt[i-15+j]<127?pkt[i-15+j]:'.'); 194 } 195 printf("%c\n%c%c%c%c%c%c%c%c ", '|', 196 XCHR((i+1)>>28),XCHR((i+1)>>24),XCHR((i+1)>>20),XCHR((i+1)>>16), 197 XCHR((i+1)>>12), XCHR((i+1)>>8), XCHR((i+1)>>4), XCHR(i+1)); 198 } 199 } 200 printf("\n"); 201 } 202 #endif 203 204 int 205 espmatch_intio(parent, cf, aux) 206 struct device *parent; 207 struct cfdata *cf; 208 void *aux; 209 { 210 /* should probably probe here */ 211 /* Should also probably set up data from config */ 212 213 return(1); 214 } 215 216 void 217 espattach_intio(parent, self, aux) 218 struct device *parent, *self; 219 void *aux; 220 { 221 struct esp_softc *esc = (void *)self; 222 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 223 224 #ifdef ESP_DEBUG 225 esp_debug_sc = sc; 226 #endif 227 228 esc->sc_bst = NEXT68K_INTIO_BUS_SPACE; 229 if (bus_space_map(esc->sc_bst, NEXT_P_SCSI, 230 ESP_DEVICE_SIZE, 0, &esc->sc_bsh)) { 231 panic("\n%s: can't map ncr53c90 registers", 232 sc->sc_dev.dv_xname); 233 } 234 235 sc->sc_id = 7; 236 sc->sc_freq = 20; /* Mhz */ 237 238 /* 239 * Set up glue for MI code early; we use some of it here. 240 */ 241 sc->sc_glue = &esp_glue; 242 243 /* 244 * XXX More of this should be in ncr53c9x_attach(), but 245 * XXX should we really poke around the chip that much in 246 * XXX the MI code? Think about this more... 247 */ 248 249 /* 250 * It is necessary to try to load the 2nd config register here, 251 * to find out what rev the esp chip is, else the ncr53c9x_reset 252 * will not set up the defaults correctly. 253 */ 254 sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB; 255 sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE; 256 sc->sc_cfg3 = NCRCFG3_CDB; 257 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 258 259 if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) != 260 (NCRCFG2_SCSI2 | NCRCFG2_RPE)) { 261 sc->sc_rev = NCR_VARIANT_ESP100; 262 } else { 263 sc->sc_cfg2 = NCRCFG2_SCSI2; 264 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2); 265 sc->sc_cfg3 = 0; 266 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 267 sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK); 268 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 269 if (NCR_READ_REG(sc, NCR_CFG3) != 270 (NCRCFG3_CDB | NCRCFG3_FCLK)) { 271 sc->sc_rev = NCR_VARIANT_ESP100A; 272 } else { 273 /* NCRCFG2_FE enables > 64K transfers */ 274 sc->sc_cfg2 |= NCRCFG2_FE; 275 sc->sc_cfg3 = 0; 276 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3); 277 sc->sc_rev = NCR_VARIANT_ESP200; 278 } 279 } 280 281 /* 282 * XXX minsync and maxxfer _should_ be set up in MI code, 283 * XXX but it appears to have some dependency on what sort 284 * XXX of DMA we're hooked up to, etc. 285 */ 286 287 /* 288 * This is the value used to start sync negotiations 289 * Note that the NCR register "SYNCTP" is programmed 290 * in "clocks per byte", and has a minimum value of 4. 291 * The SCSI period used in negotiation is one-fourth 292 * of the time (in nanoseconds) needed to transfer one byte. 293 * Since the chip's clock is given in MHz, we have the following 294 * formula: 4 * period = (1000 / freq) * 4 295 */ 296 sc->sc_minsync = 1000 / sc->sc_freq; 297 298 /* 299 * Alas, we must now modify the value a bit, because it's 300 * only valid when can switch on FASTCLK and FASTSCSI bits 301 * in config register 3... 302 */ 303 switch (sc->sc_rev) { 304 case NCR_VARIANT_ESP100: 305 sc->sc_maxxfer = 64 * 1024; 306 sc->sc_minsync = 0; /* No synch on old chip? */ 307 break; 308 309 case NCR_VARIANT_ESP100A: 310 sc->sc_maxxfer = 64 * 1024; 311 /* Min clocks/byte is 5 */ 312 sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5); 313 break; 314 315 case NCR_VARIANT_ESP200: 316 sc->sc_maxxfer = 16 * 1024 * 1024; 317 /* XXX - do actually set FAST* bits */ 318 break; 319 } 320 321 /* @@@ Some ESP_DCTL bits probably need setting */ 322 NCR_WRITE_REG(sc, ESP_DCTL, 323 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_RESET); 324 DELAY(10); 325 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL))); 326 NCR_WRITE_REG(sc, ESP_DCTL, ESPDCTL_20MHZ | ESPDCTL_INTENB); 327 DELAY(10); 328 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL))); 329 330 /* Set up SCSI DMA */ 331 { 332 esc->sc_scsi_dma.nd_bst = NEXT68K_INTIO_BUS_SPACE; 333 334 if (bus_space_map(esc->sc_scsi_dma.nd_bst, NEXT_P_SCSI_CSR, 335 DD_SIZE,0, &esc->sc_scsi_dma.nd_bsh)) { 336 panic("\n%s: can't map scsi DMA registers", 337 sc->sc_dev.dv_xname); 338 } 339 340 esc->sc_scsi_dma.nd_intr = NEXT_I_SCSI_DMA; 341 esc->sc_scsi_dma.nd_shutdown_cb = &esp_dmacb_shutdown; 342 esc->sc_scsi_dma.nd_continue_cb = &esp_dmacb_continue; 343 esc->sc_scsi_dma.nd_completed_cb = &esp_dmacb_completed; 344 esc->sc_scsi_dma.nd_cb_arg = sc; 345 nextdma_config(&esc->sc_scsi_dma); 346 nextdma_init(&esc->sc_scsi_dma); 347 348 #if 0 349 /* Turn on target selection using the `dma' method */ 350 sc->sc_features |= NCR_F_DMASELECT; 351 #endif 352 353 esc->sc_datain = -1; 354 esc->sc_dmaaddr = 0; 355 esc->sc_dmalen = 0; 356 esc->sc_dmasize = 0; 357 358 esc->sc_loaded = 0; 359 360 esc->sc_begin = 0; 361 esc->sc_begin_size = 0; 362 363 { 364 int error; 365 if ((error = bus_dmamap_create(esc->sc_scsi_dma.nd_dmat, 366 sc->sc_maxxfer, sc->sc_maxxfer/NBPG+1, sc->sc_maxxfer, 367 0, BUS_DMA_ALLOCNOW, &esc->sc_main_dmamap)) != 0) { 368 panic("%s: can't create main i/o DMA map, error = %d", 369 sc->sc_dev.dv_xname,error); 370 } 371 } 372 esc->sc_main = 0; 373 esc->sc_main_size = 0; 374 375 { 376 int error; 377 if ((error = bus_dmamap_create(esc->sc_scsi_dma.nd_dmat, 378 ESP_DMA_TAILBUFSIZE, 379 1, ESP_DMA_TAILBUFSIZE, 380 0, BUS_DMA_ALLOCNOW, &esc->sc_tail_dmamap)) != 0) { 381 panic("%s: can't create tail i/o DMA map, error = %d", 382 sc->sc_dev.dv_xname,error); 383 } 384 } 385 esc->sc_tail = 0; 386 esc->sc_tail_size = 0; 387 388 } 389 390 /* Establish interrupt channel */ 391 isrlink_autovec(ncr53c9x_intr, sc, NEXT_I_IPL(NEXT_I_SCSI), 0); 392 INTR_ENABLE(NEXT_I_SCSI); 393 394 /* register interrupt stats */ 395 evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL, 396 sc->sc_dev.dv_xname, "intr"); 397 398 /* Do the common parts of attachment. */ 399 sc->sc_adapter.adapt_minphys = minphys; 400 sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request; 401 ncr53c9x_attach(sc); 402 } 403 404 /* 405 * Glue functions. 406 */ 407 408 u_char 409 esp_read_reg(sc, reg) 410 struct ncr53c9x_softc *sc; 411 int reg; 412 { 413 struct esp_softc *esc = (struct esp_softc *)sc; 414 415 return(bus_space_read_1(esc->sc_bst, esc->sc_bsh, reg)); 416 } 417 418 void 419 esp_write_reg(sc, reg, val) 420 struct ncr53c9x_softc *sc; 421 int reg; 422 u_char val; 423 { 424 struct esp_softc *esc = (struct esp_softc *)sc; 425 426 bus_space_write_1(esc->sc_bst, esc->sc_bsh, reg, val); 427 } 428 429 int 430 esp_dma_isintr(sc) 431 struct ncr53c9x_softc *sc; 432 { 433 struct esp_softc *esc = (struct esp_softc *)sc; 434 435 int r = (INTR_OCCURRED(NEXT_I_SCSI)); 436 437 if (r) { 438 439 { 440 int flushcount; 441 int s; 442 s = spldma(); 443 444 flushcount = 0; 445 446 #ifdef ESP_DEBUG 447 esp_dma_nest++; 448 449 if (esp_debug) { 450 char sbuf[256]; 451 452 bitmask_snprintf((*(volatile u_long *)IIOV(NEXT_P_INTRSTAT)), 453 NEXT_INTR_BITS, sbuf, sizeof(sbuf)); 454 printf("esp_dma_isintr = 0x%s\n", sbuf); 455 } 456 #endif 457 458 while (esp_dma_isactive(sc)) { 459 flushcount++; 460 461 #ifdef DIAGNOSTIC 462 r = (INTR_OCCURRED(NEXT_I_SCSI)); 463 if (!r) panic("esp intr enabled but dma failed to flush"); 464 #endif 465 #ifdef DIAGNOSTIC 466 #if 0 467 if ((esc->sc_loaded & (ESP_LOADED_TAIL/* |ESP_UNLOADED_MAIN */)) 468 != (ESP_LOADED_TAIL /* |ESP_UNLOADED_MAIN */)) { 469 if (esc->sc_datain) { 470 NCR_WRITE_REG(sc, ESP_DCTL, 471 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_DMARD); 472 } else { 473 NCR_WRITE_REG(sc, ESP_DCTL, 474 ESPDCTL_20MHZ | ESPDCTL_INTENB); 475 } 476 next_dma_print(&esc->sc_scsi_dma); 477 esp_dma_print(sc); 478 printf("%s: unexpected flush: tc=0x%06x\n", 479 sc->sc_dev.dv_xname, 480 (((sc->sc_cfg2 & NCRCFG2_FE) 481 ? NCR_READ_REG(sc, NCR_TCH) : 0)<<16)| 482 (NCR_READ_REG(sc, NCR_TCM)<<8)| 483 NCR_READ_REG(sc, NCR_TCL)); 484 ncr53c9x_readregs(sc); 485 printf("%s: readregs[intr=%02x,stat=%02x,step=%02x]\n", 486 sc->sc_dev.dv_xname, 487 sc->sc_espintr, sc->sc_espstat, sc->sc_espstep); 488 panic("%s: flushing flushing non-tail dma\n", 489 sc->sc_dev.dv_xname); 490 } 491 #endif 492 #endif 493 DPRINTF(("%s: flushing dma, count = %d\n", sc->sc_dev.dv_xname,flushcount)); 494 if (esc->sc_datain) { 495 NCR_WRITE_REG(sc, ESP_DCTL, 496 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_DMAMOD | ESPDCTL_DMARD | ESPDCTL_FLUSH); 497 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL))); 498 NCR_WRITE_REG(sc, ESP_DCTL, 499 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_DMAMOD | ESPDCTL_DMARD); 500 } else { 501 NCR_WRITE_REG(sc, ESP_DCTL, 502 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_DMAMOD | ESPDCTL_FLUSH); 503 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL))); 504 NCR_WRITE_REG(sc, ESP_DCTL, 505 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_DMAMOD); 506 } 507 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL))); 508 509 { 510 int nr; 511 nr = nextdma_intr(&esc->sc_scsi_dma); 512 if (nr) { 513 DPRINTF(("nextma_intr = %d\n",nr)); 514 #ifdef DIAGNOSTIC 515 if (flushcount > 4) { 516 printf("%s: unexpected flushcount %d\n",sc->sc_dev.dv_xname,flushcount); 517 } 518 #endif 519 #ifdef DIAGNOSTIC 520 #if 0 521 if (esp_dma_isactive(sc)) { 522 esp_dma_print(sc); 523 printf("%s: dma still active after a flush with count %d\n", 524 sc->sc_dev.dv_xname,flushcount); 525 526 } 527 #endif 528 #endif 529 flushcount = 0; 530 } 531 } 532 } 533 534 #ifdef ESP_DEBUG 535 esp_dma_nest--; 536 #endif 537 538 splx(s); 539 } 540 541 #ifdef DIAGNOSTIC 542 r = (INTR_OCCURRED(NEXT_I_SCSI)); 543 if (!r) panic("esp intr not enabled after dma flush"); 544 #endif 545 546 /* Clear the DMAMOD bit in the DCTL register, since if this 547 * routine returns true, then the ncr53c9x_intr handler will 548 * be called and needs access to the scsi registers. 549 */ 550 if (esc->sc_datain) { 551 NCR_WRITE_REG(sc, ESP_DCTL, 552 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_DMARD); 553 } else { 554 NCR_WRITE_REG(sc, ESP_DCTL, 555 ESPDCTL_20MHZ | ESPDCTL_INTENB); 556 } 557 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL))); 558 559 } 560 561 return (r); 562 } 563 564 void 565 esp_dma_reset(sc) 566 struct ncr53c9x_softc *sc; 567 { 568 struct esp_softc *esc = (struct esp_softc *)sc; 569 570 DPRINTF(("esp dma reset\n")); 571 572 #ifdef ESP_DEBUG 573 if (esp_debug) { 574 char sbuf[256]; 575 576 bitmask_snprintf((*(volatile u_long *)IIOV(NEXT_P_INTRSTAT)), 577 NEXT_INTR_BITS, sbuf, sizeof(sbuf)); 578 printf(" *intrstat = 0x%s\n", sbuf); 579 580 bitmask_snprintf((*(volatile u_long *)IIOV(NEXT_P_INTRMASK)), 581 NEXT_INTR_BITS, sbuf, sizeof(sbuf)); 582 printf(" *intrmask = 0x%s\n", sbuf); 583 } 584 #endif 585 586 /* Clear the DMAMOD bit in the DCTL register: */ 587 NCR_WRITE_REG(sc, ESP_DCTL, 588 ESPDCTL_20MHZ | ESPDCTL_INTENB); 589 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL))); 590 591 nextdma_reset(&esc->sc_scsi_dma); 592 593 esc->sc_datain = -1; 594 esc->sc_dmaaddr = 0; 595 esc->sc_dmalen = 0; 596 esc->sc_dmasize = 0; 597 598 esc->sc_loaded = 0; 599 600 esc->sc_begin = 0; 601 esc->sc_begin_size = 0; 602 603 if (esc->sc_main_dmamap->dm_mapsize) { 604 bus_dmamap_unload(esc->sc_scsi_dma.nd_dmat, esc->sc_main_dmamap); 605 } 606 esc->sc_main = 0; 607 esc->sc_main_size = 0; 608 609 if (esc->sc_tail_dmamap->dm_mapsize) { 610 bus_dmamap_unload(esc->sc_scsi_dma.nd_dmat, esc->sc_tail_dmamap); 611 } 612 esc->sc_tail = 0; 613 esc->sc_tail_size = 0; 614 } 615 616 int 617 esp_dma_intr(sc) 618 struct ncr53c9x_softc *sc; 619 { 620 #ifdef DIAGNOSTIC 621 panic("%s: esp_dma_intr shouldn't be invoked.\n", sc->sc_dev.dv_xname); 622 #endif 623 624 return -1; 625 } 626 627 /* it appears that: 628 * addr and len arguments to this need to be kept up to date 629 * with the status of the transfter. 630 * the dmasize of this is the actual length of the transfer 631 * request, which is guaranteed to be less than maxxfer. 632 * (len may be > maxxfer) 633 */ 634 635 int 636 esp_dma_setup(sc, addr, len, datain, dmasize) 637 struct ncr53c9x_softc *sc; 638 caddr_t *addr; 639 size_t *len; 640 int datain; 641 size_t *dmasize; 642 { 643 struct esp_softc *esc = (struct esp_softc *)sc; 644 645 #ifdef DIAGNOSTIC 646 #ifdef ESP_DEBUG 647 /* if this is a read DMA, pre-fill the buffer with 0xdeadbeef 648 * to identify bogus reads 649 */ 650 if (datain) { 651 int *v = (int *)(*addr); 652 int i; 653 for(i=0;i<((*len)/4);i++) v[i] = 0xdeadbeef; 654 v = (int *)(&(esc->sc_tailbuf[0])); 655 for(i=0;i<((sizeof(esc->sc_tailbuf)/4));i++) v[i] = 0xdeaffeed; 656 } else { 657 int *v; 658 int i; 659 v = (int *)(&(esc->sc_tailbuf[0])); 660 for(i=0;i<((sizeof(esc->sc_tailbuf)/4));i++) v[i] = 0xfeeb1eed; 661 } 662 #endif 663 #endif 664 665 DPRINTF(("esp_dma_setup(%p,0x%08x,0x%08x)\n",*addr,*len,*dmasize)); 666 667 #if 0 668 #ifdef DIAGNOSTIC /* @@@ this is ok sometimes. verify that we handle it ok 669 * and then remove this check 670 */ 671 if (*len != *dmasize) { 672 panic("esp dmalen 0x%lx != size 0x%lx",*len,*dmasize); 673 } 674 #endif 675 #endif 676 677 #ifdef DIAGNOSTIC 678 if ((esc->sc_datain != -1) || 679 (esc->sc_main_dmamap->dm_mapsize != 0) || 680 (esc->sc_tail_dmamap->dm_mapsize != 0) || 681 (esc->sc_dmasize != 0)) { 682 panic("%s: map already loaded in esp_dma_setup\n" 683 "\tdatain = %d\n\tmain_mapsize=%ld\n\tail_mapsize=%ld\n\tdmasize = %d", 684 sc->sc_dev.dv_xname, esc->sc_datain, 685 esc->sc_main_dmamap->dm_mapsize, 686 esc->sc_tail_dmamap->dm_mapsize, 687 esc->sc_dmasize); 688 } 689 #endif 690 691 /* we are sometimes asked to dma zero bytes, that's easy */ 692 if (*dmasize <= 0) { 693 return(0); 694 } 695 696 /* Save these in case we have to abort DMA */ 697 esc->sc_datain = datain; 698 esc->sc_dmaaddr = addr; 699 esc->sc_dmalen = len; 700 esc->sc_dmasize = *dmasize; 701 702 esc->sc_loaded = 0; 703 704 #define DMA_SCSI_ALIGNMENT 16 705 #define DMA_SCSI_ALIGN(type, addr) \ 706 ((type)(((unsigned)(addr)+DMA_SCSI_ALIGNMENT-1) \ 707 &~(DMA_SCSI_ALIGNMENT-1))) 708 #define DMA_SCSI_ALIGNED(addr) \ 709 (((unsigned)(addr)&(DMA_SCSI_ALIGNMENT-1))==0) 710 711 { 712 size_t slop_bgn_size; /* # bytes to be fifo'd at beginning */ 713 size_t slop_end_size; /* # bytes to be transferred in tail buffer */ 714 715 { 716 u_long bgn = (u_long)(*esc->sc_dmaaddr); 717 u_long end = (u_long)(*esc->sc_dmaaddr+esc->sc_dmasize); 718 719 slop_bgn_size = DMA_SCSI_ALIGNMENT-(bgn % DMA_SCSI_ALIGNMENT); 720 if (slop_bgn_size == DMA_SCSI_ALIGNMENT) slop_bgn_size = 0; 721 slop_end_size = (end % DMA_ENDALIGNMENT); 722 } 723 724 /* Force a minimum slop end size. This ensures that write 725 * requests will overrun, as required to get completion interrupts. 726 * In addition, since the tail buffer is guaranteed to be mapped 727 * in a single dma segment, the overrun won't accidentally 728 * end up in its own segment. 729 */ 730 if (!esc->sc_datain) { 731 #if 0 732 slop_end_size += ESP_DMA_MAXTAIL; 733 #else 734 slop_end_size += 0x10; 735 #endif 736 } 737 738 /* Check to make sure we haven't counted extra slop 739 * as would happen for a very short dma buffer, also 740 * for short buffers, just stuff the entire thing in the tail 741 */ 742 if ((slop_bgn_size+slop_end_size >= esc->sc_dmasize) 743 #if 0 744 || (esc->sc_dmasize <= ESP_DMA_MAXTAIL) 745 #endif 746 ) 747 { 748 slop_bgn_size = 0; 749 slop_end_size = esc->sc_dmasize; 750 } 751 752 /* initialize the fifo buffer */ 753 if (slop_bgn_size) { 754 esc->sc_begin = *esc->sc_dmaaddr; 755 esc->sc_begin_size = slop_bgn_size; 756 } else { 757 esc->sc_begin = 0; 758 esc->sc_begin_size = 0; 759 } 760 761 /* Load the normal DMA map */ 762 { 763 esc->sc_main = *esc->sc_dmaaddr+slop_bgn_size; 764 esc->sc_main_size = (esc->sc_dmasize)-(slop_end_size+slop_bgn_size); 765 766 if (esc->sc_main_size) { 767 int error; 768 error = bus_dmamap_load(esc->sc_scsi_dma.nd_dmat, 769 esc->sc_main_dmamap, 770 esc->sc_main, esc->sc_main_size, 771 NULL, BUS_DMA_NOWAIT); 772 if (error) { 773 #ifdef ESP_DEBUG 774 printf("%s: esc->sc_main_dmamap->_dm_size = %ld\n", 775 sc->sc_dev.dv_xname,esc->sc_main_dmamap->_dm_size); 776 printf("%s: esc->sc_main_dmamap->_dm_segcnt = %d\n", 777 sc->sc_dev.dv_xname,esc->sc_main_dmamap->_dm_segcnt); 778 printf("%s: esc->sc_main_dmamap->_dm_maxsegsz = %ld\n", 779 sc->sc_dev.dv_xname,esc->sc_main_dmamap->_dm_maxsegsz); 780 printf("%s: esc->sc_main_dmamap->_dm_boundary = %ld\n", 781 sc->sc_dev.dv_xname,esc->sc_main_dmamap->_dm_boundary); 782 esp_dma_print(sc); 783 #endif 784 panic("%s: can't load main dma map. error = %d, addr=%p, size=0x%08x", 785 sc->sc_dev.dv_xname, error,esc->sc_main,esc->sc_main_size); 786 } 787 #if 0 788 bus_dmamap_sync(esc->sc_scsi_dma.nd_dmat, esc->sc_main_dmamap, 789 0, esc->sc_main_dmamap->dm_mapsize, 790 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)); 791 esc->sc_main_dmamap->dm_xfer_len = 0; 792 #endif 793 } else { 794 esc->sc_main = 0; 795 } 796 } 797 798 /* Load the tail DMA map */ 799 if (slop_end_size) { 800 esc->sc_tail = DMA_ENDALIGN(caddr_t,esc->sc_tailbuf+slop_end_size)-slop_end_size; 801 /* If the beginning of the tail is not correctly aligned, 802 * we have no choice but to align the start, which might then unalign the end. 803 */ 804 esc->sc_tail = DMA_SCSI_ALIGN(caddr_t,esc->sc_tail); 805 /* So therefore, we change the tail size to be end aligned again. */ 806 esc->sc_tail_size = DMA_ENDALIGN(caddr_t,esc->sc_tail+slop_end_size)-esc->sc_tail; 807 808 /* @@@ next dma overrun lossage */ 809 if (!esc->sc_datain) { 810 esc->sc_tail_size += ESP_DMA_OVERRUN; 811 } 812 813 { 814 int error; 815 error = bus_dmamap_load(esc->sc_scsi_dma.nd_dmat, 816 esc->sc_tail_dmamap, 817 esc->sc_tail, esc->sc_tail_size, 818 NULL, BUS_DMA_NOWAIT); 819 if (error) { 820 panic("%s: can't load tail dma map. error = %d, addr=%p, size=0x%08x", 821 sc->sc_dev.dv_xname, error,esc->sc_tail,esc->sc_tail_size); 822 } 823 #if 0 824 bus_dmamap_sync(esc->sc_scsi_dma.nd_dmat, esc->sc_tail_dmamap, 825 0, esc->sc_tail_dmamap->dm_mapsize, 826 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)); 827 esc->sc_tail_dmamap->dm_xfer_len = 0; 828 #endif 829 } 830 } 831 } 832 833 return (0); 834 } 835 836 #ifdef ESP_DEBUG 837 /* For debugging */ 838 void 839 esp_dma_store(sc) 840 struct ncr53c9x_softc *sc; 841 { 842 struct esp_softc *esc = (struct esp_softc *)sc; 843 char *p = &esp_dma_dump[0]; 844 845 p += sprintf(p,"%s: sc_datain=%d\n",sc->sc_dev.dv_xname,esc->sc_datain); 846 p += sprintf(p,"%s: sc_loaded=0x%08x\n",sc->sc_dev.dv_xname,esc->sc_loaded); 847 848 if (esc->sc_dmaaddr) { 849 p += sprintf(p,"%s: sc_dmaaddr=%p\n",sc->sc_dev.dv_xname,*esc->sc_dmaaddr); 850 } else { 851 p += sprintf(p,"%s: sc_dmaaddr=NULL\n",sc->sc_dev.dv_xname); 852 } 853 if (esc->sc_dmalen) { 854 p += sprintf(p,"%s: sc_dmalen=0x%08x\n",sc->sc_dev.dv_xname,*esc->sc_dmalen); 855 } else { 856 p += sprintf(p,"%s: sc_dmalen=NULL\n",sc->sc_dev.dv_xname); 857 } 858 p += sprintf(p,"%s: sc_dmasize=0x%08x\n",sc->sc_dev.dv_xname,esc->sc_dmasize); 859 860 p += sprintf(p,"%s: sc_begin = %p, sc_begin_size = 0x%08x\n", 861 sc->sc_dev.dv_xname, esc->sc_begin, esc->sc_begin_size); 862 p += sprintf(p,"%s: sc_main = %p, sc_main_size = 0x%08x\n", 863 sc->sc_dev.dv_xname, esc->sc_main, esc->sc_main_size); 864 { 865 int i; 866 bus_dmamap_t map = esc->sc_main_dmamap; 867 p += sprintf(p,"%s: sc_main_dmamap. mapsize = 0x%08lx, nsegs = %d\n", 868 sc->sc_dev.dv_xname, map->dm_mapsize, map->dm_nsegs); 869 for(i=0;i<map->dm_nsegs;i++) { 870 p += sprintf(p,"%s: map->dm_segs[%d].ds_addr = 0x%08lx, len = 0x%08lx\n", 871 sc->sc_dev.dv_xname, i, map->dm_segs[i].ds_addr, map->dm_segs[i].ds_len); 872 } 873 } 874 p += sprintf(p,"%s: sc_tail = %p, sc_tail_size = 0x%08x\n", 875 sc->sc_dev.dv_xname, esc->sc_tail, esc->sc_tail_size); 876 { 877 int i; 878 bus_dmamap_t map = esc->sc_tail_dmamap; 879 p += sprintf(p,"%s: sc_tail_dmamap. mapsize = 0x%08lx, nsegs = %d\n", 880 sc->sc_dev.dv_xname, map->dm_mapsize, map->dm_nsegs); 881 for(i=0;i<map->dm_nsegs;i++) { 882 p += sprintf(p,"%s: map->dm_segs[%d].ds_addr = 0x%08lx, len = 0x%08lx\n", 883 sc->sc_dev.dv_xname, i, map->dm_segs[i].ds_addr, map->dm_segs[i].ds_len); 884 } 885 } 886 } 887 888 void 889 esp_dma_print(sc) 890 struct ncr53c9x_softc *sc; 891 { 892 esp_dma_store(sc); 893 printf("%s",esp_dma_dump); 894 } 895 #endif 896 897 void 898 esp_dma_go(sc) 899 struct ncr53c9x_softc *sc; 900 { 901 struct esp_softc *esc = (struct esp_softc *)sc; 902 903 DPRINTF(("%s: esp_dma_go(datain = %d)\n", 904 sc->sc_dev.dv_xname, esc->sc_datain)); 905 906 #ifdef ESP_DEBUG 907 if (esp_debug) esp_dma_print(sc); 908 else esp_dma_store(sc); 909 #endif 910 911 #ifdef ESP_DEBUG 912 { 913 int n = NCR_READ_REG(sc, NCR_FFLAG); 914 DPRINTF(("%s: fifo size = %d, seq = 0x%x\n", 915 sc->sc_dev.dv_xname, 916 n & NCRFIFO_FF, (n & NCRFIFO_SS)>>5)); 917 } 918 #endif 919 920 /* zero length dma transfers are boring */ 921 if (esc->sc_dmasize == 0) { 922 return; 923 } 924 925 #if defined(DIAGNOSTIC) 926 if ((esc->sc_begin_size == 0) && 927 (esc->sc_main_dmamap->dm_mapsize == 0) && 928 (esc->sc_tail_dmamap->dm_mapsize == 0)) { 929 esp_dma_print(sc); 930 panic("%s: No DMA requested!",sc->sc_dev.dv_xname); 931 } 932 #endif 933 934 /* Stuff the fifo with the begin buffer */ 935 if (esc->sc_datain) { 936 int i; 937 DPRINTF(("%s: FIFO read of %d bytes:", 938 sc->sc_dev.dv_xname,esc->sc_begin_size)); 939 for(i=0;i<esc->sc_begin_size;i++) { 940 esc->sc_begin[i]=NCR_READ_REG(sc, NCR_FIFO); 941 DPRINTF((" %02x",esc->sc_begin[i]&0xff)); 942 } 943 DPRINTF(("\n")); 944 } else { 945 int i; 946 DPRINTF(("%s: FIFO write of %d bytes:", 947 sc->sc_dev.dv_xname,esc->sc_begin_size)); 948 for(i=0;i<esc->sc_begin_size;i++) { 949 NCR_WRITE_REG(sc, NCR_FIFO, esc->sc_begin[i]); 950 DPRINTF((" %02x",esc->sc_begin[i]&0xff)); 951 } 952 DPRINTF(("\n")); 953 } 954 955 /* if we are a dma write cycle, copy the end slop */ 956 if (esc->sc_datain == 0) { 957 memcpy(esc->sc_tail, 958 (*esc->sc_dmaaddr+esc->sc_begin_size+esc->sc_main_size), 959 (esc->sc_dmasize-(esc->sc_begin_size+esc->sc_main_size))); 960 } 961 962 if (esc->sc_main_dmamap->dm_mapsize) { 963 bus_dmamap_sync(esc->sc_scsi_dma.nd_dmat, esc->sc_main_dmamap, 964 0, esc->sc_main_dmamap->dm_mapsize, 965 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)); 966 esc->sc_main_dmamap->dm_xfer_len = 0; 967 } 968 969 if (esc->sc_tail_dmamap->dm_mapsize) { 970 bus_dmamap_sync(esc->sc_scsi_dma.nd_dmat, esc->sc_tail_dmamap, 971 0, esc->sc_tail_dmamap->dm_mapsize, 972 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)); 973 esc->sc_tail_dmamap->dm_xfer_len = 0; 974 } 975 976 nextdma_start(&esc->sc_scsi_dma, 977 (esc->sc_datain ? DMACSR_SETREAD : DMACSR_SETWRITE)); 978 979 if (esc->sc_datain) { 980 NCR_WRITE_REG(sc, ESP_DCTL, 981 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_DMAMOD | ESPDCTL_DMARD); 982 } else { 983 NCR_WRITE_REG(sc, ESP_DCTL, 984 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_DMAMOD); 985 } 986 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL))); 987 } 988 989 void 990 esp_dma_stop(sc) 991 struct ncr53c9x_softc *sc; 992 { 993 struct esp_softc *esc = (struct esp_softc *)sc; 994 next_dma_print(&esc->sc_scsi_dma); 995 esp_dma_print(sc); 996 panic("%s: stop not yet implemented\n",sc->sc_dev.dv_xname); 997 } 998 999 int 1000 esp_dma_isactive(sc) 1001 struct ncr53c9x_softc *sc; 1002 { 1003 struct esp_softc *esc = (struct esp_softc *)sc; 1004 int r = !nextdma_finished(&esc->sc_scsi_dma); 1005 DPRINTF(("esp_dma_isactive = %d\n",r)); 1006 return(r); 1007 } 1008 1009 /****************************************************************/ 1010 1011 /* Internal dma callback routines */ 1012 bus_dmamap_t 1013 esp_dmacb_continue(arg) 1014 void *arg; 1015 { 1016 struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg; 1017 struct esp_softc *esc = (struct esp_softc *)sc; 1018 1019 DPRINTF(("%s: dma continue\n",sc->sc_dev.dv_xname)); 1020 1021 #ifdef DIAGNOSTIC 1022 if ((esc->sc_datain < 0) || (esc->sc_datain > 1)) { 1023 panic("%s: map not loaded in dma continue callback, datain = %d", 1024 sc->sc_dev.dv_xname,esc->sc_datain); 1025 } 1026 #endif 1027 1028 if ((!(esc->sc_loaded & ESP_LOADED_MAIN)) && 1029 (esc->sc_main_dmamap->dm_mapsize)) { 1030 DPRINTF(("%s: Loading main map\n",sc->sc_dev.dv_xname)); 1031 #if 0 1032 bus_dmamap_sync(esc->sc_scsi_dma.nd_dmat, esc->sc_main_dmamap, 1033 0, esc->sc_main_dmamap->dm_mapsize, 1034 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)); 1035 esc->sc_main_dmamap->dm_xfer_len = 0; 1036 #endif 1037 esc->sc_loaded |= ESP_LOADED_MAIN; 1038 return(esc->sc_main_dmamap); 1039 } 1040 1041 if ((!(esc->sc_loaded & ESP_LOADED_TAIL)) && 1042 (esc->sc_tail_dmamap->dm_mapsize)) { 1043 DPRINTF(("%s: Loading tail map\n",sc->sc_dev.dv_xname)); 1044 #if 0 1045 bus_dmamap_sync(esc->sc_scsi_dma.nd_dmat, esc->sc_tail_dmamap, 1046 0, esc->sc_tail_dmamap->dm_mapsize, 1047 (esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)); 1048 esc->sc_tail_dmamap->dm_xfer_len = 0; 1049 #endif 1050 esc->sc_loaded |= ESP_LOADED_TAIL; 1051 return(esc->sc_tail_dmamap); 1052 } 1053 1054 DPRINTF(("%s: not loading map\n",sc->sc_dev.dv_xname)); 1055 return(0); 1056 } 1057 1058 1059 void 1060 esp_dmacb_completed(map, arg) 1061 bus_dmamap_t map; 1062 void *arg; 1063 { 1064 struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg; 1065 struct esp_softc *esc = (struct esp_softc *)sc; 1066 1067 DPRINTF(("%s: dma completed\n",sc->sc_dev.dv_xname)); 1068 1069 #ifdef DIAGNOSTIC 1070 if ((esc->sc_datain < 0) || (esc->sc_datain > 1)) { 1071 panic("%s: invalid dma direction in completed callback, datain = %d", 1072 sc->sc_dev.dv_xname,esc->sc_datain); 1073 } 1074 #endif 1075 1076 #if defined(DIAGNOSTIC) && 0 1077 { 1078 int i; 1079 for(i=0;i<map->dm_nsegs;i++) { 1080 if (map->dm_xfer_len != map->dm_mapsize) { 1081 printf("%s: map->dm_mapsize = %d\n", sc->sc_dev.dv_xname,map->dm_mapsize); 1082 printf("%s: map->dm_nsegs = %d\n", sc->sc_dev.dv_xname,map->dm_nsegs); 1083 printf("%s: map->dm_xfer_len = %d\n", sc->sc_dev.dv_xname,map->dm_xfer_len); 1084 for(i=0;i<map->dm_nsegs;i++) { 1085 printf("%s: map->dm_segs[%d].ds_addr = 0x%08lx\n", 1086 sc->sc_dev.dv_xname,i,map->dm_segs[i].ds_addr); 1087 printf("%s: map->dm_segs[%d].ds_len = %d\n", 1088 sc->sc_dev.dv_xname,i,map->dm_segs[i].ds_len); 1089 } 1090 panic("%s: incomplete dma transfer\n",sc->sc_dev.dv_xname); 1091 } 1092 } 1093 } 1094 #endif 1095 1096 if (map == esc->sc_main_dmamap) { 1097 #ifdef DIAGNOSTIC 1098 if ((esc->sc_loaded & ESP_UNLOADED_MAIN) || 1099 !(esc->sc_loaded & ESP_LOADED_MAIN)) { 1100 panic("%s: unexpected completed call for main map\n",sc->sc_dev.dv_xname); 1101 } 1102 #endif 1103 esc->sc_loaded |= ESP_UNLOADED_MAIN; 1104 } else if (map == esc->sc_tail_dmamap) { 1105 #ifdef DIAGNOSTIC 1106 if ((esc->sc_loaded & ESP_UNLOADED_TAIL) || 1107 !(esc->sc_loaded & ESP_LOADED_TAIL)) { 1108 panic("%s: unexpected completed call for tail map\n",sc->sc_dev.dv_xname); 1109 } 1110 #endif 1111 esc->sc_loaded |= ESP_UNLOADED_TAIL; 1112 } 1113 #ifdef DIAGNOSTIC 1114 else { 1115 panic("%s: unexpected completed map", sc->sc_dev.dv_xname); 1116 } 1117 #endif 1118 1119 #ifdef ESP_DEBUG 1120 if (esp_debug) { 1121 if (map == esc->sc_main_dmamap) { 1122 printf("%s: completed main map\n",sc->sc_dev.dv_xname); 1123 } else if (map == esc->sc_tail_dmamap) { 1124 printf("%s: completed tail map\n",sc->sc_dev.dv_xname); 1125 } 1126 } 1127 #endif 1128 1129 #if 0 1130 if ((map == esc->sc_tail_dmamap) || 1131 ((esc->sc_tail_size == 0) && (map == esc->sc_main_dmamap))) { 1132 1133 /* Clear the DMAMOD bit in the DCTL register to give control 1134 * back to the scsi chip. 1135 */ 1136 if (esc->sc_datain) { 1137 NCR_WRITE_REG(sc, ESP_DCTL, 1138 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_DMARD); 1139 } else { 1140 NCR_WRITE_REG(sc, ESP_DCTL, 1141 ESPDCTL_20MHZ | ESPDCTL_INTENB); 1142 } 1143 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL))); 1144 } 1145 #endif 1146 1147 1148 #if 0 1149 bus_dmamap_sync(esc->sc_scsi_dma.nd_dmat, map, 1150 0, map->dm_mapsize, 1151 (esc->sc_datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE)); 1152 #endif 1153 1154 } 1155 1156 void 1157 esp_dmacb_shutdown(arg) 1158 void *arg; 1159 { 1160 struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg; 1161 struct esp_softc *esc = (struct esp_softc *)sc; 1162 bus_size_t xfer_len = 0; 1163 1164 DPRINTF(("%s: dma shutdown\n",sc->sc_dev.dv_xname)); 1165 1166 #if 0 1167 { 1168 /* Clear the DMAMOD bit in the DCTL register to give control 1169 * back to the scsi chip. 1170 */ 1171 if (esc->sc_datain) { 1172 NCR_WRITE_REG(sc, ESP_DCTL, 1173 ESPDCTL_20MHZ | ESPDCTL_INTENB | ESPDCTL_DMARD); 1174 } else { 1175 NCR_WRITE_REG(sc, ESP_DCTL, 1176 ESPDCTL_20MHZ | ESPDCTL_INTENB); 1177 } 1178 DPRINTF(("esp dctl is 0x%02x\n",NCR_READ_REG(sc,ESP_DCTL))); 1179 } 1180 #endif 1181 1182 DPRINTF(("%s: esp_dma_nest == %d\n",sc->sc_dev.dv_xname,esp_dma_nest)); 1183 1184 /* Stuff the end slop into fifo */ 1185 1186 #ifdef ESP_DEBUG 1187 if (esp_debug) { 1188 1189 int n = NCR_READ_REG(sc, NCR_FFLAG); 1190 DPRINTF(("%s: fifo size = %d, seq = 0x%x\n", 1191 sc->sc_dev.dv_xname,n & NCRFIFO_FF, (n & NCRFIFO_SS)>>5)); 1192 } 1193 #endif 1194 1195 xfer_len += esc->sc_begin_size; 1196 1197 if (esc->sc_main_dmamap->dm_mapsize) { 1198 xfer_len += esc->sc_main_dmamap->dm_xfer_len; 1199 bus_dmamap_sync(esc->sc_scsi_dma.nd_dmat, esc->sc_main_dmamap, 1200 0, esc->sc_main_dmamap->dm_mapsize, 1201 (esc->sc_datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE)); 1202 bus_dmamap_unload(esc->sc_scsi_dma.nd_dmat, esc->sc_main_dmamap); 1203 } 1204 1205 if (esc->sc_tail_dmamap->dm_mapsize) { 1206 xfer_len += esc->sc_tail_dmamap->dm_xfer_len; 1207 bus_dmamap_sync(esc->sc_scsi_dma.nd_dmat, esc->sc_tail_dmamap, 1208 0, esc->sc_tail_dmamap->dm_mapsize, 1209 (esc->sc_datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE)); 1210 bus_dmamap_unload(esc->sc_scsi_dma.nd_dmat, esc->sc_tail_dmamap); 1211 } 1212 1213 /* truncate in case tail overran */ 1214 if (xfer_len > esc->sc_dmasize) { 1215 xfer_len = esc->sc_dmasize; 1216 } 1217 1218 /* copy the tail dma buffer data for read transfers */ 1219 if (esc->sc_datain == 1) { 1220 memcpy((*esc->sc_dmaaddr+esc->sc_begin_size+esc->sc_main_size), 1221 esc->sc_tail, 1222 (esc->sc_dmasize-(esc->sc_begin_size+esc->sc_main_size))); 1223 } 1224 1225 #ifdef ESP_DEBUG 1226 if (esp_debug) { 1227 printf("%s: dma_shutdown: addr=%p,len=0x%08x,size=0x%08x\n", 1228 sc->sc_dev.dv_xname, 1229 *esc->sc_dmaaddr, *esc->sc_dmalen, esc->sc_dmasize); 1230 if (esp_debug > 10) { 1231 esp_hex_dump(*(esc->sc_dmaaddr),esc->sc_dmasize); 1232 printf("%s: tail=%p,tailbuf=%p,tail_size=0x%08x\n", 1233 sc->sc_dev.dv_xname, 1234 esc->sc_tail, &(esc->sc_tailbuf[0]), esc->sc_tail_size); 1235 esp_hex_dump(&(esc->sc_tailbuf[0]),sizeof(esc->sc_tailbuf)); 1236 } 1237 } 1238 #endif 1239 1240 #if 0 1241 KASSERT(xfer_len == esc->sc_dmasize); 1242 #endif 1243 1244 *(esc->sc_dmaaddr) += xfer_len; 1245 *(esc->sc_dmalen) -= xfer_len; 1246 1247 esc->sc_main = 0; 1248 esc->sc_main_size = 0; 1249 esc->sc_tail = 0; 1250 esc->sc_tail_size = 0; 1251 1252 esc->sc_datain = -1; 1253 esc->sc_dmaaddr = 0; 1254 esc->sc_dmalen = 0; 1255 esc->sc_dmasize = 0; 1256 1257 esc->sc_loaded = 0; 1258 1259 esc->sc_begin = 0; 1260 esc->sc_begin_size = 0; 1261 1262 #ifdef ESP_DEBUG 1263 if (esp_debug) { 1264 char sbuf[256]; 1265 1266 bitmask_snprintf((*(volatile u_long *)IIOV(NEXT_P_INTRSTAT)), 1267 NEXT_INTR_BITS, sbuf, sizeof(sbuf)); 1268 printf(" *intrstat = 0x%s\n", sbuf); 1269 1270 bitmask_snprintf((*(volatile u_long *)IIOV(NEXT_P_INTRMASK)), 1271 NEXT_INTR_BITS, sbuf, sizeof(sbuf)); 1272 printf(" *intrmask = 0x%s\n", sbuf); 1273 } 1274 #endif 1275 } 1276