static int unipro_continue_xfer(struct unipro_xfer_descriptor *desc) { size_t xfer_len; desc->remaining_xfer_len -= desc->dma_arg.unipro_tx_arg.next_transfer_len; xfer_len = unipro_get_tx_free_buffer_space(desc->cport); if (!xfer_len) return -ENOSPC; xfer_len = MIN(desc->remaining_xfer_len, xfer_len); desc->dma_arg.unipro_tx_arg.next_transfer_len = xfer_len; if (xfer_len == desc->remaining_xfer_len) desc->dma_arg.unipro_tx_arg.eom_addr = CPORT_EOM_BIT(desc->cport); return 0; }
static int unipro_dma_xfer(struct unipro_xfer_descriptor *desc, struct dma_channel *channel) { int retval; size_t xfer_len; void *cport_buf; void *xfer_buf; xfer_len = unipro_get_tx_free_buffer_space(desc->cport); if (!xfer_len) return -ENOSPC; xfer_len = MIN(desc->remaining_xfer_len, xfer_len); desc->channel = channel; desc->dma_arg.unipro_tx_arg.next_transfer_len = xfer_len; if (xfer_len == desc->remaining_xfer_len) desc->dma_arg.unipro_tx_arg.eom_addr = CPORT_EOM_BIT(desc->cport); DBG_UNIPRO("xfer: chan=%u, len=%zu\n", channel->id, xfer_len); cport_buf = desc->cport->tx_buf; xfer_buf = (void*) desc->data; /* resuming a paused xfer */ if (desc->remaining_xfer_len != desc->len) { cport_buf = (char*) cport_buf + 1; /* skip the start byte */ /* move buffer offset to the beginning of the remaning bytes to xfer */ xfer_buf = (char*) xfer_buf + (desc->len - desc->remaining_xfer_len); } retval = device_dma_transfer(unipro_dma.dev, channel->id, xfer_buf, cport_buf, xfer_len, &desc->dma_arg); if (retval) { lowsyslog("unipro: failed to start DMA transfer: %d\n", retval); return retval; } return 0; }
/** * @brief Set EOM (End Of Message) flag * @param[in] cport: CPort handle */ static inline void unipro_set_eom_flag(struct cport *cport) { putreg8(1, CPORT_EOM_BIT(cport)); }