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 // 66 typedef 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 // 79 typedef 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 87 class CDspCommObject; 88 89 class CDaffyDuck 90 { 91 public: 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 112 protected: 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 148 public: 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 // GetNumFreeEntries()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 // Wrapped()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 272 typedef CDaffyDuck * PCDaffyDuck; 273 274 #endif // _DAFFYDUCKOBJECT_ 275 276 // *** CDaffyDuck.H *** 277