After finding a match between a hardware device and its driver, the driver initialization code must check to make sure that all needed resources are available. This section describes a typical algorithm for resource verification. Driver initialization code should perform this algorithm for two reasons:
The driver must enable the card's address space for a PCI device to be usable.
The following is a typical resource verification and card address enabling procedure:
82006810 00000000 80000000 000000000 00008000
|
80000000 F2000400
|
Listing 7-2 Enabling PCI spaces
ExpMgrConfigReadWord (yourNode, 4, &yourvalue);
yourvalue = yourvalue | yourEnables; /* if I/O space, bit 0;
if memory space, bit 1 */
ExpMgrConfigWriteWord (yourNode, 4, yourvalue);
Listing 7-3 shows a routine that extracts a device's logical address by using its assigned-addresses and AAPL,address properties. It accepts as input the offsets into PCI configuration space that match the device's space request. For example, an Ethernet card may want two address spaces, I/O and memory. The card is designed so that offset 0x10 in configuration space corresponds to the I/O space and 0x14 corresponds to the memory space.
Listing 7-3 Getting a device's logical address
//The following values are valid for offset Values(:
//
// #define kPCIConfigBase10Offset 0x10
// #define kPCIConfigBase14Offset 0x14
// #define kPCIConfigBase18Offset 0x18
// #define kPCIConfigBase1COffset 0x1C
// #define kPCIConfigBase20Offset 0x20
// #define kPCIConfigBase24Offset 0x24
// #define kPCIConfigBaseROM30Offset 0x30
//Input:
// theID - the NameRegistryID for a PCI card
// base RegAddress - no input value
// offsetValue - config base offset, determines which address space
// logical address is returned
// spaceAllocated - noinputvalue
//Output:
// ifer = kOTNoError, *baseRegAddress - contains the logical address of a PCI
// addresss pace, also space Allocated is a byte count fortheamountofspace
// that was allocated
// returns various errors
//
//----------------------------------------------------------------------------------
OSStatus GetPCICardBaseAddress(RegEntryID *theID, UInt32 *baseRegAddress,
UInt 8offsetValue, UInt32 *spaceAllocated)
{
OSStatus osStatus;
PCIAssignedAddress *assignedArray;
RegPropertyValueSize propertySize;
UInt32 numberOfElements,*virtualArray;
Boolean foundMatch;
UInt16 index;
*baseRegAddress = NULL; //defaultvalue
foundMatch = kFalse;
osStatus = GetAProperty(theID, kPCIAssignedAddressProperty,(void**)&assignedArray,
&propertySize);
if ((osStatus == kOTNoError) && propertySize)
{
numberOfElements = propertySize/sizeof(PCIAssignedAddress);
osStatus = GetAProperty(theID, kAAPLDeviceLogicalAddress, (void**)&virtualArray,
&propertySize);
if ((osStatus == kOTNoError) && propertySize)
{
// search through the assigned addresses property looking for base register
for (index = 0;(index !=numberOfElements) && !foundMatch; ++index)
{
if (assignedArray[index].registerNumber == offsetValue)
{
*spaceAllocated = assignedArray[index].size.lo;
*baseRegAddress = virtualArray[index];
foundMatch = kTrue;
}
}
DisposeProperty((void **)&virtualArray);
}
else
osStatus = kENXIOErr;
DisposeProperty((void **)&assignedArray);
}
else
osStatus = kENXIOErr;
return osStatus;
}