1// **************************************************************************** 2// 3// CDaffyDuck.H 4// 5// Include file for interfacing with the CDaffyDuck class. 6// 7// A daffy duck maintains a scatter-gather list used by the DSP to 8// transfer audio data via bus mastering. 9// 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. 13// 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 18// or a ring buffer. 19// 20// If you want a ring DMA buffer for your audio data, refer to the 21// Wrap() method, below. 22// 23// The name "daffy duck" is an inside joke that dates back to the 24// original VxD for Windows 95. 25// 26// Set editor tabs to 3 for your viewing pleasure. 27// 28//--------------------------------------------------------------------------- 29// 30// ---------------------------------------------------------------------------- 31// 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 35// www.echoaudio.com 36// 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. 41// 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. 46// 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 50// 51// **************************************************************************** 52 53// Prevent problems with multiple includes 54 55#ifndef _DAFFYDUCKOBJECT_ 56#define _DAFFYDUCKOBJECT_ 57 58#ifdef _DEBUG 59//#define INTEGRITY_CHECK 60#endif 61 62// 63// DUCKENTRY is a single entry for the scatter-gather list. A DUCKENTRY 64// struct is read by the DSP. 65// 66typedef struct 67{ 68 DWORD PhysAddr; 69 DWORD dwSize; 70} DUCKENTRY, * PDUCKENTRY; 71 72 73// 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. 78// 79typedef struct 80{ 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) 84} MAPPING; 85 86 87class CDspCommObject; 88 89class CDaffyDuck 90{ 91public: 92 93 // 94 // Number of entries in the circular buffer. 95 // 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. 98 // 99 enum 100 { 101 MAX_ENTRIES = 64, // Note this must be a power of 2 102 ENTRY_INDEX_MASK = MAX_ENTRIES-1 103 }; 104 105 // 106 // Destructor 107 // 108 ~CDaffyDuck(); 109 110 static CDaffyDuck * MakeDaffyDuck(COsSupport *pOsSupport); 111 112protected: 113 114 // 115 // Protected constructor 116 // 117 CDaffyDuck(PCOsSupport pOsSupport); 118 119 DWORD m_dwPipeIndex; 120 121 PPAGE_BLOCK m_pDuckPage; 122 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 127 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 132 133 DWORD m_dwDuckEntriesPhys; // The DSP needs this - physical address 134 // of page pointed to by m_DuckEntries 135 136 ULONGLONG m_ullLastEndPos; // Used to calculate ullEndPos for new entries 137 138 PCOsSupport m_pOsSupport; 139 140 BOOL m_fWrapped; 141 142#ifdef INTEGRITY_CHECK 143 void CheckIntegrity(); 144#endif 145 146 void EjectTail(); 147 148public: 149 150 void Reset(); 151 152 void ResetStartPos(); 153 154 // 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. 159 // 160 // The buffer must be physically contiguous. 161 // 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. 165 // 166 // dwInterrupt is true if you want the DSP to generate an IRQ after it 167 // consumes this audio buffer. 168 // 169 // dwNumFreeEntries is useful if you are calling this in a loop and 170 // want to know when to stop; 171 // 172 ECHOSTATUS AddMapping 173 ( 174 DWORD dwPhysAddr, 175 DWORD dwBytes, 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 179 ); 180 181 // 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. 185 // 186 ECHOSTATUS AddDoubleZero(); 187 188 // 189 // Call Wrap if you are creating a circular DMA buffer; to make a circular 190 // double buffer, do this: 191 // 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 197 // 198 // Once you call Wrap, you shouldn't add any more mappings. 199 // 200 void Wrap(); 201 202 // 203 // Call ReleaseUsedMapping to conditionally remove the oldest duck entries. 204 // 205 // The return value is the number of tags written to the Tags array. 206 // 207 DWORD ReleaseUsedMappings 208 ( 209 ULONGLONG ullDmaPos, 210 NUINT *Tags, 211 DWORD dwMaxTags 212 ); 213 214 // 215 // Adjusts the duck so that DMA will start from a given position; useful 216 // when resuming from pause 217 // 218 void AdjustStartPos(ULONGLONG ullPos); 219 220 // 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. 223 // 224 DWORD GetPhysStartAddr(); 225 226 // 227 // Any more room in the s.g. list? 228 // 229 DWORD GetNumFreeEntries() 230 { 231 return MAX_ENTRIES - m_dwCount; 232 } 233 234 // 235 // RevokeMappings is here specifically to support WDM; it removes 236 // any entries from the list if their tag is >= dwFirstTag and <= dwLastTag. 237 // 238 DWORD RevokeMappings 239 ( 240 NUINT FirstTag, 241 NUINT LastTag 242 ); 243 244 // 245 // Returns TRUE if Wrap has been called for this duck 246 // 247 BOOL Wrapped() 248 { 249 return m_fWrapped; 250 } 251 252 // 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 255 // 256 void CleanUpTail(); 257 258 // 259 // Spew out some info 260 // 261 VOID DbgDump(); 262 263 // 264 // Overload new & delete to make sure these objects are allocated from 265 // non-paged memory. 266 // 267 PVOID operator new( size_t Size ); 268 VOID operator delete( PVOID pVoid ); 269 270}; // class CDaffyDuck 271 272typedef CDaffyDuck * PCDaffyDuck; 273 274#endif // _DAFFYDUCKOBJECT_ 275 276// *** CDaffyDuck.H *** 277