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