1/* $NetBSD: esp.c,v 1.64 2022/08/15 12:16:25 rin Exp $ */ 2 3/* 4 * Copyright (c) 1997 Jason R. Thorpe. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed for the NetBSD Project 18 * by Jason R. Thorpe. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34/* 35 * Copyright (c) 1994 Peter Galbavy 36 * All rights reserved. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 3. All advertising materials mentioning features or use of this software 47 * must display the following acknowledgement: 48 * This product includes software developed by Peter Galbavy 49 * 4. The name of the author may not be used to endorse or promote products 50 * derived from this software without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 53 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 54 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 55 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 56 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 57 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 58 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 60 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 61 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 62 * POSSIBILITY OF SUCH DAMAGE. 63 */ 64 65/* 66 * Based on aic6360 by Jarle Greipsland 67 * 68 * Acknowledgements: Many of the algorithms used in this driver are 69 * inspired by the work of Julian Elischer (julian@tfs.com) and 70 * Charles Hannum (mycroft@duality.gnu.ai.mit.edu). Thanks a million! 71 */ 72 73/* 74 * Initial m68k mac support from Allen Briggs <briggs@macbsd.com> 75 * (basically consisting of the match, a bit of the attach, and the 76 * "DMA" glue functions). 77 */ 78 79/* 80 * AV DMA support from Michael Zucca (mrz5149@acm.org) 81 */ 82 83#include <sys/cdefs.h> 84__KERNEL_RCSID(0, "$NetBSD: esp.c,v 1.64 2022/08/15 12:16:25 rin Exp $"); 85 86#include <sys/types.h> 87#include <sys/param.h> 88#include <sys/buf.h> 89#include <sys/bus.h> 90#include <sys/device.h> 91 92#include <uvm/uvm_extern.h> 93 94#include <dev/scsipi/scsiconf.h> 95 96#include <dev/ic/ncr53c9xreg.h> 97#include <dev/ic/ncr53c9xvar.h> 98 99#include <machine/cpu.h> 100#include <machine/psc.h> 101#include <machine/viareg.h> 102 103#include <mac68k/obio/espvar.h> 104#include <mac68k/obio/obiovar.h> 105 106static int espmatch(device_t, cfdata_t, void *); 107static void espattach(device_t, device_t, void *); 108 109/* Linkup to the rest of the kernel */ 110CFATTACH_DECL_NEW(esp, sizeof(struct esp_softc), 111 espmatch, espattach, NULL, NULL); 112 113/* 114 * Functions and the switch for the MI code. 115 */ 116static uint8_t esp_read_reg(struct ncr53c9x_softc *, int); 117static void esp_write_reg(struct ncr53c9x_softc *, int, uint8_t); 118static int esp_dma_isintr(struct ncr53c9x_softc *); 119static void esp_dma_reset(struct ncr53c9x_softc *); 120static int esp_dma_intr(struct ncr53c9x_softc *); 121static int esp_dma_setup(struct ncr53c9x_softc *, uint8_t **, size_t *, 122 int, size_t *); 123static void esp_dma_go(struct ncr53c9x_softc *); 124static void esp_dma_stop(struct ncr53c9x_softc *); 125static int esp_dma_isactive(struct ncr53c9x_softc *); 126static void esp_dma_write_reg(struct ncr53c9x_softc *, int, uint8_t); 127static int esp_quick_dma_intr(struct ncr53c9x_softc *); 128static int esp_quick_dma_setup(struct ncr53c9x_softc *, uint8_t **, 129 size_t *, int, size_t *); 130static void esp_quick_dma_go(struct ncr53c9x_softc *); 131 132static void esp_av_dma_reset(struct ncr53c9x_softc *); 133static int esp_av_dma_intr(struct ncr53c9x_softc *); 134static int esp_av_dma_setup(struct ncr53c9x_softc *, uint8_t **, size_t *, 135 int, size_t *); 136static void esp_av_dma_go(struct ncr53c9x_softc *); 137static void esp_av_dma_stop(struct ncr53c9x_softc *); 138 139static void esp_intr(void *); 140static void esp_dualbus_intr(void *); 141 142static int esp_dafb_have_dreq(struct esp_softc *); 143static int esp_iosb_have_dreq(struct esp_softc *); 144int (*esp_have_dreq)(struct esp_softc *); 145 146static struct esp_softc *esp0, *esp1; 147 148static struct ncr53c9x_glue esp_glue = { 149 .gl_read_reg = esp_read_reg, 150 .gl_write_reg = esp_write_reg, 151 .gl_dma_isintr = esp_dma_isintr, 152 .gl_dma_reset = esp_dma_reset, 153 .gl_dma_intr = esp_dma_intr, 154 .gl_dma_setup = esp_dma_setup, 155 .gl_dma_go = esp_dma_go, 156 .gl_dma_stop = esp_dma_stop, 157 .gl_dma_isactive = esp_dma_isactive, 158 .gl_clear_latched_intr = NULL, 159}; 160 161static int 162espmatch(device_t parent, cfdata_t cf, void *aux) 163{ 164 struct obio_attach_args *oa = aux; 165 166 if (oa->oa_addr == 0 && mac68k_machine.scsi96) 167 return 1; 168 if (oa->oa_addr == 1 && mac68k_machine.scsi96_2) 169 return 1; 170 return 0; 171} 172 173/* 174 * Attach this instance, and then all the sub-devices 175 */ 176static void 177espattach(device_t parent, device_t self, void *aux) 178{ 179 struct esp_softc *esc = device_private(self); 180 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x; 181 struct obio_attach_args *oa = aux; 182 bus_addr_t addr; 183 unsigned long reg_offset; 184 int quick = 0, avdma = 0; 185 uint8_t irq_mask; /* mask for clearing IRQ */ 186 extern vaddr_t SCSIBase; 187 188 sc->sc_dev = self; 189 190 reg_offset = SCSIBase - IOBase; 191 192 /* 193 * For Wombat, Primus and Optimus motherboards, DREQ is 194 * visible on bit 0 of the IOSB's emulated VIA2 vIFR (and 195 * the scsi registers are offset 0x1000 bytes from IOBase). 196 * 197 * For the Q700/900/950 it's at f9800024 for bus 0 and 198 * f9800028 for bus 1 (900/950). For these machines, that is also 199 * a (12-bit) configuration register for DAFB's control of the 200 * pseudo-DMA timing. The default value is 0x1d1. 201 */ 202 if (oa->oa_addr == 0) { 203 switch (reg_offset) { 204 case 0x10000: 205 quick = 1; 206 esp_have_dreq = esp_iosb_have_dreq; 207 break; 208 case 0x18000: 209 avdma = 1; 210 break; 211 default: 212 addr = 0xf9800024; 213 goto dafb_dreq; 214 } 215 } else { 216 bus_space_tag_t bst; 217 bus_space_handle_t bsh; 218 219 addr = 0xf9800028; 220 221dafb_dreq: bst = oa->oa_tag; 222 if (bus_space_map(bst, addr, 4, 0, &bsh)) 223 aprint_error(": failed to map 4 at 0x%lx.\n", addr); 224 else { 225 quick = 1; 226 esp_have_dreq = esp_dafb_have_dreq; 227 esc->sc_dreqreg = (volatile uint32_t *) 228 bus_space_vaddr(bst, bsh); 229 *esc->sc_dreqreg = 0x1d1; 230 } 231 } 232 233 if (quick) { 234 esp_glue.gl_write_reg = esp_dma_write_reg; 235 esp_glue.gl_dma_intr = esp_quick_dma_intr; 236 esp_glue.gl_dma_setup = esp_quick_dma_setup; 237 esp_glue.gl_dma_go = esp_quick_dma_go; 238 } else if (avdma) { 239 esp_glue.gl_write_reg = esp_dma_write_reg; 240 esp_glue.gl_dma_reset = esp_av_dma_reset; 241 esp_glue.gl_dma_intr = esp_av_dma_intr; 242 esp_glue.gl_dma_setup = esp_av_dma_setup; 243 esp_glue.gl_dma_go = esp_av_dma_go; 244 esp_glue.gl_dma_stop = esp_av_dma_stop; 245 } 246 247 /* 248 * Set up the glue for MI code early; we use some of it here. 249 */ 250 sc->sc_glue = &esp_glue; 251 252 /* 253 * Save the regs 254 */ 255 if (oa->oa_addr == 0) { 256 esp0 = esc; 257 258 esc->sc_reg = (volatile uint8_t *)SCSIBase; 259 via2_register_irq(VIA2_SCSIIRQ, esp_intr, esc); 260 irq_mask = V2IF_SCSIIRQ; 261 switch (reg_offset) { 262 case 0x10000: 263 /* From the Q650 developer's note */ 264 sc->sc_freq = 16500000; 265 break; 266 case 0x18000: 267 /* From Quadra 840AV Service Source */ 268 sc->sc_freq = 20000000; 269 break; 270 default: 271 sc->sc_freq = 25000000; 272 break; 273 } 274 } else { 275 esp1 = esc; 276 277 esc->sc_reg = (volatile uint8_t *)SCSIBase + 0x402; 278 via2_register_irq(VIA2_SCSIIRQ, esp_dualbus_intr, NULL); 279 irq_mask = 0; 280 sc->sc_freq = 25000000; 281 } 282 283 if (quick) 284 aprint_normal(" (quick)"); 285 else if (avdma) 286 aprint_normal(" (avdma)"); 287 288 aprint_normal(": address %p", esc->sc_reg); 289 290 sc->sc_id = 7; 291 292 /* gimme MHz */ 293 sc->sc_freq /= 1000000; 294 295 /* 296 * It is necessary to try to load the 2nd config register here, 297 * to find out what rev the esp chip is, else the esp_reset 298 * will not set up the defaults correctly. 299 */ 300 sc->sc_cfg1 = sc->sc_id; /* | NCRCFG1_PARENB; */ 301 sc->sc_cfg2 = NCRCFG2_SCSI2; 302 if (avdma) { 303 sc->sc_cfg3 = NCRCFG3_CDB; 304 sc->sc_rev = NCR_VARIANT_NCR53C94; 305 } else { 306 sc->sc_cfg3 = 0; 307 sc->sc_rev = NCR_VARIANT_NCR53C96; 308 } 309 310 /* 311 * This is the value used to start sync negotiations 312 * Note that the NCR register "SYNCTP" is programmed 313 * in "clocks per byte", and has a minimum value of 4. 314 * The SCSI period used in negotiation is one-fourth 315 * of the time (in nanoseconds) needed to transfer one byte. 316 * Since the chip's clock is given in MHz, we have the following 317 * formula: 4 * period = (1000 / freq) * 4 318 */ 319 sc->sc_minsync = 1000 / sc->sc_freq; 320 321 /* We need this to fit into the TCR... */ 322 sc->sc_maxxfer = 64 * 1024; 323 324 switch (current_mac_model->machineid) { 325 case MACH_MACQ630: 326 /* XXX on LC630 64k xfer causes timeout error */ 327 sc->sc_maxxfer = 63 * 1024; 328 break; 329 } 330 331 if (!quick && !avdma) { 332 /* 333 * No synchronous xfers w/o DMA. 334 */ 335 sc->sc_minsync = 0; 336 337 sc->sc_maxxfer = 8 * 1024; 338 } 339 340 /* 341 * Configure interrupts. 342 */ 343 if (irq_mask) { 344 via2_reg(vPCR) = 0x22; 345 via2_reg(vIFR) = irq_mask; 346 via2_reg(vIER) = 0x80 | irq_mask; 347 } 348 349 /* 350 * Setup for AV DMA 351 */ 352 if (avdma) { 353 bus_dma_segment_t osegs, isegs; 354 int orsegs, irsegs; 355 356 esc->sc_rset = 0; 357 esc->sc_dmat = oa->oa_dmat; 358 359 if (bus_dmamap_create(esc->sc_dmat, sc->sc_maxxfer, 1, 360 sc->sc_maxxfer, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, 361 &esc->sc_dmap)) { 362 printf("failed to create DMA map.\n"); 363 return; 364 } 365 366 /* 367 * Allocate ``bounce'' buffers which satisfy constraints 368 * required by PSC, see esp_av_dma_setup(). 369 */ 370 if (bus_dmamem_alloc(esc->sc_dmat, NBPG, 16, NBPG, 371 &osegs, 1, &orsegs, BUS_DMA_NOWAIT)) { 372 printf("failed to allocate o-bounce buffer.\n"); 373 goto out1; 374 } 375 if (bus_dmamem_map(esc->sc_dmat, &osegs, orsegs, 376 NBPG, (void **)&esc->sc_obuf, 377 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) { 378 printf("failed to map o-bounce buffer.\n"); 379 goto out2; 380 } 381 if (bus_dmamem_alloc(esc->sc_dmat, NBPG, 16, NBPG, 382 &isegs, 1, &irsegs, BUS_DMA_NOWAIT)) { 383 printf("failed to allocate i-bounce buffer.\n"); 384 goto out3; 385 } 386 if (bus_dmamem_map(esc->sc_dmat, &isegs, irsegs, 387 NBPG, (void **)&esc->sc_ibuf, 388 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) { 389 printf("failed to map i-bounce buffer.\n"); 390 391 bus_dmamem_free(esc->sc_dmat, &isegs, irsegs); 392 out3: bus_dmamem_unmap(esc->sc_dmat, sc->sc_omess, 393 sc->sc_maxxfer); 394 out2: bus_dmamem_free(esc->sc_dmat, &osegs, orsegs); 395 out1: bus_dmamap_destroy(esc->sc_dmat, esc->sc_dmap); 396 return; 397 } 398 } 399 400#if 0 401 /* 402 * This degrades performance; FIFO is better than bounce DMA for 403 * short SCSI commands and their responses. 404 */ 405 if (avdma) { 406 /* Turn on target selection using the `DMA' method */ 407 sc->sc_features |= NCR_F_DMASELECT; 408 } 409#endif 410 411 /* 412 * Now try to attach all the sub-devices 413 */ 414 sc->sc_adapter.adapt_minphys = minphys; 415 sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request; 416 ncr53c9x_attach(sc); 417} 418 419/* 420 * Glue functions. 421 */ 422 423static uint8_t 424esp_read_reg(struct ncr53c9x_softc *sc, int reg) 425{ 426 struct esp_softc *esc = (struct esp_softc *)sc; 427 428 return esc->sc_reg[reg * 16]; 429} 430 431static void 432esp_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t val) 433{ 434 struct esp_softc *esc = (struct esp_softc *)sc; 435 uint8_t v = val; 436 437 if (reg == NCR_CMD && v == (NCRCMD_TRANS|NCRCMD_DMA)) { 438 v = NCRCMD_TRANS; 439 } 440 esc->sc_reg[reg * 16] = v; 441} 442 443static void 444esp_dma_stop(struct ncr53c9x_softc *sc) 445{ 446} 447 448static int 449esp_dma_isactive(struct ncr53c9x_softc *sc) 450{ 451 struct esp_softc *esc = (struct esp_softc *)sc; 452 453 return esc->sc_active; 454} 455 456static int 457esp_dma_isintr(struct ncr53c9x_softc *sc) 458{ 459 struct esp_softc *esc = (struct esp_softc *)sc; 460 461 return esc->sc_reg[NCR_STAT * 16] & NCRSTAT_INT; 462} 463 464static void 465esp_dma_reset(struct ncr53c9x_softc *sc) 466{ 467 struct esp_softc *esc = (struct esp_softc *)sc; 468 469 esc->sc_active = 0; 470 esc->sc_tc = 0; 471} 472 473static int 474esp_dma_intr(struct ncr53c9x_softc *sc) 475{ 476 struct esp_softc *esc = (struct esp_softc *)sc; 477 volatile uint8_t *cmdreg, *intrreg, *statreg, *fiforeg; 478 uint8_t *p; 479 u_int espphase, espstat, espintr; 480 int cnt, s; 481 482 if (esc->sc_active == 0) { 483 printf("dma_intr--inactive DMA\n"); 484 return -1; 485 } 486 487 if ((sc->sc_espintr & NCRINTR_BS) == 0) { 488 esc->sc_active = 0; 489 return 0; 490 } 491 492 cnt = *esc->sc_dmalen; 493 if (*esc->sc_dmalen == 0) { 494 printf("data interrupt, but no count left.\n"); 495 } 496 497 p = *esc->sc_dmaaddr; 498 espphase = sc->sc_phase; 499 espstat = (u_int)sc->sc_espstat; 500 espintr = (u_int)sc->sc_espintr; 501 cmdreg = esc->sc_reg + NCR_CMD * 16; 502 fiforeg = esc->sc_reg + NCR_FIFO * 16; 503 statreg = esc->sc_reg + NCR_STAT * 16; 504 intrreg = esc->sc_reg + NCR_INTR * 16; 505 do { 506 if (esc->sc_datain) { 507 *p++ = *fiforeg; 508 cnt--; 509 if (espphase == DATA_IN_PHASE) { 510 *cmdreg = NCRCMD_TRANS; 511 } else { 512 esc->sc_active = 0; 513 } 514 } else { 515 if ( (espphase == DATA_OUT_PHASE) 516 || (espphase == MESSAGE_OUT_PHASE)) { 517 *fiforeg = *p++; 518 cnt--; 519 *cmdreg = NCRCMD_TRANS; 520 } else { 521 esc->sc_active = 0; 522 } 523 } 524 525 if (esc->sc_active) { 526 while (!(*statreg & 0x80)); 527 s = splhigh(); 528 espstat = *statreg; 529 espintr = *intrreg; 530 espphase = (espintr & NCRINTR_DIS) 531 ? /* Disconnected */ BUSFREE_PHASE 532 : espstat & PHASE_MASK; 533 splx(s); 534 } 535 } while (esc->sc_active && (espintr & NCRINTR_BS)); 536 sc->sc_phase = espphase; 537 sc->sc_espstat = (uint8_t)espstat; 538 sc->sc_espintr = (uint8_t)espintr; 539 *esc->sc_dmaaddr = p; 540 *esc->sc_dmalen = cnt; 541 542 if (*esc->sc_dmalen == 0) { 543 esc->sc_tc = NCRSTAT_TC; 544 } 545 sc->sc_espstat |= esc->sc_tc; 546 return 0; 547} 548 549static int 550esp_dma_setup(struct ncr53c9x_softc *sc, uint8_t **addr, size_t *len, 551 int datain, size_t *dmasize) 552{ 553 struct esp_softc *esc = (struct esp_softc *)sc; 554 555 esc->sc_dmaaddr = addr; 556 esc->sc_dmalen = len; 557 esc->sc_datain = datain; 558 esc->sc_dmasize = *dmasize; 559 esc->sc_tc = 0; 560 561 return 0; 562} 563 564static void 565esp_dma_go(struct ncr53c9x_softc *sc) 566{ 567 struct esp_softc *esc = (struct esp_softc *)sc; 568 569 if (esc->sc_datain == 0) { 570 esc->sc_reg[NCR_FIFO * 16] = **esc->sc_dmaaddr; 571 (*esc->sc_dmalen)--; 572 (*esc->sc_dmaaddr)++; 573 } 574 esc->sc_active = 1; 575} 576 577static void 578esp_dma_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t val) 579{ 580 struct esp_softc *esc = (struct esp_softc *)sc; 581 582 esc->sc_reg[reg * 16] = val; 583} 584 585#if DEBUG 586int mac68k_esp_debug=0; 587#endif 588 589static int 590esp_quick_dma_intr(struct ncr53c9x_softc *sc) 591{ 592 struct esp_softc *esc = (struct esp_softc *)sc; 593 int trans=0, resid=0; 594 595 if (esc->sc_active == 0) 596 panic("dma_intr--inactive DMA"); 597 598 esc->sc_active = 0; 599 600 if (esc->sc_dmasize == 0) { 601 int res; 602 603 res = NCR_READ_REG(sc, NCR_TCL); 604 res += NCR_READ_REG(sc, NCR_TCM) << 8; 605 /* This can happen in the case of a TRPAD operation */ 606 /* Pretend that it was complete */ 607 sc->sc_espstat |= NCRSTAT_TC; 608#if DEBUG 609 if (mac68k_esp_debug) { 610 printf("dmaintr: DMA xfer of zero xferred %d\n", 611 65536 - res); 612 } 613#endif 614 return 0; 615 } 616 617 if ((sc->sc_espstat & NCRSTAT_TC) == 0) { 618 if (esc->sc_datain == 0) { 619 resid = NCR_READ_REG(sc, NCR_FFLAG) & 0x1f; 620#if DEBUG 621 if (mac68k_esp_debug) { 622 printf("Write FIFO residual %d bytes\n", resid); 623 } 624#endif 625 } 626 resid += NCR_READ_REG(sc, NCR_TCL); 627 resid += NCR_READ_REG(sc, NCR_TCM) << 8; 628 if (resid == 0) 629 resid = 65536; 630 } 631 632 trans = esc->sc_dmasize - resid; 633 if (trans < 0) { 634 printf("dmaintr: trans < 0????\n"); 635 trans = *esc->sc_dmalen; 636 } 637 638 NCR_DMA(("dmaintr: trans %d, resid %d.\n", trans, resid)); 639#if DEBUG 640 if (mac68k_esp_debug) { 641 printf("eqd_intr: trans %d, resid %d.\n", trans, resid); 642 } 643#endif 644 *esc->sc_dmaaddr += trans; 645 *esc->sc_dmalen -= trans; 646 647 return 0; 648} 649 650static int 651esp_quick_dma_setup(struct ncr53c9x_softc *sc, uint8_t **addr, size_t *len, 652 int datain, size_t *dmasize) 653{ 654 struct esp_softc *esc = (struct esp_softc *)sc; 655 656 esc->sc_dmaaddr = addr; 657 esc->sc_dmalen = len; 658 659 if (*len & 1) { 660 esc->sc_pad = 1; 661 } else { 662 esc->sc_pad = 0; 663 } 664 665 esc->sc_datain = datain; 666 esc->sc_dmasize = *dmasize; 667 668#if DIAGNOSTIC 669 if (esc->sc_dmasize == 0) { 670 /* This can happen in the case of a TRPAD operation */ 671 } 672#endif 673#if DEBUG 674 if (mac68k_esp_debug) { 675 printf("eqd_setup: addr %lx, len %lx, in? %d, dmasize %lx\n", 676 (long) *addr, (long) *len, datain, (long) esc->sc_dmasize); 677 } 678#endif 679 680 return 0; 681} 682 683static int 684esp_dafb_have_dreq(struct esp_softc *esc) 685{ 686 687 return *esc->sc_dreqreg & 0x200; 688} 689 690static int 691esp_iosb_have_dreq(struct esp_softc *esc) 692{ 693 694 return via2_reg(vIFR) & V2IF_SCSIDRQ; 695} 696 697static volatile int espspl = -1; 698 699/* 700 * Apple "DMA" is weird. 701 * 702 * Basically, the CPU acts like the DMA controller. The DREQ/ off the 703 * chip goes to a register that we've mapped at attach time (on the 704 * IOSB or DAFB, depending on the machine). Apple also provides some 705 * space for which the memory controller handshakes data to/from the 706 * NCR chip with the DACK/ line. This space appears to be mapped over 707 * and over, every 4 bytes, but only the lower 16 bits are valid (but 708 * reading the upper 16 bits will handshake DACK/ just fine, so if you 709 * read *uint16_t++ = *uint16_t++ in a loop, you'll get 710 * <databyte><databyte>0xff0xff<databyte><databyte>0xff0xff... 711 * 712 * When you're attempting to read or write memory to this DACK/ed space, 713 * and the NCR is not ready for some timeout period, the system will 714 * generate a bus error. This might be for one of several reasons: 715 * 716 * 1) (on write) The FIFO is full and is not draining. 717 * 2) (on read) The FIFO is empty and is not filling. 718 * 3) An interrupt condition has occurred. 719 * 4) Anything else? 720 * 721 * So if a bus error occurs, we first turn off the nofault bus error handler, 722 * then we check for an interrupt (which would render the first two 723 * possibilities moot). If there's no interrupt, check for a DREQ/. If we 724 * have that, then attempt to resume stuffing (or unstuffing) the FIFO. If 725 * neither condition holds, pause briefly and check again. 726 * 727 * NOTE!!! In order to make allowances for the hardware structure of 728 * the mac, spl values in here are hardcoded!!!!!!!!! 729 * This is done to allow serial interrupts to get in during 730 * scsi transfers. This is ugly. 731 */ 732static void 733esp_quick_dma_go(struct ncr53c9x_softc *sc) 734{ 735 struct esp_softc *esc = (struct esp_softc *)sc; 736 extern long mac68k_a2_fromfault; 737 extern int *nofault; 738 label_t faultbuf; 739 uint16_t volatile *pdma; 740 uint16_t *addr; 741 int len, res; 742 uint16_t cnt32, cnt2; 743 volatile uint8_t *statreg; 744 745 esc->sc_active = 1; 746 747 espspl = splhigh(); 748 749 addr = (uint16_t *)*esc->sc_dmaaddr; 750 len = esc->sc_dmasize; 751 752restart_dmago: 753#if DEBUG 754 if (mac68k_esp_debug) { 755 printf("eqdg: a %lx, l %lx, in? %d ... ", 756 (long) addr, (long) len, esc->sc_datain); 757 } 758#endif 759 nofault = (int *)&faultbuf; 760 if (setjmp((label_t *)nofault)) { 761 int i = 0; 762 763 nofault = NULL; 764#if DEBUG 765 if (mac68k_esp_debug) { 766 printf("be\n"); 767 } 768#endif 769 /* 770 * Bus error... 771 * So, we first check for an interrupt. If we have 772 * one, go handle it. Next we check for DREQ/. If 773 * we have it, then we restart the transfer. If 774 * neither, then loop until we get one or the other. 775 */ 776 statreg = esc->sc_reg + NCR_STAT * 16; 777 for (;;) { 778 spl2(); /* Give serial a chance... */ 779 splhigh(); /* That's enough... */ 780 781 if (*statreg & 0x80) { 782 goto gotintr; 783 } 784 785 if (esp_have_dreq(esc)) { 786 /* 787 * Get the remaining length from the address 788 * differential. 789 */ 790 addr = (uint16_t *)mac68k_a2_fromfault; 791 len = esc->sc_dmasize - 792 ((long)addr - (long)*esc->sc_dmaaddr); 793 794 if (esc->sc_datain == 0) { 795 /* 796 * Let the FIFO drain before we read 797 * the transfer count. 798 * Do we need to do this? 799 * Can we do this? 800 */ 801 while (NCR_READ_REG(sc, NCR_FFLAG) 802 & 0x1f); 803 /* 804 * Get the length from the transfer 805 * counters. 806 */ 807 res = NCR_READ_REG(sc, NCR_TCL); 808 res += NCR_READ_REG(sc, NCR_TCM) << 8; 809 /* 810 * If they don't agree, 811 * adjust accordingly. 812 */ 813 while (res > len) { 814 len+=2; addr--; 815 } 816 if (res != len) { 817 panic("%s: res %d != len %d", 818 __func__, res, len); 819 } 820 } 821 break; 822 } 823 824 DELAY(1); 825 if (i++ > 1000000) 826 panic("%s: Bus error, but no condition! Argh!", 827 __func__); 828 } 829 goto restart_dmago; 830 } 831 832 len &= ~1; 833 834 statreg = esc->sc_reg + NCR_STAT * 16; 835 pdma = (volatile uint16_t *)(esc->sc_reg + 0x100); 836 837 /* 838 * These loops are unrolled into assembly for two reasons: 839 * 1) We can make sure that they are as efficient as possible, and 840 * 2) (more importantly) we need the address that we are reading 841 * from or writing to to be in a2. 842 */ 843 cnt32 = len / 32; 844 cnt2 = (len % 32) / 2; 845 if (esc->sc_datain == 0) { 846 /* while (cnt32--) { 16 instances of *pdma = *addr++; } */ 847 /* while (cnt2--) { *pdma = *addr++; } */ 848 __asm volatile ( 849 " movl %1, %%a2 \n" 850 " movl %2, %%a3 \n" 851 " movw %3, %%d2 \n" 852 " cmpw #0, %%d2 \n" 853 " beq 2f \n" 854 " subql #1, %%d2 \n" 855 "1: movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 856 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 857 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 858 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 859 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 860 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 861 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 862 " movw %%a2@+,%%a3@; movw %%a2@+,%%a3@ \n" 863 " movw #8704,%%sr \n" 864 " movw #9728,%%sr \n" 865 " dbra %%d2, 1b \n" 866 "2: movw %4, %%d2 \n" 867 " cmpw #0, %%d2 \n" 868 " beq 4f \n" 869 " subql #1, %%d2 \n" 870 "3: movw %%a2@+,%%a3@ \n" 871 " dbra %%d2, 3b \n" 872 "4: movl %%a2, %0" 873 : "=g" (addr) 874 : "0" (addr), "g" (pdma), "g" (cnt32), "g" (cnt2) 875 : "a2", "a3", "d2"); 876 if (esc->sc_pad) { 877 volatile uint8_t *c; 878 c = (volatile uint8_t *) addr; 879 /* Wait for DREQ */ 880 while (!esp_have_dreq(esc)) { 881 if (*statreg & 0x80) { 882 nofault = NULL; 883 goto gotintr; 884 } 885 } 886 *(volatile int8_t *)pdma = *c; 887 } 888 } else { 889 /* while (cnt32--) { 16 instances of *addr++ = *pdma; } */ 890 /* while (cnt2--) { *addr++ = *pdma; } */ 891 __asm volatile ( 892 " movl %1, %%a2 \n" 893 " movl %2, %%a3 \n" 894 " movw %3, %%d2 \n" 895 " cmpw #0, %%d2 \n" 896 " beq 6f \n" 897 " subql #1, %%d2 \n" 898 "5: movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 899 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 900 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 901 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 902 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 903 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 904 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 905 " movw %%a3@,%%a2@+; movw %%a3@,%%a2@+ \n" 906 " movw #8704,%%sr \n" 907 " movw #9728,%%sr \n" 908 " dbra %%d2, 5b \n" 909 "6: movw %4, %%d2 \n" 910 " cmpw #0, %%d2 \n" 911 " beq 8f \n" 912 " subql #1, %%d2 \n" 913 "7: movw %%a3@,%%a2@+ \n" 914 " dbra %%d2, 7b \n" 915 "8: movl %%a2, %0" 916 : "=g" (addr) 917 : "0" (addr), "g" (pdma), "g" (cnt32), "g" (cnt2) 918 : "a2", "a3", "d2"); 919 if (esc->sc_pad) { 920 volatile uint8_t *c; 921 c = (volatile int8_t *)addr; 922 /* Wait for DREQ */ 923 while (!esp_have_dreq(esc)) { 924 if (*statreg & 0x80) { 925 nofault = NULL; 926 goto gotintr; 927 } 928 } 929 *c = *(volatile uint8_t *)pdma; 930 } 931 } 932 933 nofault = NULL; 934 935 /* 936 * If we have not received an interrupt yet, we should shortly, 937 * and we can't prevent it, so return and wait for it. 938 */ 939 if ((*statreg & 0x80) == 0) { 940#if DEBUG 941 if (mac68k_esp_debug) { 942 printf("g.\n"); 943 } 944#endif 945 if (espspl != -1) 946 splx(espspl); 947 espspl = -1; 948 return; 949 } 950 951gotintr: 952#if DEBUG 953 if (mac68k_esp_debug) { 954 printf("g!\n"); 955 } 956#endif 957 /* 958 * We have been called from the MI ncr53c9x_intr() handler, 959 * which protects itself against multiple invocation with a 960 * lock. Follow the example of ncr53c9x_poll(). 961 */ 962 mutex_exit(&sc->sc_lock); 963 ncr53c9x_intr(sc); 964 mutex_enter(&sc->sc_lock); 965 if (espspl != -1) 966 splx(espspl); 967 espspl = -1; 968} 969 970static void 971esp_intr(void *sc) 972{ 973 struct esp_softc *esc = (struct esp_softc *)sc; 974 975 if (esc->sc_reg[NCR_STAT * 16] & 0x80) { 976 ncr53c9x_intr((struct ncr53c9x_softc *)esp0); 977 } 978} 979 980static void 981esp_dualbus_intr(void *sc) 982{ 983 if (esp0 && (esp0->sc_reg[NCR_STAT * 16] & 0x80)) { 984 ncr53c9x_intr((struct ncr53c9x_softc *)esp0); 985 } 986 987 if (esp1 && (esp1->sc_reg[NCR_STAT * 16] & 0x80)) { 988 ncr53c9x_intr((struct ncr53c9x_softc *)esp1); 989 } 990} 991 992static void 993esp_av_dma_reset(struct ncr53c9x_softc *sc) 994{ 995 struct esp_softc *esc = (struct esp_softc *)sc; 996 uint32_t res; 997 998 if (esc->sc_active) 999 stop_psc_dma(PSC_DMA_CHANNEL_SCSI, esc->sc_rset, &res, 1000 esc->sc_datain); 1001 1002 esc->sc_active = 0; 1003} 1004 1005static int 1006esp_av_dma_intr(struct ncr53c9x_softc *sc) 1007{ 1008 struct esp_softc *esc = (struct esp_softc *)sc; 1009 uint32_t resid; 1010 int trans; 1011 1012 KASSERT(esc->sc_active); 1013 1014#if DEBUG 1015 int tc_size; 1016 tc_size = NCR_READ_REG(sc, NCR_TCM); 1017 tc_size <<= 8; 1018 tc_size |= NCR_READ_REG(sc, NCR_TCL); 1019 printf("[av_dma_intr: intr 0x%x stat 0x%x tc 0x%x dmasize %zu]\n", 1020 sc->sc_espintr, sc->sc_espstat, tc_size, esc->sc_dmasize); 1021#endif 1022 1023 esc->sc_active = 0; 1024 1025 if (esc->sc_dmasize == 0) { 1026 /* A "Transfer Pad" operation completed */ 1027#if DEBUG 1028 printf("%s: TRPAD done\n", __func__); 1029#endif 1030 return 0; 1031 } 1032 1033#if 0 1034 /* 1035 * XXXRO dead code 1036 * Left unremoved for reference how to use wait_psc_dma(). 1037 */ 1038 if ((sc->sc_espintr & NCRINTR_BS) && (sc->sc_espstat & NCRSTAT_TC)) { 1039 /* Wait for engine to finish the transfer */ 1040 wait_psc_dma(PSC_DMA_CHANNEL_SCSI, esc->sc_rset, &resid); 1041# if DEBUG 1042 printf("[av_dma_intr: DMA %s done]\n", esc->sc_datain ? 1043 "read" : "write"); 1044# endif 1045 } 1046#endif 1047 1048 /* Halt the DMA engine */ 1049 stop_psc_dma(PSC_DMA_CHANNEL_SCSI, esc->sc_rset, &resid, 1050 esc->sc_datain); 1051 1052#if DEBUG 1053 printf("[av_dma_intr: DMA resid %u]\n", resid); 1054#endif 1055 1056 bus_dmamap_sync(esc->sc_dmat, esc->sc_dmap, 0, esc->sc_dmasize, 1057 esc->sc_datain ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 1058 bus_dmamap_unload(esc->sc_dmat, esc->sc_dmap); 1059 1060 trans = esc->sc_dmasize - resid; 1061 if (__predict_false(trans < 0)) { 1062#if DEBUG 1063 printf("[av_dma_intr: xfer (%d) > req (%zu)]\n", 1064 trans, esc->sc_dmasize); 1065#endif 1066 trans = esc->sc_dmasize; 1067 } 1068 1069#if DEBUG 1070 printf("[av_dma_intr: DMA %s of %d bytes done with %u residual]\n", 1071 esc->sc_datain ? "read" : "write", trans, resid); 1072#endif 1073 1074 if (__predict_false(esc->sc_ibuf_used)) { 1075 memcpy(*esc->sc_dmaaddr, esc->sc_ibuf, trans); 1076 esc->sc_ibuf_used = 0; 1077 } 1078 1079 *esc->sc_dmaaddr += trans; 1080 *esc->sc_dmalen -= trans; 1081 1082 return 0; 1083} 1084 1085static int 1086esp_av_dma_setup(struct ncr53c9x_softc *sc, uint8_t **addr, size_t *len, 1087 int datain, size_t *dmasize) 1088{ 1089 struct esp_softc *esc = (struct esp_softc *)sc; 1090 uint8_t **dmaaddr; 1091 1092 esc->sc_dmaaddr = dmaaddr = addr; 1093 esc->sc_dmalen = len; 1094 esc->sc_datain = datain; 1095 1096 /* 1097 * XXXRO 1098 * No need to set up DMA in `Transfer Pad' operation. 1099 */ 1100 if (*dmasize == 0) { 1101 esc->sc_dmasize = 0; 1102 return 0; 1103 } 1104 1105 /* 1106 * According to analysis by Michael Zucca, PSC seems to 1107 * require that DMA buffer is 1108 * (1) aligned to 16-byte boundares, and 1109 * (2) multiple of 16 bytes in size. 1110 * If the buffer does not satisfy these constraints, use 1111 * ``bounce'' buffer instead. 1112 * 1113 * Note that this does not hurt I/O performance at all; 1114 * bounce buffer is not used by MI routines for data 1115 * transfer for filesystem nor swap operations. It is 1116 * used only 1117 * (a) when disk is attached, and 1118 * (b) for special utilities like fsck(8) or fdisk(8) 1119 * as far as we can tell. 1120 * 1121 * Also note that PSC seems to allow buffer which does not 1122 * satisfy constraint (2) above. However, we use bounce 1123 * buffer for safety. This cannot affect performance anyway. 1124 * 1125 * Further, we prefer bounce buffer over PIO: 1126 * (A) NCR53C94/PSC do not seem to allow partial PIO. 1127 * (port-mac68k/56131) 1128 * (B) Synchronous transfer fails with PIO. 1129 */ 1130 if (__predict_false(*dmasize % 16 || (uintptr_t)*addr & 0xf)) { 1131#if 1 /* XXXRO */ 1132 printf("[avdma bounce DMA %s addr %p size %zu]\n", 1133 datain ? "read" : "write", *addr, *dmasize); 1134#endif 1135 *dmasize = uimin(*dmasize, NBPG); 1136 if (datain) { 1137 dmaaddr = &esc->sc_ibuf; 1138 esc->sc_ibuf_used = 1; 1139 } else { 1140 memset(esc->sc_obuf, 0, roundup2(*dmasize, 16)); 1141 memcpy(esc->sc_obuf, *addr, *dmasize); 1142 dmaaddr = &esc->sc_obuf; 1143 } 1144 } 1145 1146 bus_dmamap_load(esc->sc_dmat, esc->sc_dmap, *dmaaddr, 1147 *dmasize, NULL, BUS_DMA_NOWAIT); 1148 1149 /* 1150 * The DMA engine can only transfer one contiguous segment at a time. 1151 */ 1152 *dmasize = esc->sc_dmap->dm_segs[0].ds_len; 1153 esc->sc_dmasize = *dmasize; 1154 1155 bus_dmamap_sync(esc->sc_dmat, esc->sc_dmap, 0, esc->sc_dmasize, 1156 esc->sc_datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); 1157 1158 /* 1159 * We must start a DMA before the device is ready to transfer 1160 * data or the DMA engine gets confused and thinks it has to 1161 * do a write when it should really do a read. 1162 * 1163 * Doing this here also seems to work fine for DMA writes. 1164 */ 1165#ifdef DEBUG 1166 printf("[av_dma_setup: DMA req %zu act %zu v %p p 0x%lx %s]\n", 1167 *len, esc->sc_dmasize, *esc->sc_dmaaddr, 1168 esc->sc_dmap->dm_segs[0].ds_addr, esc->sc_datain ? 1169 "read" : "write"); 1170#endif 1171 start_psc_dma(PSC_DMA_CHANNEL_SCSI, &esc->sc_rset, 1172 esc->sc_dmap->dm_segs[0].ds_addr, 1173 esc->sc_dmasize, esc->sc_datain); 1174 1175 return 0; 1176} 1177 1178static void 1179esp_av_dma_go(struct ncr53c9x_softc *sc) 1180{ 1181 struct esp_softc *esc = (struct esp_softc *)sc; 1182 1183 /* 1184 * XXXRO 1185 * No DMA transfer in Transfer Pad operation 1186 */ 1187 if (esc->sc_dmasize == 0) 1188 return; 1189 1190 esc->sc_active = 1; 1191} 1192 1193static void 1194esp_av_dma_stop(struct ncr53c9x_softc *sc) 1195{ 1196 struct esp_softc *esc = (struct esp_softc *)sc; 1197 uint32_t res; 1198 1199 if (esc->sc_active) 1200 stop_psc_dma(PSC_DMA_CHANNEL_SCSI, esc->sc_rset, &res, 1201 esc->sc_datain); 1202 1203 bus_dmamap_unload(esc->sc_dmat, esc->sc_dmap); 1204 1205 esc->sc_active = 0; 1206} 1207