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

Last change on this file since 777 was 205, checked in by stevenhl, 18 years ago

Make warnings away - SHL
Use drv16/midi_idc.h only - SHL
Add interrupts 16-23 - MF

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