1 /*- 2 * Copyright (c) 2017-2018 Ruslan Bukin <[email protected]> 3 * All rights reserved. 4 * 5 * This software was developed by SRI International and the University of 6 * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 7 * ("CTSRD"), as part of the DARPA CRASH research programme. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 /* This is driver for SoftDMA device built using Altera FIFO component. */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 #include "opt_platform.h" 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/conf.h> 40 #include <sys/bus.h> 41 #include <sys/endian.h> 42 #include <sys/kernel.h> 43 #include <sys/kthread.h> 44 #include <sys/module.h> 45 #include <sys/lock.h> 46 #include <sys/mutex.h> 47 #include <sys/resource.h> 48 #include <sys/rman.h> 49 50 #include <machine/bus.h> 51 52 #ifdef FDT 53 #include <dev/fdt/fdt_common.h> 54 #include <dev/ofw/ofw_bus.h> 55 #include <dev/ofw/ofw_bus_subr.h> 56 #endif 57 58 #include <dev/altera/softdma/a_api.h> 59 60 #include <dev/xdma/xdma.h> 61 #include "xdma_if.h" 62 63 #define SOFTDMA_DEBUG 64 #undef SOFTDMA_DEBUG 65 66 #ifdef SOFTDMA_DEBUG 67 #define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__) 68 #else 69 #define dprintf(fmt, ...) 70 #endif 71 72 #define AVALON_FIFO_TX_BASIC_OPTS_DEPTH 16 73 #define SOFTDMA_NCHANNELS 1 74 #define CONTROL_GEN_SOP (1 << 0) 75 #define CONTROL_GEN_EOP (1 << 1) 76 #define CONTROL_OWN (1 << 31) 77 78 #define SOFTDMA_RX_EVENTS \ 79 (A_ONCHIP_FIFO_MEM_CORE_INTR_FULL | \ 80 A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW | \ 81 A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW) 82 #define SOFTDMA_TX_EVENTS \ 83 (A_ONCHIP_FIFO_MEM_CORE_INTR_EMPTY | \ 84 A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW | \ 85 A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW) 86 87 struct softdma_channel { 88 struct softdma_softc *sc; 89 struct mtx mtx; 90 xdma_channel_t *xchan; 91 struct proc *p; 92 int used; 93 int index; 94 int run; 95 uint32_t idx_tail; 96 uint32_t idx_head; 97 struct softdma_desc *descs; 98 99 uint32_t descs_num; 100 uint32_t descs_used_count; 101 }; 102 103 struct softdma_desc { 104 uint64_t src_addr; 105 uint64_t dst_addr; 106 uint32_t len; 107 uint32_t access_width; 108 uint32_t count; 109 uint16_t src_incr; 110 uint16_t dst_incr; 111 uint32_t direction; 112 struct softdma_desc *next; 113 uint32_t transfered; 114 uint32_t status; 115 uint32_t reserved; 116 uint32_t control; 117 }; 118 119 struct softdma_softc { 120 device_t dev; 121 struct resource *res[3]; 122 bus_space_tag_t bst; 123 bus_space_handle_t bsh; 124 bus_space_tag_t bst_c; 125 bus_space_handle_t bsh_c; 126 void *ih; 127 struct softdma_channel channels[SOFTDMA_NCHANNELS]; 128 }; 129 130 static struct resource_spec softdma_spec[] = { 131 { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* fifo */ 132 { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* core */ 133 { SYS_RES_IRQ, 0, RF_ACTIVE }, 134 { -1, 0 } 135 }; 136 137 static int softdma_probe(device_t dev); 138 static int softdma_attach(device_t dev); 139 static int softdma_detach(device_t dev); 140 141 static inline uint32_t 142 softdma_next_desc(struct softdma_channel *chan, uint32_t curidx) 143 { 144 145 return ((curidx + 1) % chan->descs_num); 146 } 147 148 static void 149 softdma_mem_write(struct softdma_softc *sc, uint32_t reg, uint32_t val) 150 { 151 152 bus_write_4(sc->res[0], reg, htole32(val)); 153 } 154 155 static uint32_t 156 softdma_mem_read(struct softdma_softc *sc, uint32_t reg) 157 { 158 uint32_t val; 159 160 val = bus_read_4(sc->res[0], reg); 161 162 return (le32toh(val)); 163 } 164 165 static void 166 softdma_memc_write(struct softdma_softc *sc, uint32_t reg, uint32_t val) 167 { 168 169 bus_write_4(sc->res[1], reg, htole32(val)); 170 } 171 172 static uint32_t 173 softdma_memc_read(struct softdma_softc *sc, uint32_t reg) 174 { 175 uint32_t val; 176 177 val = bus_read_4(sc->res[1], reg); 178 179 return (le32toh(val)); 180 } 181 182 static uint32_t 183 softdma_fill_level(struct softdma_softc *sc) 184 { 185 uint32_t val; 186 187 val = softdma_memc_read(sc, 188 A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_FILL_LEVEL); 189 190 return (val); 191 } 192 193 static uint32_t 194 fifo_fill_level_wait(struct softdma_softc *sc) 195 { 196 uint32_t val; 197 198 do 199 val = softdma_fill_level(sc); 200 while (val == AVALON_FIFO_TX_BASIC_OPTS_DEPTH); 201 202 return (val); 203 } 204 205 static void 206 softdma_intr(void *arg) 207 { 208 struct softdma_channel *chan; 209 struct softdma_softc *sc; 210 int reg; 211 int err; 212 213 sc = arg; 214 215 chan = &sc->channels[0]; 216 217 reg = softdma_memc_read(sc, A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT); 218 219 if (reg & (A_ONCHIP_FIFO_MEM_CORE_EVENT_OVERFLOW | 220 A_ONCHIP_FIFO_MEM_CORE_EVENT_UNDERFLOW)) { 221 /* Errors */ 222 err = (((reg & A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) >> \ 223 A_ONCHIP_FIFO_MEM_CORE_ERROR_SHIFT) & 0xff); 224 } 225 226 if (reg != 0) { 227 softdma_memc_write(sc, 228 A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, reg); 229 chan->run = 1; 230 wakeup(chan); 231 } 232 } 233 234 static int 235 softdma_probe(device_t dev) 236 { 237 238 if (!ofw_bus_status_okay(dev)) 239 return (ENXIO); 240 241 if (!ofw_bus_is_compatible(dev, "altr,softdma")) 242 return (ENXIO); 243 244 device_set_desc(dev, "SoftDMA"); 245 246 return (BUS_PROBE_DEFAULT); 247 } 248 249 static int 250 softdma_attach(device_t dev) 251 { 252 struct softdma_softc *sc; 253 phandle_t xref, node; 254 int err; 255 256 sc = device_get_softc(dev); 257 sc->dev = dev; 258 259 if (bus_alloc_resources(dev, softdma_spec, sc->res)) { 260 device_printf(dev, 261 "could not allocate resources for device\n"); 262 return (ENXIO); 263 } 264 265 /* FIFO memory interface */ 266 sc->bst = rman_get_bustag(sc->res[0]); 267 sc->bsh = rman_get_bushandle(sc->res[0]); 268 269 /* FIFO control memory interface */ 270 sc->bst_c = rman_get_bustag(sc->res[1]); 271 sc->bsh_c = rman_get_bushandle(sc->res[1]); 272 273 /* Setup interrupt handler */ 274 err = bus_setup_intr(dev, sc->res[2], INTR_TYPE_MISC | INTR_MPSAFE, 275 NULL, softdma_intr, sc, &sc->ih); 276 if (err) { 277 device_printf(dev, "Unable to alloc interrupt resource.\n"); 278 return (ENXIO); 279 } 280 281 node = ofw_bus_get_node(dev); 282 xref = OF_xref_from_node(node); 283 OF_device_register_xref(xref, dev); 284 285 return (0); 286 } 287 288 static int 289 softdma_detach(device_t dev) 290 { 291 struct softdma_softc *sc; 292 293 sc = device_get_softc(dev); 294 295 return (0); 296 } 297 298 static int 299 softdma_process_tx(struct softdma_channel *chan, struct softdma_desc *desc) 300 { 301 struct softdma_softc *sc; 302 uint64_t addr; 303 uint64_t buf; 304 uint32_t word; 305 uint32_t missing; 306 uint32_t reg; 307 int got_bits; 308 int len; 309 310 sc = chan->sc; 311 312 fifo_fill_level_wait(sc); 313 314 /* Set start of packet. */ 315 if (desc->control & CONTROL_GEN_SOP) 316 softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA, 317 A_ONCHIP_FIFO_MEM_CORE_SOP); 318 319 got_bits = 0; 320 buf = 0; 321 322 addr = desc->src_addr; 323 len = desc->len; 324 325 if (addr & 1) { 326 buf = (buf << 8) | *(uint8_t *)addr; 327 got_bits += 8; 328 addr += 1; 329 len -= 1; 330 } 331 332 if (len >= 2 && addr & 2) { 333 buf = (buf << 16) | *(uint16_t *)addr; 334 got_bits += 16; 335 addr += 2; 336 len -= 2; 337 } 338 339 while (len >= 4) { 340 buf = (buf << 32) | (uint64_t)*(uint32_t *)addr; 341 addr += 4; 342 len -= 4; 343 word = (uint32_t)((buf >> got_bits) & 0xffffffff); 344 345 fifo_fill_level_wait(sc); 346 if (len == 0 && got_bits == 0 && 347 (desc->control & CONTROL_GEN_EOP) != 0) 348 softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA, 349 A_ONCHIP_FIFO_MEM_CORE_EOP); 350 bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, word); 351 } 352 353 if (len & 2) { 354 buf = (buf << 16) | *(uint16_t *)addr; 355 got_bits += 16; 356 addr += 2; 357 len -= 2; 358 } 359 360 if (len & 1) { 361 buf = (buf << 8) | *(uint8_t *)addr; 362 got_bits += 8; 363 addr += 1; 364 len -= 1; 365 } 366 367 if (got_bits >= 32) { 368 got_bits -= 32; 369 word = (uint32_t)((buf >> got_bits) & 0xffffffff); 370 371 fifo_fill_level_wait(sc); 372 if (len == 0 && got_bits == 0 && 373 (desc->control & CONTROL_GEN_EOP) != 0) 374 softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA, 375 A_ONCHIP_FIFO_MEM_CORE_EOP); 376 bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, word); 377 } 378 379 if (got_bits) { 380 missing = 32 - got_bits; 381 got_bits /= 8; 382 383 fifo_fill_level_wait(sc); 384 reg = A_ONCHIP_FIFO_MEM_CORE_EOP | 385 ((4 - got_bits) << A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT); 386 softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA, reg); 387 word = (uint32_t)((buf << missing) & 0xffffffff); 388 bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, word); 389 } 390 391 return (desc->len); 392 } 393 394 static int 395 softdma_process_rx(struct softdma_channel *chan, struct softdma_desc *desc) 396 { 397 uint32_t src_offs, dst_offs; 398 struct softdma_softc *sc; 399 uint32_t fill_level; 400 uint32_t empty; 401 uint32_t meta; 402 uint32_t data; 403 int sop_rcvd; 404 int timeout; 405 size_t len; 406 int error; 407 408 sc = chan->sc; 409 empty = 0; 410 src_offs = dst_offs = 0; 411 error = 0; 412 413 fill_level = softdma_fill_level(sc); 414 if (fill_level == 0) { 415 /* Nothing to receive. */ 416 return (0); 417 } 418 419 len = desc->len; 420 421 sop_rcvd = 0; 422 while (fill_level) { 423 empty = 0; 424 data = bus_read_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA); 425 meta = softdma_mem_read(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA); 426 427 if (meta & A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) { 428 error = 1; 429 break; 430 } 431 432 if ((meta & A_ONCHIP_FIFO_MEM_CORE_CHANNEL_MASK) != 0) { 433 error = 1; 434 break; 435 } 436 437 if (meta & A_ONCHIP_FIFO_MEM_CORE_SOP) { 438 sop_rcvd = 1; 439 } 440 441 if (meta & A_ONCHIP_FIFO_MEM_CORE_EOP) { 442 empty = (meta & A_ONCHIP_FIFO_MEM_CORE_EMPTY_MASK) >> 443 A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT; 444 } 445 446 if (sop_rcvd == 0) { 447 error = 1; 448 break; 449 } 450 451 if (empty == 0) { 452 *(uint32_t *)(desc->dst_addr + dst_offs) = data; 453 dst_offs += 4; 454 } else if (empty == 1) { 455 *(uint16_t *)(desc->dst_addr + dst_offs) = 456 ((data >> 16) & 0xffff); 457 dst_offs += 2; 458 459 *(uint8_t *)(desc->dst_addr + dst_offs) = 460 ((data >> 8) & 0xff); 461 dst_offs += 1; 462 } else { 463 panic("empty %d\n", empty); 464 } 465 466 if (meta & A_ONCHIP_FIFO_MEM_CORE_EOP) 467 break; 468 469 fill_level = softdma_fill_level(sc); 470 timeout = 100; 471 while (fill_level == 0 && timeout--) 472 fill_level = softdma_fill_level(sc); 473 if (timeout == 0) { 474 /* No EOP received. Broken packet. */ 475 error = 1; 476 break; 477 } 478 } 479 480 if (error) { 481 return (-1); 482 } 483 484 return (dst_offs); 485 } 486 487 static uint32_t 488 softdma_process_descriptors(struct softdma_channel *chan, 489 xdma_transfer_status_t *status) 490 { 491 struct xdma_channel *xchan; 492 struct softdma_desc *desc; 493 struct softdma_softc *sc; 494 xdma_transfer_status_t st; 495 int ret; 496 497 sc = chan->sc; 498 499 xchan = chan->xchan; 500 501 desc = &chan->descs[chan->idx_tail]; 502 503 while (desc != NULL) { 504 505 if ((desc->control & CONTROL_OWN) == 0) { 506 break; 507 } 508 509 if (desc->direction == XDMA_MEM_TO_DEV) { 510 ret = softdma_process_tx(chan, desc); 511 } else { 512 ret = softdma_process_rx(chan, desc); 513 if (ret == 0) { 514 /* No new data available. */ 515 break; 516 } 517 } 518 519 /* Descriptor processed. */ 520 desc->control = 0; 521 522 if (ret >= 0) { 523 st.error = 0; 524 st.transferred = ret; 525 } else { 526 st.error = ret; 527 st.transferred = 0; 528 } 529 530 xchan_seg_done(xchan, &st); 531 atomic_subtract_int(&chan->descs_used_count, 1); 532 533 if (ret >= 0) { 534 status->transferred += ret; 535 } else { 536 status->error = 1; 537 break; 538 } 539 540 chan->idx_tail = softdma_next_desc(chan, chan->idx_tail); 541 542 /* Process next descriptor, if any. */ 543 desc = desc->next; 544 } 545 546 return (0); 547 } 548 549 static void 550 softdma_worker(void *arg) 551 { 552 xdma_transfer_status_t status; 553 struct softdma_channel *chan; 554 struct softdma_softc *sc; 555 556 chan = arg; 557 558 sc = chan->sc; 559 560 while (1) { 561 mtx_lock(&chan->mtx); 562 563 do { 564 mtx_sleep(chan, &chan->mtx, 0, "softdma_wait", hz / 2); 565 } while (chan->run == 0); 566 567 status.error = 0; 568 status.transferred = 0; 569 570 softdma_process_descriptors(chan, &status); 571 572 /* Finish operation */ 573 chan->run = 0; 574 xdma_callback(chan->xchan, &status); 575 576 mtx_unlock(&chan->mtx); 577 } 578 579 } 580 581 static int 582 softdma_proc_create(struct softdma_channel *chan) 583 { 584 struct softdma_softc *sc; 585 586 sc = chan->sc; 587 588 if (chan->p != NULL) { 589 /* Already created */ 590 return (0); 591 } 592 593 mtx_init(&chan->mtx, "SoftDMA", NULL, MTX_DEF); 594 595 if (kproc_create(softdma_worker, (void *)chan, &chan->p, 0, 0, 596 "softdma_worker") != 0) { 597 device_printf(sc->dev, 598 "%s: Failed to create worker thread.\n", __func__); 599 return (-1); 600 } 601 602 return (0); 603 } 604 605 static int 606 softdma_channel_alloc(device_t dev, struct xdma_channel *xchan) 607 { 608 struct softdma_channel *chan; 609 struct softdma_softc *sc; 610 int i; 611 612 sc = device_get_softc(dev); 613 614 for (i = 0; i < SOFTDMA_NCHANNELS; i++) { 615 chan = &sc->channels[i]; 616 if (chan->used == 0) { 617 chan->xchan = xchan; 618 xchan->chan = (void *)chan; 619 xchan->caps |= XCHAN_CAP_NOBUFS; 620 xchan->caps |= XCHAN_CAP_NOSEG; 621 chan->index = i; 622 chan->idx_head = 0; 623 chan->idx_tail = 0; 624 chan->descs_used_count = 0; 625 chan->descs_num = 1024; 626 chan->sc = sc; 627 628 if (softdma_proc_create(chan) != 0) { 629 return (-1); 630 } 631 632 chan->used = 1; 633 634 return (0); 635 } 636 } 637 638 return (-1); 639 } 640 641 static int 642 softdma_channel_free(device_t dev, struct xdma_channel *xchan) 643 { 644 struct softdma_channel *chan; 645 struct softdma_softc *sc; 646 647 sc = device_get_softc(dev); 648 649 chan = (struct softdma_channel *)xchan->chan; 650 651 if (chan->descs != NULL) { 652 free(chan->descs, M_DEVBUF); 653 } 654 655 chan->used = 0; 656 657 return (0); 658 } 659 660 static int 661 softdma_desc_alloc(struct xdma_channel *xchan) 662 { 663 struct softdma_channel *chan; 664 uint32_t nsegments; 665 666 chan = (struct softdma_channel *)xchan->chan; 667 668 nsegments = chan->descs_num; 669 670 chan->descs = malloc(nsegments * sizeof(struct softdma_desc), 671 M_DEVBUF, (M_WAITOK | M_ZERO)); 672 673 return (0); 674 } 675 676 static int 677 softdma_channel_prep_sg(device_t dev, struct xdma_channel *xchan) 678 { 679 struct softdma_channel *chan; 680 struct softdma_desc *desc; 681 struct softdma_softc *sc; 682 int ret; 683 int i; 684 685 sc = device_get_softc(dev); 686 687 chan = (struct softdma_channel *)xchan->chan; 688 689 ret = softdma_desc_alloc(xchan); 690 if (ret != 0) { 691 device_printf(sc->dev, 692 "%s: Can't allocate descriptors.\n", __func__); 693 return (-1); 694 } 695 696 for (i = 0; i < chan->descs_num; i++) { 697 desc = &chan->descs[i]; 698 699 if (i == (chan->descs_num - 1)) { 700 desc->next = &chan->descs[0]; 701 } else { 702 desc->next = &chan->descs[i+1]; 703 } 704 } 705 706 return (0); 707 } 708 709 static int 710 softdma_channel_capacity(device_t dev, xdma_channel_t *xchan, 711 uint32_t *capacity) 712 { 713 struct softdma_channel *chan; 714 uint32_t c; 715 716 chan = (struct softdma_channel *)xchan->chan; 717 718 /* At least one descriptor must be left empty. */ 719 c = (chan->descs_num - chan->descs_used_count - 1); 720 721 *capacity = c; 722 723 return (0); 724 } 725 726 static int 727 softdma_channel_submit_sg(device_t dev, struct xdma_channel *xchan, 728 struct xdma_sglist *sg, uint32_t sg_n) 729 { 730 struct softdma_channel *chan; 731 struct softdma_desc *desc; 732 struct softdma_softc *sc; 733 uint32_t enqueued; 734 uint32_t saved_dir; 735 uint32_t tmp; 736 uint32_t len; 737 int i; 738 739 sc = device_get_softc(dev); 740 741 chan = (struct softdma_channel *)xchan->chan; 742 743 enqueued = 0; 744 745 for (i = 0; i < sg_n; i++) { 746 len = (uint32_t)sg[i].len; 747 748 desc = &chan->descs[chan->idx_head]; 749 desc->src_addr = sg[i].src_addr; 750 desc->dst_addr = sg[i].dst_addr; 751 if (sg[i].direction == XDMA_MEM_TO_DEV) { 752 desc->src_incr = 1; 753 desc->dst_incr = 0; 754 } else { 755 desc->src_incr = 0; 756 desc->dst_incr = 1; 757 } 758 desc->direction = sg[i].direction; 759 saved_dir = sg[i].direction; 760 desc->len = len; 761 desc->transfered = 0; 762 desc->status = 0; 763 desc->reserved = 0; 764 desc->control = 0; 765 766 if (sg[i].first == 1) 767 desc->control |= CONTROL_GEN_SOP; 768 if (sg[i].last == 1) 769 desc->control |= CONTROL_GEN_EOP; 770 771 tmp = chan->idx_head; 772 chan->idx_head = softdma_next_desc(chan, chan->idx_head); 773 atomic_add_int(&chan->descs_used_count, 1); 774 desc->control |= CONTROL_OWN; 775 enqueued += 1; 776 } 777 778 if (enqueued == 0) 779 return (0); 780 781 if (saved_dir == XDMA_MEM_TO_DEV) { 782 chan->run = 1; 783 wakeup(chan); 784 } else 785 softdma_memc_write(sc, 786 A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, 787 SOFTDMA_RX_EVENTS); 788 789 return (0); 790 } 791 792 static int 793 softdma_channel_request(device_t dev, struct xdma_channel *xchan, 794 struct xdma_request *req) 795 { 796 struct softdma_channel *chan; 797 struct softdma_desc *desc; 798 struct softdma_softc *sc; 799 int ret; 800 801 sc = device_get_softc(dev); 802 803 chan = (struct softdma_channel *)xchan->chan; 804 805 ret = softdma_desc_alloc(xchan); 806 if (ret != 0) { 807 device_printf(sc->dev, 808 "%s: Can't allocate descriptors.\n", __func__); 809 return (-1); 810 } 811 812 desc = &chan->descs[0]; 813 814 desc->src_addr = req->src_addr; 815 desc->dst_addr = req->dst_addr; 816 desc->len = req->block_len; 817 desc->src_incr = 1; 818 desc->dst_incr = 1; 819 desc->next = NULL; 820 821 return (0); 822 } 823 824 static int 825 softdma_channel_control(device_t dev, xdma_channel_t *xchan, int cmd) 826 { 827 struct softdma_channel *chan; 828 struct softdma_softc *sc; 829 830 sc = device_get_softc(dev); 831 832 chan = (struct softdma_channel *)xchan->chan; 833 834 switch (cmd) { 835 case XDMA_CMD_BEGIN: 836 case XDMA_CMD_TERMINATE: 837 case XDMA_CMD_PAUSE: 838 /* TODO: implement me */ 839 return (-1); 840 } 841 842 return (0); 843 } 844 845 #ifdef FDT 846 static int 847 softdma_ofw_md_data(device_t dev, pcell_t *cells, 848 int ncells, void **ptr) 849 { 850 851 return (0); 852 } 853 #endif 854 855 static device_method_t softdma_methods[] = { 856 /* Device interface */ 857 DEVMETHOD(device_probe, softdma_probe), 858 DEVMETHOD(device_attach, softdma_attach), 859 DEVMETHOD(device_detach, softdma_detach), 860 861 /* xDMA Interface */ 862 DEVMETHOD(xdma_channel_alloc, softdma_channel_alloc), 863 DEVMETHOD(xdma_channel_free, softdma_channel_free), 864 DEVMETHOD(xdma_channel_request, softdma_channel_request), 865 DEVMETHOD(xdma_channel_control, softdma_channel_control), 866 867 /* xDMA SG Interface */ 868 DEVMETHOD(xdma_channel_prep_sg, softdma_channel_prep_sg), 869 DEVMETHOD(xdma_channel_submit_sg, softdma_channel_submit_sg), 870 DEVMETHOD(xdma_channel_capacity, softdma_channel_capacity), 871 872 #ifdef FDT 873 DEVMETHOD(xdma_ofw_md_data, softdma_ofw_md_data), 874 #endif 875 876 DEVMETHOD_END 877 }; 878 879 static driver_t softdma_driver = { 880 "softdma", 881 softdma_methods, 882 sizeof(struct softdma_softc), 883 }; 884 885 static devclass_t softdma_devclass; 886 887 EARLY_DRIVER_MODULE(softdma, simplebus, softdma_driver, softdma_devclass, 0, 0, 888 BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); 889