source: cmedia/trunk/Drv16/rm.cpp@ 354

Last change on this file since 354 was 354, checked in by stevenhl, 17 years ago

Import untested baseline cmedia sources, work products and binaries
Binaries and work products should be deleted from repository.
once new builds are verified to work.

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