PATH 
ADC Home > Documentation > Hardware > Device Managers and Drivers > PCI Card Services > Designing PCI Cards and Drivers for Power Macintosh Computers


  

Driver Initialization and Resource Verification

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:

IMPORTANT

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:

  1. Check for existence of an assigned-addresses property for the device. If no assigned-addresses property exists, exit the driver initialization routine with an error message (address resources not available). The assigned-addresses property is discussed in Standard Properties. If an assigned-addresses property exists, go to step 2.
  2. Check the assigned-addresses property for the existence of the base registers required for full operation of the driver. Do this by looking at the last byte of the first long word of each assigned-addresses entry that is required. A typical assigned-addresses entry looks like this: If the required base registers are not present, exit the driver initialization routine with an error message (address resources not available). If the required base registers are present, continue.
  3. 82006810 00000000 80000000 000000000 00008000
    81006814 00000000 00000400 000000000 00000100
  4. Note where in the assigned-addresses property the entries for the required base registers are located. The first entry is 0, the next is 1, and so on. That same order will be preserved in the AAPL,address property, which is an array of 32-bit values corresponding to the logical address for your base register's physical address. For more information about the AAPL,address property, see Fast I/O Space Cycle Generation. A typical AAPL,address property looks like this: If the driver uses Expansion Bus Manager routines (such as ExpMgrIOReadByte ) it must pass the physical address for the I/O base register, which it gets from the assigned-addresses property. The Expansion Bus Manager does byte swapping and EIEIO synchronization for the driver, but it's node-based and it's slow. The AAPL,address version just uses a pointer, so it's as fast as accessing memory space.
  5. 80000000 F2000400
  6. If the driver can be confused with another driver--if, for example, the card doesn't have FCode and another vendor uses the same PCI ASIC on a different card--the driver must perform a diagnostic routine on the card to make sure that it has been matched correctly. The DeviceProbe function, described below, helps a driver determine if a device is present at an address. If the diagnostic routine fails, the driver must exit its initialization routine with an error message (not my card). If the driver verifies that the card is correct, continue.
  7. The driver must read or write to the device's configuration command register to enable its PCI spaces. Listing 7-2 presents typical code for doing this. It uses the ExpMgrConfigReadWord routine ExpMgrConfigReadWord.

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;
}

DeviceProbe


© 1999 Apple Computer, Inc. – (Last Updated 26 March 99)