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 if ((desc->control & CONTROL_OWN) == 0) { 505 break; 506 } 507 508 if (desc->direction == XDMA_MEM_TO_DEV) { 509 ret = softdma_process_tx(chan, desc); 510 } else { 511 ret = softdma_process_rx(chan, desc); 512 if (ret == 0) { 513 /* No new data available. */ 514 break; 515 } 516 } 517 518 /* Descriptor processed. */ 519 desc->control = 0; 520 521 if (ret >= 0) { 522 st.error = 0; 523 st.transferred = ret; 524 } else { 525 st.error = ret; 526 st.transferred = 0; 527 } 528 529 xchan_seg_done(xchan, &st); 530 atomic_subtract_int(&chan->descs_used_count, 1); 531 532 if (ret >= 0) { 533 status->transferred += ret; 534 } else { 535 status->error = 1; 536 break; 537 } 538 539 chan->idx_tail = softdma_next_desc(chan, chan->idx_tail); 540 541 /* Process next descriptor, if any. */ 542 desc = desc->next; 543 } 544 545 return (0); 546 } 547 548 static void 549 softdma_worker(void *arg) 550 { 551 xdma_transfer_status_t status; 552 struct softdma_channel *chan; 553 struct softdma_softc *sc; 554 555 chan = arg; 556 557 sc = chan->sc; 558 559 while (1) { 560 mtx_lock(&chan->mtx); 561 562 do { 563 mtx_sleep(chan, &chan->mtx, 0, "softdma_wait", hz / 2); 564 } while (chan->run == 0); 565 566 status.error = 0; 567 status.transferred = 0; 568 569 softdma_process_descriptors(chan, &status); 570 571 /* Finish operation */ 572 chan->run = 0; 573 xdma_callback(chan->xchan, &status); 574 575 mtx_unlock(&chan->mtx); 576 } 577 578 } 579 580 static int 581 softdma_proc_create(struct softdma_channel *chan) 582 { 583 struct softdma_softc *sc; 584 585 sc = chan->sc; 586 587 if (chan->p != NULL) { 588 /* Already created */ 589 return (0); 590 } 591 592 mtx_init(&chan->mtx, "SoftDMA", NULL, MTX_DEF); 593 594 if (kproc_create(softdma_worker, (void *)chan, &chan->p, 0, 0, 595 "softdma_worker") != 0) { 596 device_printf(sc->dev, 597 "%s: Failed to create worker thread.\n", __func__); 598 return (-1); 599 } 600 601 return (0); 602 } 603 604 static int 605 softdma_channel_alloc(device_t dev, struct xdma_channel *xchan) 606 { 607 struct softdma_channel *chan; 608 struct softdma_softc *sc; 609 int i; 610 611 sc = device_get_softc(dev); 612 613 for (i = 0; i < SOFTDMA_NCHANNELS; i++) { 614 chan = &sc->channels[i]; 615 if (chan->used == 0) { 616 chan->xchan = xchan; 617 xchan->chan = (void *)chan; 618 xchan->caps |= XCHAN_CAP_NOSEG; 619 chan->index = i; 620 chan->idx_head = 0; 621 chan->idx_tail = 0; 622 chan->descs_used_count = 0; 623 chan->descs_num = 1024; 624 chan->sc = sc; 625 626 if (softdma_proc_create(chan) != 0) { 627 return (-1); 628 } 629 630 chan->used = 1; 631 632 return (0); 633 } 634 } 635 636 return (-1); 637 } 638 639 static int 640 softdma_channel_free(device_t dev, struct xdma_channel *xchan) 641 { 642 struct softdma_channel *chan; 643 struct softdma_softc *sc; 644 645 sc = device_get_softc(dev); 646 647 chan = (struct softdma_channel *)xchan->chan; 648 649 if (chan->descs != NULL) { 650 free(chan->descs, M_DEVBUF); 651 } 652 653 chan->used = 0; 654 655 return (0); 656 } 657 658 static int 659 softdma_desc_alloc(struct xdma_channel *xchan) 660 { 661 struct softdma_channel *chan; 662 uint32_t nsegments; 663 664 chan = (struct softdma_channel *)xchan->chan; 665 666 nsegments = chan->descs_num; 667 668 chan->descs = malloc(nsegments * sizeof(struct softdma_desc), 669 M_DEVBUF, (M_WAITOK | M_ZERO)); 670 671 return (0); 672 } 673 674 static int 675 softdma_channel_prep_sg(device_t dev, struct xdma_channel *xchan) 676 { 677 struct softdma_channel *chan; 678 struct softdma_desc *desc; 679 struct softdma_softc *sc; 680 int ret; 681 int i; 682 683 sc = device_get_softc(dev); 684 685 chan = (struct softdma_channel *)xchan->chan; 686 687 ret = softdma_desc_alloc(xchan); 688 if (ret != 0) { 689 device_printf(sc->dev, 690 "%s: Can't allocate descriptors.\n", __func__); 691 return (-1); 692 } 693 694 for (i = 0; i < chan->descs_num; i++) { 695 desc = &chan->descs[i]; 696 697 if (i == (chan->descs_num - 1)) { 698 desc->next = &chan->descs[0]; 699 } else { 700 desc->next = &chan->descs[i+1]; 701 } 702 } 703 704 return (0); 705 } 706 707 static int 708 softdma_channel_capacity(device_t dev, xdma_channel_t *xchan, 709 uint32_t *capacity) 710 { 711 struct softdma_channel *chan; 712 uint32_t c; 713 714 chan = (struct softdma_channel *)xchan->chan; 715 716 /* At least one descriptor must be left empty. */ 717 c = (chan->descs_num - chan->descs_used_count - 1); 718 719 *capacity = c; 720 721 return (0); 722 } 723 724 static int 725 softdma_channel_submit_sg(device_t dev, struct xdma_channel *xchan, 726 struct xdma_sglist *sg, uint32_t sg_n) 727 { 728 struct softdma_channel *chan; 729 struct softdma_desc *desc; 730 struct softdma_softc *sc; 731 uint32_t enqueued; 732 uint32_t saved_dir; 733 uint32_t tmp; 734 uint32_t len; 735 int i; 736 737 sc = device_get_softc(dev); 738 739 chan = (struct softdma_channel *)xchan->chan; 740 741 enqueued = 0; 742 743 for (i = 0; i < sg_n; i++) { 744 len = (uint32_t)sg[i].len; 745 746 desc = &chan->descs[chan->idx_head]; 747 desc->src_addr = sg[i].src_addr; 748 desc->dst_addr = sg[i].dst_addr; 749 if (sg[i].direction == XDMA_MEM_TO_DEV) { 750 desc->src_incr = 1; 751 desc->dst_incr = 0; 752 } else { 753 desc->src_incr = 0; 754 desc->dst_incr = 1; 755 } 756 desc->direction = sg[i].direction; 757 saved_dir = sg[i].direction; 758 desc->len = len; 759 desc->transfered = 0; 760 desc->status = 0; 761 desc->reserved = 0; 762 desc->control = 0; 763 764 if (sg[i].first == 1) 765 desc->control |= CONTROL_GEN_SOP; 766 if (sg[i].last == 1) 767 desc->control |= CONTROL_GEN_EOP; 768 769 tmp = chan->idx_head; 770 chan->idx_head = softdma_next_desc(chan, chan->idx_head); 771 atomic_add_int(&chan->descs_used_count, 1); 772 desc->control |= CONTROL_OWN; 773 enqueued += 1; 774 } 775 776 if (enqueued == 0) 777 return (0); 778 779 if (saved_dir == XDMA_MEM_TO_DEV) { 780 chan->run = 1; 781 wakeup(chan); 782 } else 783 softdma_memc_write(sc, 784 A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, 785 SOFTDMA_RX_EVENTS); 786 787 return (0); 788 } 789 790 static int 791 softdma_channel_request(device_t dev, struct xdma_channel *xchan, 792 struct xdma_request *req) 793 { 794 struct softdma_channel *chan; 795 struct softdma_desc *desc; 796 struct softdma_softc *sc; 797 int ret; 798 799 sc = device_get_softc(dev); 800 801 chan = (struct softdma_channel *)xchan->chan; 802 803 ret = softdma_desc_alloc(xchan); 804 if (ret != 0) { 805 device_printf(sc->dev, 806 "%s: Can't allocate descriptors.\n", __func__); 807 return (-1); 808 } 809 810 desc = &chan->descs[0]; 811 812 desc->src_addr = req->src_addr; 813 desc->dst_addr = req->dst_addr; 814 desc->len = req->block_len; 815 desc->src_incr = 1; 816 desc->dst_incr = 1; 817 desc->next = NULL; 818 819 return (0); 820 } 821 822 static int 823 softdma_channel_control(device_t dev, xdma_channel_t *xchan, int cmd) 824 { 825 struct softdma_channel *chan; 826 struct softdma_softc *sc; 827 828 sc = device_get_softc(dev); 829 830 chan = (struct softdma_channel *)xchan->chan; 831 832 switch (cmd) { 833 case XDMA_CMD_BEGIN: 834 case XDMA_CMD_TERMINATE: 835 case XDMA_CMD_PAUSE: 836 /* TODO: implement me */ 837 return (-1); 838 } 839 840 return (0); 841 } 842 843 #ifdef FDT 844 static int 845 softdma_ofw_md_data(device_t dev, pcell_t *cells, 846 int ncells, void **ptr) 847 { 848 849 return (0); 850 } 851 #endif 852 853 static device_method_t softdma_methods[] = { 854 /* Device interface */ 855 DEVMETHOD(device_probe, softdma_probe), 856 DEVMETHOD(device_attach, softdma_attach), 857 DEVMETHOD(device_detach, softdma_detach), 858 859 /* xDMA Interface */ 860 DEVMETHOD(xdma_channel_alloc, softdma_channel_alloc), 861 DEVMETHOD(xdma_channel_free, softdma_channel_free), 862 DEVMETHOD(xdma_channel_request, softdma_channel_request), 863 DEVMETHOD(xdma_channel_control, softdma_channel_control), 864 865 /* xDMA SG Interface */ 866 DEVMETHOD(xdma_channel_prep_sg, softdma_channel_prep_sg), 867 DEVMETHOD(xdma_channel_submit_sg, softdma_channel_submit_sg), 868 DEVMETHOD(xdma_channel_capacity, softdma_channel_capacity), 869 870 #ifdef FDT 871 DEVMETHOD(xdma_ofw_md_data, softdma_ofw_md_data), 872 #endif 873 874 DEVMETHOD_END 875 }; 876 877 static driver_t softdma_driver = { 878 "softdma", 879 softdma_methods, 880 sizeof(struct softdma_softc), 881 }; 882 883 EARLY_DRIVER_MODULE(softdma, simplebus, softdma_driver, 0, 0, 884 BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); 885