1 1.40 isaki /* $NetBSD: intio_dmac.c,v 1.40 2024/01/07 07:58:33 isaki Exp $ */ 2 1.2 minoura 3 1.2 minoura /*- 4 1.2 minoura * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 5 1.2 minoura * All rights reserved. 6 1.2 minoura * 7 1.2 minoura * This code is derived from software contributed to The NetBSD Foundation 8 1.2 minoura * by Minoura Makoto. 9 1.2 minoura * 10 1.2 minoura * Redistribution and use in source and binary forms, with or without 11 1.2 minoura * modification, are permitted provided that the following conditions 12 1.2 minoura * are met: 13 1.2 minoura * 1. Redistributions of source code must retain the above copyright 14 1.2 minoura * notice, this list of conditions and the following disclaimer. 15 1.2 minoura * 2. Redistributions in binary form must reproduce the above copyright 16 1.2 minoura * notice, this list of conditions and the following disclaimer in the 17 1.2 minoura * documentation and/or other materials provided with the distribution. 18 1.2 minoura * 19 1.2 minoura * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.2 minoura * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.2 minoura * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.2 minoura * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.2 minoura * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.2 minoura * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.2 minoura * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.2 minoura * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.2 minoura * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.2 minoura * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.2 minoura * POSSIBILITY OF SUCH DAMAGE. 30 1.2 minoura */ 31 1.2 minoura 32 1.2 minoura /* 33 1.2 minoura * Hitachi HD63450 (= Motorola MC68450) DMAC driver for x68k. 34 1.2 minoura */ 35 1.19 lukem 36 1.33 mrg #include "opt_m68k_arch.h" 37 1.33 mrg 38 1.19 lukem #include <sys/cdefs.h> 39 1.40 isaki __KERNEL_RCSID(0, "$NetBSD: intio_dmac.c,v 1.40 2024/01/07 07:58:33 isaki Exp $"); 40 1.2 minoura 41 1.2 minoura #include <sys/param.h> 42 1.2 minoura #include <sys/systm.h> 43 1.2 minoura #include <sys/device.h> 44 1.8 minoura #include <uvm/uvm_extern.h> 45 1.2 minoura 46 1.2 minoura #include <machine/bus.h> 47 1.2 minoura #include <machine/cpu.h> 48 1.2 minoura #include <machine/frame.h> 49 1.2 minoura 50 1.2 minoura #include <arch/x68k/dev/intiovar.h> 51 1.2 minoura #include <arch/x68k/dev/dmacvar.h> 52 1.2 minoura 53 1.2 minoura #ifdef DMAC_DEBUG 54 1.13 isaki #define DPRINTF(n,x) if (dmacdebug>((n)&0x0f)) printf x 55 1.13 isaki #define DDUMPREGS(n,x) if (dmacdebug>((n)&0x0f)) {printf x; dmac_dump_regs();} 56 1.2 minoura int dmacdebug = 0; 57 1.2 minoura #else 58 1.2 minoura #define DPRINTF(n,x) 59 1.2 minoura #define DDUMPREGS(n,x) 60 1.2 minoura #endif 61 1.2 minoura 62 1.21 chs static void dmac_init_channels(struct dmac_softc *); 63 1.9 minoura #ifdef DMAC_ARRAYCHAIN 64 1.30 isaki static int dmac_program_arraychain(device_t, struct dmac_dma_xfer *, 65 1.21 chs u_int, u_int); 66 1.9 minoura #endif 67 1.21 chs static int dmac_done(void *); 68 1.21 chs static int dmac_error(void *); 69 1.2 minoura 70 1.3 minoura #ifdef DMAC_DEBUG 71 1.21 chs static int dmac_dump_regs(void); 72 1.3 minoura #endif 73 1.2 minoura 74 1.2 minoura /* 75 1.2 minoura * autoconf stuff 76 1.2 minoura */ 77 1.30 isaki static int dmac_match(device_t, cfdata_t, void *); 78 1.30 isaki static void dmac_attach(device_t, device_t, void *); 79 1.2 minoura 80 1.30 isaki CFATTACH_DECL_NEW(dmac, sizeof(struct dmac_softc), 81 1.17 thorpej dmac_match, dmac_attach, NULL, NULL); 82 1.2 minoura 83 1.20 chs static int dmac_attached; 84 1.20 chs 85 1.2 minoura static int 86 1.30 isaki dmac_match(device_t parent, cfdata_t cf, void *aux) 87 1.2 minoura { 88 1.2 minoura struct intio_attach_args *ia = aux; 89 1.2 minoura 90 1.25 isaki if (strcmp(ia->ia_name, "dmac") != 0) 91 1.2 minoura return (0); 92 1.20 chs if (dmac_attached) 93 1.2 minoura return (0); 94 1.2 minoura 95 1.2 minoura if (ia->ia_addr == INTIOCF_ADDR_DEFAULT) 96 1.2 minoura ia->ia_addr = DMAC_ADDR; 97 1.2 minoura 98 1.2 minoura /* fixed address */ 99 1.2 minoura if (ia->ia_addr != DMAC_ADDR) 100 1.2 minoura return (0); 101 1.2 minoura if (ia->ia_intr != INTIOCF_INTR_DEFAULT) 102 1.2 minoura return (0); 103 1.2 minoura 104 1.2 minoura return 1; 105 1.2 minoura } 106 1.2 minoura 107 1.2 minoura static void 108 1.30 isaki dmac_attach(device_t parent, device_t self, void *aux) 109 1.2 minoura { 110 1.30 isaki struct dmac_softc *sc = device_private(self); 111 1.2 minoura struct intio_attach_args *ia = aux; 112 1.30 isaki struct intio_softc *intio; 113 1.35 christos int r __diagused; 114 1.2 minoura 115 1.30 isaki sc->sc_dev = self; 116 1.20 chs dmac_attached = 1; 117 1.20 chs 118 1.2 minoura ia->ia_size = DMAC_CHAN_SIZE * DMAC_NCHAN; 119 1.25 isaki r = intio_map_allocate_region(parent, ia, INTIO_MAP_ALLOCATE); 120 1.2 minoura #ifdef DIAGNOSTIC 121 1.2 minoura if (r) 122 1.26 isaki panic("IO map for DMAC corruption??"); 123 1.2 minoura #endif 124 1.2 minoura 125 1.30 isaki intio = device_private(parent); 126 1.30 isaki intio->sc_dmac = self; 127 1.2 minoura sc->sc_bst = ia->ia_bst; 128 1.25 isaki bus_space_map(sc->sc_bst, ia->ia_addr, ia->ia_size, 0, &sc->sc_bht); 129 1.2 minoura dmac_init_channels(sc); 130 1.2 minoura 131 1.30 isaki aprint_normal(": HD63450 DMAC\n"); 132 1.30 isaki aprint_normal_dev(self, "4 channels available.\n"); 133 1.2 minoura } 134 1.2 minoura 135 1.2 minoura static void 136 1.21 chs dmac_init_channels(struct dmac_softc *sc) 137 1.2 minoura { 138 1.2 minoura int i; 139 1.2 minoura 140 1.25 isaki DPRINTF(3, ("dmac_init_channels\n")); 141 1.2 minoura for (i=0; i<DMAC_NCHAN; i++) { 142 1.2 minoura sc->sc_channels[i].ch_channel = i; 143 1.2 minoura sc->sc_channels[i].ch_name[0] = 0; 144 1.31 isaki sc->sc_channels[i].ch_softc = sc; 145 1.2 minoura bus_space_subregion(sc->sc_bst, sc->sc_bht, 146 1.2 minoura DMAC_CHAN_SIZE*i, DMAC_CHAN_SIZE, 147 1.2 minoura &sc->sc_channels[i].ch_bht); 148 1.8 minoura sc->sc_channels[i].ch_xfer.dx_dmamap = 0; 149 1.9 minoura /* reset the status register */ 150 1.9 minoura bus_space_write_1(sc->sc_bst, sc->sc_channels[i].ch_bht, 151 1.9 minoura DMAC_REG_CSR, 0xff); 152 1.2 minoura } 153 1.2 minoura 154 1.2 minoura return; 155 1.2 minoura } 156 1.2 minoura 157 1.2 minoura 158 1.2 minoura /* 159 1.2 minoura * Channel initialization/deinitialization per user device. 160 1.2 minoura */ 161 1.2 minoura struct dmac_channel_stat * 162 1.36 isaki dmac_alloc_channel(device_t self, int ch, const char *name, 163 1.36 isaki int normalv, dmac_intr_handler_t normal, void *normalarg, 164 1.36 isaki int errorv, dmac_intr_handler_t error, void *errorarg, 165 1.36 isaki uint8_t dcr, uint8_t ocr) 166 1.2 minoura { 167 1.30 isaki struct intio_softc *intio = device_private(self); 168 1.32 isaki struct dmac_softc *dmac = device_private(intio->sc_dmac); 169 1.32 isaki struct dmac_channel_stat *chan = &dmac->sc_channels[ch]; 170 1.12 minoura #ifdef DMAC_ARRAYCHAIN 171 1.8 minoura int r, dummy; 172 1.12 minoura #endif 173 1.2 minoura 174 1.32 isaki aprint_normal_dev(dmac->sc_dev, "allocating ch %d for %s.\n", 175 1.30 isaki ch, name); 176 1.25 isaki DPRINTF(3, ("dmamap=%p\n", (void *)chan->ch_xfer.dx_dmamap)); 177 1.2 minoura #ifdef DIAGNOSTIC 178 1.2 minoura if (ch < 0 || ch >= DMAC_NCHAN) 179 1.25 isaki panic("Invalid DMAC channel."); 180 1.2 minoura if (chan->ch_name[0]) 181 1.25 isaki panic("DMAC: channel in use."); 182 1.2 minoura if (strlen(name) > 8) 183 1.40 isaki panic("DMAC: wrong user name."); 184 1.2 minoura #endif 185 1.2 minoura 186 1.9 minoura #ifdef DMAC_ARRAYCHAIN 187 1.8 minoura /* allocate the DMAC arraychaining map */ 188 1.8 minoura r = bus_dmamem_alloc(intio->sc_dmat, 189 1.8 minoura sizeof(struct dmac_sg_array) * DMAC_MAPSIZE, 190 1.8 minoura 4, 0, &chan->ch_seg[0], 1, &dummy, 191 1.8 minoura BUS_DMA_NOWAIT); 192 1.8 minoura if (r) 193 1.25 isaki panic("DMAC: cannot alloc DMA safe memory"); 194 1.8 minoura r = bus_dmamem_map(intio->sc_dmat, 195 1.8 minoura &chan->ch_seg[0], 1, 196 1.8 minoura sizeof(struct dmac_sg_array) * DMAC_MAPSIZE, 197 1.24 christos (void **) &chan->ch_map, 198 1.8 minoura BUS_DMA_NOWAIT|BUS_DMA_COHERENT); 199 1.8 minoura if (r) 200 1.25 isaki panic("DMAC: cannot map DMA safe memory"); 201 1.9 minoura #endif 202 1.8 minoura 203 1.9 minoura /* fill the channel status structure by the default values. */ 204 1.2 minoura strcpy(chan->ch_name, name); 205 1.36 isaki chan->ch_dcr = dcr; 206 1.36 isaki chan->ch_ocr = ocr; 207 1.2 minoura chan->ch_normalv = normalv; 208 1.2 minoura chan->ch_errorv = errorv; 209 1.2 minoura chan->ch_normal = normal; 210 1.2 minoura chan->ch_error = error; 211 1.2 minoura chan->ch_normalarg = normalarg; 212 1.2 minoura chan->ch_errorarg = errorarg; 213 1.8 minoura chan->ch_xfer.dx_dmamap = 0; 214 1.2 minoura 215 1.2 minoura /* setup the device-specific registers */ 216 1.32 isaki bus_space_write_1(dmac->sc_bst, chan->ch_bht, DMAC_REG_CSR, 0xff); 217 1.32 isaki bus_space_write_1(dmac->sc_bst, chan->ch_bht, 218 1.2 minoura DMAC_REG_DCR, chan->ch_dcr); 219 1.32 isaki bus_space_write_1(dmac->sc_bst, chan->ch_bht, DMAC_REG_CPR, 0); 220 1.36 isaki /* OCR will be written at dmac_load_xfer() */ 221 1.2 minoura 222 1.2 minoura /* 223 1.2 minoura * X68k physical user space is a subset of the kernel space; 224 1.2 minoura * the memory is always included in the physical user space, 225 1.2 minoura * while the device is not. 226 1.2 minoura */ 227 1.32 isaki bus_space_write_1(dmac->sc_bst, chan->ch_bht, 228 1.2 minoura DMAC_REG_BFCR, DMAC_FC_USER_DATA); 229 1.32 isaki bus_space_write_1(dmac->sc_bst, chan->ch_bht, 230 1.2 minoura DMAC_REG_MFCR, DMAC_FC_USER_DATA); 231 1.32 isaki bus_space_write_1(dmac->sc_bst, chan->ch_bht, 232 1.2 minoura DMAC_REG_DFCR, DMAC_FC_KERNEL_DATA); 233 1.2 minoura 234 1.2 minoura /* setup the interrupt handlers */ 235 1.32 isaki bus_space_write_1(dmac->sc_bst, chan->ch_bht, DMAC_REG_NIVR, normalv); 236 1.32 isaki bus_space_write_1(dmac->sc_bst, chan->ch_bht, DMAC_REG_EIVR, errorv); 237 1.2 minoura 238 1.29 isaki intio_intr_establish_ext(normalv, name, "dma", dmac_done, chan); 239 1.29 isaki intio_intr_establish_ext(errorv, name, "dmaerr", dmac_error, chan); 240 1.2 minoura 241 1.2 minoura return chan; 242 1.2 minoura } 243 1.2 minoura 244 1.2 minoura int 245 1.31 isaki dmac_free_channel(device_t self, int ch, void *channel) 246 1.2 minoura { 247 1.31 isaki struct intio_softc *intio = device_private(self); 248 1.31 isaki struct dmac_softc *dmac = device_private(intio->sc_dmac); 249 1.31 isaki struct dmac_channel_stat *chan = &dmac->sc_channels[ch]; 250 1.2 minoura 251 1.25 isaki DPRINTF(3, ("dmac_free_channel, %d\n", ch)); 252 1.25 isaki DPRINTF(3, ("dmamap=%p\n", (void *)chan->ch_xfer.dx_dmamap)); 253 1.2 minoura if (chan != channel) 254 1.2 minoura return -1; 255 1.2 minoura if (ch != chan->ch_channel) 256 1.2 minoura return -1; 257 1.2 minoura 258 1.9 minoura #ifdef DMAC_ARRAYCHAIN 259 1.25 isaki bus_dmamem_unmap(intio->sc_dmat, (void *)chan->ch_map, 260 1.9 minoura sizeof(struct dmac_sg_array) * DMAC_MAPSIZE); 261 1.9 minoura bus_dmamem_free(intio->sc_dmat, &chan->ch_seg[0], 1); 262 1.9 minoura #endif 263 1.2 minoura chan->ch_name[0] = 0; 264 1.2 minoura intio_intr_disestablish(chan->ch_normalv, channel); 265 1.2 minoura intio_intr_disestablish(chan->ch_errorv, channel); 266 1.2 minoura 267 1.2 minoura return 0; 268 1.2 minoura } 269 1.2 minoura 270 1.2 minoura /* 271 1.2 minoura * Initialization / deinitialization per transfer. 272 1.2 minoura */ 273 1.2 minoura struct dmac_dma_xfer * 274 1.21 chs dmac_alloc_xfer(struct dmac_channel_stat *chan, bus_dma_tag_t dmat, 275 1.21 chs bus_dmamap_t dmamap) 276 1.2 minoura { 277 1.8 minoura struct dmac_dma_xfer *xf = &chan->ch_xfer; 278 1.2 minoura 279 1.25 isaki DPRINTF(3, ("dmac_alloc_xfer\n")); 280 1.8 minoura xf->dx_channel = chan; 281 1.8 minoura xf->dx_dmamap = dmamap; 282 1.8 minoura xf->dx_tag = dmat; 283 1.9 minoura #ifdef DMAC_ARRAYCHAIN 284 1.9 minoura xf->dx_array = chan->ch_map; 285 1.9 minoura xf->dx_done = 0; 286 1.9 minoura #endif 287 1.9 minoura return xf; 288 1.9 minoura } 289 1.9 minoura 290 1.9 minoura int 291 1.31 isaki dmac_load_xfer(struct dmac_softc *dmac, struct dmac_dma_xfer *xf) 292 1.9 minoura { 293 1.9 minoura struct dmac_channel_stat *chan = xf->dx_channel; 294 1.9 minoura 295 1.25 isaki DPRINTF(3, ("dmac_load_xfer\n")); 296 1.9 minoura 297 1.9 minoura xf->dx_ocr &= ~DMAC_OCR_CHAIN_MASK; 298 1.9 minoura if (xf->dx_dmamap->dm_nsegs == 1) 299 1.9 minoura xf->dx_ocr |= DMAC_OCR_CHAIN_DISABLED; 300 1.9 minoura else { 301 1.9 minoura xf->dx_ocr |= DMAC_OCR_CHAIN_ARRAY; 302 1.9 minoura } 303 1.9 minoura 304 1.31 isaki bus_space_write_1(dmac->sc_bst, chan->ch_bht, DMAC_REG_CSR, 0xff); 305 1.31 isaki bus_space_write_1(dmac->sc_bst, chan->ch_bht, DMAC_REG_SCR, xf->dx_scr); 306 1.31 isaki bus_space_write_1(dmac->sc_bst, chan->ch_bht, 307 1.9 minoura DMAC_REG_OCR, (xf->dx_ocr | chan->ch_ocr)); 308 1.31 isaki bus_space_write_4(dmac->sc_bst, chan->ch_bht, 309 1.9 minoura DMAC_REG_DAR, (int) xf->dx_device); 310 1.9 minoura 311 1.9 minoura return 0; 312 1.9 minoura } 313 1.9 minoura 314 1.9 minoura struct dmac_dma_xfer * 315 1.21 chs dmac_prepare_xfer(struct dmac_channel_stat *chan, bus_dma_tag_t dmat, 316 1.21 chs bus_dmamap_t dmamap, int dir, int scr, void *dar) 317 1.9 minoura { 318 1.9 minoura struct dmac_dma_xfer *xf; 319 1.31 isaki struct dmac_softc *dmac = chan->ch_softc; 320 1.9 minoura 321 1.9 minoura xf = dmac_alloc_xfer(chan, dmat, dmamap); 322 1.9 minoura 323 1.8 minoura xf->dx_ocr = dir & DMAC_OCR_DIR_MASK; 324 1.8 minoura xf->dx_scr = scr & (DMAC_SCR_MAC_MASK|DMAC_SCR_DAC_MASK); 325 1.8 minoura xf->dx_device = dar; 326 1.9 minoura 327 1.31 isaki dmac_load_xfer(dmac, xf); 328 1.2 minoura 329 1.8 minoura return xf; 330 1.2 minoura } 331 1.2 minoura 332 1.2 minoura #ifdef DMAC_DEBUG 333 1.2 minoura static struct dmac_channel_stat *debugchan = 0; 334 1.2 minoura #endif 335 1.2 minoura 336 1.2 minoura /* 337 1.2 minoura * Do the actual transfer. 338 1.2 minoura */ 339 1.2 minoura int 340 1.31 isaki dmac_start_xfer(struct dmac_softc *dmac, struct dmac_dma_xfer *xf) 341 1.2 minoura { 342 1.31 isaki return dmac_start_xfer_offset(dmac, xf, 0, 0); 343 1.9 minoura } 344 1.9 minoura 345 1.9 minoura int 346 1.31 isaki dmac_start_xfer_offset(struct dmac_softc *dmac, struct dmac_dma_xfer *xf, 347 1.21 chs u_int offset, u_int size) 348 1.9 minoura { 349 1.2 minoura struct dmac_channel_stat *chan = xf->dx_channel; 350 1.9 minoura struct x68k_bus_dmamap *dmamap = xf->dx_dmamap; 351 1.12 minoura int go = DMAC_CCR_STR|DMAC_CCR_INT; 352 1.37 isaki bus_addr_t paddr; 353 1.37 isaki uint8_t csr; 354 1.12 minoura #ifdef DMAC_ARRAYCHAIN 355 1.38 andvar int c = 0; 356 1.12 minoura #endif 357 1.2 minoura 358 1.25 isaki DPRINTF(3, ("dmac_start_xfer\n")); 359 1.2 minoura #ifdef DMAC_DEBUG 360 1.2 minoura debugchan=chan; 361 1.2 minoura #endif 362 1.2 minoura 363 1.9 minoura if (size == 0) { 364 1.9 minoura #ifdef DIAGNOSTIC 365 1.9 minoura if (offset != 0) 366 1.25 isaki panic("dmac_start_xfer_offset: invalid offset %x", 367 1.9 minoura offset); 368 1.9 minoura #endif 369 1.9 minoura size = dmamap->dm_mapsize; 370 1.9 minoura } 371 1.9 minoura 372 1.9 minoura #ifdef DMAC_ARRAYCHAIN 373 1.9 minoura #ifdef DIAGNOSTIC 374 1.9 minoura if (xf->dx_done) 375 1.9 minoura panic("dmac_start_xfer: DMA transfer in progress"); 376 1.9 minoura #endif 377 1.9 minoura #endif 378 1.25 isaki DPRINTF(3, ("First program:\n")); 379 1.9 minoura #ifdef DIAGNOSTIC 380 1.9 minoura if ((offset >= dmamap->dm_mapsize) || 381 1.9 minoura (offset + size > dmamap->dm_mapsize)) 382 1.25 isaki panic("dmac_start_xfer_offset: invalid offset: " 383 1.40 isaki "offset=%d, size=%d, mapsize=%ld", 384 1.9 minoura offset, size, dmamap->dm_mapsize); 385 1.9 minoura #endif 386 1.8 minoura /* program DMAC in single block mode or array chainning mode */ 387 1.9 minoura if (dmamap->dm_nsegs == 1) { 388 1.8 minoura DPRINTF(3, ("single block mode\n")); 389 1.9 minoura #ifdef DIAGNOSTIC 390 1.9 minoura if (dmamap->dm_mapsize != dmamap->dm_segs[0].ds_len) 391 1.25 isaki panic("dmac_start_xfer_offset: dmamap curruption"); 392 1.9 minoura #endif 393 1.37 isaki paddr = dmamap->dm_segs[0].ds_addr + offset; 394 1.37 isaki csr = bus_space_read_1(dmac->sc_bst, chan->ch_bht, DMAC_REG_CSR); 395 1.37 isaki if ((csr & DMAC_CSR_ACT) != 0) { 396 1.37 isaki /* Use 'Continue Mode' */ 397 1.37 isaki bus_space_write_4(dmac->sc_bst, chan->ch_bht, 398 1.37 isaki DMAC_REG_BAR, paddr); 399 1.37 isaki bus_space_write_2(dmac->sc_bst, chan->ch_bht, 400 1.37 isaki DMAC_REG_BTCR, (int) size); 401 1.9 minoura go |= DMAC_CCR_CNT; 402 1.37 isaki go &= ~DMAC_CCR_STR; 403 1.9 minoura } else { 404 1.31 isaki bus_space_write_4(dmac->sc_bst, chan->ch_bht, 405 1.37 isaki DMAC_REG_MAR, paddr); 406 1.31 isaki bus_space_write_2(dmac->sc_bst, chan->ch_bht, 407 1.9 minoura DMAC_REG_MTCR, (int) size); 408 1.9 minoura } 409 1.9 minoura #ifdef DMAC_ARRAYCHAIN 410 1.8 minoura xf->dx_done = 1; 411 1.9 minoura #endif 412 1.8 minoura } else { 413 1.9 minoura #ifdef DMAC_ARRAYCHAIN 414 1.38 andvar c = dmac_program_arraychain(dmac->sc_dev, xf, offset, size); 415 1.31 isaki bus_space_write_4(dmac->sc_bst, chan->ch_bht, 416 1.8 minoura DMAC_REG_BAR, (int) chan->ch_seg[0].ds_addr); 417 1.31 isaki bus_space_write_2(dmac->sc_bst, chan->ch_bht, 418 1.8 minoura DMAC_REG_BTCR, c); 419 1.9 minoura #else 420 1.25 isaki panic("DMAC: unexpected use of arraychaining mode"); 421 1.9 minoura #endif 422 1.8 minoura } 423 1.2 minoura 424 1.31 isaki bus_space_write_1(dmac->sc_bst, chan->ch_bht, DMAC_REG_CSR, 0xff); 425 1.2 minoura 426 1.2 minoura /* START!! */ 427 1.25 isaki DDUMPREGS(3, ("first start\n")); 428 1.18 isaki 429 1.9 minoura #ifdef DMAC_ARRAYCHAIN 430 1.2 minoura #if defined(M68040) || defined(M68060) 431 1.9 minoura /* flush data cache for the map */ 432 1.39 andvar if (dmamap->dm_nsegs != 1 && mmutype == MMU_68040 && c > 0) 433 1.24 christos dma_cachectl((void *) xf->dx_array, 434 1.9 minoura sizeof(struct dmac_sg_array) * c); 435 1.9 minoura #endif 436 1.2 minoura #endif 437 1.31 isaki bus_space_write_1(dmac->sc_bst, chan->ch_bht, DMAC_REG_CCR, go); 438 1.9 minoura 439 1.2 minoura return 0; 440 1.2 minoura } 441 1.2 minoura 442 1.9 minoura #ifdef DMAC_ARRAYCHAIN 443 1.2 minoura static int 444 1.31 isaki dmac_program_arraychain(device_t self, struct dmac_dma_xfer *xf, 445 1.21 chs u_int offset, u_int size) 446 1.2 minoura { 447 1.2 minoura struct x68k_bus_dmamap *map = xf->dx_dmamap; 448 1.2 minoura int i, j; 449 1.2 minoura 450 1.9 minoura /* XXX not yet!! */ 451 1.9 minoura if (offset != 0 || size != map->dm_mapsize) 452 1.25 isaki panic("dmac_program_arraychain: unsupported offset/size"); 453 1.9 minoura 454 1.25 isaki DPRINTF(3, ("dmac_program_arraychain\n")); 455 1.2 minoura for (i=0, j=xf->dx_done; i<DMAC_MAPSIZE && j<map->dm_nsegs; 456 1.2 minoura i++, j++) { 457 1.8 minoura xf->dx_array[i].da_addr = map->dm_segs[j].ds_addr; 458 1.2 minoura #ifdef DIAGNOSTIC 459 1.9 minoura if (map->dm_segs[j].ds_len > DMAC_MAXSEGSZ) 460 1.25 isaki panic("dmac_program_arraychain: wrong map: %ld", 461 1.9 minoura map->dm_segs[j].ds_len); 462 1.2 minoura #endif 463 1.8 minoura xf->dx_array[i].da_count = map->dm_segs[j].ds_len; 464 1.2 minoura } 465 1.2 minoura xf->dx_done = j; 466 1.2 minoura 467 1.2 minoura return i; 468 1.2 minoura } 469 1.9 minoura #endif 470 1.2 minoura 471 1.2 minoura /* 472 1.2 minoura * interrupt handlers. 473 1.2 minoura */ 474 1.2 minoura static int 475 1.21 chs dmac_done(void *arg) 476 1.2 minoura { 477 1.2 minoura struct dmac_channel_stat *chan = arg; 478 1.31 isaki struct dmac_softc *sc = chan->ch_softc; 479 1.12 minoura #ifdef DMAC_ARRAYCHAIN 480 1.8 minoura struct dmac_dma_xfer *xf = &chan->ch_xfer; 481 1.2 minoura struct x68k_bus_dmamap *map = xf->dx_dmamap; 482 1.2 minoura int c; 483 1.12 minoura #endif 484 1.2 minoura 485 1.25 isaki DPRINTF(3, ("dmac_done\n")); 486 1.9 minoura 487 1.2 minoura bus_space_write_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CSR, 0xff); 488 1.2 minoura 489 1.9 minoura #ifdef DMAC_ARRAYCHAIN 490 1.2 minoura if (xf->dx_done == map->dm_nsegs) { 491 1.9 minoura xf->dx_done = 0; 492 1.9 minoura #endif 493 1.2 minoura /* Done */ 494 1.25 isaki return (*chan->ch_normal)(chan->ch_normalarg); 495 1.9 minoura #ifdef DMAC_ARRAYCHAIN 496 1.2 minoura } 497 1.9 minoura #endif 498 1.2 minoura 499 1.9 minoura #ifdef DMAC_ARRAYCHAIN 500 1.2 minoura /* Continue transfer */ 501 1.25 isaki DPRINTF(3, ("reprograming\n")); 502 1.30 isaki c = dmac_program_arraychain(sc->sc_dev, xf, 0, map->dm_mapsize); 503 1.2 minoura 504 1.9 minoura bus_space_write_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CSR, 0xff); 505 1.2 minoura bus_space_write_4(sc->sc_bst, chan->ch_bht, 506 1.2 minoura DMAC_REG_BAR, (int) chan->ch_map); 507 1.2 minoura bus_space_write_4(sc->sc_bst, chan->ch_bht, 508 1.2 minoura DMAC_REG_DAR, (int) xf->dx_device); 509 1.9 minoura bus_space_write_2(sc->sc_bst, chan->ch_bht, DMAC_REG_BTCR, c); 510 1.2 minoura 511 1.2 minoura /* START!! */ 512 1.25 isaki DDUMPREGS(3, ("restart\n")); 513 1.2 minoura bus_space_write_1(sc->sc_bst, chan->ch_bht, 514 1.2 minoura DMAC_REG_CCR, DMAC_CCR_STR|DMAC_CCR_INT); 515 1.2 minoura 516 1.2 minoura return 1; 517 1.9 minoura #endif 518 1.2 minoura } 519 1.2 minoura 520 1.2 minoura static int 521 1.21 chs dmac_error(void *arg) 522 1.2 minoura { 523 1.2 minoura struct dmac_channel_stat *chan = arg; 524 1.31 isaki struct dmac_softc *sc = chan->ch_softc; 525 1.34 tsutsui uint8_t csr, cer; 526 1.2 minoura 527 1.34 tsutsui csr = bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CSR); 528 1.34 tsutsui cer = bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CER); 529 1.34 tsutsui 530 1.34 tsutsui #ifndef DMAC_DEBUG 531 1.34 tsutsui /* Software abort (CER=0x11) could happen on normal xfer termination */ 532 1.34 tsutsui if (cer != 0x11) 533 1.34 tsutsui #endif 534 1.34 tsutsui { 535 1.34 tsutsui printf("DMAC transfer error CSR=%02x, CER=%02x\n", csr, cer); 536 1.34 tsutsui } 537 1.18 isaki DDUMPREGS(3, ("registers were:\n")); 538 1.2 minoura 539 1.9 minoura /* Clear the status bits */ 540 1.2 minoura bus_space_write_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CSR, 0xff); 541 1.2 minoura 542 1.9 minoura #ifdef DMAC_ARRAYCHAIN 543 1.9 minoura chan->ch_xfer.dx_done = 0; 544 1.9 minoura #endif 545 1.9 minoura 546 1.25 isaki return (*chan->ch_error)(chan->ch_errorarg); 547 1.2 minoura } 548 1.2 minoura 549 1.9 minoura int 550 1.31 isaki dmac_abort_xfer(struct dmac_softc *dmac, struct dmac_dma_xfer *xf) 551 1.9 minoura { 552 1.9 minoura struct dmac_channel_stat *chan = xf->dx_channel; 553 1.9 minoura 554 1.31 isaki bus_space_write_1(dmac->sc_bst, chan->ch_bht, DMAC_REG_CCR, 555 1.34 tsutsui DMAC_CCR_INT | DMAC_CCR_SAB); 556 1.31 isaki bus_space_write_1(dmac->sc_bst, chan->ch_bht, DMAC_REG_CSR, 0xff); 557 1.9 minoura 558 1.9 minoura return 0; 559 1.9 minoura } 560 1.2 minoura 561 1.2 minoura #ifdef DMAC_DEBUG 562 1.2 minoura static int 563 1.2 minoura dmac_dump_regs(void) 564 1.2 minoura { 565 1.2 minoura struct dmac_channel_stat *chan = debugchan; 566 1.2 minoura struct dmac_softc *sc; 567 1.2 minoura 568 1.13 isaki if ((chan == 0) || (dmacdebug & 0xf0)) 569 1.13 isaki return 0; 570 1.31 isaki sc = chan->ch_softc; 571 1.2 minoura 572 1.25 isaki printf("DMAC channel %d registers\n", chan->ch_channel); 573 1.25 isaki printf("CSR=%02x, CER=%02x, DCR=%02x, OCR=%02x, SCR=%02x, " 574 1.2 minoura "CCR=%02x, CPR=%02x, GCR=%02x\n", 575 1.2 minoura bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CSR), 576 1.2 minoura bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CER), 577 1.2 minoura bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_DCR), 578 1.2 minoura bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_OCR), 579 1.2 minoura bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_SCR), 580 1.2 minoura bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CCR), 581 1.2 minoura bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_CPR), 582 1.2 minoura bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_GCR)); 583 1.25 isaki printf("NIVR=%02x, EIVR=%02x, MTCR=%04x, BTCR=%04x, DFCR=%02x, " 584 1.2 minoura "MFCR=%02x, BFCR=%02x\n", 585 1.2 minoura bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_NIVR), 586 1.2 minoura bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_EIVR), 587 1.2 minoura bus_space_read_2(sc->sc_bst, chan->ch_bht, DMAC_REG_MTCR), 588 1.2 minoura bus_space_read_2(sc->sc_bst, chan->ch_bht, DMAC_REG_BTCR), 589 1.2 minoura bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_DFCR), 590 1.2 minoura bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_MFCR), 591 1.2 minoura bus_space_read_1(sc->sc_bst, chan->ch_bht, DMAC_REG_BFCR)); 592 1.25 isaki printf("DAR=%08x, MAR=%08x, BAR=%08x\n", 593 1.2 minoura bus_space_read_4(sc->sc_bst, chan->ch_bht, DMAC_REG_DAR), 594 1.2 minoura bus_space_read_4(sc->sc_bst, chan->ch_bht, DMAC_REG_MAR), 595 1.2 minoura bus_space_read_4(sc->sc_bst, chan->ch_bht, DMAC_REG_BAR)); 596 1.2 minoura 597 1.2 minoura return 0; 598 1.2 minoura } 599 1.2 minoura #endif 600