void IODTPlatformExpert::processTopLevel( IORegistryEntry * root )
{
    OSIterator * 	kids;
    IORegistryEntry *	next;
    IORegistryEntry *	cpus;
    IORegistryEntry *	options;

    // infanticide
    kids = IODTFindMatchingEntries( root, 0, deleteList() );
    if( kids) {
	while( (next = (IORegistryEntry *)kids->getNextObject())) {
	    next->detachAll( gIODTPlane);
	}
	kids->release();
    }

    // Publish an IODTNVRAM class on /options.
    options = root->childFromPath("options", gIODTPlane);
    if (options) {
      dtNVRAM = new IODTNVRAM;
      if (dtNVRAM) {
        if (!dtNVRAM->init(options, gIODTPlane)) {
	  dtNVRAM->release();
	  dtNVRAM = 0;
        } else {
	  dtNVRAM->attach(this);
	  dtNVRAM->registerService();
	}
      }
    }

    // Publish the cpus.
    cpus = root->childFromPath( "cpus", gIODTPlane);
    if ( cpus)
      createNubs( this, IODTFindMatchingEntries( cpus, kIODTExclusive, 0));

    // publish top level, minus excludeList
    createNubs( this, IODTFindMatchingEntries( root, kIODTExclusive, excludeList()));
}
bool RadeonController::start( IOService * provider )
{
	if (!super::start(provider)) return false;
	
	device = OSDynamicCast(IOPCIDevice, provider);
	if (device == NULL) return false;
	
	//get user options
	OSBoolean *prop;
	
	OSDictionary *dict = OSDynamicCast(OSDictionary, getProperty("UserOptions"));
	
	bzero(&options, sizeof(UserOptions));
	options.HWCursorSupport = FALSE;
	options.enableGammaTable = FALSE;
	options.enableOSXI2C = FALSE;
	
	options.lowPowerMode = FALSE;
	if (dict) {
		prop = OSDynamicCast(OSBoolean, dict->getObject("enableHWCursor"));
		if (prop) options.HWCursorSupport = prop->getValue();
		prop = OSDynamicCast(OSBoolean, dict->getObject("debugMode"));
		if (prop) options.debugMode = prop->getValue();
		if (options.debugMode) options.HWCursorSupport = FALSE;
		prop = OSDynamicCast(OSBoolean, dict->getObject("enableGammaTable"));
		if (prop) options.enableGammaTable = prop->getValue();
		prop = OSDynamicCast(OSBoolean, dict->getObject("lowPowerMode"));
		if (prop) options.lowPowerMode = prop->getValue();
	}
	options.verbosity = 1;
#ifdef DEBUG
	if (0 == getRegistryRoot()->getProperty("RadeonDumpReady")) {
		getRegistryRoot()->setProperty("RadeonDumpReady", kOSBooleanTrue);
		DumpMsg.mVerbose = 1;
		DumpMsg.client = 1;
		DumpMsg.mMsgBufferSize = 65535;
		if (dict) {
			OSNumber *optionNum;
			optionNum = OSDynamicCast(OSNumber, dict->getObject("verboseLevel"));
			if (optionNum) DumpMsg.mVerbose = optionNum->unsigned32BitValue();
			optionNum = OSDynamicCast(OSNumber, dict->getObject("MsgBufferSize"));
			if (optionNum) DumpMsg.mMsgBufferSize = max(65535, optionNum->unsigned32BitValue());
		}	
		DumpMsg.mMsgBufferEnabled = false;
		DumpMsg.mMsgBufferPos = 0;
		DumpMsg.mMessageLock = IOLockAlloc();
		DumpMsg.mMsgBuffer = (char *) IOMalloc(DumpMsg.mMsgBufferSize);
		if (!DumpMsg.mMsgBuffer) {
			IOLog("error: couldn't allocate message buffer (%ld bytes)\n", DumpMsg.mMsgBufferSize);
			return false;
		}
		enableMsgBuffer(true);
	} else DumpMsg.client += 1;
	options.verbosity = DumpMsg.mVerbose;
#endif
	
	device->setMemoryEnable(true);
	IOMap = device->mapDeviceMemoryWithRegister( kIOPCIConfigBaseAddress2 );
	if (IOMap == NULL) return false;
	FBMap = device->mapDeviceMemoryWithRegister( kIOPCIConfigBaseAddress0 );
	if (FBMap == NULL) return false;
	memoryMap.MMIOBase = (pointer) IOMap->getVirtualAddress();
	memoryMap.MMIOMapSize = IOMap->getLength();
	memoryMap.FbBase = (pointer) FBMap->getVirtualAddress();
	memoryMap.FbMapSize = FBMap->getLength();
	memoryMap.FbPhysBase = (unsigned long)FBMap->getPhysicalAddress();
	memoryMap.bitsPerPixel = 32;
	memoryMap.bitsPerComponent = 8;
	memoryMap.colorFormat = 0;	//0 for non-64 bit
	
	memoryMap.BIOSCopy = NULL;
	memoryMap.BIOSLength = 0;
	
	IOMemoryDescriptor * mem;
	mem = IOMemoryDescriptor::withPhysicalAddress((IOPhysicalAddress) RHD_VBIOS_BASE, RHD_VBIOS_SIZE, kIODirectionOut);
	if (mem) {
		memoryMap.BIOSCopy = (unsigned char *)IOMalloc(RHD_VBIOS_SIZE);
		if (memoryMap.BIOSCopy) {
			mem->prepare(kIODirectionOut);
			if (!(memoryMap.BIOSLength = mem->readBytes(0, memoryMap.BIOSCopy, RHD_VBIOS_SIZE))) {
				LOG("Cannot read BIOS image\n");
				memoryMap.BIOSLength = 0;
			}
			if ((unsigned int)memoryMap.BIOSLength != RHD_VBIOS_SIZE)
				LOG("Read only %d of %d bytes of BIOS image\n", memoryMap.BIOSLength, RHD_VBIOS_SIZE);
			mem->complete(kIODirectionOut);
		}
	}

	if (dict) {
		const char typeKey[2][8] = {"@0,TYPE", "@1,TYPE"};
		const char EDIDKey[2][8] = {"@0,EDID", "@1,EDID"};
		const char fixedModesKey[2][17] = {"@0,UseFixedModes", "@1,UseFixedModes"};
		OSString *type;
		OSData *edidData;
		OSBoolean *boolData;
		int i;
		for (i = 0;i < 2;i++) {
			type = OSDynamicCast(OSString, dict->getObject(typeKey[i]));
			if (!type) continue;
			edidData = OSDynamicCast(OSData, dict->getObject(EDIDKey[i]));
			if (edidData == NULL) continue;
			options.EDID_Block[i] = (unsigned char *)IOMalloc(edidData->getLength());
			if (options.EDID_Block[i] == NULL) continue;
			strncpy(options.outputTypes[i], type->getCStringNoCopy(), outputTypeLength);
			bcopy(edidData->getBytesNoCopy(), options.EDID_Block[i], edidData->getLength());
			options.EDID_Length[i] = edidData->getLength();
			
			boolData = OSDynamicCast(OSBoolean, dict->getObject(fixedModesKey[i]));
			if (boolData) options.UseFixedModes[i] = boolData->getValue();
		}
	}
		
	xf86Screens[0] = IONew(ScrnInfoRec, 1);	//using global variable, will change it later
	ScrnInfoPtr pScrn = xf86Screens[0];
	if (pScrn == NULL) return false;
	bzero(pScrn, sizeof(ScrnInfoRec));
	MAKE_REG_ENTRY(&nub, device);
	pciRec.chipType = device->configRead16(kIOPCIConfigDeviceID);
	pciRec.subsysVendor = device->configRead16(kIOPCIConfigSubSystemVendorID);
	pciRec.subsysCard = device->configRead16(kIOPCIConfigSubSystemID);
	pciRec.biosSize = 16;	//RHD_VBIOS_SIZE = 1 << 16
	pScrn->PciTag = &nub;
	pScrn->PciInfo = &pciRec;
	pScrn->options = &options;
	pScrn->memPhysBase = (unsigned long)FBMap->getPhysicalAddress();
	pScrn->fbOffset = 0;	//scanout offset
	pScrn->bitsPerPixel = 32;
	pScrn->bitsPerComponent = 8;
	pScrn->colorFormat = 0;
	pScrn->depth = pScrn->bitsPerPixel;
	pScrn->memoryMap = &memoryMap;
	
	
	createNubs(provider);
	
	setModel(device);
	
	return true;
}