Generic interface operation flow:
/* Get xDMA controller */ sc->xdma_tx = xdma_ofw_get(sc->dev, "tx"); /* Allocate virtual channel */ sc->xchan_tx = xdma_channel_alloc(sc->xdma_tx, caps); /* Setup transfer status callback. */ xdma_setup_intr(sc->xchan_tx, my_tx_intr, sc, &sc->ih_tx); /* Request a transfer */ ret = xdma_request(sc->xchan_tx, &req); /* Free the channel */ xdma_channel_free(sc->xdma_tx); /* Free the controller */ xdma_put(sc->xdma_tx);
Less generic (scatter-gather application based on xDMA interface) operation flow:
/* Get xDMA controller */ sc->xdma_tx = xdma_ofw_get(sc->dev, "tx"); /* Allocate virtual channel */ sc->xchan_tx = xdma_channel_alloc(sc->xdma_tx, caps);
int atse_xdma_tx_intr(void *arg, xdma_transfer_status_t *status) { for (;;) { err = xdma_dequeue_mbuf(sc->xchan_tx, &m, &st); if (err != 0) { break; } } } /* Setup interrupt handler. */ xdma_setup_intr(sc->xchan_tx, atse_xdma_tx_intr, sc, &sc->ih_tx); /* Prepare SG transfer */ xdma_prep_sg(sc->xchan_tx, TX_QUEUE_SIZE, ...);
/* Enqueue (multiple) mbufs to receive */ m = m_getcl(); xdma_enqueue_mbuf(sc->xchan_rx, &m, 0, 4, 4, XDMA_DEV_TO_MEM); m = m_getcl(); xdma_enqueue_mbuf(sc->xchan_rx, &m, 0, 4, 4, XDMA_DEV_TO_MEM); ... xdma_queue_submit(sc->xchan_rx);
/* Enqueue mbuf to transmit */ xdma_enqueue_mbuf(sc->xchan_tx, &m, 0, 4, 4, XDMA_MEM_TO_DEV); xdma_queue_submit(sc->xchan_tx);
DMA engine driver interface. These functions have to be implemented in DMA engine driver
/* Allocate real hardware channel */ int msgdma_channel_alloc(device_t dev, struct xdma_channel *xchan) { } /* Request a transfer */ static int pdma_channel_request(device_t dev, struct xdma_channel *xchan, struct xdma_request *req) { } /* Free the channel */ static int msgdma_channel_free(device_t dev, struct xdma_channel *xchan) { } /* Start/stop DMA operation */ static int msgdma_channel_control(device_t dev, xdma_channel_t *xchan, int cmd) { }
Scatter-gather DMA engine driver interface. These functions have to be implemented in DMA engine driver
/* Prepare a channel for SG transfer */ softdma_channel_prep_sg(device_t dev, struct xdma_channel *xchan) { ... } /* Submit sg list */ softdma_channel_submit_sg(device_t dev, struct xdma_channel *xchan, struct xdma_sglist *sg, uint32_t sg_n) { ... } /* Provide the amount of free entries for requests. */ softdma_channel_capacity(device_t dev, xdma_channel_t *xchan, uint32_t *capacity) { ... }