// SPDX-License-Identifier: GPL-2.0+
/*
 * COMEDI ISA DMA support functions
 * Copyright (c) 2014 H Hartley Sweeten <hsweeten@visionengravers.com>
 */

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <asm/dma.h>

#include "../comedidev.h"

#include "comedi_isadma.h"

/**
 * comedi_isadma_program - program and enable an ISA DMA transfer
 * @desc:	the ISA DMA cookie to program and enable
 */
void comedi_isadma_program(struct comedi_isadma_desc *desc)
{
	unsigned long flags;

	flags = claim_dma_lock();
	clear_dma_ff(desc->chan);
	set_dma_mode(desc->chan, desc->mode);
	set_dma_addr(desc->chan, desc->hw_addr);
	set_dma_count(desc->chan, desc->size);
	enable_dma(desc->chan);
	release_dma_lock(flags);
}
EXPORT_SYMBOL_GPL(comedi_isadma_program);

/**
 * comedi_isadma_disable - disable the ISA DMA channel
 * @dma_chan:	the DMA channel to disable
 *
 * Returns the residue (remaining bytes) left in the DMA transfer.
 */
unsigned int comedi_isadma_disable(unsigned int dma_chan)
{
	unsigned long flags;
	unsigned int residue;

	flags = claim_dma_lock();
	disable_dma(dma_chan);
	residue = get_dma_residue(dma_chan);
	release_dma_lock(flags);

	return residue;
}
EXPORT_SYMBOL_GPL(comedi_isadma_disable);

/**
 * comedi_isadma_disable_on_sample - disable the ISA DMA channel
 * @dma_chan:	the DMA channel to disable
 * @size:	the sample size (in bytes)
 *
 * Returns the residue (remaining bytes) left in the DMA transfer.
 */
unsigned int comedi_isadma_disable_on_sample(unsigned int dma_chan,
					     unsigned int size)
{
	int stalled = 0;
	unsigned long flags;
	unsigned int residue;
	unsigned int new_residue;

	residue = comedi_isadma_disable(dma_chan);
	while (residue % size) {
		/* residue is a partial sample, enable DMA to allow more data */
		flags = claim_dma_lock();
		enable_dma(dma_chan);
		release_dma_lock(flags);

		udelay(2);
		new_residue = comedi_isadma_disable(dma_chan);

		/* is DMA stalled? */
		if (new_residue == residue) {
			stalled++;
			if (stalled > 10)
				break;
		} else {
			residue = new_residue;
			stalled = 0;
		}
	}
	return residue;
}
EXPORT_SYMBOL_GPL(comedi_isadma_disable_on_sample);

/**
 * comedi_isadma_poll - poll the current DMA transfer
 * @dma:	the ISA DMA to poll
 *
 * Returns the position (in bytes) of the current DMA transfer.
 */
unsigned int comedi_isadma_poll(struct comedi_isadma *dma)
{
	struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
	unsigned long flags;
	unsigned int result;
	unsigned int result1;

	flags = claim_dma_lock();
	clear_dma_ff(desc->chan);
	if (!isa_dma_bridge_buggy)
		disable_dma(desc->chan);
	result = get_dma_residue(desc->chan);
	/*
	 * Read the counter again and choose higher value in order to
	 * avoid reading during counter lower byte roll over if the
	 * isa_dma_bridge_buggy is set.
	 */
	result1 = get_dma_residue(desc->chan);
	if (!isa_dma_bridge_buggy)
		enable_dma(desc->chan);
	release_dma_lock(flags);

	if (result < result1)
		result = result1;
	if (result >= desc->size || result == 0)
		return 0;
	return desc->size - result;
}
EXPORT_SYMBOL_GPL(comedi_isadma_poll);

/**
 * comedi_isadma_set_mode - set the ISA DMA transfer direction
 * @desc:	the ISA DMA cookie to set
 * @dma_dir:	the DMA direction
 */
void comedi_isadma_set_mode(struct comedi_isadma_desc *desc, char dma_dir)
{
	desc->mode = (dma_dir == COMEDI_ISADMA_READ) ? DMA_MODE_READ
						     : DMA_MODE_WRITE;
}
EXPORT_SYMBOL_GPL(comedi_isadma_set_mode);

