source: sbliveos2/trunk/drv16/rm.cpp@ 142

Last change on this file since 142 was 142, checked in by ktk, 25 years ago

Import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.7 KB
Line 
1/* $Id: rm.cpp 142 2000-04-23 14:55:46Z ktk $ */
2
3/* SCCSID = %W% %E% */
4/****************************************************************************
5 * *
6 * Copyright (c) IBM Corporation 1994 - 1997. *
7 * *
8 * The following IBM OS/2 source code is provided to you solely for the *
9 * the purpose of assisting you in your development of OS/2 device drivers. *
10 * You may use this code in accordance with the IBM License Agreement *
11 * provided in the IBM Device Driver Source Kit for OS/2. *
12 * *
13 ****************************************************************************/
14/**@internal %W%
15 * RM (Resource manager) object implementation
16 * @version %I%
17 * @context
18 * Unless otherwise noted, all interfaces are Ring-3, 16-bit, sysinit time
19 * execution context on the kernel stack.
20 * @notes
21 * Provides information to the audio driver on the detected devices and the
22 * resources required for device operation. Obtain required resources from
23 * Resource Manager as directed by the client of this object. The adapters
24 * and controllers will be controlled by this driver. The detected resources
25 * that will be operated should be reallocated as driver resources. This code
26 * is dumped after driver initialization is complete.
27 *
28 * Remarks :
29 * *. PnP Device ID's are always in Compressed Ascii format.
30 * *. ### Need remove malloc by adding memory mgmt support for [].
31 *
32 * @history
33 */
34
35////#pragma code_seg ("_inittext");
36////#pragma data_seg ("_initdata","endds");
37
38#include "rm.hpp" // Will include os2.h, etc.
39#include <devhelp.h>
40#include <string.h> // _fmemset()
41#include "malloc.h" // malloc()
42
43
44char DeviceName[64] = "Creative Labs SoundBlaster Live";
45
46/**@external LDev_Resources::isEmpty
47 * Returns TRUE iff the LDev_Resources structure has no information.
48 * @param None.
49 * @return BOOL
50 */
51BOOL LDev_Resources::isEmpty()
52{
53 BOOL bIsEmpty = TRUE;
54
55 for ( int i=0; i<MAX_ISA_Dev_IO; ++i) {
56 if (uIOBase[i] != NoIOValue)
57 bIsEmpty = FALSE;
58 if ((i < MAX_ISA_Dev_IRQ) && (uIRQLevel[i] != NoIOValue))
59 bIsEmpty = FALSE;
60 if ((i < MAX_ISA_Dev_DMA) && (uDMAChannel[i] != NoIOValue))
61 bIsEmpty = FALSE;
62 if ((i < MAX_ISA_Dev_MEM) && (uMemBase[i] != 0xffffffff))
63 bIsEmpty = FALSE;
64 }
65 return bIsEmpty;
66}
67
68
69/**@external LDev_Resources::vClear
70 * Set an LDev_Resources structure to Empty.
71 * @param None.
72 * @return VOID
73 */
74void LDev_Resources::vClear()
75{
76 _fmemset( (PVOID) this, NoIOValue, sizeof(LDev_Resources) );
77}
78
79
80/*
81 * --- Linkages required by system Resource Manager (rm.lib).
82 */
83
84extern "C" PFN RM_Help = 0L;
85extern "C" PFN RM_Help0 = 0L;
86extern "C" PFN RM_Help3 = 0L;
87extern "C" ULONG RMFlags = 0L;
88
89/*
90 * --- Public member functions.
91 */
92
93/**@external ResourceManager
94 * Constructor for RM object.
95 * @notes Creates a "driver" node for this device driver, but does not
96 * allocate resources.
97 */
98ResourceManager::ResourceManager ( )
99{
100 APIRET rc;
101 DRIVERSTRUCT DriverStruct;
102 PSEL p;
103 PGINFOSEG pGIS = 0;
104
105 /* Warp version level, bus type, machine ID, and much other information is
106 * readily available. Reference the RM ADD sample in the DDK for code.
107 *
108 * Create a "driver" struct for this driver. This must ALWAYS be the
109 * first true RM call executed, as it attaches the Resource Manager
110 * library and performs setup for the other RM calls.
111 */
112 _fmemset( (PVOID) &DriverStruct, 0, sizeof(DriverStruct) );
113 DriverStruct.DrvrName = (PSZ) "SBLIVE16.SYS"; /* ### IHV */
114 DriverStruct.DrvrDescript = (PSZ) "SoundBlaster Live!"; /* ### IHV */
115 DriverStruct.VendorName = (PSZ) "Creative Labs"; /* ### IHV */
116 DriverStruct.MajorVer = CMVERSION_MAJOR; //rmbase.h /* ### IHV */
117 DriverStruct.MinorVer = CMVERSION_MINOR; //rmbase.h /* ### IHV */
118 DriverStruct.Date.Year = 2000; /* ### IHV */
119 DriverStruct.Date.Month = 2; /* ### IHV */
120 DriverStruct.Date.Day = 1; /* ### IHV */
121 DriverStruct.DrvrType = DRT_AUDIO;
122 DriverStruct.DrvrSubType = 0;
123 DriverStruct.DrvrCallback = NULL;
124 rc = RMCreateDriver( &DriverStruct, &_hDriver );
125 if( rc == RMRC_SUCCESS )
126 _state = rmDriverCreated;
127 else {
128 _state = rmDriverFailed;
129 _hDriver = 0;
130 }
131
132 // Build a pointer to the Global Information Segment.
133 rc = DevHelp_GetDOSVar( DHGETDOSV_SYSINFOSEG, 0, (PPVOID)&p );
134 if (rc) {
135 _rmDetection = FALSE;
136 }
137 else {
138 SELECTOROF(pGIS) = *p;
139 _rmDetection =
140 ( (pGIS->uchMajorVersion > 20) ||
141 ((pGIS->uchMajorVersion == 20) && (pGIS->uchMinorVersion > 30)) );
142 }
143}
144
145bool ResourceManager::bIsDevDetected ( DEVID DevID , ULONG ulSearchFlags, bool fPciDevice)
146/*
147; PURPOSE: Search the Resource Manager's "current detected" tree for
148; the matching PnP ID.
149;
150; IN: - DevID - PnP Device ID being sought (Compressed Ascii).
151; - ulSearchFlags - Search flags, ref rmbase.h SEARCH_ID_*; also
152; documented as SearchFlags parm in PDD RM API RMDevIDToHandleList().
153; Defines whether DevID is a Device ID, Logical device ID, Compatible
154; ID, or Vendor ID.
155;
156; OUT: Boolean indicator, TRUE when number of matching detected devices > 0.
157;
158*/
159{
160 BOOL bReturn = FALSE;
161 NPHANDLELIST pHandleList = 0;
162
163 if ( ! _rmDetection )
164 bReturn = TRUE;
165 else {
166 pHandleList = _DevIDToHandleList( DevID, ulSearchFlags, fPciDevice);
167 // Array of RM handles for the detected
168 // devices that match the PnP device ID(s).
169 bReturn = (pHandleList->cHandles != 0);
170 // If the size of the array != 0, we found the device.
171 delete pHandleList; // Free the structure.
172 }
173
174 return bReturn ;
175}
176
177
178
179/**@internal GetRMDetectedResources
180 * Return the set of IO ports, IRQ levels, DMA channels, & memory ranges
181 * required by the specified device, as detected by the OS/2 resource
182 * manager.
183 * @param Refer to _bIsDevDetected() for parameters.
184 * @notes It's expectded that the spec'd DevID & flags will select a single
185 * device in the system. If multiples are found, the first matching device
186 * is referenced.
187 * @return LDev_Resources* object, filled in with required resources. Object
188 * is allocated from heap, is responsibility of caller to free object.
189 * Ordering on the resources is preserved. Unused fields are set to NoIOValue.
190 * @return NULL on error situations.
191 */
192LDev_Resources* ResourceManager::GetRMDetectedResources ( DEVID DevID , ULONG ulSearchFlags, bool fPciDevice)
193{
194 LDev_Resources* pResources = 0; // Used to return result.
195 NPRM_GETNODE_DATA pNode = 0; // Node resource data for spec'd DEVID's.
196 NPRESOURCELIST pResourceList = 0; // Resource list contained within Node data.
197 int indexIO = 0; // Number of IO, IRQ, etc. requested.
198 int indexIRQ = 0;
199 int indexDMA = 0;
200 int indexMEM = 0;
201 int i;
202
203 pResources = new LDev_Resources();
204 if (!pResources) goto error_cleanup;
205 pResources->vClear();
206
207 // Get resources list from system RM. Returned pNode should have
208 // pNode->NodeType equal to RMTYPE_DETECTED (=5).
209 pNode = _DevIDToNodeData( DevID, ulSearchFlags, fPciDevice );
210 if ( !pNode ) goto error_cleanup;
211
212 pResourceList = (NPRESOURCELIST) pNode->RMNode.pResourceList;
213 if (! pResourceList) {
214 goto error_cleanup;
215 }
216 if (pResourceList->Count > MAX_ResourceCount) {
217 goto error_cleanup;
218 }
219
220 //--- Format resources into an LDev_Resource format.
221 for (i=0; i < pResourceList->Count; ++i) {
222 RESOURCESTRUCT* pRes = &pResourceList->Resource[i];
223 // Pointer to next resource in list.
224 switch( pRes->ResourceType ) {
225 case RS_TYPE_IO:
226 pResources->uIOBase[ indexIO ] = pRes->IOResource.BaseIOPort;
227 pResources->uIOLength[ indexIO ] = pRes->IOResource.NumIOPorts;
228 ++indexIO;
229 break;
230
231 case RS_TYPE_IRQ:
232 pResources->uIRQLevel[ indexIRQ ] = pRes->IRQResource.IRQLevel;
233 ++indexIRQ;
234 break;
235
236 case RS_TYPE_DMA:
237 pResources->uDMAChannel[ indexDMA ] = pRes->DMAResource.DMAChannel;
238 ++indexDMA;
239 break;
240
241 case RS_TYPE_MEM:
242 pResources->uMemBase[ indexMEM ] = pRes->MEMResource.MemBase;
243 pResources->uMemLength[ indexMEM ] = pRes->MEMResource.MemSize;
244 ++indexMEM;
245 break;
246 }
247 } /* end for loop through resource list. */
248
249 delete pNode;
250 return pResources;
251
252error_cleanup:
253 delete pNode;
254 delete pResources;
255 return NULL;
256}
257
258
259// declarations for functions defined in rmWarp3.cpp
260LDev_Resources* GetPnpLDevConfig( int iLDev );
261void SetPnpLDevConfig( int iLDev, LDev_Resources* pResources );
262
263/**@external pGetDevResources
264 *
265 * Allocate set of IO ports, IRQ levels, DMA channels requested by the
266 * specified device.
267 *
268 * @param Refer to bIsDevDetected()
269 *
270 * @return LDev_Resources object, filled in with required resources. Object
271 * is returned on stack. Ordering on the resources is preserved. Unused
272 * fields are set to 0xFF.
273 *
274 * @notes The allocation from OS/2's RM is required; if not performed, the
275 * resources could be allocated by a driver which loads after this one.
276 * Also perform other bookeepping by registering driver, adapter, and
277 * device with the system RM.
278 *
279 * @notes Additional comments from DevCon 'ADD' sample for RM: "Create all
280 * Resource Manager nodes required by this driver. The Resource Manager
281 * structures created in this module may be thought of as being allocated
282 * in a seperate tree called the 'driver' tree. The snooper resource nodes
283 * were created in the 'current detected' tree. Therefore, these
284 * allocations will not compete with previous snooper resource allocations.
285 *
286 * @notes
287 *
288 * - Fetch defaults for named device
289 * - Warp3: GetSpecDefaults( pnpID )
290 * - (not implemented:) snoop on Warp3 -> GetSnoopedResources()
291 * - Warp4: GetLDev_Resources( pnpID ) (rename to GetRMDetectedResources())
292 * - @return LDev_Resources structure
293 * - Fill in any user overrides
294 * - object Override( pnpID ) subclasses an LDev_Resources
295 * - has an added "exists" flag, set true if any overrides exist
296 * - on creation, interacts with parsed information for overrides
297 * - bool Override.exist( pnpID )
298 * - LDev_Resources Override.apply( pnpID, LDev_Resources )
299 * - Format LDev_Resources into RESOURCELIST
300 * - pResourceList = MakeResourceList( LDev_Resources )
301 * - Allocate adapter if this is the 1st time through
302 * - RMCreateAdapter()
303 * - Allocate resources to device
304 * - Call GetDescriptiveName( pnpID ) if Warp3
305 * - Call RMCreateDevice() to allocate the resources
306 * - Add as last step:
307 * - if (Warp3 or any command line overrides) and
308 * - if resources are successfully allocated
309 * - then SLAM the chip with the allocated resources
310 */
311
312LDev_Resources* ResourceManager::pGetDevResources ( DEVID DevID , ULONG ulSearchFlags, bool fPciDevice)
313{
314 APIRET rc;
315
316 // These pointers must be initialized to 0 so that they're valid for
317 // delete operation on an exception cleanup.
318
319 NPRM_GETNODE_DATA pNode = 0; // Resources list from RM. Be sure to
320 // return this memory to heap when done.
321 NPRESOURCELIST pResourceList = 0; // Pointer to the resource list; may or
322 // may not be contained within the Node data.
323 NPAHRESOURCE pahResources = 0; // Pointer to the resource handle
324 // structure.
325 LDev_Resources* pResources = 0; // Used to return result.
326
327 // Initialize resource object. Use detected information if available,
328 // otherwise use hardcoded defaults.
329 pResources = GetRMDetectedResources( DevID, ulSearchFlags, fPciDevice );
330 if (!pResources) goto exit;
331
332 // Convert the data format into an OS/2 RM RESOURCELIST & allocate resources.
333 pResourceList = _makeResourceList( *pResources );
334 if (! pResourceList) goto exit;
335 pahResources = _pahRMAllocResources( pResourceList );
336 if (! pahResources) goto exit;
337
338 //--- Here, we got all the resources we wanted. Register adapter if not yet done.
339 //### Problem here with mult adpaters, would need to cross ref PnP ID's to adapters created.
340 if (_state != rmAdapterCreated) {
341 rc = _rmCreateAdapter();
342 }
343
344 // Register the device with OS/2 RM.
345 _rmCreateDevice((unsigned char __far *)DeviceName, pahResources );
346
347exit:
348 delete pahResources;
349 delete pResourceList;
350
351 return pResources;
352}
353
354/*
355 * --- Private member functions.
356 */
357
358
359/**@internal ResourceManager::_makeResourceList
360 * Converts an LDevResource structure into an RESOURCELIST.
361 * @param LDev_Resources resources - structure to translate
362 * @return PRESOURCELIST pResourceList - pointer to resource list.
363 * @return NULL on storage allocation exception.
364 * @notes Storage for the RESOURCELIST is allocated from the heap, and
365 * it's the responsibility of the caller to free this storage after use.
366 */
367NPRESOURCELIST ResourceManager::_makeResourceList( const LDev_Resources& resources )
368{
369 int i, j; // Index vbls
370 int nResources; // Number of resources.
371 PRESOURCELIST pRL; // Return value, pointer to resource list
372 // constructured in the heap.
373 // Count up number of resources.
374 for ( i=0, nResources=0; i<MAX_ISA_Dev_IO; ++i) {
375 if (resources.uIOBase[i] != NoIOValue)
376 ++ nResources;
377 if ((i < MAX_ISA_Dev_IRQ) && (resources.uIRQLevel[i] != NoIOValue))
378 ++ nResources;
379 if ((i < MAX_ISA_Dev_DMA) && (resources.uDMAChannel[i] != NoIOValue))
380 ++ nResources;
381 if ((i < MAX_ISA_Dev_MEM) && (resources.uMemBase[i] != 0xffffffff))
382 ++ nResources;
383 }
384
385 // Allocate storage for the resource list.
386 USHORT nBytes = sizeof(RESOURCELIST) +
387 (nResources * sizeof(RESOURCESTRUCT));
388 pRL = (PRESOURCELIST) malloc( nBytes );
389 if (!pRL) return NULL;
390
391 // Fill in resource list values.
392 _fmemset( (PVOID) pRL, 0, nBytes );
393 pRL->Count = nResources;
394
395 // 'i' is the resource list index and points to next empty slot.
396 // 'j' indexes the LDev_Resources struct.
397 i = 0;
398 for ( j=0; j<MAX_ISA_Dev_IO; ++j) {
399 if (resources.uIOBase[j] != NoIOValue) {
400 pRL->Resource[i].ResourceType = RS_TYPE_IO;
401 pRL->Resource[i].IOResource.BaseIOPort = resources.uIOBase[j];
402 pRL->Resource[i].IOResource.NumIOPorts = resources.uIOLength[j];
403 pRL->Resource[i].IOResource.IOFlags = RS_IO_EXCLUSIVE;
404 if (resources.uIOBase[j] > 0x3ff) // ### IHV
405 pRL->Resource[i].IOResource.IOAddressLines = 16; // ### IHV
406 else // ### IHV
407 pRL->Resource[i].IOResource.IOAddressLines = 10; // ### IHV
408 ++i;
409 }
410 }
411 for ( j=0; j<MAX_ISA_Dev_IRQ; ++j) {
412 if (resources.uIRQLevel[j] != NoIOValue) {
413 pRL->Resource[i].ResourceType = RS_TYPE_IRQ;
414 pRL->Resource[i].IRQResource.IRQLevel = resources.uIRQLevel[j];
415 pRL->Resource[i].IRQResource.IRQFlags = RS_IRQ_SHARED;
416 pRL->Resource[i].IRQResource.PCIIrqPin = RS_PCI_INT_NONE;
417 ++i;
418 }
419 }
420 for ( j=0; j<MAX_ISA_Dev_DMA; ++j) {
421 if (resources.uDMAChannel[j] != NoIOValue) {
422 pRL->Resource[i].ResourceType = RS_TYPE_DMA;
423 pRL->Resource[i].DMAResource.DMAChannel = resources.uDMAChannel[j];
424 pRL->Resource[i].DMAResource.DMAFlags = RS_DMA_EXCLUSIVE;
425 ++i;
426 }
427 }
428
429 for ( j=0; j<MAX_ISA_Dev_MEM; ++j) {
430 if (resources.uMemBase[j] != 0xffffffff) {
431 pRL->Resource[i].ResourceType = RS_TYPE_MEM;
432 pRL->Resource[i].MEMResource.MemBase = resources.uMemBase[j];
433 pRL->Resource[i].MEMResource.MemSize = resources.uMemLength[j];
434 pRL->Resource[i].MEMResource.MemFlags = RS_MEM_EXCLUSIVE;
435 ++i;
436 }
437 }
438
439 return pRL;
440}
441
442
443
444NPHANDLELIST ResourceManager::_DevIDToHandleList ( DEVID DevID , ULONG ulSearchFlags, bool fPciDevice)
445/*
446; PURPOSE: Search the Resource Manager's "current detected" tree for
447; the specified PnP ID, and return all matching RM handles.
448;
449; IN: Refer to bIsDevDetected()
450;
451; OUT: List of RM handles matching the search, in HandleList format (rmbase.h)
452; Info returned in heap memory, caller must ensure this is later freed.
453*/
454{
455 APIRET rc;
456 DEVID DeviceID, FunctionID, CompatID, VendorID;
457
458 //--- Stuff the search value into the appropriate vbl. Need not initialize
459 // or zero out the other vbls, they won't be referenced during the search.
460 switch (ulSearchFlags) {
461 case SEARCH_ID_DEVICEID:
462 DeviceID = DevID;
463 break;
464 case SEARCH_ID_FUNCTIONID:
465 FunctionID = DevID;
466 break;
467 case SEARCH_ID_COMPATIBLEID:
468 CompatID = DevID;
469 break;
470 case SEARCH_ID_VENDOR:
471 VendorID = DevID;
472 break;
473 default:
474 return NULL;
475 }
476
477 NPHANDLELIST pDevHandleList = (NPHANDLELIST)
478 malloc ( sizeof(HANDLELIST) + (sizeof(RMHANDLE) * MAX_DevID) ); //###
479 //### new char[ sizeof(HANDLELIST) + (sizeof(RMHANDLE) * MAX_DevID) ];
480
481 // List of RM handles associated w/ Device ID. Will normally
482 // be a single handle for the single adapter or function found.
483
484 pDevHandleList->cHandles = 0; // clear handle count
485 pDevHandleList->cMaxHandles = MAX_DevID; // set size dimension
486
487 // Use the PnP ID to get a list of detected devices which used this ID,
488 // by searching for all snooped devices in the CURRENT detected tree.
489 rc = RMDevIDToHandleList(
490 (fPciDevice) ? RM_IDTYPE_PCI : RM_IDTYPE_EISA, // input device IDs' format
491 DeviceID, // device (adapter) ID
492 FunctionID, // logical device (function) ID
493 CompatID, // compatible ID
494 VendorID, // vendor ID
495 0, // serial number
496 ulSearchFlags,
497 HANDLE_CURRENT_DETECTED,
498 pDevHandleList ); // place output here
499 if (rc != RMRC_SUCCESS) {
500 return NULL;
501 }
502
503 return pDevHandleList;
504}
505
506
507NPRM_GETNODE_DATA ResourceManager::_RMHandleToNodeData ( RMHANDLE rmHandle )
508/*
509; PURPOSE: Return the list of resources requested by the device
510; represented by the resource manager handle.
511;
512; IN: - rmHandle - rmHandle representing the Device or Logical device of
513; interest.
514;
515; OUT: List of resources (GETNODE_DATA format, rmbase.h, rmioctl.h), saved
516; in heap memory. Caller must ensure this memory is later freed.
517;
518; ALGORITHM:
519; 1. Call RMHandleToResourceHandleList to get a count of # of resources.
520; 2. Allocate heap memory for array of Resources.
521; 3. Construct resource list by one of the following methods
522; a. Call RMGetNodeInfo on each resource hangle (n calls to RM)
523; used-> b. Call RMGetNodeInfo with device handle (1 call to RM)
524*/
525{
526 APIRET rc;
527
528 //--- Fetch list of resource handles for this device handle. We use the
529 // handle list only to get a count on the number of resources.
530 char work[ sizeof(HANDLELIST) + (sizeof(RMHANDLE) * MAX_ResourceCount) ];
531 PHANDLELIST pResourceHandleList = (PHANDLELIST) work;
532 // List of handles for IO, IRQ, DMA, etc. resources.
533
534 pResourceHandleList->cHandles = 0;
535 pResourceHandleList->cMaxHandles = MAX_ResourceCount;
536 rc = RMHandleToResourceHandleList( rmHandle, pResourceHandleList );
537 if (rc != RMRC_SUCCESS) {
538 return NULL;
539 }
540
541 //--- Allocate heap memory to hold complete list of resources for device.
542 USHORT uNodeSize = sizeof(RM_GETNODE_DATA)
543 + sizeof(ADAPTERSTRUCT) + MAX_DescTextLen
544 + sizeof(DRIVERSTRUCT) + MAX_DescTextLen
545 + (sizeof(RESOURCESTRUCT) * pResourceHandleList->cHandles);
546 //### NPRM_GETNODE_DATA pNodeData = (NPRM_GETNODE_DATA) new char[ uNodeSize ];
547 NPRM_GETNODE_DATA pNodeData = (NPRM_GETNODE_DATA) malloc( uNodeSize );
548
549 //--- Get resource info, use single call to GetNodeInfo on device handle.
550 rc = RMGetNodeInfo( rmHandle, pNodeData, uNodeSize );
551 if (rc != RMRC_SUCCESS) {
552 delete pNodeData;
553 return NULL;
554 }
555
556 return pNodeData; // Return getnode data.
557}
558
559
560NPRM_GETNODE_DATA ResourceManager::_DevIDToNodeData ( DEVID DevID , ULONG ulSearchFlags, bool fPciDevice )
561/*
562; PURPOSE: Compose the functions
563; _DevIDToHandleList
564; _RMHandleToNodeData (applied to 1st RM handle in handle list)
565;
566; IN: Refer to bIsDevDetected()
567; OUT: Refer to _RMHandleToNodeData.
568;
569; REMARKS: Returns pointer to heap memory allocated. Caller must ensure heap memory
570; freed after use.
571*/
572{
573 NPHANDLELIST pDevHandleList; // RM handles for spec'd DEVID's
574 NPRM_GETNODE_DATA pNode; // Node resource data for spec'd DEVID's.
575
576 pDevHandleList = _DevIDToHandleList( DevID, ulSearchFlags, fPciDevice );
577 // Convert PnP ID -> RM handle.
578 if ( pDevHandleList ) { // If we got a valid handle list
579 if ( pDevHandleList->cHandles ) // ... and if we got >0 handles
580 pNode = _RMHandleToNodeData( pDevHandleList->Handles[0] );
581
582 delete pDevHandleList; // We've made the transform, now free memory.
583 }
584
585 return pNode;
586}
587
588
589/**@internal _pahRMAllocResources
590 * Allocate a set of resources from OS/2 by interfacing with the
591 * OS/2 resource manager.
592 * @param PRESOURCELIST pResourceList - list of resources to allocate.
593 * @return PAHRESOURCE - normal return, pointer to an AHRESOURCE structure
594 * as defined by OS/2 RM. This structure is allocated from the heap and
595 * must be freed by the caller.
596 * @return NULL - on failure
597 * @notes Logs appropriate errors in global error log if any allocation
598 * problem.
599 * @notes Either all resources are allocated, or none. If there is a
600 * failure within this function when some (but not all) resources are
601 * allocated, then any allocated resources are freed.
602 */
603NPAHRESOURCE ResourceManager::_pahRMAllocResources( NPRESOURCELIST pResourceList )
604{
605 APIRET rc;
606 USHORT nBytes =
607 sizeof(AHRESOURCE) + (sizeof(HRESOURCE) * pResourceList->Count);
608 NPAHRESOURCE pahResource = (NPAHRESOURCE) malloc( nBytes );
609 // Handles for allocated resources are saved here.
610 if (!pahResource) return NULL;
611
612 pahResource->NumResource = 0; // Init # of resources successfully allocated.
613
614 //--- Allocate each resource requested.
615 for (int i=0; i < pResourceList->Count; ++i) {
616 rc = RMAllocResource( _hDriver, // Handle to driver.
617 &pahResource->hResource[i], // OUT: "allocated" resource node handle
618 &pResourceList->Resource[i] ); // Resource to allocate.
619 if (rc == RMRC_SUCCESS)
620 ++pahResource->NumResource;
621 else {
622 PRESOURCESTRUCT pRes = &pResourceList->Resource[i];
623 // Pointer to the resource that we can't allocate.
624
625 // Put a good error message out on the resource that couldn't be allocated.
626 switch( pRes->ResourceType ) {
627 case RS_TYPE_IO:
628 break;
629 case RS_TYPE_IRQ:
630 break;
631 case RS_TYPE_DMA:
632 break;
633 case RS_TYPE_MEM:
634 break;
635 default:
636 break;
637 }
638
639 // Deallocate any allocated resources, then fail the function call.
640 for (int j=0; i < pahResource->NumResource; ++j)
641 RMDeallocResource( _hDriver, pahResource->hResource[j] );
642 // Deallocate any resources we've reserved.
643
644 delete pahResource;
645 return NULL;
646 }
647 }
648
649 return pahResource;
650}
651
652/**@internal _rmCreateAdapter
653 * Create the "adapter" node. The "adapter" node belongs to this driver's
654 * "driver" node. Also as part of this operation, the "resource" nodes
655 * associated with this driver will be moved to the "adapter" node.
656 * @param None.
657 * @notes Changes state of the RM object to 'rmAdapterCreated'.
658 * @return APIRET rc - 0 iff good creation. Returns non-zero and logs a soft
659 * error on failure.
660 */
661APIRET ResourceManager::_rmCreateAdapter()
662{
663 APIRET rc;
664 ADAPTERSTRUCT AdapterStruct;
665
666 if (_state != rmAdapterCreated) {
667 _fmemset( (PVOID) &AdapterStruct, 0, sizeof(AdapterStruct) );
668 AdapterStruct.AdaptDescriptName = (PSZ) "SoundBlaster Live!" ; /* ### IHV */
669 AdapterStruct.AdaptFlags = AS_16MB_ADDRESS_LIMIT; // AdaptFlags /* ### IHV */
670 AdapterStruct.BaseType = AS_BASE_MMEDIA; // BaseType
671 AdapterStruct.SubType = AS_SUB_MM_AUDIO; // SubType
672 AdapterStruct.InterfaceType = AS_INTF_GENERIC; // InterfaceType
673 AdapterStruct.HostBusType = AS_HOSTBUS_PCI; // HostBusType /* ### IHV */
674 AdapterStruct.HostBusWidth = AS_BUSWIDTH_32BIT; // HostBusWidth /* ### IHV */
675 AdapterStruct.pAdjunctList = NULL; // pAdjunctList /* ### IHV */
676
677 //--- Register adapter. We'll record any error code, but won't fail
678 // the driver initialization and won't return resources.
679 rc = RMCreateAdapter( _hDriver, // Handle to driver
680 &_hAdapter, // (OUT) Handle to adapter
681 &AdapterStruct, // Adapter structure
682 NULL, // Parent device (defaults OK)
683 NULL ); // Allocated resources. We assign ownership
684 // of the IO, IRQ, etc. resources to the
685 // device (via RMCreateDevice()), not to the
686 // adapter (as done in disk DD sample).
687 if (rc == RMRC_SUCCESS)
688 _state = rmAdapterCreated;
689 }
690 return rc;
691}
692
693/**@internal _rmCreateDevice
694 * Create Device node in the OS/2 RM allocation tree. Device nodes belong
695 * to the Adapter node, just like the Resource nodes.
696 * @param PSZ pszName - Descriptive name of device.
697 * @param PAHRESOURCE pahResource - Handles of allocated resources that are
698 * owned by this device.
699 * @return APIRET rc - Value returned by RMCreateDevice() call.
700 * @notes Same "soft" error strategy as adapter registration: we'll record
701 * any errors but hold onto the resources and continue to operate the
702 * driver.
703 * @notes
704 */
705APIRET ResourceManager::_rmCreateDevice( PSZ pszName, NPAHRESOURCE pahResource )
706{
707 DEVICESTRUCT DeviceStruct;
708 HDEVICE hDevice;
709 APIRET rc;
710
711 _fmemset( (PVOID) &DeviceStruct, 0, sizeof(DeviceStruct) );
712 DeviceStruct.DevDescriptName = pszName;
713 DeviceStruct.DevFlags = DS_FIXED_LOGICALNAME;
714 DeviceStruct.DevType = DS_TYPE_AUDIO;
715 DeviceStruct.pAdjunctList = NULL;
716
717 rc = RMCreateDevice( _hDriver, // Handle to driver
718 &hDevice, // (OUT) Handle to device, unused.
719 &DeviceStruct, // Device structure
720 _hAdapter, // Parent adapter
721 pahResource ); // Allocated resources
722 return rc;
723}
724
Note: See TracBrowser for help on using the repository browser.