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