-bool IODTResolveAddressCell( IORegistryEntry * regEntry,
- UInt32 cellsIn[],
- IOPhysicalAddress * phys, IOPhysicalLength * lenOut )
-{
- IORegistryEntry *parent;
- OSData *prop;
- // cells in addresses at regEntry
- UInt32 sizeCells, addressCells;
- // cells in addresses below regEntry
- UInt32 childSizeCells, childAddressCells;
- UInt32 childCells;
- UInt32 cell[ 8 ], propLen;
- UInt64 offset = 0;
- UInt32 endCell[ 8 ];
- UInt32 *range;
- UInt32 *lookRange;
- UInt32 *startRange;
- UInt32 *endRanges;
- bool ok = true;
- SInt64 diff, diff2, endDiff;
- UInt64 len, rangeLen;
-
- IODTPersistent *persist;
- IODTCompareAddressCellFunc compare;
-
- IODTGetCellCounts( regEntry, &childSizeCells, &childAddressCells );
- childCells = childAddressCells + childSizeCells;
-
- if (childCells > sizeof(cell)/sizeof(cell[0]))
- panic("IODTResolveAddressCell: Invalid device tree (%u,%u)", (uint32_t)childAddressCells, (uint32_t)childSizeCells);
-
- bcopy( cellsIn, cell, sizeof(UInt32) * childCells );
- *lenOut = CellsValue( childSizeCells, cellsIn + childAddressCells );
-
- do
- {
- prop = OSDynamicCast( OSData, regEntry->getProperty( gIODTRangeKey ));
- if( 0 == prop) {
- /* end of the road */
- *phys = CellsValue( childAddressCells, cell );
- *phys += offset;
- break;
- }
-
- parent = regEntry->getParentEntry( gIODTPlane );
- IODTGetCellCounts( parent, &sizeCells, &addressCells );
-
- if( (propLen = prop->getLength())) {
- // search
- startRange = (UInt32 *) prop->getBytesNoCopy();
- range = startRange;
- endRanges = range + (propLen / sizeof(UInt32));
-
- prop = (OSData *) regEntry->getProperty( gIODTPersistKey );
- if( prop) {
- persist = (IODTPersistent *) prop->getBytesNoCopy();
- compare = persist->compareFunc;
- } else if (addressCells == childAddressCells) {
- compare = DefaultCompare;
- } else {
- panic("There is no mixed comparison function yet...");
- }
-
- for( ok = false;
- range < endRanges;
- range += (childCells + addressCells) ) {
-
- // is cell start within range?
- diff = (*compare)( childAddressCells, cell, range );
-
- if (childAddressCells > sizeof(endCell)/sizeof(endCell[0]))
- panic("IODTResolveAddressCell: Invalid device tree (%u)", (uint32_t)childAddressCells);
-
- bcopy(range, endCell, childAddressCells * sizeof(UInt32));
-
- rangeLen = CellsValue(childSizeCells, range + childAddressCells + addressCells);
- AddLengthToCells(childAddressCells, endCell, rangeLen);
-
- diff2 = (*compare)( childAddressCells, cell, endCell );
-
- // if start of cell < start of range, or end of range >= start of cell, skip
- if ((diff < 0) || (diff2 >= 0))
- continue;
-
- len = CellsValue(childSizeCells, cell + childAddressCells);
- ok = (0 == len);
-
- if (!ok)
- {
- // search for cell end
- bcopy(cell, endCell, childAddressCells * sizeof(UInt32));
-
- AddLengthToCells(childAddressCells, endCell, len - 1);
-
- for( lookRange = startRange;
- lookRange < endRanges;
- lookRange += (childCells + addressCells) )
- {
- // make sure end of cell >= range start
- endDiff = (*compare)( childAddressCells, endCell, lookRange );
- if( endDiff < 0)
- continue;
-
- UInt64 rangeStart = CellsValue(addressCells, range + childAddressCells);
- UInt64 lookRangeStart = CellsValue(addressCells, lookRange + childAddressCells);
- if ((endDiff - len + 1 + lookRangeStart) == (diff + rangeStart))
- {
- ok = true;
- break;
- }
- }
- if (!ok)
- continue;
- }
- offset += diff;
- break;
- }
-
- if (addressCells + sizeCells > sizeof(cell)/sizeof(cell[0]))
- panic("IODTResolveAddressCell: Invalid device tree (%u, %u)", (uint32_t)addressCells, (uint32_t)sizeCells);
-
- // Get the physical start of the range from our parent
- bcopy( range + childAddressCells, cell, sizeof(UInt32) * addressCells );
- bzero( cell + addressCells, sizeof(UInt32) * sizeCells );
-
- } /* else zero length range => pass thru to parent */
-
- regEntry = parent;
- childSizeCells = sizeCells;
- childAddressCells = addressCells;
- childCells = childAddressCells + childSizeCells;
- }
- while( ok && regEntry);
-
- return( ok);
-}
-
-
-OSArray * IODTResolveAddressing( IORegistryEntry * regEntry,
- const char * addressPropertyName,
- IODeviceMemory * parent )
-{
- IORegistryEntry *parentEntry;
- OSData *addressProperty;
- UInt32 sizeCells, addressCells, cells;
- int i, num;
- UInt32 *reg;
- IOPhysicalAddress phys;
- IOPhysicalLength len;
- OSArray *array;
- IODeviceMemory *range;
-
- parentEntry = regEntry->getParentEntry( gIODTPlane );
- addressProperty = (OSData *) regEntry->getProperty( addressPropertyName );
- if( (0 == addressProperty) || (0 == parentEntry))
- return( 0);
-
- IODTGetCellCounts( parentEntry, &sizeCells, &addressCells );
- if( 0 == sizeCells)
- return( 0);
-
- cells = sizeCells + addressCells;
- reg = (UInt32 *) addressProperty->getBytesNoCopy();
- num = addressProperty->getLength() / (4 * cells);
-
- array = OSArray::withCapacity( 1 );
- if( 0 == array)
- return( 0);
-
- for( i = 0; i < num; i++) {
- if( IODTResolveAddressCell( parentEntry, reg, &phys, &len )) {
- range = 0;
- if( parent)
- range = IODeviceMemory::withSubRange( parent,
- phys - parent->getPhysicalSegment(0, 0, kIOMemoryMapperNone), len );
- if( 0 == range)
- range = IODeviceMemory::withRange( phys, len );
- if( range)
- array->setObject( range );
- }
- reg += cells;
- }
-
- regEntry->setProperty( gIODeviceMemoryKey, array);
- array->release(); /* ??? */
-
- return( array);
-}
-
-static void IODTGetNVLocation(
- IORegistryEntry * parent,
- IORegistryEntry * regEntry,
- UInt8 * busNum, UInt8 * deviceNum, UInt8 * functionNum )