/*1* ISA DMA support functions2* Copyright (c) by Jaroslav Kysela <[email protected]>3*4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* (at your option) any later version.9*10* This program is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13* GNU General Public License for more details.14*15* You should have received a copy of the GNU General Public License16* along with this program; if not, write to the Free Software17* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA18*19*/2021/*22* Defining following add some delay. Maybe this helps for some broken23* ISA DMA controllers.24*/2526#undef HAVE_REALLY_SLOW_DMA_CONTROLLER2728#include <sound/core.h>29#include <asm/dma.h>3031/**32* snd_dma_program - program an ISA DMA transfer33* @dma: the dma number34* @addr: the physical address of the buffer35* @size: the DMA transfer size36* @mode: the DMA transfer mode, DMA_MODE_XXX37*38* Programs an ISA DMA transfer for the given buffer.39*/40void snd_dma_program(unsigned long dma,41unsigned long addr, unsigned int size,42unsigned short mode)43{44unsigned long flags;4546flags = claim_dma_lock();47disable_dma(dma);48clear_dma_ff(dma);49set_dma_mode(dma, mode);50set_dma_addr(dma, addr);51set_dma_count(dma, size);52if (!(mode & DMA_MODE_NO_ENABLE))53enable_dma(dma);54release_dma_lock(flags);55}5657EXPORT_SYMBOL(snd_dma_program);5859/**60* snd_dma_disable - stop the ISA DMA transfer61* @dma: the dma number62*63* Stops the ISA DMA transfer.64*/65void snd_dma_disable(unsigned long dma)66{67unsigned long flags;6869flags = claim_dma_lock();70clear_dma_ff(dma);71disable_dma(dma);72release_dma_lock(flags);73}7475EXPORT_SYMBOL(snd_dma_disable);7677/**78* snd_dma_pointer - return the current pointer to DMA transfer buffer in bytes79* @dma: the dma number80* @size: the dma transfer size81*82* Returns the current pointer in DMA tranfer buffer in bytes83*/84unsigned int snd_dma_pointer(unsigned long dma, unsigned int size)85{86unsigned long flags;87unsigned int result, result1;8889flags = claim_dma_lock();90clear_dma_ff(dma);91if (!isa_dma_bridge_buggy)92disable_dma(dma);93result = get_dma_residue(dma);94/*95* HACK - read the counter again and choose higher value in order to96* avoid reading during counter lower byte roll over if the97* isa_dma_bridge_buggy is set.98*/99result1 = get_dma_residue(dma);100if (!isa_dma_bridge_buggy)101enable_dma(dma);102release_dma_lock(flags);103if (unlikely(result < result1))104result = result1;105#ifdef CONFIG_SND_DEBUG106if (result > size)107snd_printk(KERN_ERR "pointer (0x%x) for DMA #%ld is greater than transfer size (0x%x)\n", result, dma, size);108#endif109if (result >= size || result == 0)110return 0;111else112return size - result;113}114115EXPORT_SYMBOL(snd_dma_pointer);116117118