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 void 194 softdma_intr(void *arg) 195 { 196 struct softdma_channel *chan; 197 struct softdma_softc *sc; 198 int reg; 199 int err; 200 201 sc = arg; 202 203 chan = &sc->channels[0]; 204 205 reg = softdma_memc_read(sc, A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT); 206 207 if (reg & (A_ONCHIP_FIFO_MEM_CORE_EVENT_OVERFLOW | 208 A_ONCHIP_FIFO_MEM_CORE_EVENT_UNDERFLOW)) { 209 /* Errors */ 210 err = (((reg & A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) >> \ 211 A_ONCHIP_FIFO_MEM_CORE_ERROR_SHIFT) & 0xff); 212 } 213 214 if (reg != 0) { 215 softdma_memc_write(sc, 216 A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, reg); 217 chan->run = 1; 218 wakeup(chan); 219 } 220 } 221 222 static int 223 softdma_probe(device_t dev) 224 { 225 226 if (!ofw_bus_status_okay(dev)) 227 return (ENXIO); 228 229 if (!ofw_bus_is_compatible(dev, "altr,softdma")) 230 return (ENXIO); 231 232 device_set_desc(dev, "SoftDMA"); 233 234 return (BUS_PROBE_DEFAULT); 235 } 236 237 static int 238 softdma_attach(device_t dev) 239 { 240 struct softdma_softc *sc; 241 phandle_t xref, node; 242 int err; 243 244 sc = device_get_softc(dev); 245 sc->dev = dev; 246 247 if (bus_alloc_resources(dev, softdma_spec, sc->res)) { 248 device_printf(dev, 249 "could not allocate resources for device\n"); 250 return (ENXIO); 251 } 252 253 /* FIFO memory interface */ 254 sc->bst = rman_get_bustag(sc->res[0]); 255 sc->bsh = rman_get_bushandle(sc->res[0]); 256 257 /* FIFO control memory interface */ 258 sc->bst_c = rman_get_bustag(sc->res[1]); 259 sc->bsh_c = rman_get_bushandle(sc->res[1]); 260 261 /* Setup interrupt handler */ 262 err = bus_setup_intr(dev, sc->res[2], INTR_TYPE_MISC | INTR_MPSAFE, 263 NULL, softdma_intr, sc, &sc->ih); 264 if (err) { 265 device_printf(dev, "Unable to alloc interrupt resource.\n"); 266 return (ENXIO); 267 } 268 269 node = ofw_bus_get_node(dev); 270 xref = OF_xref_from_node(node); 271 OF_device_register_xref(xref, dev); 272 273 return (0); 274 } 275 276 static int 277 softdma_detach(device_t dev) 278 { 279 struct softdma_softc *sc; 280 281 sc = device_get_softc(dev); 282 283 return (0); 284 } 285 286 static int 287 softdma_process_tx(struct softdma_channel *chan, struct softdma_desc *desc) 288 { 289 struct softdma_softc *sc; 290 uint32_t src_offs, dst_offs; 291 uint32_t reg; 292 uint32_t fill_level; 293 uint32_t leftm; 294 uint32_t tmp; 295 uint32_t val; 296 uint32_t c; 297 298 sc = chan->sc; 299 300 fill_level = softdma_fill_level(sc); 301 while (fill_level == AVALON_FIFO_TX_BASIC_OPTS_DEPTH) 302 fill_level = softdma_fill_level(sc); 303 304 /* Set start of packet. */ 305 if (desc->control & CONTROL_GEN_SOP) { 306 reg = 0; 307 reg |= A_ONCHIP_FIFO_MEM_CORE_SOP; 308 softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA, reg); 309 } 310 311 src_offs = dst_offs = 0; 312 c = 0; 313 while ((desc->len - c) >= 4) { 314 val = *(uint32_t *)(desc->src_addr + src_offs); 315 bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, val); 316 if (desc->src_incr) 317 src_offs += 4; 318 if (desc->dst_incr) 319 dst_offs += 4; 320 fill_level += 1; 321 322 while (fill_level == AVALON_FIFO_TX_BASIC_OPTS_DEPTH) { 323 fill_level = softdma_fill_level(sc); 324 } 325 c += 4; 326 } 327 328 val = 0; 329 leftm = (desc->len - c); 330 331 switch (leftm) { 332 case 1: 333 val = *(uint8_t *)(desc->src_addr + src_offs); 334 val <<= 24; 335 src_offs += 1; 336 break; 337 case 2: 338 case 3: 339 val = *(uint16_t *)(desc->src_addr + src_offs); 340 val <<= 16; 341 src_offs += 2; 342 343 if (leftm == 3) { 344 tmp = *(uint8_t *)(desc->src_addr + src_offs); 345 val |= (tmp << 8); 346 src_offs += 1; 347 } 348 break; 349 case 0: 350 default: 351 break; 352 } 353 354 /* Set end of packet. */ 355 reg = 0; 356 if (desc->control & CONTROL_GEN_EOP) 357 reg |= A_ONCHIP_FIFO_MEM_CORE_EOP; 358 reg |= ((4 - leftm) << A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT); 359 softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA, reg); 360 361 /* Ensure there is a FIFO entry available. */ 362 fill_level = softdma_fill_level(sc); 363 while (fill_level == AVALON_FIFO_TX_BASIC_OPTS_DEPTH) 364 fill_level = softdma_fill_level(sc); 365 366 /* Final write */ 367 bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, val); 368 369 return (dst_offs); 370 } 371 372 static int 373 softdma_process_rx(struct softdma_channel *chan, struct softdma_desc *desc) 374 { 375 uint32_t src_offs, dst_offs; 376 struct softdma_softc *sc; 377 uint32_t fill_level; 378 uint32_t empty; 379 uint32_t meta; 380 uint32_t data; 381 int sop_rcvd; 382 int timeout; 383 size_t len; 384 int error; 385 386 sc = chan->sc; 387 empty = 0; 388 src_offs = dst_offs = 0; 389 error = 0; 390 391 fill_level = softdma_fill_level(sc); 392 if (fill_level == 0) { 393 /* Nothing to receive. */ 394 return (0); 395 } 396 397 len = desc->len; 398 399 sop_rcvd = 0; 400 while (fill_level) { 401 empty = 0; 402 data = bus_read_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA); 403 meta = softdma_mem_read(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA); 404 405 if (meta & A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) { 406 error = 1; 407 break; 408 } 409 410 if ((meta & A_ONCHIP_FIFO_MEM_CORE_CHANNEL_MASK) != 0) { 411 error = 1; 412 break; 413 } 414 415 if (meta & A_ONCHIP_FIFO_MEM_CORE_SOP) { 416 sop_rcvd = 1; 417 } 418 419 if (meta & A_ONCHIP_FIFO_MEM_CORE_EOP) { 420 empty = (meta & A_ONCHIP_FIFO_MEM_CORE_EMPTY_MASK) >> 421 A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT; 422 } 423 424 if (sop_rcvd == 0) { 425 error = 1; 426 break; 427 } 428 429 if (empty == 0) { 430 *(uint32_t *)(desc->dst_addr + dst_offs) = data; 431 dst_offs += 4; 432 } else if (empty == 1) { 433 *(uint16_t *)(desc->dst_addr + dst_offs) = 434 ((data >> 16) & 0xffff); 435 dst_offs += 2; 436 437 *(uint8_t *)(desc->dst_addr + dst_offs) = 438 ((data >> 8) & 0xff); 439 dst_offs += 1; 440 } else { 441 panic("empty %d\n", empty); 442 } 443 444 if (meta & A_ONCHIP_FIFO_MEM_CORE_EOP) 445 break; 446 447 fill_level = softdma_fill_level(sc); 448 timeout = 100; 449 while (fill_level == 0 && timeout--) 450 fill_level = softdma_fill_level(sc); 451 if (timeout == 0) { 452 /* No EOP received. Broken packet. */ 453 error = 1; 454 break; 455 } 456 } 457 458 if (error) { 459 return (-1); 460 } 461 462 return (dst_offs); 463 } 464 465 static uint32_t 466 softdma_process_descriptors(struct softdma_channel *chan, 467 xdma_transfer_status_t *status) 468 { 469 struct xdma_channel *xchan; 470 struct softdma_desc *desc; 471 struct softdma_softc *sc; 472 xdma_transfer_status_t st; 473 int ret; 474 475 sc = chan->sc; 476 477 xchan = chan->xchan; 478 479 desc = &chan->descs[chan->idx_tail]; 480 481 while (desc != NULL) { 482 483 if ((desc->control & CONTROL_OWN) == 0) { 484 break; 485 } 486 487 if (desc->direction == XDMA_MEM_TO_DEV) { 488 ret = softdma_process_tx(chan, desc); 489 } else { 490 ret = softdma_process_rx(chan, desc); 491 if (ret == 0) { 492 /* No new data available. */ 493 break; 494 } 495 } 496 497 /* Descriptor processed. */ 498 desc->control = 0; 499 500 if (ret >= 0) { 501 st.error = 0; 502 st.transferred = ret; 503 } else { 504 st.error = ret; 505 st.transferred = 0; 506 } 507 508 xchan_seg_done(xchan, &st); 509 atomic_subtract_int(&chan->descs_used_count, 1); 510 511 if (ret >= 0) { 512 status->transferred += ret; 513 } else { 514 status->error = 1; 515 break; 516 } 517 518 chan->idx_tail = softdma_next_desc(chan, chan->idx_tail); 519 520 /* Process next descriptor, if any. */ 521 desc = desc->next; 522 } 523 524 return (0); 525 } 526 527 static void 528 softdma_worker(void *arg) 529 { 530 xdma_transfer_status_t status; 531 struct softdma_channel *chan; 532 struct softdma_softc *sc; 533 534 chan = arg; 535 536 sc = chan->sc; 537 538 while (1) { 539 mtx_lock(&chan->mtx); 540 541 do { 542 mtx_sleep(chan, &chan->mtx, 0, "softdma_wait", hz / 2); 543 } while (chan->run == 0); 544 545 status.error = 0; 546 status.transferred = 0; 547 548 softdma_process_descriptors(chan, &status); 549 550 /* Finish operation */ 551 chan->run = 0; 552 xdma_callback(chan->xchan, &status); 553 554 mtx_unlock(&chan->mtx); 555 } 556 557 } 558 559 static int 560 softdma_proc_create(struct softdma_channel *chan) 561 { 562 struct softdma_softc *sc; 563 564 sc = chan->sc; 565 566 if (chan->p != NULL) { 567 /* Already created */ 568 return (0); 569 } 570 571 mtx_init(&chan->mtx, "SoftDMA", NULL, MTX_DEF); 572 573 if (kproc_create(softdma_worker, (void *)chan, &chan->p, 0, 0, 574 "softdma_worker") != 0) { 575 device_printf(sc->dev, 576 "%s: Failed to create worker thread.\n", __func__); 577 return (-1); 578 } 579 580 return (0); 581 } 582 583 static int 584 softdma_channel_alloc(device_t dev, struct xdma_channel *xchan) 585 { 586 struct softdma_channel *chan; 587 struct softdma_softc *sc; 588 int i; 589 590 sc = device_get_softc(dev); 591 592 for (i = 0; i < SOFTDMA_NCHANNELS; i++) { 593 chan = &sc->channels[i]; 594 if (chan->used == 0) { 595 chan->xchan = xchan; 596 xchan->chan = (void *)chan; 597 chan->index = i; 598 chan->idx_head = 0; 599 chan->idx_tail = 0; 600 chan->descs_used_count = 0; 601 chan->descs_num = 1024; 602 chan->sc = sc; 603 604 if (softdma_proc_create(chan) != 0) { 605 return (-1); 606 } 607 608 chan->used = 1; 609 610 return (0); 611 } 612 } 613 614 return (-1); 615 } 616 617 static int 618 softdma_channel_free(device_t dev, struct xdma_channel *xchan) 619 { 620 struct softdma_channel *chan; 621 struct softdma_softc *sc; 622 623 sc = device_get_softc(dev); 624 625 chan = (struct softdma_channel *)xchan->chan; 626 627 if (chan->descs != NULL) { 628 free(chan->descs, M_DEVBUF); 629 } 630 631 chan->used = 0; 632 633 return (0); 634 } 635 636 static int 637 softdma_desc_alloc(struct xdma_channel *xchan) 638 { 639 struct softdma_channel *chan; 640 uint32_t nsegments; 641 642 chan = (struct softdma_channel *)xchan->chan; 643 644 nsegments = chan->descs_num; 645 646 chan->descs = malloc(nsegments * sizeof(struct softdma_desc), 647 M_DEVBUF, (M_WAITOK | M_ZERO)); 648 649 return (0); 650 } 651 652 static int 653 softdma_channel_prep_sg(device_t dev, struct xdma_channel *xchan) 654 { 655 struct softdma_channel *chan; 656 struct softdma_desc *desc; 657 struct softdma_softc *sc; 658 int ret; 659 int i; 660 661 sc = device_get_softc(dev); 662 663 chan = (struct softdma_channel *)xchan->chan; 664 665 ret = softdma_desc_alloc(xchan); 666 if (ret != 0) { 667 device_printf(sc->dev, 668 "%s: Can't allocate descriptors.\n", __func__); 669 return (-1); 670 } 671 672 for (i = 0; i < chan->descs_num; i++) { 673 desc = &chan->descs[i]; 674 675 if (i == (chan->descs_num - 1)) { 676 desc->next = &chan->descs[0]; 677 } else { 678 desc->next = &chan->descs[i+1]; 679 } 680 } 681 682 return (0); 683 } 684 685 static int 686 softdma_channel_capacity(device_t dev, xdma_channel_t *xchan, 687 uint32_t *capacity) 688 { 689 struct softdma_channel *chan; 690 uint32_t c; 691 692 chan = (struct softdma_channel *)xchan->chan; 693 694 /* At least one descriptor must be left empty. */ 695 c = (chan->descs_num - chan->descs_used_count - 1); 696 697 *capacity = c; 698 699 return (0); 700 } 701 702 static int 703 softdma_channel_submit_sg(device_t dev, struct xdma_channel *xchan, 704 struct xdma_sglist *sg, uint32_t sg_n) 705 { 706 struct softdma_channel *chan; 707 struct softdma_desc *desc; 708 struct softdma_softc *sc; 709 uint32_t enqueued; 710 uint32_t saved_dir; 711 uint32_t tmp; 712 uint32_t len; 713 int i; 714 715 sc = device_get_softc(dev); 716 717 chan = (struct softdma_channel *)xchan->chan; 718 719 enqueued = 0; 720 721 for (i = 0; i < sg_n; i++) { 722 len = (uint32_t)sg[i].len; 723 724 desc = &chan->descs[chan->idx_head]; 725 desc->src_addr = sg[i].src_addr; 726 desc->dst_addr = sg[i].dst_addr; 727 if (sg[i].direction == XDMA_MEM_TO_DEV) { 728 desc->src_incr = 1; 729 desc->dst_incr = 0; 730 } else { 731 desc->src_incr = 0; 732 desc->dst_incr = 1; 733 } 734 desc->direction = sg[i].direction; 735 saved_dir = sg[i].direction; 736 desc->len = len; 737 desc->transfered = 0; 738 desc->status = 0; 739 desc->reserved = 0; 740 desc->control = 0; 741 742 if (sg[i].first == 1) 743 desc->control |= CONTROL_GEN_SOP; 744 if (sg[i].last == 1) 745 desc->control |= CONTROL_GEN_EOP; 746 747 tmp = chan->idx_head; 748 chan->idx_head = softdma_next_desc(chan, chan->idx_head); 749 atomic_add_int(&chan->descs_used_count, 1); 750 desc->control |= CONTROL_OWN; 751 enqueued += 1; 752 } 753 754 if (enqueued == 0) 755 return (0); 756 757 if (saved_dir == XDMA_MEM_TO_DEV) { 758 chan->run = 1; 759 wakeup(chan); 760 } else 761 softdma_memc_write(sc, 762 A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, 763 SOFTDMA_RX_EVENTS); 764 765 return (0); 766 } 767 768 static int 769 softdma_channel_request(device_t dev, struct xdma_channel *xchan, 770 struct xdma_request *req) 771 { 772 struct softdma_channel *chan; 773 struct softdma_desc *desc; 774 struct softdma_softc *sc; 775 int ret; 776 777 sc = device_get_softc(dev); 778 779 chan = (struct softdma_channel *)xchan->chan; 780 781 ret = softdma_desc_alloc(xchan); 782 if (ret != 0) { 783 device_printf(sc->dev, 784 "%s: Can't allocate descriptors.\n", __func__); 785 return (-1); 786 } 787 788 desc = &chan->descs[0]; 789 790 desc->src_addr = req->src_addr; 791 desc->dst_addr = req->dst_addr; 792 desc->len = req->block_len; 793 desc->src_incr = 1; 794 desc->dst_incr = 1; 795 desc->next = NULL; 796 797 return (0); 798 } 799 800 static int 801 softdma_channel_control(device_t dev, xdma_channel_t *xchan, int cmd) 802 { 803 struct softdma_channel *chan; 804 struct softdma_softc *sc; 805 806 sc = device_get_softc(dev); 807 808 chan = (struct softdma_channel *)xchan->chan; 809 810 switch (cmd) { 811 case XDMA_CMD_BEGIN: 812 case XDMA_CMD_TERMINATE: 813 case XDMA_CMD_PAUSE: 814 /* TODO: implement me */ 815 return (-1); 816 } 817 818 return (0); 819 } 820 821 #ifdef FDT 822 static int 823 softdma_ofw_md_data(device_t dev, pcell_t *cells, 824 int ncells, void **ptr) 825 { 826 827 return (0); 828 } 829 #endif 830 831 static device_method_t softdma_methods[] = { 832 /* Device interface */ 833 DEVMETHOD(device_probe, softdma_probe), 834 DEVMETHOD(device_attach, softdma_attach), 835 DEVMETHOD(device_detach, softdma_detach), 836 837 /* xDMA Interface */ 838 DEVMETHOD(xdma_channel_alloc, softdma_channel_alloc), 839 DEVMETHOD(xdma_channel_free, softdma_channel_free), 840 DEVMETHOD(xdma_channel_request, softdma_channel_request), 841 DEVMETHOD(xdma_channel_control, softdma_channel_control), 842 843 /* xDMA SG Interface */ 844 DEVMETHOD(xdma_channel_prep_sg, softdma_channel_prep_sg), 845 DEVMETHOD(xdma_channel_submit_sg, softdma_channel_submit_sg), 846 DEVMETHOD(xdma_channel_capacity, softdma_channel_capacity), 847 848 #ifdef FDT 849 DEVMETHOD(xdma_ofw_md_data, softdma_ofw_md_data), 850 #endif 851 852 DEVMETHOD_END 853 }; 854 855 static driver_t softdma_driver = { 856 "softdma", 857 softdma_methods, 858 sizeof(struct softdma_softc), 859 }; 860 861 static devclass_t softdma_devclass; 862 863 EARLY_DRIVER_MODULE(softdma, simplebus, softdma_driver, softdma_devclass, 0, 0, 864 BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); 865