/* $Id: rm.cpp 205 2007-06-14 01:33:51Z stevenhl $ */ /* SCCSID = %W% %E% */ /**************************************************************************** * * * Copyright (c) IBM Corporation 1994 - 1997. * * * * The following IBM OS/2 source code is provided to you solely for the * * the purpose of assisting you in your development of OS/2 device drivers. * * You may use this code in accordance with the IBM License Agreement * * provided in the IBM Device Driver Source Kit for OS/2. * * * ****************************************************************************/ /**@internal %W% * RM (Resource manager) object implementation * @version %I% * @context * Unless otherwise noted, all interfaces are Ring-3, 16-bit, sysinit time * execution context on the kernel stack. * @notes * Provides information to the audio driver on the detected devices and the * resources required for device operation. Obtain required resources from * Resource Manager as directed by the client of this object. The adapters * and controllers will be controlled by this driver. The detected resources * that will be operated should be reallocated as driver resources. This code * is dumped after driver initialization is complete. * * Remarks : * *. PnP Device ID's are always in Compressed Ascii format. * *. ### Need remove malloc by adding memory mgmt support for []. * * @history */ ////#pragma code_seg ("_inittext"); ////#pragma data_seg ("_initdata","endds"); #include "rm.hpp" // Will include os2.h, etc. #include #include // _fmemset() #include "malloc.h" // malloc() #include #define EMU10K1_JOYSTICK_EXTENT 0x8 /* 8 byte I/O space */ #define EMU10K1_EXTENT 0x20 /* 32 byte I/O space */ char DeviceName[64] = "Creative Labs SoundBlaster Live!"; char DeviceNameJoy[64] = "Creative Labs SoundBlaster Live! Joystick"; /**@external LDev_Resources::isEmpty * Returns TRUE iff the LDev_Resources structure has no information. * @param None. * @return BOOL */ BOOL LDev_Resources::isEmpty() { BOOL bIsEmpty = TRUE; for ( int i=0; iuchMajorVersion > 20) || ((pGIS->uchMajorVersion == 20) && (pGIS->uchMinorVersion > 30)) ); } } #pragma off (unreferenced) bool ResourceManager::bIsDevDetected( DEVID DevID , ULONG ulSearchFlags, bool fPciDevice) #pragma on (unreferenced) /* ; PURPOSE: Search the Resource Manager's "current detected" tree for ; the matching PnP ID. ; ; IN: - DevID - PnP Device ID being sought (Compressed Ascii). ; - ulSearchFlags - Search flags, ref rmbase.h SEARCH_ID_*; also ; documented as SearchFlags parm in PDD RM API RMDevIDToHandleList(). ; Defines whether DevID is a Device ID, Logical device ID, Compatible ; ID, or Vendor ID. ; ; OUT: Boolean indicator, TRUE when number of matching detected devices > 0. ; */ { #if 1 if(getPCIConfiguration(DevID) == FALSE) { return FALSE; } //Manual detection in ResourceManager class constructor; return (_state == rmDriverCreated || _state == rmAdapterCreated); #else BOOL bReturn = FALSE; NPHANDLELIST pHandleList = 0; if ( ! _rmDetection ) bReturn = TRUE; else { pHandleList = _DevIDToHandleList( DevID, ulSearchFlags, fPciDevice); // Array of RM handles for the detected // devices that match the PnP device ID(s). bReturn = (pHandleList->cHandles != 0); // If the size of the array != 0, we found the device. delete pHandleList; // Free the structure. } return bReturn ; #endif } /**@internal GetRMDetectedResources * Return the set of IO ports, IRQ levels, DMA channels, & memory ranges * required by the specified device, as detected by the OS/2 resource * manager. * @param Refer to _bIsDevDetected() for parameters. * @notes It's expectded that the spec'd DevID & flags will select a single * device in the system. If multiples are found, the first matching device * is referenced. * @return LDev_Resources* object, filled in with required resources. Object * is allocated from heap, is responsibility of caller to free object. * Ordering on the resources is preserved. Unused fields are set to NoIOValue. * @return NULL on error situations. */ #pragma off (unreferenced) LDev_Resources* ResourceManager::GetRMDetectedResources ( DEVID DevID , ULONG ulSearchFlags, bool fPciDevice, bool fJoystick) #pragma on (unreferenced) { #if 1 LDev_Resources* pResources = 0; // Used to return result. pResources = new LDev_Resources(); if (!pResources) return NULL; pResources->vClear(); //Fill in resources read from PCI Configuration space if(!fJoystick) { pResources->uIRQLevel[0] = pciConfigData->InterruptLine; if(pResources->uIRQLevel[0] == 0 || pResources->uIRQLevel[0] > 15) { dprintf(("Invalid PCI irq %x", (int)pResources->uIRQLevel[0])); DebugInt3(); return NULL; } } pResources->uIOBase[0] = (USHORT)(pciConfigData->Bar0 & 0xFFFFFFF0); if(fJoystick) { pResources->uIOLength[0] = EMU10K1_JOYSTICK_EXTENT; } else pResources->uIOLength[0] = EMU10K1_EXTENT; return pResources; #else LDev_Resources* pResources = 0; // Used to return result. NPRM_GETNODE_DATA pNode = 0; // Node resource data for spec'd DEVID's. NPRESOURCELIST pResourceList = 0; // Resource list contained within Node data. int indexIO = 0; // Number of IO, IRQ, etc. requested. int indexIRQ = 0; int indexDMA = 0; int indexMEM = 0; int i; pResources = new LDev_Resources(); if (!pResources) goto error_cleanup; pResources->vClear(); // Get resources list from system RM. Returned pNode should have // pNode->NodeType equal to RMTYPE_DETECTED (=5). pNode = _DevIDToNodeData( DevID, ulSearchFlags, fPciDevice ); if ( !pNode ) goto error_cleanup; pResourceList = (NPRESOURCELIST) pNode->RMNode.pResourceList; if (! pResourceList) { goto error_cleanup; } if (pResourceList->Count > MAX_ResourceCount) { goto error_cleanup; } //--- Format resources into an LDev_Resource format. for (i=0; i < pResourceList->Count; ++i) { RESOURCESTRUCT* pRes = &pResourceList->Resource[i]; // Pointer to next resource in list. switch( pRes->ResourceType ) { case RS_TYPE_IO: pResources->uIOBase[ indexIO ] = pRes->IOResource.BaseIOPort; pResources->uIOLength[ indexIO ] = pRes->IOResource.NumIOPorts; ++indexIO; break; case RS_TYPE_IRQ: pResources->uIRQLevel[ indexIRQ ] = pRes->IRQResource.IRQLevel; ++indexIRQ; break; case RS_TYPE_DMA: pResources->uDMAChannel[ indexDMA ] = pRes->DMAResource.DMAChannel; ++indexDMA; break; case RS_TYPE_MEM: pResources->uMemBase[ indexMEM ] = pRes->MEMResource.MemBase; pResources->uMemLength[ indexMEM ] = pRes->MEMResource.MemSize; ++indexMEM; break; } } /* end for loop through resource list. */ delete pNode; return pResources; error_cleanup: delete pNode; delete pResources; return NULL; #endif } // declarations for functions defined in rmWarp3.cpp LDev_Resources* GetPnpLDevConfig( int iLDev ); void SetPnpLDevConfig( int iLDev, LDev_Resources* pResources ); /**@external pGetDevResources * * Allocate set of IO ports, IRQ levels, DMA channels requested by the * specified device. * * @param Refer to bIsDevDetected() * * @return LDev_Resources object, filled in with required resources. Object * is returned on stack. Ordering on the resources is preserved. Unused * fields are set to 0xFF. * * @notes The allocation from OS/2's RM is required; if not performed, the * resources could be allocated by a driver which loads after this one. * Also perform other bookeepping by registering driver, adapter, and * device with the system RM. * * @notes Additional comments from DevCon 'ADD' sample for RM: "Create all * Resource Manager nodes required by this driver. The Resource Manager * structures created in this module may be thought of as being allocated * in a seperate tree called the 'driver' tree. The snooper resource nodes * were created in the 'current detected' tree. Therefore, these * allocations will not compete with previous snooper resource allocations. * * @notes * * - Fetch defaults for named device * - Warp3: GetSpecDefaults( pnpID ) * - (not implemented:) snoop on Warp3 -> GetSnoopedResources() * - Warp4: GetLDev_Resources( pnpID ) (rename to GetRMDetectedResources()) * - @return LDev_Resources structure * - Fill in any user overrides * - object Override( pnpID ) subclasses an LDev_Resources * - has an added "exists" flag, set true if any overrides exist * - on creation, interacts with parsed information for overrides * - bool Override.exist( pnpID ) * - LDev_Resources Override.apply( pnpID, LDev_Resources ) * - Format LDev_Resources into RESOURCELIST * - pResourceList = MakeResourceList( LDev_Resources ) * - Allocate adapter if this is the 1st time through * - RMCreateAdapter() * - Allocate resources to device * - Call GetDescriptiveName( pnpID ) if Warp3 * - Call RMCreateDevice() to allocate the resources * - Add as last step: * - if (Warp3 or any command line overrides) and * - if resources are successfully allocated * - then SLAM the chip with the allocated resources */ LDev_Resources* ResourceManager::pGetDevResources ( DEVID DevID , ULONG ulSearchFlags, bool fPciDevice, bool fJoystick) { APIRET rc; // These pointers must be initialized to 0 so that they're valid for // delete operation on an exception cleanup. NPRM_GETNODE_DATA pNode = 0; // Resources list from RM. Be sure to // return this memory to heap when done. NPRESOURCELIST pResourceList = 0; // Pointer to the resource list; may or // may not be contained within the Node data. NPAHRESOURCE pahResources = 0; // Pointer to the resource handle // structure. LDev_Resources* pResources = 0; // Used to return result. // Initialize resource object. Use detected information if available, // otherwise use hardcoded defaults. pResources = GetRMDetectedResources( DevID, ulSearchFlags, fPciDevice, fJoystick); if (!pResources) goto exit; // Convert the data format into an OS/2 RM RESOURCELIST & allocate resources. pResourceList = _makeResourceList( *pResources ); if (! pResourceList) goto exit; pahResources = _pahRMAllocResources( pResourceList ); if (! pahResources) { _state = rmAllocFailed; goto exit; } //--- Here, we got all the resources we wanted. Register adapter if not yet done. //### Problem here with mult adpaters, would need to cross ref PnP ID's to adapters created. if (_state != rmAdapterCreated) { rc = _rmCreateAdapter(); } // Register the device with OS/2 RM. if(fJoystick) { _rmCreateDevice((unsigned char __far *)DeviceNameJoy, pahResources ); } else _rmCreateDevice((unsigned char __far *)DeviceName, pahResources ); exit: delete pahResources; delete pResourceList; return pResources; } /* * --- Private member functions. */ /**@internal ResourceManager::_makeResourceList * Converts an LDevResource structure into an RESOURCELIST. * @param LDev_Resources resources - structure to translate * @return PRESOURCELIST pResourceList - pointer to resource list. * @return NULL on storage allocation exception. * @notes Storage for the RESOURCELIST is allocated from the heap, and * it's the responsibility of the caller to free this storage after use. */ NPRESOURCELIST ResourceManager::_makeResourceList( const LDev_Resources& resources ) { int i, j; // Index vbls int nResources; // Number of resources. PRESOURCELIST pRL; // Return value, pointer to resource list // constructed in the heap. // Count up number of resources. for ( i=0, nResources=0; iCount = nResources; // 'i' is the resource list index and points to next empty slot. // 'j' indexes the LDev_Resources struct. i = 0; for ( j=0; jResource[i].ResourceType = RS_TYPE_IO; pRL->Resource[i].IOResource.BaseIOPort = resources.uIOBase[j]; pRL->Resource[i].IOResource.NumIOPorts = resources.uIOLength[j]; pRL->Resource[i].IOResource.IOFlags = RS_IO_EXCLUSIVE; if (resources.uIOBase[j] > 0x3ff) // ### IHV pRL->Resource[i].IOResource.IOAddressLines = 16; // ### IHV else // ### IHV pRL->Resource[i].IOResource.IOAddressLines = 10; // ### IHV ++i; } } for ( j=0; jResource[i].ResourceType = RS_TYPE_IRQ; pRL->Resource[i].IRQResource.IRQLevel = resources.uIRQLevel[j]; pRL->Resource[i].IRQResource.IRQFlags = RS_IRQ_SHARED; pRL->Resource[i].IRQResource.PCIIrqPin = RS_PCI_INT_NONE; ++i; } } for ( j=0; jResource[i].ResourceType = RS_TYPE_DMA; pRL->Resource[i].DMAResource.DMAChannel = resources.uDMAChannel[j]; pRL->Resource[i].DMAResource.DMAFlags = RS_DMA_EXCLUSIVE; ++i; } } for ( j=0; jResource[i].ResourceType = RS_TYPE_MEM; pRL->Resource[i].MEMResource.MemBase = resources.uMemBase[j]; pRL->Resource[i].MEMResource.MemSize = resources.uMemLength[j]; pRL->Resource[i].MEMResource.MemFlags = RS_MEM_EXCLUSIVE; ++i; } } return (NPRESOURCELIST)pRL; } NPHANDLELIST ResourceManager::_DevIDToHandleList ( DEVID DevID , ULONG ulSearchFlags, bool fPciDevice) /* ; PURPOSE: Search the Resource Manager's "current detected" tree for ; the specified PnP ID, and return all matching RM handles. ; ; IN: Refer to bIsDevDetected() ; ; OUT: List of RM handles matching the search, in HandleList format (rmbase.h) ; Info returned in heap memory, caller must ensure this is later freed. */ { APIRET rc; DEVID DeviceID, FunctionID, CompatID, VendorID; //--- Stuff the search value into the appropriate vbl. Need not initialize // or zero out the other vbls, they won't be referenced during the search. switch (ulSearchFlags) { case SEARCH_ID_DEVICEID: DeviceID = DevID; break; case SEARCH_ID_FUNCTIONID: FunctionID = DevID; break; case SEARCH_ID_COMPATIBLEID: CompatID = DevID; break; case SEARCH_ID_VENDOR: VendorID = DevID; break; default: return NULL; } NPHANDLELIST pDevHandleList = (NPHANDLELIST) malloc ( sizeof(HANDLELIST) + (sizeof(RMHANDLE) * MAX_DevID) ); //### //### new char[ sizeof(HANDLELIST) + (sizeof(RMHANDLE) * MAX_DevID) ]; // List of RM handles associated w/ Device ID. Will normally // be a single handle for the single adapter or function found. pDevHandleList->cHandles = 0; // clear handle count pDevHandleList->cMaxHandles = MAX_DevID; // set size dimension // Use the PnP ID to get a list of detected devices which used this ID, // by searching for all snooped devices in the CURRENT detected tree. rc = RMDevIDToHandleList( (fPciDevice) ? RM_IDTYPE_PCI : RM_IDTYPE_EISA, // input device IDs' format DeviceID, // device (adapter) ID FunctionID, // logical device (function) ID CompatID, // compatible ID VendorID, // vendor ID 0, // serial number ulSearchFlags, HANDLE_CURRENT_DETECTED, pDevHandleList ); // place output here if (rc != RMRC_SUCCESS) { return NULL; } return pDevHandleList; } NPRM_GETNODE_DATA ResourceManager::_RMHandleToNodeData ( RMHANDLE rmHandle ) /* ; PURPOSE: Return the list of resources requested by the device ; represented by the resource manager handle. ; ; IN: - rmHandle - rmHandle representing the Device or Logical device of ; interest. ; ; OUT: List of resources (GETNODE_DATA format, rmbase.h, rmioctl.h), saved ; in heap memory. Caller must ensure this memory is later freed. ; ; ALGORITHM: ; 1. Call RMHandleToResourceHandleList to get a count of # of resources. ; 2. Allocate heap memory for array of Resources. ; 3. Construct resource list by one of the following methods ; a. Call RMGetNodeInfo on each resource hangle (n calls to RM) ; used-> b. Call RMGetNodeInfo with device handle (1 call to RM) */ { APIRET rc; //--- Fetch list of resource handles for this device handle. We use the // handle list only to get a count on the number of resources. char work[ sizeof(HANDLELIST) + (sizeof(RMHANDLE) * MAX_ResourceCount) ]; PHANDLELIST pResourceHandleList = (PHANDLELIST) work; // List of handles for IO, IRQ, DMA, etc. resources. pResourceHandleList->cHandles = 0; pResourceHandleList->cMaxHandles = MAX_ResourceCount; rc = RMHandleToResourceHandleList( rmHandle, pResourceHandleList ); if (rc != RMRC_SUCCESS) { return NULL; } //--- Allocate heap memory to hold complete list of resources for device. USHORT uNodeSize = sizeof(RM_GETNODE_DATA) + sizeof(ADAPTERSTRUCT) + MAX_DescTextLen + sizeof(DRIVERSTRUCT) + MAX_DescTextLen + (sizeof(RESOURCESTRUCT) * pResourceHandleList->cHandles); //### NPRM_GETNODE_DATA pNodeData = (NPRM_GETNODE_DATA) new char[ uNodeSize ]; NPRM_GETNODE_DATA pNodeData = (NPRM_GETNODE_DATA) malloc( uNodeSize ); //--- Get resource info, use single call to GetNodeInfo on device handle. rc = RMGetNodeInfo( rmHandle, pNodeData, uNodeSize ); if (rc != RMRC_SUCCESS) { delete pNodeData; return NULL; } return pNodeData; // Return getnode data. } NPRM_GETNODE_DATA ResourceManager::_DevIDToNodeData ( DEVID DevID , ULONG ulSearchFlags, bool fPciDevice ) /* ; PURPOSE: Compose the functions ; _DevIDToHandleList ; _RMHandleToNodeData (applied to 1st RM handle in handle list) ; ; IN: Refer to bIsDevDetected() ; OUT: Refer to _RMHandleToNodeData. ; ; REMARKS: Returns pointer to heap memory allocated. Caller must ensure heap memory ; freed after use. */ { NPHANDLELIST pDevHandleList; // RM handles for spec'd DEVID's NPRM_GETNODE_DATA pNode; // Node resource data for spec'd DEVID's. pDevHandleList = _DevIDToHandleList( DevID, ulSearchFlags, fPciDevice ); // Convert PnP ID -> RM handle. if ( pDevHandleList ) { // If we got a valid handle list if ( pDevHandleList->cHandles ) // ... and if we got >0 handles pNode = _RMHandleToNodeData( pDevHandleList->Handles[0] ); delete pDevHandleList; // We've made the transform, now free memory. } return pNode; } /**@internal _pahRMAllocResources * Allocate a set of resources from OS/2 by interfacing with the * OS/2 resource manager. * @param PRESOURCELIST pResourceList - list of resources to allocate. * @return PAHRESOURCE - normal return, pointer to an AHRESOURCE structure * as defined by OS/2 RM. This structure is allocated from the heap and * must be freed by the caller. * @return NULL - on failure * @notes Logs appropriate errors in global error log if any allocation * problem. * @notes Either all resources are allocated, or none. If there is a * failure within this function when some (but not all) resources are * allocated, then any allocated resources are freed. */ NPAHRESOURCE ResourceManager::_pahRMAllocResources( NPRESOURCELIST pResourceList ) { APIRET rc; // 13 Jun 07 SHL fixme to check overflow even though unlikely USHORT nBytes = sizeof(AHRESOURCE) + (sizeof(HRESOURCE) * (USHORT)pResourceList->Count); NPAHRESOURCE pahResource = (NPAHRESOURCE) malloc( nBytes ); // Handles for allocated resources are saved here. if (!pahResource) return NULL; pahResource->NumResource = 0; // Init # of resources successfully allocated. //--- Allocate each resource requested. for (int i=0; i < pResourceList->Count; ++i) { rc = RMAllocResource( _hDriver, // Handle to driver. &pahResource->hResource[i], // OUT: "allocated" resource node handle &pResourceList->Resource[i] ); // Resource to allocate. if (rc == RMRC_SUCCESS) ++pahResource->NumResource; else { PRESOURCESTRUCT pRes = &pResourceList->Resource[i]; // Pointer to the resource that we can't allocate. // Put a good error message out on the resource that couldn't be allocated. switch( pRes->ResourceType ) { case RS_TYPE_IO: break; case RS_TYPE_IRQ: break; case RS_TYPE_DMA: break; case RS_TYPE_MEM: break; default: break; } // Deallocate any allocated resources, then fail the function call. for (int j=0; i < pahResource->NumResource; ++j) RMDeallocResource( _hDriver, pahResource->hResource[j] ); // Deallocate any resources we've reserved. delete pahResource; return NULL; } } return pahResource; } /**@internal _rmCreateAdapter * Create the "adapter" node. The "adapter" node belongs to this driver's * "driver" node. Also as part of this operation, the "resource" nodes * associated with this driver will be moved to the "adapter" node. * @param None. * @notes Changes state of the RM object to 'rmAdapterCreated'. * @return APIRET rc - 0 iff good creation. Returns non-zero and logs a soft * error on failure. */ APIRET ResourceManager::_rmCreateAdapter() { APIRET rc; ADAPTERSTRUCT AdapterStruct; if (_state != rmAdapterCreated) { _fmemset( (PVOID) &AdapterStruct, 0, sizeof(AdapterStruct) ); AdapterStruct.AdaptDescriptName = (PSZ) "SoundBlaster Live!" ; /* ### IHV */ AdapterStruct.AdaptFlags = AS_16MB_ADDRESS_LIMIT; // AdaptFlags /* ### IHV */ AdapterStruct.BaseType = AS_BASE_MMEDIA; // BaseType AdapterStruct.SubType = AS_SUB_MM_AUDIO; // SubType AdapterStruct.InterfaceType = AS_INTF_GENERIC; // InterfaceType AdapterStruct.HostBusType = AS_HOSTBUS_PCI; // HostBusType /* ### IHV */ AdapterStruct.HostBusWidth = AS_BUSWIDTH_32BIT; // HostBusWidth /* ### IHV */ AdapterStruct.pAdjunctList = NULL; // pAdjunctList /* ### IHV */ //--- Register adapter. We'll record any error code, but won't fail // the driver initialization and won't return resources. rc = RMCreateAdapter( _hDriver, // Handle to driver &_hAdapter, // (OUT) Handle to adapter &AdapterStruct, // Adapter structure NULL, // Parent device (defaults OK) NULL ); // Allocated resources. We assign ownership // of the IO, IRQ, etc. resources to the // device (via RMCreateDevice()), not to the // adapter (as done in disk DD sample). if (rc == RMRC_SUCCESS) _state = rmAdapterCreated; } return rc; } /**@internal _rmCreateDevice * Create Device node in the OS/2 RM allocation tree. Device nodes belong * to the Adapter node, just like the Resource nodes. * @param PSZ pszName - Descriptive name of device. * @param PAHRESOURCE pahResource - Handles of allocated resources that are * owned by this device. * @return APIRET rc - Value returned by RMCreateDevice() call. * @notes Same "soft" error strategy as adapter registration: we'll record * any errors but hold onto the resources and continue to operate the * driver. * @notes */ APIRET ResourceManager::_rmCreateDevice( PSZ pszName, NPAHRESOURCE pahResource ) { DEVICESTRUCT DeviceStruct; HDEVICE hDevice; APIRET rc; _fmemset( (PVOID) &DeviceStruct, 0, sizeof(DeviceStruct) ); DeviceStruct.DevDescriptName = pszName; DeviceStruct.DevFlags = DS_FIXED_LOGICALNAME; DeviceStruct.DevType = DS_TYPE_AUDIO; DeviceStruct.pAdjunctList = NULL; rc = RMCreateDevice( _hDriver, // Handle to driver &hDevice, // (OUT) Handle to device, unused. &DeviceStruct, // Device structure _hAdapter, // Parent adapter pahResource ); // Allocated resources return rc; } #define PCI_CONFIG_ENABLE 0x80000000 #define PCI_CONFIG_ADDRESS 0xCF8 #define PCI_CONFIG_DATA 0xCFC unsigned long _inpd(unsigned short); #pragma aux _inpd "_inpd" \ parm [dx] \ value [dx ax]; //COMPILER BUG: bx cx == cx bx void _outpd(unsigned short, unsigned long); #pragma aux _outpd "_outpd" \ parm [dx] [cx bx] \ modify [ax dx]; BOOL ResourceManager::getPCIConfiguration(ULONG pciId) { ULONG devNr, busNr, funcNr, temp, cfgaddrreg, detectedId; BOOL found = FALSE; cfgaddrreg = _inpd(PCI_CONFIG_ADDRESS); for(busNr=0;busNr<255;busNr++) //BusNumber<255 { for(devNr=0;devNr<32;devNr++) { for(funcNr=0;funcNr<8;funcNr++) { temp = ((ULONG)((ULONG)devNr<<11UL) + ((ULONG)busNr<<16UL) + ((ULONG)funcNr << 8UL)); _outpd(PCI_CONFIG_ADDRESS, PCI_CONFIG_ENABLE|temp); detectedId = _inpd(PCI_CONFIG_DATA); if(detectedId == pciId) { found = TRUE; break; } } if(found) break; } if(found) break; } if(!found) { _outpd(PCI_CONFIG_ADDRESS, cfgaddrreg); return FALSE; } for(int i=0;i<64;i++) { temp = ((ULONG)((ULONG)devNr<<11UL) + ((ULONG)busNr<<16UL) + ((ULONG)funcNr << 8UL) + (i << 2)); _outpd(PCI_CONFIG_ADDRESS, PCI_CONFIG_ENABLE|temp); PCIConfig[i] = _inpd(PCI_CONFIG_DATA); } _outpd(PCI_CONFIG_ADDRESS, cfgaddrreg); pciConfigData = (PCIConfigData *)&PCIConfig[0]; if(pciConfigData->Bar0 == 0 || pciConfigData->Bar0 == 0xFFFFFFFF) { DebugInt3(); return(FALSE); } return TRUE; }