/**
 * comedi_isadma_alloc - allocate and initialize the ISA DMA
 * @dev:	comedi_device struct
 * @n_desc:	the number of cookies to allocate
 * @dma_chan:	DMA channel for the first cookie
 * @dma_chan2:	DMA channel for the second cookie
 * @maxsize:	the size of the buffer to allocate for each cookie
 * @dma_dir:	the DMA direction
 *
 * Returns the allocated and initialized ISA DMA or NULL if anything fails.
 */
struct comedi_isadma *comedi_isadma_alloc(struct comedi_device *dev,
					  int n_desc, unsigned int dma_chan1,
					  unsigned int dma_chan2,
					  unsigned int maxsize, char dma_dir)
{
	struct comedi_isadma *dma = NULL;
	struct comedi_isadma_desc *desc;
	unsigned int dma_chans[2];
	int i;

	if (n_desc < 1 || n_desc > 2)
		goto no_dma;

	dma = kzalloc(sizeof(*dma), GFP_KERNEL);
	if (!dma)
		goto no_dma;

	desc = kcalloc(n_desc, sizeof(*desc), GFP_KERNEL);
	if (!desc)
		goto no_dma;
	dma->desc = desc;
	dma->n_desc = n_desc;
	if (dev->hw_dev) {
		dma->dev = dev->hw_dev;
	} else {
		/* Fall back to using the "class" device. */
		if (!dev->class_dev)
			goto no_dma;
		/* Need 24-bit mask for ISA DMA. */
		if (dma_coerce_mask_and_coherent(dev->class_dev,
						 DMA_BIT_MASK(24))) {
			goto no_dma;
		}
		dma->dev = dev->class_dev;
	}

	dma_chans[0] = dma_chan1;
	if (dma_chan2 == 0 || dma_chan2 == dma_chan1)
		dma_chans[1] = dma_chan1;
	else
		dma_chans[1] = dma_chan2;

	if (request_dma(dma_chans[0], dev->board_name))
		goto no_dma;
	dma->chan = dma_chans[0];
	if (dma_chans[1] != dma_chans[0]) {
		if (request_dma(dma_chans[1], dev->board_name))
			goto no_dma;
	}
	dma->chan2 = dma_chans[1];

	for (i = 0; i < n_desc; i++) {
		desc = &dma->desc[i];
		desc->chan = dma_chans[i];
		desc->maxsize = maxsize;
		desc->virt_addr = dma_alloc_coherent(dma->dev, desc->maxsize,
						     &desc->hw_addr,
						     GFP_KERNEL);
		if (!desc->virt_addr)
			goto no_dma;
		comedi_isadma_set_mode(desc, dma_dir);
	}

	return dma;

no_dma:
	comedi_isadma_free(dma);
	return NULL;
}
EXPORT_SYMBOL_GPL(comedi_isadma_alloc);

/**
 * comedi_isadma_free - free the ISA DMA
 * @dma:	the ISA DMA to free
 */
void comedi_isadma_free(struct comedi_isadma *dma)
{
	struct comedi_isadma_desc *desc;
	int i;

	if (!dma)
		return;

	if (dma->desc) {
		for (i = 0; i < dma->n_desc; i++) {
			desc = &dma->desc[i];
			if (desc->virt_addr)
				dma_free_coherent(dma->dev, desc->maxsize,
						  desc->virt_addr,
						  desc->hw_addr);
		}
		kfree(dma->desc);
	}
	if (dma->chan2 && dma->chan2 != dma->chan)
		free_dma(dma->chan2);
	if (dma->chan)
		free_dma(dma->chan);
	kfree(dma);
}
EXPORT_SYMBOL_GPL(comedi_isadma_free);

static int __init comedi_isadma_init(void)
{
	return 0;
}
module_init(comedi_isadma_init);

static void __exit comedi_isadma_exit(void)
{
}
module_exit(comedi_isadma_exit);

MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
MODULE_DESCRIPTION("Comedi ISA DMA support");
MODULE_LICENSE("GPL");
