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

Last change on this file since 160 was 157, checked in by sandervl, 25 years ago

pci detection fix

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