Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/core/isadma.c
10814 views
1
/*
2
* ISA DMA support functions
3
* Copyright (c) by Jaroslav Kysela <[email protected]>
4
*
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
*
20
*/
21
22
/*
23
* Defining following add some delay. Maybe this helps for some broken
24
* ISA DMA controllers.
25
*/
26
27
#undef HAVE_REALLY_SLOW_DMA_CONTROLLER
28
29
#include <sound/core.h>
30
#include <asm/dma.h>
31
32
/**
33
* snd_dma_program - program an ISA DMA transfer
34
* @dma: the dma number
35
* @addr: the physical address of the buffer
36
* @size: the DMA transfer size
37
* @mode: the DMA transfer mode, DMA_MODE_XXX
38
*
39
* Programs an ISA DMA transfer for the given buffer.
40
*/
41
void snd_dma_program(unsigned long dma,
42
unsigned long addr, unsigned int size,
43
unsigned short mode)
44
{
45
unsigned long flags;
46
47
flags = claim_dma_lock();
48
disable_dma(dma);
49
clear_dma_ff(dma);
50
set_dma_mode(dma, mode);
51
set_dma_addr(dma, addr);
52
set_dma_count(dma, size);
53
if (!(mode & DMA_MODE_NO_ENABLE))
54
enable_dma(dma);
55
release_dma_lock(flags);
56
}
57
58
EXPORT_SYMBOL(snd_dma_program);
59
60
/**
61
* snd_dma_disable - stop the ISA DMA transfer
62
* @dma: the dma number
63
*
64
* Stops the ISA DMA transfer.
65
*/
66
void snd_dma_disable(unsigned long dma)
67
{
68
unsigned long flags;
69
70
flags = claim_dma_lock();
71
clear_dma_ff(dma);
72
disable_dma(dma);
73
release_dma_lock(flags);
74
}
75
76
EXPORT_SYMBOL(snd_dma_disable);
77
78
/**
79
* snd_dma_pointer - return the current pointer to DMA transfer buffer in bytes
80
* @dma: the dma number
81
* @size: the dma transfer size
82
*
83
* Returns the current pointer in DMA tranfer buffer in bytes
84
*/
85
unsigned int snd_dma_pointer(unsigned long dma, unsigned int size)
86
{
87
unsigned long flags;
88
unsigned int result, result1;
89
90
flags = claim_dma_lock();
91
clear_dma_ff(dma);
92
if (!isa_dma_bridge_buggy)
93
disable_dma(dma);
94
result = get_dma_residue(dma);
95
/*
96
* HACK - read the counter again and choose higher value in order to
97
* avoid reading during counter lower byte roll over if the
98
* isa_dma_bridge_buggy is set.
99
*/
100
result1 = get_dma_residue(dma);
101
if (!isa_dma_bridge_buggy)
102
enable_dma(dma);
103
release_dma_lock(flags);
104
if (unlikely(result < result1))
105
result = result1;
106
#ifdef CONFIG_SND_DEBUG
107
if (result > size)
108
snd_printk(KERN_ERR "pointer (0x%x) for DMA #%ld is greater than transfer size (0x%x)\n", result, dma, size);
109
#endif
110
if (result >= size || result == 0)
111
return 0;
112
else
113
return size - result;
114
}
115
116
EXPORT_SYMBOL(snd_dma_pointer);
117
118