1 // **************************************************************************** 2 // 3 // OsSupportWDM.cpp 4 // 5 // Implementation file for WDM support services to the CEchoGals 6 // generic driver class. 7 // 8 // This will need to be rewritten for each new target OS. 9 // 10 // Set editor tabs to 3 for your viewing pleasure. 11 // 12 // Copyright Echo Digital Audio Corporation (c) 1998 - 2002 13 // All rights reserved 14 // www.echoaudio.com 15 // 16 // Modifications for OpenBeOS Copyright Andrew Bachmann (c) 2002 17 // All rights reserved 18 // www.openbeos.org 19 // 20 // Permission is hereby granted, free of charge, to any person obtaining a 21 // copy of this software and associated documentation files (the 22 // "Software"), to deal with the Software without restriction, including 23 // without limitation the rights to use, copy, modify, merge, publish, 24 // distribute, sublicense, and/or sell copies of the Software, and to 25 // permit persons to whom the Software is furnished to do so, subject to 26 // the following conditions: 27 // 28 // - Redistributions of source code must retain the above copyright 29 // notice, this list of conditions and the following disclaimers. 30 // 31 // - Redistributions in binary form must reproduce the above copyright 32 // notice, this list of conditions and the following disclaimers in the 33 // documentation and/or other materials provided with the distribution. 34 // 35 // - Neither the name of Echo Digital Audio, nor the names of its 36 // contributors may be used to endorse or promote products derived from 37 // this Software without specific prior written permission. 38 // 39 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 40 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 41 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 42 // IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR 43 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 44 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 45 // SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. 46 // 47 // **************************************************************************** 48 49 #include "CEchoGals.h" 50 #include <stdarg.h> 51 #include <RealtimeAlloc.h> 52 #include <OS.h> 53 #include <Alert.h> 54 55 /**************************************************************************** 56 57 Memory management - not part of COsSupport 58 59 ****************************************************************************/ 60 61 //=========================================================================== 62 // 63 // Init the memory tracking counter; right now, this just uses a simple 64 // scheme that tracks the number of allocations 65 // 66 //=========================================================================== 67 68 DWORD gdwAllocNonPagedCount = 0; 69 rtm_pool * echo_pool = 0; 70 71 void OsAllocateInit() 72 { 73 gdwAllocNonPagedCount = 0; 74 rtm_create_pool(&echo_pool,0xFFFF, ECHO_POOL_TAG); 75 if ( NULL == echo_pool ) 76 { 77 ECHO_DEBUGPRINTF( ("OsAllocateInit : Failed to create the pool\n") ); 78 ECHO_DEBUGBREAK(); 79 return; 80 } 81 82 } // OsAllocateInit 83 84 85 //=========================================================================== 86 // 87 // OsAllocateNonPaged is used to allocate a block of memory that will always 88 // be resident; that is, this particular block of memory won't be swapped 89 // out as virtual memory and can always be accessed at interrupt time. 90 // 91 // gdwAllocNonPagedCount tracks the number of times this has been 92 // successfully called. 93 // 94 // This is primarily used for overloading the new operator for the various 95 // generic classes. 96 // 97 //=========================================================================== 98 99 // OsAllocateNonPaged is used to (surprise!) allocate non-paged memory. Non-paged 100 // memory is defined as memory that is always physically resident - that is, the virtual 101 // memory manager won't swap this memory to disk. Nonpaged memory can be accessed 102 // from the interrupt handler. 103 // Nonpaged memory has no particular requirements on address alignment. 104 105 ECHOSTATUS OsAllocateNonPaged 106 ( 107 DWORD dwByteCt, // Block size in bytes 108 PPVOID ppMemAddr // Where to return memory ptr 109 ) 110 { 111 *ppMemAddr = rtm_alloc( echo_pool, dwByteCt ); 112 113 if ( NULL == *ppMemAddr ) 114 { 115 ECHO_DEBUGPRINTF( ("OsAllocateNonPaged : Failed on %d bytes\n", 116 dwByteCt) ); 117 ECHO_DEBUGBREAK(); 118 return ECHOSTATUS_NO_MEM; 119 } 120 121 OsZeroMemory( *ppMemAddr, dwByteCt ); 122 123 gdwAllocNonPagedCount++; 124 ECHO_DEBUGPRINTF(("gdwAllocNonPagedCount %d\n",gdwAllocNonPagedCount)); 125 126 return ECHOSTATUS_OK; 127 128 } // ECHOSTATUS OsAllocateNonPaged 129 130 131 //=========================================================================== 132 // 133 // OsFreeNonPaged is used to free memory allocated by OsAllocateNonPaged. 134 // 135 // gdwAllocNonPagedCount tracks the number of times this has been 136 // successfully called. 137 // 138 //=========================================================================== 139 140 ECHOSTATUS OsFreeNonPaged 141 ( 142 PVOID pMemAddr 143 ) 144 { 145 rtm_free( pMemAddr ); 146 147 gdwAllocNonPagedCount--; 148 ECHO_DEBUGPRINTF(("gdwAllocNonPagedCount %d\n",gdwAllocNonPagedCount)); 149 150 return ECHOSTATUS_OK; 151 152 } // ECHOSTATUS OsFreeNonPaged 153 154 155 //*********************************************************************** 156 157 // 158 // This class is uniquely defined for each OS. It provides 159 // information that other components may require. 160 // 161 // For example, in Windows NT it contains a device object used by various 162 // memory management methods. 163 // 164 // An instance of this class must be constructed and initialized prior to 165 // constructing the CEchoGals derived object. The CEchoGals and 166 // CDspCommObject classes must have access to it during their respective 167 // construction times. 168 // 169 //*********************************************************************** 170 171 //=========================================================================== 172 // 173 // Construction/destruction 174 // 175 //=========================================================================== 176 177 COsSupport::COsSupport 178 ( 179 DWORD dwDeviceId // PCI bus subsystem ID 180 ) 181 { 182 m_ullStartTime = system_time(); // All system time calls relative to this 183 184 m_dwDeviceId = dwDeviceId; 185 186 } // COsSupport::COsSupport() 187 188 189 COsSupport::~COsSupport() 190 { 191 } // COsSupport::~COsSupport() 192 193 194 //=========================================================================== 195 // 196 // Timer methods 197 // 198 //=========================================================================== 199 200 //--------------------------------------------------------------------------- 201 // 202 // Return the system time in microseconds. 203 // Return error status if the OS doesn't support this function. 204 // 205 //--------------------------------------------------------------------------- 206 207 ECHOSTATUS COsSupport::OsGetSystemTime 208 ( 209 PULONGLONG pullTime // Where to return system time 210 ) 211 { 212 *pullTime = ULONGLONG(system_time()); 213 214 return ECHOSTATUS_OK; 215 216 } // ECHOSTATUS COsSupport::OsGetSystemTime 217 218 219 //--------------------------------------------------------------------------- 220 // 221 // Stall execution for dwTime microseconds. 222 // Return error status if the OS doesn't support this 223 // function. 224 // 225 //--------------------------------------------------------------------------- 226 227 ECHOSTATUS COsSupport::OsSnooze 228 ( 229 DWORD dwTime // Duration in micro seconds 230 ) 231 { 232 status_t status; 233 status = snooze(bigtime_t(dwTime)); 234 switch (status) { 235 case B_OK: 236 return ECHOSTATUS_OK; 237 break; 238 case B_INTERRUPTED: 239 return ECHOSTATUS_OPERATION_CANCELED; // maybe not appropriate, but anyway 240 break; 241 default: 242 return ECHOSTATUS_NOT_SUPPORTED; // no generic error? 243 break; 244 } 245 } 246 247 248 //=========================================================================== 249 // 250 // More memory management 251 // 252 //=========================================================================== 253 254 //--------------------------------------------------------------------------- 255 // 256 // Allocate locked, non-pageable, physically contiguous memory pages 257 // in the drivers address space. Used to allocate memory for the DSP 258 // communications area. 259 // 260 // Currently, none of the generic code ever sets dwPageCt to higher than 261 // one. On the platforms we've developed for so far, a page is 4096 262 // bytes and is aligned on a 4096 byte boundary. None of the structures 263 // allocated by OsPageAllocate are more than 4096 bytes; memory 264 // allocated by this routine should be at least aligned on a 32 byte 265 // boundary and be physically contiguous. 266 // 267 // Note that this code is not 64 bit ready, since it's only using 268 // the low 32 bits of the physical address. 269 // 270 //--------------------------------------------------------------------------- 271 272 // COsSupport::OsPageAllocate is used for allocating memory that is read and written by 273 // the DSP. This means that any memory allocated by OsPageAllocate must be nonpaged 274 // and should be aligned on at least a 32 byte address boundary. It must be aligned on at 275 // least a 4 byte boundary. 276 277 ECHOSTATUS COsSupport::OsPageAllocate 278 ( 279 DWORD dwPageCt, // How many pages to allocate 280 PPVOID ppPageAddr, // Where to return the memory ptr 281 PPHYS_ADDR pPhysicalPageAddr // Where to return the physical PCI address 282 ) 283 { 284 PHYSICAL_ADDRESS LogicalAddress; 285 286 *ppPageAddr = rtm_alloc ( echo_pool, dwPageCt ); 287 288 if (NULL != *ppPageAddr) 289 { 290 physical_entry PhysTemp; 291 292 get_memory_map(ppPageAddr, dwPageCt, &PhysTemp, 1); 293 294 PhysTemp = MmGetPhysicalAddress(*ppPageAddr); // XXX: ? 295 *pPhysicalPageAddr = PhysTemp.address; 296 } 297 298 OsZeroMemory( *ppPageAddr, dwPageCt * PAGE_SIZE ); 299 300 return ECHOSTATUS_OK; 301 302 } // ECHOSTATUS COsSupport::OsPageAllocate 303 304 305 //--------------------------------------------------------------------------- 306 // 307 // Unlock and free non-pageable, physically contiguous memory pages in 308 // the drivers address space; the inverse of OsPageAllocate 309 // 310 //--------------------------------------------------------------------------- 311 312 ECHOSTATUS COsSupport::OsPageFree 313 ( 314 DWORD dwPageCt, // How many pages to free 315 PVOID pPageAddr, // Virtual memory ptr 316 PHYS_ADDR PhysicalPageAddr // Physical PCI addr 317 ) 318 { 319 PHYSICAL_ADDRESS LogicalAddress; 320 321 if (NULL == pPageAddr) 322 return ECHOSTATUS_OK; 323 324 rtm_free(pPageAddr); 325 326 return ECHOSTATUS_OK; 327 328 } // ECHOSTATUS COsSupport::OsPageFree 329 330 331 //--------------------------------------------------------------------------- 332 // 333 // Display an error message w/title; currently not supported under WDM. 334 // 335 //--------------------------------------------------------------------------- 336 337 void COsSupport::EchoErrorMsg 338 ( 339 PCHAR pszMsg, 340 PCHAR pszTitle 341 ) 342 { 343 BAlert alert(pszTitle,pszMsg,"Ok",NULL,NULL,B_WIDTH_AS_USUAL,B_STOP_ALERT); 344 alert.Go(); 345 } // void COsSupport::EchoErrorMsg( PCHAR ) 346 347 348 //--------------------------------------------------------------------------- 349 // 350 // Overload new & delete so memory for this object is allocated from 351 // non-paged memory. 352 // 353 //--------------------------------------------------------------------------- 354 355 PVOID COsSupport::operator new( size_t Size ) 356 { 357 PVOID pMemory; 358 359 // it's probably better to not rtm alloc this 360 // but it does need to be resident 361 pMemory = rtm_alloc(NULL,Size); 362 363 if ( NULL == pMemory ) 364 { 365 ECHO_DEBUGPRINTF(("COsSupport::operator new - memory allocation failed\n")); 366 367 pMemory = NULL; 368 } 369 else 370 { 371 memset( pMemory, 0, Size ); 372 } 373 374 return pMemory; 375 376 } // PVOID COsSupport::operator new( size_t Size ) 377 378 379 VOID COsSupport::operator delete( PVOID pVoid ) 380 { 381 status_t status; 382 status = rtm_free(pVoid); 383 384 if (status != B_OK) { 385 ECHO_DEBUGPRINTF(("COsSupport::operator delete " 386 "memory free failed\n")); 387 } 388 389 } // VOID COsSupport::operator delete( PVOID pVoid ) 390 391