1 /*- 2 * Copyright (c) 2017-2018 Ruslan Bukin <br@bsdpad.com> 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_NOSEG; 620 chan->index = i; 621 chan->idx_head = 0; 622 chan->idx_tail = 0; 623 chan->descs_used_count = 0; 624 chan->descs_num = 1024; 625 chan->sc = sc; 626 627 if (softdma_proc_create(chan) != 0) { 628 return (-1); 629 } 630 631 chan->used = 1; 632 633 return (0); 634 } 635 } 636 637 return (-1); 638 } 639 640 static int 641 softdma_channel_free(device_t dev, struct xdma_channel *xchan) 642 { 643 struct softdma_channel *chan; 644 struct softdma_softc *sc; 645 646 sc = device_get_softc(dev); 647 648 chan = (struct softdma_channel *)xchan->chan; 649 650 if (chan->descs != NULL) { 651 free(chan->descs, M_DEVBUF); 652 } 653 654 chan->used = 0; 655 656 return (0); 657 } 658 659 static int 660 softdma_desc_alloc(struct xdma_channel *xchan) 661 { 662 struct softdma_channel *chan; 663 uint32_t nsegments; 664 665 chan = (struct softdma_channel *)xchan->chan; 666 667 nsegments = chan->descs_num; 668 669 chan->descs = malloc(nsegments * sizeof(struct softdma_desc), 670 M_DEVBUF, (M_WAITOK | M_ZERO)); 671 672 return (0); 673 } 674 675 static int 676 softdma_channel_prep_sg(device_t dev, struct xdma_channel *xchan) 677 { 678 struct softdma_channel *chan; 679 struct softdma_desc *desc; 680 struct softdma_softc *sc; 681 int ret; 682 int i; 683 684 sc = device_get_softc(dev); 685 686 chan = (struct softdma_channel *)xchan->chan; 687 688 ret = softdma_desc_alloc(xchan); 689 if (ret != 0) { 690 device_printf(sc->dev, 691 "%s: Can't allocate descriptors.\n", __func__); 692 return (-1); 693 } 694 695 for (i = 0; i < chan->descs_num; i++) { 696 desc = &chan->descs[i]; 697 698 if (i == (chan->descs_num - 1)) { 699 desc->next = &chan->descs[0]; 700 } else { 701 desc->next = &chan->descs[i+1]; 702 } 703 } 704 705 return (0); 706 } 707 708 static int 709 softdma_channel_capacity(device_t dev, xdma_channel_t *xchan, 710 uint32_t *capacity) 711 { 712 struct softdma_channel *chan; 713 uint32_t c; 714 715 chan = (struct softdma_channel *)xchan->chan; 716 717 /* At least one descriptor must be left empty. */ 718 c = (chan->descs_num - chan->descs_used_count - 1); 719 720 *capacity = c; 721 722 return (0); 723 } 724 725 static int 726 softdma_channel_submit_sg(device_t dev, struct xdma_channel *xchan, 727 struct xdma_sglist *sg, uint32_t sg_n) 728 { 729 struct softdma_channel *chan; 730 struct softdma_desc *desc; 731 struct softdma_softc *sc; 732 uint32_t enqueued; 733 uint32_t saved_dir; 734 uint32_t tmp; 735 uint32_t len; 736 int i; 737 738 sc = device_get_softc(dev); 739 740 chan = (struct softdma_channel *)xchan->chan; 741 742 enqueued = 0; 743 744 for (i = 0; i < sg_n; i++) { 745 len = (uint32_t)sg[i].len; 746 747 desc = &chan->descs[chan->idx_head]; 748 desc->src_addr = sg[i].src_addr; 749 desc->dst_addr = sg[i].dst_addr; 750 if (sg[i].direction == XDMA_MEM_TO_DEV) { 751 desc->src_incr = 1; 752 desc->dst_incr = 0; 753 } else { 754 desc->src_incr = 0; 755 desc->dst_incr = 1; 756 } 757 desc->direction = sg[i].direction; 758 saved_dir = sg[i].direction; 759 desc->len = len; 760 desc->transfered = 0; 761 desc->status = 0; 762 desc->reserved = 0; 763 desc->control = 0; 764 765 if (sg[i].first == 1) 766 desc->control |= CONTROL_GEN_SOP; 767 if (sg[i].last == 1) 768 desc->control |= CONTROL_GEN_EOP; 769 770 tmp = chan->idx_head; 771 chan->idx_head = softdma_next_desc(chan, chan->idx_head); 772 atomic_add_int(&chan->descs_used_count, 1); 773 desc->control |= CONTROL_OWN; 774 enqueued += 1; 775 } 776 777 if (enqueued == 0) 778 return (0); 779 780 if (saved_dir == XDMA_MEM_TO_DEV) { 781 chan->run = 1; 782 wakeup(chan); 783 } else 784 softdma_memc_write(sc, 785 A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, 786 SOFTDMA_RX_EVENTS); 787 788 return (0); 789 } 790 791 static int 792 softdma_channel_request(device_t dev, struct xdma_channel *xchan, 793 struct xdma_request *req) 794 { 795 struct softdma_channel *chan; 796 struct softdma_desc *desc; 797 struct softdma_softc *sc; 798 int ret; 799 800 sc = device_get_softc(dev); 801 802 chan = (struct softdma_channel *)xchan->chan; 803 804 ret = softdma_desc_alloc(xchan); 805 if (ret != 0) { 806 device_printf(sc->dev, 807 "%s: Can't allocate descriptors.\n", __func__); 808 return (-1); 809 } 810 811 desc = &chan->descs[0]; 812 813 desc->src_addr = req->src_addr; 814 desc->dst_addr = req->dst_addr; 815 desc->len = req->block_len; 816 desc->src_incr = 1; 817 desc->dst_incr = 1; 818 desc->next = NULL; 819 820 return (0); 821 } 822 823 static int 824 softdma_channel_control(device_t dev, xdma_channel_t *xchan, int cmd) 825 { 826 struct softdma_channel *chan; 827 struct softdma_softc *sc; 828 829 sc = device_get_softc(dev); 830 831 chan = (struct softdma_channel *)xchan->chan; 832 833 switch (cmd) { 834 case XDMA_CMD_BEGIN: 835 case XDMA_CMD_TERMINATE: 836 case XDMA_CMD_PAUSE: 837 /* TODO: implement me */ 838 return (-1); 839 } 840 841 return (0); 842 } 843 844 #ifdef FDT 845 static int 846 softdma_ofw_md_data(device_t dev, pcell_t *cells, 847 int ncells, void **ptr) 848 { 849 850 return (0); 851 } 852 #endif 853 854 static device_method_t softdma_methods[] = { 855 /* Device interface */ 856 DEVMETHOD(device_probe, softdma_probe), 857 DEVMETHOD(device_attach, softdma_attach), 858 DEVMETHOD(device_detach, softdma_detach), 859 860 /* xDMA Interface */ 861 DEVMETHOD(xdma_channel_alloc, softdma_channel_alloc), 862 DEVMETHOD(xdma_channel_free, softdma_channel_free), 863 DEVMETHOD(xdma_channel_request, softdma_channel_request), 864 DEVMETHOD(xdma_channel_control, softdma_channel_control), 865 866 /* xDMA SG Interface */ 867 DEVMETHOD(xdma_channel_prep_sg, softdma_channel_prep_sg), 868 DEVMETHOD(xdma_channel_submit_sg, softdma_channel_submit_sg), 869 DEVMETHOD(xdma_channel_capacity, softdma_channel_capacity), 870 871 #ifdef FDT 872 DEVMETHOD(xdma_ofw_md_data, softdma_ofw_md_data), 873 #endif 874 875 DEVMETHOD_END 876 }; 877 878 static driver_t softdma_driver = { 879 "softdma", 880 softdma_methods, 881 sizeof(struct softdma_softc), 882 }; 883 884 static devclass_t softdma_devclass; 885 886 EARLY_DRIVER_MODULE(softdma, simplebus, softdma_driver, softdma_devclass, 0, 0, 887 BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); 888