OSReturn NoSleepExtension::writeNVRAM(UInt8 value)
{
#ifdef DEBUG
    IOLog("%s: writing nvram, value: 0x%02x\n", getName(), value);
#endif
    
    bool ret;
    IORegistryEntry *entry = IORegistryEntry::fromPath( "/options", gIODTPlane );
    if ( entry )
    {
        OSData *dataToSave = OSData::withBytes(&value, 1);
        
        ret = entry->setProperty(IORegistrySleepSuppressionMode, dataToSave);
        
        dataToSave->release();
        entry->release();
#ifdef DEBUG
        IOLog("%s: writing nvram, result: %s\n", getName(), ret?"true":"false");
#endif
    } else {
        return kOSReturnError;
    }
    
    return ret?kOSReturnSuccess:kOSReturnError;
}
//====================================================================================================
// IOHIDEventService::handleServicePublicationGated
//====================================================================================================
void IOHIDEventSystem::handleServicePublicationGated(IOService * service)
{
    IOLog("IOHIDEventSystem::handleServicePublicationGated\n");

    EventServiceInfo    tempEventServiceInfo;
    OSData *            tempData;
    IOHIDEventService * eventService;
    
    if ( !(eventService = OSDynamicCast(IOHIDEventService, service)) )
        return;
    
    attach( eventService );

    tempEventServiceInfo.service = eventService;
    
    tempData = OSData::withBytes(&tempEventServiceInfo, sizeof(EventServiceInfo));
    
    if ( tempData )
    {
        _eventServiceInfoArray->setObject(tempData);
        tempData->release();
    }
    
    if ( _eventsOpen )
        registerEventSource( eventService );
        
}
boolean_t PEWriteNVRAMProperty(const char *symbol, const void *value, 
                               const unsigned int len)
{
    const OSSymbol *sym;
    OSData *data;
    bool ret = false;

    if (!symbol || !value || !len)
        goto err;

    if (init_gIOOptionsEntry() < 0)
        goto err;

    sym = OSSymbol::withCStringNoCopy(symbol);
    if (!sym)
        goto err;

    data = OSData::withBytes((void *) value, len);
    if (!data)
        goto sym_done;

    ret = gIOOptionsEntry->setProperty(sym, data);
    data->release();

sym_done:
    sym->release();

    if (ret == true) {
        gIOOptionsEntry->sync();
        return TRUE;
    }

err:
    return FALSE;
}
bool IOPlatformExpert::start( IOService * provider )
{
    IORangeAllocator *	physicalRanges;
    OSData *		busFrequency;
    
    if (!super::start(provider))
      return false;

    // Register the presence or lack thereof a system 
    // PCI address mapper with the IOMapper class

#if 1
    IORegistryEntry * regEntry = IORegistryEntry::fromPath("/u3/dart", gIODTPlane);
    if (!regEntry)
	regEntry = IORegistryEntry::fromPath("/dart", gIODTPlane);
    if (regEntry) {
	int debugFlags;
	if (!PE_parse_boot_arg("dart", &debugFlags) || debugFlags)
	    setProperty(kIOPlatformMapperPresentKey, kOSBooleanTrue);
	regEntry->release();
    }
#endif

    IOMapper::setMapperRequired(0 != getProperty(kIOPlatformMapperPresentKey));
    
    gIOInterruptControllers = OSDictionary::withCapacity(1);
    gIOInterruptControllersLock = IOLockAlloc();
    
    // Correct the bus frequency in the device tree.
    busFrequency = OSData::withBytesNoCopy((void *)&gPEClockFrequencyInfo.bus_clock_rate_hz, 4);
    provider->setProperty("clock-frequency", busFrequency);
    busFrequency->release();
    
    gPlatformInterruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("IOPlatformInterruptController");
    
    physicalRanges = IORangeAllocator::withRange(0xffffffff, 1, 16,
						 IORangeAllocator::kLocking);
    assert(physicalRanges);
    setProperty("Platform Memory Ranges", physicalRanges);
    
    setPlatform( this );
    gIOPlatform = this;
    
    PMInstantiatePowerDomains();
    
    // Parse the serial-number data and publish a user-readable string
    OSData* mydata = (OSData*) (provider->getProperty("serial-number"));
    if (mydata != NULL) {
        OSString *serNoString = createSystemSerialNumberString(mydata);
        if (serNoString != NULL) {
            provider->setProperty(kIOPlatformSerialNumberKey, serNoString);
            serNoString->release();
        }
    }
    
    return( configure(provider) );
}
Exemple #5
0
void net_habitue_device_SC101::handleResolvePacket(sockaddr_in *addr, mbuf_t m, size_t len, outstanding *out, void *ctx)
{
  clock_get_uptime(&_lastReply);
  
  if (mbuf_len(m) < out->len &&
      mbuf_pullup(&m, out->len) != 0)
  {
    KINFO("pullup failed");
    return;
  }
  
  KDEBUG("resolve succeeded!");
  
  psan_resolve_response_t *res = (psan_resolve_response_t *)mbuf_data(m);
  
  sockaddr_in part;
  bzero(&part, sizeof(part));
  part.sin_len = sizeof(part);
  part.sin_family = AF_INET;
  part.sin_port = htons(PSAN_PORT);
  part.sin_addr = res->ip4;
  
  OSData *partData = OSData::withBytes(&part, sizeof(part));
  if (partData)
  {
    setProperty(gSC101DevicePartitionAddressKey, partData);
    partData->release();
  }
  
  OSData *rootData = OSData::withBytes(addr, sizeof(*addr));
  if (rootData)
  {
    setProperty(gSC101DeviceRootAddressKey, rootData);
    rootData->release();
  }
  
  IODelete(out, outstanding, 1);
  
  mbuf_freem(m);

  if (!getProperty(gSC101DeviceSizeKey))
    disk();
}
Exemple #6
0
IOMapper * IOMapper::copyMapperForDeviceWithIndex(IOService * device, unsigned int index)
{
    OSData *data;
    OSObject * obj;
    IOMapper * mapper = NULL;
    OSDictionary * matching;
    
    obj = device->copyProperty("iommu-parent");
    if (!obj) return (NULL);

    if ((mapper = OSDynamicCast(IOMapper, obj))) goto found;

    if ((data = OSDynamicCast(OSData, obj)))
    {
        if (index >= data->getLength() / sizeof(UInt32)) goto done;
        
        data = OSData::withBytesNoCopy((UInt32 *)data->getBytesNoCopy() + index, sizeof(UInt32));
        if (!data) goto done;

        matching = IOService::propertyMatching(gIOMapperIDKey, data);
        data->release();
    }
    else
        matching = IOService::propertyMatching(gIOMapperIDKey, obj);

    if (matching)
    {
        mapper = OSDynamicCast(IOMapper, IOService::waitForMatchingService(matching));
        matching->release();
    }

done:
    if (obj) obj->release();
found:
    if (mapper)
    {
        if (!mapper->fAllocName)
        {
            char name[MACH_ZONE_NAME_MAX_LEN];
            char kmodname[KMOD_MAX_NAME];
            vm_tag_t tag;
            uint32_t kmodid;

            tag = IOMemoryTag(kernel_map);
            if (!(kmodid = vm_tag_get_kext(tag, &kmodname[0], KMOD_MAX_NAME)))
            {
                snprintf(kmodname, sizeof(kmodname), "%d", tag);
            }
            snprintf(name, sizeof(name), "%s.DMA.%s", kmodname, device->getName());
            mapper->fAllocName = kern_allocation_name_allocate(name, 16);
        }
    }

    return (mapper);
}
int VoodooI2CHIDDevice::i2c_get_slave_address(I2CDevice* hid_device){
    OSObject* result = NULL;
    
    hid_device->provider->evaluateObject("_CRS", &result);
    
    OSData* data = OSDynamicCast(OSData, result);
    
    hid_device->addr = *(int*)data->getBytesNoCopy(16,1) & 0xFF;

    data->release();
    
    return 0;
    
}
bool IOHIKeyboardMapper::serialize(OSSerialize *s) const
{
	OSData * data;
	bool ok;

	if (s->previouslySerialized(this)) return true;

	data = OSData::withBytesNoCopy( (void *) _parsedMapping.mapping, _parsedMapping.mappingLen );
	if (data) {
	ok = data->serialize(s);
	data->release();
	} else
	ok = false;

	return( ok );
}
static void AppendNewKeyboardReservedStructForService(IOHIKeyboard *service)
{
    KeyboardReserved 	temp;
    OSData 		* data		= 0;
    
    if (gKeyboardReservedArray)
    {
        bzero(&temp, sizeof(KeyboardReserved));
        temp.repeatMode = true;
        temp.service = service;
        
        data = OSData::withBytes(&temp, sizeof(KeyboardReserved));
        gKeyboardReservedArray->setObject(data);
        data->release();
    }
}
Exemple #10
0
void SMBPackedStrings::setDataProperty( IORegistryEntry * entry,
                                       const char *      key,
                                       UInt8             index ) const
{
    UInt8        length;
    const char * string = SMBPackedStrings::stringAtIndex(index, &length);
    
    if (length)
    {
        OSData * data = OSData::withCapacity(length + 1);
        if (data)
        {
            data->appendBytes(string, length);
            data->appendByte('\0', 1);
            entry->setProperty(key, data);
            data->release();
        }
    }
}
Exemple #11
0
void net_habitue_device_SC101::diskCompletion(void *parameter, IOReturn status, UInt64 actualByteCount)
{
  if (status != kIOReturnSuccess || actualByteCount != sizeof(psan_get_response_disk_t))
  {
    KINFO("disk query on %s failed", getID()->getCStringNoCopy());
    return;
  }
  
  IOBufferMemoryDescriptor *buffer = (IOBufferMemoryDescriptor *)parameter;
  
  psan_get_response_disk_t *disk = (psan_get_response_disk_t *)buffer->getBytesNoCopy();
  
  OSData *partNumber = OSData::withBytes(disk->part_number, sizeof(disk->part_number));
  if (partNumber)
  {
    OSString *resourceFile = NULL;

    if (partNumber->isEqualTo(kSC101PartNumber, sizeof(kSC101PartNumber)))
      resourceFile = OSString::withCString("SC101.icns");
    else if (partNumber->isEqualTo(kSC101TPartNumber, sizeof(kSC101TPartNumber)))
      resourceFile = OSString::withCString("SC101T.icns");
    
    if (resourceFile)
    {
      setIcon(resourceFile);
      resourceFile->release();
    }
    
    setProperty(gSC101DevicePartNumberKey, partNumber);    
    partNumber->release();
  }
  
  OSString *version = OSString::withCString(disk->version);
  if (version)
  {
    setProperty(gSC101DeviceVersionKey, version);
    version->release();
  }
  
  partition(disk->partitions);
}
static IORegistryEntry *
MakeReferenceTable( DTEntry dtEntry, bool copy )
{
    IORegistryEntry		*regEntry;
    OSDictionary		*propTable;
    const OSSymbol		*nameKey;
    OSData				*data;
    const OSSymbol		*sym;
    DTPropertyIterator	dtIter;
    void				*prop;
    unsigned int		propSize;
    char				*name;
    char				location[ 32 ];
    bool				noLocation = true;

    regEntry = new IOService;

    if( regEntry && (false == regEntry->init())) {
        regEntry->release();
        regEntry = 0;
    }

    if( regEntry &&
      (kSuccess == DTCreatePropertyIterator( dtEntry, &dtIter))) {

        propTable = regEntry->getPropertyTable();

        while( kSuccess == DTIterateProperties( dtIter, &name)) {

            if(  kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize ))
                continue;

            if( copy) {
                nameKey = OSSymbol::withCString(name);
                data = OSData::withBytes(prop, propSize);
            } else {
                nameKey = OSSymbol::withCStringNoCopy(name);
                data = OSData::withBytesNoCopy(prop, propSize);
            }
            assert( nameKey && data );

            propTable->setObject( nameKey, data);
            data->release();
            nameKey->release();

            if( nameKey == gIODTNameKey ) {
                if( copy)
                    sym = OSSymbol::withCString( (const char *) prop);
                else
                    sym = OSSymbol::withCStringNoCopy( (const char *) prop);
                regEntry->setName( sym );
                sym->release();

            } else if( nameKey == gIODTUnitKey ) {
                // all OF strings are null terminated... except this one
                if( propSize >= (int) sizeof(location))
                    propSize = sizeof(location) - 1;
                strncpy( location, (const char *) prop, propSize );
                location[ propSize ] = 0;
                regEntry->setLocation( location );
                propTable->removeObject( gIODTUnitKey );
                noLocation = false;
    
            } else if(noLocation && (!strncmp(name, "reg", sizeof("reg")))) {
                // default location - override later
                snprintf(location, sizeof(location), "%X", *((uint32_t *) prop));
                regEntry->setLocation( location );
            }
        }
        DTDisposePropertyIterator( dtIter);
    }

    return( regEntry);
}
Exemple #13
0
/*********************************************************************
* This function reads the startup extensions dictionary to get the
* address and length of the executable data for the requested kmod.
*********************************************************************/
static
int map_and_patch(const char * kmod_name) {

    char *address;

    // Does the kld system already know about this kmod?
    address = (char *) kld_file_getaddr(kmod_name, NULL);
    if (address)
	return 1;

    // None of these needs to be released.
    OSDictionary * extensionsDict;
    OSDictionary * kmodDict;
    OSData * compressedCode = 0;

    // Driver Code may need to be released
    OSData * driverCode;

   /* Get the requested kmod's info dictionary from the global
    * startup extensions dictionary.
    */
    extensionsDict = getStartupExtensions();
    if (!extensionsDict) {
        IOLog("map_and_patch(): No extensions dictionary.\n");
        LOG_DELAY();
        return 0;
    }
    
    kmodDict = OSDynamicCast(OSDictionary,
        extensionsDict->getObject(kmod_name));
    if (!kmodDict) {
        IOLog("map_and_patch(): "
            "Extension \"%s\" cannot be found.\n", kmod_name);
        LOG_DELAY();
        return 0;
    }

    Boolean ret = false;

    driverCode = OSDynamicCast(OSData, kmodDict->getObject("code"));
    if (driverCode) {
	ret =  kld_file_map(kmod_name,
			    (unsigned char *) driverCode->getBytesNoCopy(),
			    (size_t) driverCode->getLength(),
			    /* isKmem */ false);
    }
    else {	// May be an compressed extension

	// If we have a compressed segment the uncompressModule
	// will return a new OSData object that points to the kmem_alloced
	// memory.  Note we don't take a reference to driverCode so later
	// when we release it we will actually free this driver.  Ownership
	// of the kmem has been handed of to kld_file.
	compressedCode = OSDynamicCast(OSData,
	    kmodDict->getObject("compressedCode"));
	if (!compressedCode) {
	    IOLog("map_and_patch(): "
		 "Extension \"%s\" has no \"code\" property.\n", kmod_name);
	    LOG_DELAY();
	    return 0;
	}
	if (!uncompressModule(compressedCode, &driverCode)) {
	    IOLog("map_and_patch(): "
		 "Extension \"%s\" Couldn't uncompress code.\n", kmod_name);
	    LOG_DELAY();
	    return 0;
	}

	unsigned char *driver = (unsigned char *) driverCode->getBytesNoCopy();
	size_t driverSize = driverCode->getLength();

	ret =  kld_file_map(kmod_name, driver, driverSize, /* isKmem */ true);
	driverCode->release();
	if (!ret)
	    kmem_free(kernel_map, (vm_address_t) driver, driverSize);
    }

    if (!ret) {
        IOLog("map_and_patch(): "
              "Extension \"%s\" Didn't successfully load.\n", kmod_name);
        LOG_DELAY();
	return 0;
    }

    ret = TRUE;
    if (!kld_file_patch_OSObjects(kmod_name)) {
        IOLog("map_and_patch(): "
              "Extension \"%s\" Error binding OSObjects.\n", kmod_name);
        LOG_DELAY();
        
        // RY: Instead of returning here, set the return value.
        // We still need to call kld_file_prepare_for_link because
        // we might have patched files outside of the driver.  Don't
        // worry, it will know to ignore the damaged file
        ret = FALSE;
    }

    // Now repair any damage that the kld patcher may have done to the image
    kld_file_prepare_for_link();

    return ret;
}
bool SMBIOSResolver::start(IOService * provider)
{
	if( super::start(provider) != true ) return false;	// Oh no	
	if( IOService::getResourceService()->getProperty("SMBIOS-Resolver") ) return false;	// We should exist only once	
	if( !IOService::getResourceService()->getProperty("SMBIOS") ) return false;	// AppleSMBIOS.kext didn´t start we bail out
	
	IOService * iosRoot = getServiceRoot();
	if( !iosRoot ) return false;	// Unable to get IOServiceRoot
	
	int doVerbose = 0;
	// PE_parse_boot_arg("smbios", &doVerbose);	// bootarg SMBIOS=1 will give a verbose output to log (when I find something verbose worth outputting)
	
	// Dictionary from plist
	OSDictionary * hwDict = OSDynamicCast( OSDictionary, getProperty("Override"));
	
	//	/rom/version
	IORegistryEntry * dtROMNode = fromPath("/rom", gIODTPlane);
	if( dtROMNode )
	{
		OSString * romVersion = OSDynamicCast( OSString, hwDict->getObject("rom-version"));
		if(romVersion->getLength() > 0) dtROMNode->setProperty("version", OSData::withBytes(romVersion->getCStringNoCopy(), romVersion->getLength() + 1) );
		dtROMNode->release();
	}
	else
	{
		return false;	// No /rom node in IODeviceTree plane
	}
	
	// root entries
	OSObject * dictString = 0;
	
	dictString = hwDict->getObject("manufacturer");
	if(dictString)
	{
		OSString * rootManufacturer = OSDynamicCast( OSString, dictString);
		if(rootManufacturer->getLength() > 1) iosRoot->setProperty("manufacturer", OSData::withBytes(rootManufacturer->getCStringNoCopy(), rootManufacturer->getLength() + 1) );
	}
	
	dictString = hwDict->getObject("system-type");
	if(dictString)
	{
		OSData * systemType = OSDynamicCast( OSData, dictString);
		if(systemType) iosRoot->setProperty("system-type", systemType );
	}
	
	dictString = hwDict->getObject("compatible");
	if(dictString) 
	{
		OSString * rootCompatible = OSDynamicCast( OSString, dictString);
		if(rootCompatible->getLength() > 1) iosRoot->setProperty("compatible", OSData::withBytes(rootCompatible->getCStringNoCopy(), rootCompatible->getLength() + 1) );
	}
	
	dictString = hwDict->getObject("product-name");
	if(dictString) 
	{
		OSString * rootProductName = OSDynamicCast( OSString, dictString);
		if(rootProductName->getLength() > 1) iosRoot->setProperty("product-name", OSData::withBytes(rootProductName->getCStringNoCopy(), rootProductName->getLength() + 1) );
	}
	
	dictString = hwDict->getObject("model");
	if(dictString) 
	{
		OSString * rootModel = OSDynamicCast( OSString, dictString);
		if(rootModel->getLength() > 1)
		{
			iosRoot->setProperty("model", OSData::withBytes(rootModel->getCStringNoCopy(), rootModel->getLength() + 1) );
			iosRoot->setName(rootModel->getCStringNoCopy());
		}
	}
	
	dictString = hwDict->getObject("version");
	if(dictString) 
	{
		OSString * rootVersion = OSDynamicCast( OSString, dictString);
		if(rootVersion->getLength() > 1) iosRoot->setProperty("version", OSData::withBytes(rootVersion->getCStringNoCopy(), rootVersion->getLength() + 1) );
	}
	
	dictString = hwDict->getObject("board-id");
	if(dictString) 
	{
		OSString * rootBoardId = OSDynamicCast( OSString, dictString);
		if(rootBoardId->getLength() > 1) iosRoot->setProperty("board-id", OSData::withBytes(rootBoardId->getCStringNoCopy(), rootBoardId->getLength() + 1) );
	}
	
	dictString = hwDict->getObject("serial-number");
	if(dictString) 
	{
		OSString * rootSerial = OSDynamicCast( OSString, dictString);
		if(rootSerial->getLength() > 1)
		{
			UInt8 length = rootSerial->getLength();
			const char *serialNumberString = rootSerial->getCStringNoCopy();
			
			// The serial-number property in the IORegistry is a 43-byte data object.
			// Bytes 0 through 2 are the last three bytes of the serial number string.
			// Bytes 11 through 20, inclusive, are the serial number string itself.
			// All other bytes are '\0'.
			OSData * data = OSData::withCapacity(43);
			if (data)
			{
				data->appendBytes(serialNumberString + (length - 3), 3);
				data->appendBytes(NULL, 10);
				data->appendBytes(serialNumberString, length);
				data->appendBytes(NULL, 43 - length - 10 - 3);
				iosRoot->setProperty("serial-number", data);
				data->release();
			}
			
			iosRoot->setProperty(kIOPlatformSerialNumberKey, rootSerial);
		}
	}
	
	dictString = hwDict->getObject("UUID-key");
	if(dictString) 
	{
		OSString * rootUUIDKey = OSDynamicCast( OSString, hwDict->getObject("UUID-key"));
		iosRoot->setProperty(kIOPlatformUUIDKey, rootUUIDKey);
		publishResource(kIOPlatformUUIDKey, rootUUIDKey);
	}
	
	bool useEfiBus = false;
	UInt64 fsbFrequency = 0;
	UInt64 msr;
	dictString = hwDict->getObject("use-efi-bus");
	if (dictString) useEfiBus = (OSDynamicCast(OSBoolean, dictString))->getValue(); 
	IORegistryEntry * efiPlatform = fromPath("/efi/platform", gIODTPlane);
	if (efiPlatform && useEfiBus)
	{
		OSData * efiFSBFreq = OSDynamicCast(OSData, efiPlatform->getProperty("FSBFrequency"));
		bcopy(efiFSBFreq->getBytesNoCopy(), &fsbFrequency, efiFSBFreq->getLength());
		efiPlatform->release();
	}
	else
	{	// No /efi/platform found
		fsbFrequency = gPEClockFrequencyInfo.bus_frequency_hz;	// Value previously set by AppleSMBIOS 
		if (!strncmp(cpuid_info()->cpuid_vendor, CPUID_VID_INTEL, sizeof(CPUID_VID_INTEL)) && (cpuid_info()->cpuid_features & CPUID_FEATURE_SSE2)) fsbFrequency /= 4;
	}

	dictString = hwDict->getObject("hardcode-bus");
	if(dictString) 
	{
		fsbFrequency = (OSDynamicCast(OSNumber, dictString))->unsigned64BitValue();
		if (fsbFrequency)
		{
			if (fsbFrequency <= 10000) fsbFrequency *= 1000000;
		}
		else
		{
			if (!strncmp(cpuid_info()->cpuid_vendor, CPUID_VID_INTEL, sizeof(CPUID_VID_INTEL)))
			{
				if ((cpuid_info()->cpuid_family == 0x0f) && (cpuid_info()->cpuid_model >= 2))
				{
					msr = rdmsr64(0x0000002C);
					switch ((msr >> 16) & 0x7) {
						case 0:
							if (cpuid_info()->cpuid_model == 2) fsbFrequency = 100 * 1000000;
							else 
							{
								fsbFrequency = (800 * 1000000) / 3;	// 266
								fsbFrequency++;
							}
							break;
						case 1:
							fsbFrequency = (400 * 1000000) / 3;	//	133
							break;
						case 2:
							fsbFrequency = (600 * 1000000) / 3;	// 200
							break;
						case 3:
							fsbFrequency = (500 * 1000000) / 3;	//	166
							fsbFrequency++;
							break;
						case 4:
							fsbFrequency = (1000 * 1000000) / 3;	//	333
							break;
						default:
							break;
					}
				}
				else
				{
					fsbFrequency = 100 * 1000000;
				}
				
				if (cpuid_info()->cpuid_family == 0x06)
				{
					msr = rdmsr64(0x000000CD);
					switch (msr & 0x7) {
						case 0:
							fsbFrequency = (800 * 1000000) / 3;	//	266
							fsbFrequency++;
							break;
						case 1:
							fsbFrequency = (400 * 1000000) / 3;	//	133
							break;
						case 2:
							fsbFrequency = (600 * 1000000) / 3;	//	200
							break;
						case 3:
							fsbFrequency = (500 * 1000000) / 3;	//	166
							fsbFrequency++;
							break;
						case 4:
							fsbFrequency = (1000 * 1000000) / 3;//	333
							break;
						case 5:
							fsbFrequency = (300 * 1000000) / 3;	//	100
							break;
						case 6:
							fsbFrequency = (1200 * 1000000) / 3;//	400
							break;
						case 7:		// should check
							fsbFrequency = (1400 * 1000000) / 3;//	466
							fsbFrequency++;
							break;
						default:
							break;
					}
				}
				 
			}
		}
IOReturn
IOEthernetInterface::setupMulticastFilter(IONetworkController * ctr)
{
    void *               multiAddrs = 0;
    UInt                 mcount;
    OSData *             mcData = 0;
    ifnet_t				interface;
    struct sockaddr  dlAddress;
    IOReturn             ret = kIOReturnSuccess;
    bool                 ok;
	ifmultiaddr_t		*addressList;
	
    interface = getIfnet();
	
	assert(interface);

    // get the list and count how many mcast link addresses there are
	if(ifnet_get_multicast_list(interface, &addressList))
		return kIOReturnNoMemory;
	mcount = 0;
	for(int i=0; addressList[i]; i++)
	{
		ifmaddr_address(addressList[i], &dlAddress, sizeof(dlAddress));

		if (dlAddress.sa_family == AF_UNSPEC || dlAddress.sa_family == AF_LINK)
			mcount++;
	}
	
	_mcAddrCount = mcount;

	// now rewalk the list and copy the addresses to a format suitable to give to the controller
    if ( mcount )
    {
        char * addrp;
            
        mcData = OSData::withCapacity(mcount * ETHER_ADDR_LEN);
        if (!mcData)
        {
            DLOG("%s: no memory for multicast address list\n", getName());
			ifnet_free_multicast_list(addressList);
            return kIOReturnNoMemory;
        }
        
        // Loop through the list and copy the link multicast
        // address to the OSData.
		for(int i = 0; addressList[i]; i++)
		{
			//retrieve the datalink mcast address
			ifmaddr_address(addressList[i], &dlAddress, sizeof(dlAddress));
			
			if (dlAddress.sa_family == AF_UNSPEC)
                addrp = &dlAddress.sa_data[0];
            else if (dlAddress.sa_family == AF_LINK)
                addrp = LLADDR((struct sockaddr_dl *)&dlAddress);
            else
                continue;

            ok = mcData->appendBytes((const void *) addrp, ETHER_ADDR_LEN);
            assert(ok);
        }

        multiAddrs = (void *) mcData->getBytesNoCopy();
        assert(multiAddrs);
    }

    // Issue a controller command to setup the multicast filter.

    ret = ((IOEthernetController *)ctr)->setMulticastList(
                                            (IOEthernetAddress *) multiAddrs,
                                            mcount);
    if (mcData)
    {
        if (ret == kIOReturnSuccess)
            setProperty(kIOMulticastAddressList, mcData);

        mcData->release();
    }
    else {
        removeProperty(kIOMulticastAddressList);
    }
	ifnet_free_multicast_list(addressList);
    return ret;
}