1 // ****************************************************************************
5 // Include file for interfacing with the CDaffyDuck class.
7 // A daffy duck maintains a scatter-gather list used by the DSP to
8 // transfer audio data via bus mastering.
10 // The scatter-gather list takes the form of a circular buffer of
11 // duck entries; each duck entry is an address/count pair that points
12 // to an audio data buffer somewhere in memory.
14 // Although the scatter-gather list itself is a circular buffer, that
15 // does not mean that the audio data pointed to by the scatter-gather
16 // list is necessarily a circular buffer. The audio buffers pointed to
17 // by the SG list may be either a non-circular linked list of buffers
20 // If you want a ring DMA buffer for your audio data, refer to the
21 // Wrap() method, below.
23 // The name "daffy duck" is an inside joke that dates back to the
24 // original VxD for Windows 95.
26 // Set editor tabs to 3 for your viewing pleasure.
28 //---------------------------------------------------------------------------
30 // ----------------------------------------------------------------------------
32 // This file is part of Echo Digital Audio's generic driver library.
33 // Copyright Echo Digital Audio Corporation (c) 1998 - 2005
34 // All rights reserved
37 // This library is free software; you can redistribute it and/or
38 // modify it under the terms of the GNU Lesser General Public
39 // License as published by the Free Software Foundation; either
40 // version 2.1 of the License, or (at your option) any later version.
42 // This library is distributed in the hope that it will be useful,
43 // but WITHOUT ANY WARRANTY; without even the implied warranty of
44 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
45 // Lesser General Public License for more details.
47 // You should have received a copy of the GNU Lesser General Public
48 // License along with this library; if not, write to the Free Software
49 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
51 // ****************************************************************************
53 // Prevent problems with multiple includes
55 #ifndef _DAFFYDUCKOBJECT_
56 #define _DAFFYDUCKOBJECT_
59 //#define INTEGRITY_CHECK
63 // DUCKENTRY is a single entry for the scatter-gather list. A DUCKENTRY
64 // struct is read by the DSP.
70 } DUCKENTRY
, * PDUCKENTRY
;
74 // The CDaffyDuck class keeps a parallel array of MAPPING structures
75 // that corresponds to the DUCKENTRY array. You can't just pack everything
76 // into one struct since the DSP reads the DUCKENTRY structs and wouldn't
77 // know what to do with the other fields.
81 NUINT Tag
; // Unique ID for this mapping
82 ULONGLONG ullEndPos
; // The cumulative 64-bit end position for this mapping
83 // = (previous ullEndPos) + (# of bytes mapped)
94 // Number of entries in the circular buffer.
96 // If MAX_ENTRIES is set too high, SONAR crashes in Windows XP if you are
97 // using super-interleave mode. 64 seems to work.
101 MAX_ENTRIES
= 64, // Note this must be a power of 2
102 ENTRY_INDEX_MASK
= MAX_ENTRIES
-1
110 static CDaffyDuck
* MakeDaffyDuck(COsSupport
*pOsSupport
);
115 // Protected constructor
117 CDaffyDuck(PCOsSupport pOsSupport
);
121 PPAGE_BLOCK m_pDuckPage
;
123 DUCKENTRY
*m_DuckEntries
; // Points to a locked physical page (4096 bytes)
124 // These are for the benefit of the DSP
125 MAPPING m_Mappings
[MAX_ENTRIES
];// Parallel circular buffer to m_DuckEntries;
126 // these are for the benefit of port class
128 DWORD m_dwHead
; // Index where next mapping will be added;
129 // points to an empty slot
130 DWORD m_dwTail
; // Next mapping to discard (read index)
131 DWORD m_dwCount
; // Number of entries in the circular buffer
133 DWORD m_dwDuckEntriesPhys
; // The DSP needs this - physical address
134 // of page pointed to by m_DuckEntries
136 ULONGLONG m_ullLastEndPos
; // Used to calculate ullEndPos for new entries
138 PCOsSupport m_pOsSupport
;
142 #ifdef INTEGRITY_CHECK
143 void CheckIntegrity();
152 void ResetStartPos();
155 // Call AddMapping to add a buffer of audio data to the scatter-gather list.
156 // Note that dwPhysAddr will be asserted on the PCI bus; you will need
157 // to make the appropriate translation between the virtual address of
158 // the page and the bus address *before* calling this function.
160 // The buffer must be physically contiguous.
162 // The Tag parameter is a unique ID for this mapping that is used by
163 // ReleaseUsedMapping and RevokeMappings; if you are building a circular
164 // buffer, the tag isn't important.
166 // dwInterrupt is true if you want the DSP to generate an IRQ after it
167 // consumes this audio buffer.
169 // dwNumFreeEntries is useful if you are calling this in a loop and
170 // want to know when to stop;
172 ECHOSTATUS AddMapping
176 NUINT Tag
, // Unique ID for this mapping
177 DWORD dwInterrupt
, // Set TRUE if you want an IRQ after this mapping
178 DWORD
&dwNumFreeEntries
// Return value - number of slots left in the list
182 // AddDoubleZero is used to have the DSP generate an interrupt;
183 // calling AddDoubleZero will cause the DSP to interrupt after it finishes the
184 // previous duck entry.
186 ECHOSTATUS
AddDoubleZero();
189 // Call Wrap if you are creating a circular DMA buffer; to make a circular
190 // double buffer, do this:
192 // AddMapping() Several times
193 // AddDoubleZero() First half-buffer interrupt
194 // AddMapping() Several more times
195 // AddDoubleZero() Second half-buffer interrupt
196 // Wrap() Wraps the scatter list around to make a circular buffer
198 // Once you call Wrap, you shouldn't add any more mappings.
203 // Call ReleaseUsedMapping to conditionally remove the oldest duck entries.
205 // The return value is the number of tags written to the Tags array.
207 DWORD ReleaseUsedMappings
215 // Adjusts the duck so that DMA will start from a given position; useful
216 // when resuming from pause
218 void AdjustStartPos(ULONGLONG ullPos
);
221 // This returns the physical address of the start of the scatter-gather
222 // list; used to tell the DSP where to start looking for duck entries.
224 DWORD
GetPhysStartAddr();
227 // Any more room in the s.g. list?
229 DWORD
GetNumFreeEntries()
231 return MAX_ENTRIES
- m_dwCount
;
235 // RevokeMappings is here specifically to support WDM; it removes
236 // any entries from the list if their tag is >= dwFirstTag and <= dwLastTag.
245 // Returns TRUE if Wrap has been called for this duck
253 // CleanUpTail is used to clean out any non-audio entries from the tail
254 // of the list that might be left over from earlier
259 // Spew out some info
264 // Overload new & delete to make sure these objects are allocated from
267 PVOID
operator new( size_t Size
);
268 VOID
operator delete( PVOID pVoid
);
270 }; // class CDaffyDuck
272 typedef CDaffyDuck
* PCDaffyDuck
;
274 #endif // _DAFFYDUCKOBJECT_
276 // *** CDaffyDuck.H ***