1/* 2 * Copyright (c) 1998-2008 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23#include <IOKit/assert.h> 24#include <IOKit/IOLib.h> 25#include <libkern/c++/OSObject.h> 26#include <libkern/c++/OSNumber.h> 27#include <libkern/c++/OSCollectionIterator.h> 28#include <libkern/c++/OSDictionary.h> 29#include <libkern/c++/OSSerialize.h> 30#include <IOKit/network/IONetworkMedium.h> 31 32//--------------------------------------------------------------------------- 33// OSMetaClass macros. 34 35#define super OSObject 36OSDefineMetaClassAndStructors( IONetworkMedium, OSObject ) 37OSMetaClassDefineReservedUnused( IONetworkMedium, 0); 38OSMetaClassDefineReservedUnused( IONetworkMedium, 1); 39OSMetaClassDefineReservedUnused( IONetworkMedium, 2); 40OSMetaClassDefineReservedUnused( IONetworkMedium, 3); 41 42//--------------------------------------------------------------------------- 43// Initialize an IONetworkMedium instance. 44// 45// type: The medium type, the fields are encoded with bits defined in 46// IONetworkMedium.h. 47// 48// speed: The maximum (or the only) link speed supported over this medium 49// in units of bits per second. 50// 51// flags: An optional flag for the medium object. 52// See IONetworkMedium.h for defined flags. 53// 54// index: An optional 32-bit index assigned by the caller. Drivers can use 55// this to store an index or a pointer to a media table inside the 56// driver, or it may map to a driver defined media type. 57// 58// name: An name to assign to this medium object. If 0, then a name 59// will be created based on the medium type given using nameForType(). 60// 61// Returns true on success, false otherwise. 62 63bool IONetworkMedium::init(IOMediumType type, 64 UInt64 speed, 65 UInt32 flags, 66 UInt32 index, 67 const char * name) 68{ 69 if ( super::init() == false ) 70 return false; 71 72 _type = type; 73 _flags = flags; 74 _speed = speed; 75 _index = index; 76 77 if (name) 78 _name = OSSymbol::withCString(name); 79 else 80 _name = IONetworkMedium::nameForType(type); 81 82 if (!_name) 83 return false; 84 85 return true; 86} 87 88//--------------------------------------------------------------------------- 89// Factory method which performs allocation and initialization 90// of an IONetworkMedium instance. 91// 92// Returns an IONetworkMedium instance on success, or 0 otherwise. 93 94IONetworkMedium * IONetworkMedium::medium(IOMediumType type, 95 UInt64 speed, 96 UInt32 flags, 97 UInt32 index, 98 const char * name) 99{ 100 IONetworkMedium * medium = new IONetworkMedium; 101 102 if (medium && !medium->init(type, speed, flags, index, name)) 103 { 104 medium->release(); 105 medium = 0; 106 } 107 108 return medium; 109} 110 111//--------------------------------------------------------------------------- 112// Free the IONetworkMedium instance. 113 114void IONetworkMedium::free() 115{ 116 if (_name) 117 { 118 _name->release(); 119 _name = 0; 120 } 121 super::free(); 122} 123 124//--------------------------------------------------------------------------- 125// Return the assigned medium type. 126 127IOMediumType IONetworkMedium::getType() const 128{ 129 return _type; 130} 131 132//--------------------------------------------------------------------------- 133// Return the medium flags. 134 135UInt32 IONetworkMedium::getFlags() const 136{ 137 return _flags; 138} 139 140//--------------------------------------------------------------------------- 141// Return the maximum medium speed. 142 143UInt64 IONetworkMedium::getSpeed() const 144{ 145 return _speed; 146} 147 148//--------------------------------------------------------------------------- 149// Return the assigned index. 150 151UInt32 IONetworkMedium::getIndex() const 152{ 153 return _index; 154} 155 156//--------------------------------------------------------------------------- 157// Return the name for this instance. 158 159const OSSymbol * IONetworkMedium::getName() const 160{ 161 return _name; 162} 163 164//--------------------------------------------------------------------------- 165// Given a medium type, create an unique OSymbol name for the medium. 166// The caller is responsible for releasing the OSSymbol object returned. 167// 168// type: A medium type. See IONetworkMedium.h for type encoding. 169// 170// Returns an OSSymbol created based on the type provided. 171 172const OSSymbol * IONetworkMedium::nameForType(IOMediumType type) 173{ 174 char buffer[10]; 175 176 snprintf(buffer, sizeof(buffer), "%08x", (uint32_t) type); 177 178 // Caller must remember to free the OSSymbol! 179 // 180 return OSSymbol::withCString(buffer); 181} 182 183//--------------------------------------------------------------------------- 184// Test for equality between two IONetworkMedium objects. 185// Two IONetworkMedium objects are considered equal if 186// they have similar properties assigned to them during initialization. 187// 188// medium: An IONetworkMedium to test against the IONetworkMedium 189// object being called. 190// 191// Returns true if equal, false otherwise. 192 193bool IONetworkMedium::isEqualTo(const IONetworkMedium * medium) const 194{ 195 return ( (medium->_name == _name) && 196 (medium->_type == _type) && 197 (medium->_flags == _flags) && 198 (medium->_speed == _speed) && 199 (medium->_index == _index) ); 200} 201 202//--------------------------------------------------------------------------- 203// Test for equality between a IONetworkMedium object and an OSObject. 204// The OSObject is considered equal to the IONetworkMedium object if the 205// OSObject is an IONetworkMedium, and they have similar properties assigned 206// to them during initialization. 207// 208// obj: An OSObject to test against the IONetworkMedium object being called. 209// 210// Returns true if equal, false otherwise. 211 212bool IONetworkMedium::isEqualTo(const OSMetaClassBase * obj) const 213{ 214 IONetworkMedium * medium; 215 if ((medium = OSDynamicCast(IONetworkMedium, obj))) 216 return isEqualTo(medium); 217 else 218 return false; 219} 220 221//--------------------------------------------------------------------------- 222// Create an OSData containing an IOMediumDescriptor structure (not copied), 223// and ask the OSData to serialize. 224// 225// s: An OSSerialize object to handle the serialization. 226// 227// Returns true on success, false otherwise. 228 229static bool addNumberToDict(OSDictionary * dict, 230 const char * key, 231 UInt32 val, 232 UInt32 bits = 32) 233{ 234 OSNumber * num = OSNumber::withNumber(val, bits); 235 bool ret; 236 237 if ( num == 0 ) return false; 238 ret = dict->setObject( key, num ); 239 num->release(); 240 return ret; 241} 242 243bool IONetworkMedium::serialize(OSSerialize * s) const 244{ 245 bool ret; 246 OSDictionary * dict; 247 248 dict = OSDictionary::withCapacity(4); 249 if ( dict == 0 ) return false; 250 251 addNumberToDict(dict, kIOMediumType, getType()); 252 addNumberToDict(dict, kIOMediumSpeed, getSpeed(), 64); 253 addNumberToDict(dict, kIOMediumIndex, getIndex()); 254 addNumberToDict(dict, kIOMediumFlags, getFlags()); 255 256 ret = dict->serialize(s); 257 dict->release(); 258 259 return ret; 260} 261 262//--------------------------------------------------------------------------- 263// A helper function to add an IONetworkMedium object to a given dictionary. 264// The name of the medium is used as the key for the new dictionary entry. 265// 266// dict: An OSDictionary object where the medium object should be added to. 267// medium: The IONetworkMedium object to add to the dictionary. 268// 269// Returns true on success, false otherwise. 270 271bool IONetworkMedium::addMedium(OSDictionary * dict, 272 const IONetworkMedium * medium) 273{ 274 // Arguments type checking. 275 // 276 if (!OSDynamicCast(OSDictionary, dict) || 277 !OSDynamicCast(IONetworkMedium, medium)) 278 return false; 279 280 return dict->setObject(medium->getName(), medium); 281} 282 283//--------------------------------------------------------------------------- 284// A helper function to remove an entry in a dictionary with a key that 285// matches the name of the IONetworkMedium object provided. 286// 287// dict: An OSDictionary object where the medium object should be removed 288// from. 289// medium: The name of this medium object is used as the removal key. 290 291void IONetworkMedium::removeMedium(OSDictionary * dict, 292 const IONetworkMedium * medium) 293{ 294 // Arguments type checking. 295 // 296 if (!OSDynamicCast(OSDictionary, dict) || 297 !OSDynamicCast(IONetworkMedium, medium)) 298 return; 299 300 dict->removeObject(medium->getName()); 301} 302 303//--------------------------------------------------------------------------- 304// Iterate through a dictionary and return an IONetworkMedium entry that 305// satisfies the matching criteria. Returns 0 if there is no match. 306 307IONetworkMedium * IONetworkMedium::getMediumWithType( 308 const OSDictionary * dict, 309 IOMediumType type, 310 IOMediumType mask) 311{ 312 OSCollectionIterator * iter; 313 OSSymbol * key; 314 IONetworkMedium * medium; 315 IONetworkMedium * match = 0; 316 317 if (!dict) return 0; 318 319 // Shouldn't withCollection take an (const OSDictionary *) argument? 320 321 iter = OSCollectionIterator::withCollection((OSDictionary *) dict); 322 if (!iter) 323 return 0; 324 325 while ( (key = (OSSymbol *) iter->getNextObject()) ) 326 { 327 medium = OSDynamicCast(IONetworkMedium, dict->getObject(key)); 328 if (medium == 0) continue; 329 330 if ( ( (medium->getType() ^ type) & ~mask) == 0 ) 331 { 332 match = medium; 333 break; 334 } 335 } 336 337 iter->release(); 338 339 return match; 340} 341 342IONetworkMedium * IONetworkMedium::getMediumWithIndex( 343 const OSDictionary * dict, 344 UInt32 index, 345 UInt32 mask) 346{ 347 OSCollectionIterator * iter; 348 OSSymbol * key; 349 IONetworkMedium * medium; 350 IONetworkMedium * match = 0; 351 352 if (!dict) return 0; 353 354 // Shouldn't withCollection take an (const OSDictionary *) argument? 355 356 iter = OSCollectionIterator::withCollection((OSDictionary *) dict); 357 if (!iter) 358 return 0; 359 360 while ( (key = (OSSymbol *) iter->getNextObject()) ) 361 { 362 medium = OSDynamicCast(IONetworkMedium, dict->getObject(key)); 363 if (medium == 0) continue; 364 365 if ( ( (medium->getIndex() ^ index) & ~mask) == 0 ) 366 { 367 match = medium; 368 break; 369 } 370 } 371 372 iter->release(); 373 374 return match; 375} 376