Source to iokit/Drivers/platform/drvAppleCore99PE/Core99.cpp


Enter a symbol's name here to quickly find it.

/*
 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * The contents of this file constitute Original Code as defined in and
 * are subject to the Apple Public Source License Version 1.1 (the
 * "License").  You may not use this file except in compliance with the
 * License.  Please obtain a copy of the License at
 * http://www.apple.com/publicsource and read it before using this file.
 * 
 * This Original Code and all software distributed under the License are
 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */
/*
 * Copyright (c) 1999 Apple Computer, Inc.  All rights reserved.
 *
 *  DRI: Josh de Cesare
 *
 */

#include <ppc/machine_routines.h>

#include <IOKit/IODeviceTreeSupport.h>

#include "Core99.h"

static unsigned long core99Speed[] = { 0, 1 };

#include <IOKit/pwr_mgt/RootDomain.h>
#include "IOPMSlots99.h"
#include "IOPMUSB99.h"

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#define super ApplePlatformExpert

OSDefineMetaClassAndStructors(Core99PE, ApplePlatformExpert);

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

bool Core99PE::start(IOService *provider)
{
  OSData          *tmpData;
  IORegistryEntry *uniNRegEntry;
  
  setFamily(4); // Core99...
  
  // Set the machine type.
  if (IODTMatchNubWithKeys(provider, "'PowerMac2,1'"))
    machineType = kCore99TypeKihei;
  else if (IODTMatchNubWithKeys(provider, "'PowerMac3,1'"))
    machineType = kCore99TypeSawtooth;
  else if (IODTMatchNubWithKeys(provider, "'PowerBook2,1'"))
    machineType = kCore99TypeP1;
  else if (IODTMatchNubWithKeys(provider, "'PowerBook3,1'"))
    machineType = kCore99TypePismo;
  
  // Find out if this an all in one.
  allInOne = 0;
  switch (machineType) {
  case kCore99TypeKihei :
    allInOne = 1;
    break;
  }
  
  // Get the bus speed from the Device Tree.
  tmpData = OSDynamicCast(OSData, provider->getProperty("clock-frequency"));
  if (tmpData == 0) return false;
  core99Speed[0] = *(unsigned long *)tmpData->getBytesNoCopy();
  
  // Get a memory mapping for Uni-N's registers.
  uniNRegEntry = provider->childFromPath("uni-n", gIODTPlane);
  if (uniNRegEntry == 0) return false;
  tmpData = OSDynamicCast(OSData, uniNRegEntry->getProperty("reg"));
  if (tmpData == 0) return false;
  uniNBaseAddress = ((unsigned long *)tmpData->getBytesNoCopy())[0];
  uniNBaseAddress = ml_io_map(uniNBaseAddress, 0x1000);
  if (uniNBaseAddress == 0) return false;
  
  return super::start(provider);
}


void Core99PE::getDefaultBusSpeeds(int *numSpeeds,
				   unsigned long **speedList)
{
  if ((numSpeeds == 0) || (speedList == 0)) return;
  
  *numSpeeds = 1;
  *speedList = core99Speed;
}


bool Core99PE::platformAdjustService(IOService *service)
{
  
  if (!strcmp(service->getName(), "pmu")) {
    // Change the interrupt mapping for pmu source 4.
    OSArray              *tmpArray;
    OSCollectionIterator *extIntList;
    IORegistryEntry      *extInt;
    OSObject             *extIntControllerName;
    OSObject             *extIntControllerData;
    
    // Set the no-nvram property.
    service->setProperty("no-nvram", service);
    
    // Set the no-adb property if not on P1.
    if ((machineType != kCore99TypeP1) &&
	(machineType != kCore99TypePismo)) {
      service->setProperty("no-adb", service);
    }
    
    // Find the new interrupt information.
    extIntList = IODTFindMatchingEntries(getProvider(), kIODTRecursive,
					 "'extint-gpio1'");
    extInt = (IORegistryEntry *)extIntList->getNextObject();
    
    tmpArray = (OSArray *)extInt->getProperty(gIOInterruptControllersKey);
    extIntControllerName = tmpArray->getObject(0);
    tmpArray = (OSArray *)extInt->getProperty(gIOInterruptSpecifiersKey);
    extIntControllerData = tmpArray->getObject(0);
    
    // Replace the interrupt infomation for pmu source 4.
    tmpArray = (OSArray *)service->getProperty(gIOInterruptControllersKey);
    tmpArray->replaceObject(4, extIntControllerName);
    tmpArray = (OSArray *)service->getProperty(gIOInterruptSpecifiersKey);
    tmpArray->replaceObject(4, extIntControllerData);
    
    extIntList->release();
  }

  // Publish out the dual display heads on Pismo.
  if (machineType == kCore99TypePismo) {
    if (!strcmp(service->getName(), "ATY,RageM3pParent")) {
      if (kIOReturnSuccess == IONDRVLibrariesInitialize(service)) {
        createNubs(this, service->getChildIterator( gIODTPlane ));
      }
      return true;
    }
  }
  
  return true;
}


unsigned long Core99PE::readUniNReg(unsigned long offest)
{
  return uniNBaseAddress[offest / 4];
}

void Core99PE::writeUniNReg(unsigned long offest, unsigned long data)
{
  uniNBaseAddress[offest / 4] = data;
}


//*********************************************************************************
// PMInstantiatePowerDomains
//
// This overrides the vanilla implementation in IOPlatformExpert.  It instantiates
// a root domain with two children, one for the USB bus (to handle the USB idle
// power budget), and one for the expansions slots on the PCI bus (to handle
// the idle PCI power budget)
//*********************************************************************************

void Core99PE::PMInstantiatePowerDomains ( void )
{    
   root = new IOPMrootDomain;
   root->init();
   root->attach(this);
   root->start(this);
   root->youAreRoot();

   slot_domain = new IOPMSlots99;
   slot_domain->init();
   slot_domain->attach(this);
   slot_domain->start(this);
   root->addChild(slot_domain);

   usb_domain = new IOPMUSB99;
   usb_domain->init();
   usb_domain->attach(this);
   usb_domain->start(this);
   root->addChild(usb_domain);
}


//*********************************************************************************
// PMRegisterDevice
//
// This overrides the vanilla implementation in IOPlatformExpert.  When a device
// registers and has a "AAPL,slot-name" property, it is added to the hierarchy
// as a child of the IOPMSlots99 power domain.
// If it has a "name" property equal to "usb", it is added to the hierarchy
// as a child of the IOPMUSB99 power domain.
// Any other callers are added as children of the root.
//*********************************************************************************

void Core99PE::PMRegisterDevice(IOService * theNub, IOService * theDevice)
{
    OSObject * anObject;
    OSData * aString;

    aString = (OSData *)theNub ->getProperty("name");
    if ( aString != NULL ) {
        if ( strcmp(aString->getBytesNoCopy(),"usb") == 0 ) {
            usb_domain->addChild ( theDevice );
            return;
        }
    }
    anObject = theNub ->getProperty("AAPL,slot-name");
    if ( anObject != NULL ) {
        slot_domain->addChild ( theDevice );
        return;
    }
   root->addChild ( theDevice );
}