1/* 2 * 3 * @APPLE_LICENSE_HEADER_START@ 4 * 5 * Copyright (c) 1998-2003 Apple Computer, Inc. All Rights Reserved. 6 * 7 * This file contains Original Code and/or Modifications of Original Code 8 * as defined in and that are subject to the Apple Public Source License 9 * Version 2.0 (the 'License'). You may not use this file except in 10 * compliance with the License. Please obtain a copy of the License at 11 * http://www.opensource.apple.com/apsl/ and read it before using this 12 * file. 13 * 14 * The Original Code and all software distributed under the License are 15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 * Please see the License for the specific language governing rights and 20 * limitations under the License. 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24 25#include <machine/limits.h> /* UINT_MAX */ 26#include <libkern/OSByteOrder.h> 27 28#include <IOKit/network/IOEthernetController.h> 29#include <IOKit/network/IOEthernetInterface.h> 30#include <IOKit/network/IOGatedOutputQueue.h> 31 32#include <IOKit/IOTimerEventSource.h> 33#include <IOKit/assert.h> 34#include <IOKit/IOLib.h> 35#include <IOKit/IOService.h> 36#include <IOKit/IOBufferMemoryDescriptor.h> 37#include <IOKit/IOMessage.h> 38 39#include <IOKit/pwr_mgt/RootDomain.h> 40 41#if !TARGET_OS_IPHONE 42#include <IOKit/usb/IOUSBBus.h> 43#endif /* TARGET_OS_IPHONE */ 44 45#include <IOKit/usb/IOUSBNub.h> 46#include <IOKit/usb/IOUSBDevice.h> 47#include <IOKit/usb/IOUSBPipe.h> 48#include <IOKit/usb/USB.h> 49#include <IOKit/usb/IOUSBInterface.h> 50 51#include <UserNotification/KUNCUserNotifications.h> 52 53extern "C" 54{ 55 #include <sys/param.h> 56 #include <sys/mbuf.h> 57} 58 59#define DEBUG_NAME "AppleUSBCDCECMData" 60 61#include "AppleUSBCDCECM.h" 62#include "AppleUSBCDCECMData.h" 63#include "linkup.h" 64 65#define MIN_BAUD (50 << 1) 66 67static IOPMPowerState gOurPowerStates[kNumCDCStates] = 68{ 69 {1,0,0,0,0,0,0,0,0,0,0,0}, 70 {1,IOPMDeviceUsable,IOPMPowerOn,IOPMPowerOn,0,0,0,0,0,0,0,0} 71}; 72 73static struct MediumTable 74{ 75 UInt32 type; 76 UInt32 speed; 77} 78 79mediumTable[] = 80{ 81 { kIOMediumEthernetNone, 0 }, 82 { kIOMediumEthernetAuto, 0 }, 83 { kIOMediumEthernet10BaseT | kIOMediumOptionHalfDuplex, 10 }, 84 { kIOMediumEthernet10BaseT | kIOMediumOptionFullDuplex, 10 }, 85 { kIOMediumEthernet10BaseT | kIOMediumOptionFullDuplex | kIOMediumOptionFlowControl, 10 }, 86 { kIOMediumEthernet100BaseTX | kIOMediumOptionHalfDuplex, 100 }, 87 { kIOMediumEthernet100BaseTX | kIOMediumOptionFullDuplex, 100 }, 88 { kIOMediumEthernet100BaseTX | kIOMediumOptionFullDuplex | kIOMediumOptionFlowControl, 100 }, 89 { kIOMediumEthernet1000BaseTX | kIOMediumOptionFullDuplex, 1000 }, 90 { kIOMediumEthernet1000BaseTX | kIOMediumOptionFullDuplex | kIOMediumOptionFlowControl, 1000 } 91}; 92 93#define super IOEthernetController 94 95OSDefineMetaClassAndStructors(AppleUSBCDCECMData, IOEthernetController); 96 97/****************************************************************************************************/ 98// 99// Function: findCDCDriverED 100// 101// Inputs: myDevice - Address of the controlling device 102// dataAddr - my address 103// dataInterfaceNum - the data interface number 104// 105// Outputs: 106// 107// Desc: Finds the initiating CDC driver and confirm the interface number 108// 109/****************************************************************************************************/ 110 111IOReturn findCDCDriverED(IOUSBDevice *myDevice, void *dataAddr, UInt8 dataInterfaceNum) 112{ 113 AppleUSBCDCECMData *me = (AppleUSBCDCECMData *)dataAddr; 114 AppleUSBCDC *CDCDriver = NULL; 115 bool driverOK = false; 116 OSIterator *iterator = NULL; 117 OSDictionary *matchingDictionary = NULL; 118 UInt16 i; 119 120 XTRACE(me, 0, 0, "findCDCDriverED"); 121 122 // Get matching dictionary 123 124 matchingDictionary = IOService::serviceMatching("AppleUSBCDC"); 125 if (!matchingDictionary) 126 { 127 XTRACE(me, 0, 0, "findCDCDriverED - Couldn't create a matching dictionary"); 128 return kIOReturnError; 129 } 130 131 // Get an iterator 132 133 iterator = IOService::getMatchingServices(matchingDictionary); 134 if (!iterator) 135 { 136 XTRACE(me, 0, 0, "findCDCDriverED - No AppleUSBCDC driver found!"); 137 matchingDictionary->release(); 138 return kIOReturnError; 139 } 140 141#if 0 142 // Use iterator to find driver (there's only one so we won't bother to iterate) 143 144 CDCDriver = (AppleUSBCDC *)iterator->getNextObject(); 145 if (CDCDriver) 146 { 147 driverOK = CDCDriver->confirmDriver(kUSBEthernetControlModel, dataInterfaceNum); 148 } 149#endif 150 151 // Iterate until we find our matching CDC driver 152 153 CDCDriver = (AppleUSBCDC *)iterator->getNextObject(); 154 while (CDCDriver) 155 { 156 XTRACEP(me, 0, CDCDriver, "findCDCDriverED - CDC driver candidate"); 157 158 if (me->fDataInterface->GetDevice() == CDCDriver->getCDCDevice()) 159 { 160 XTRACEP(me, 0, CDCDriver, "findCDCDriverED - Found our CDC driver"); 161 driverOK = CDCDriver->confirmDriver(kUSBEthernetControlModel, dataInterfaceNum); 162 break; 163 } 164 CDCDriver = (AppleUSBCDC *)iterator->getNextObject(); 165 } 166 167 matchingDictionary->release(); 168 iterator->release(); 169 170 if (!CDCDriver) 171 { 172 XTRACE(me, 0, 0, "findCDCDriverED - CDC driver not found"); 173 return kIOReturnNotReady; 174 } 175 176 if (!driverOK) 177 { 178 XTRACE(me, kUSBEthernetControlModel, dataInterfaceNum, "findCDCDriverED - Not my interface"); 179 return kIOReturnError; 180 } 181 182 me->fConfigAttributes = CDCDriver->fbmAttributes; 183 184 for (i=0; i<6; i++) 185 { 186 me->fEthernetaddr[i] = CDCDriver->fCacheEaddr[i]; 187 } 188 189 return kIOReturnSuccess; 190 191}/* end findCDCDriverED */ 192 193/****************************************************************************************************/ 194// 195// Function: findControlDriverED 196// 197// Inputs: me - my address 198// 199// Outputs: 200// 201// Desc: Finds our matching control driver 202// 203/****************************************************************************************************/ 204 205IOReturn findControlDriverED(AppleUSBCDCECMData *me) 206{ 207 AppleUSBCDCECMControl *tempDriver = NULL; 208 OSIterator *iterator = NULL; 209 OSDictionary *matchingDictionary = NULL; 210 211 XTRACE(me, 0, 0, "findControlDriverED"); 212 213 me->fControlDriver = NULL; 214 215 // Get matching dictionary 216 217 matchingDictionary = IOService::serviceMatching("AppleUSBCDCECMControl"); 218 if (!matchingDictionary) 219 { 220 XTRACE(me, 0, 0, "findControlDriverED - Couldn't create a matching dictionary"); 221 return kIOReturnError; 222 } 223 224 // Get an iterator 225 226 iterator = IOService::getMatchingServices(matchingDictionary); 227 if (!iterator) 228 { 229 XTRACE(me, 0, 0, "findControlDriverED - No AppleUSBCDCECMControl drivers found (iterator)"); 230 matchingDictionary->release(); 231 return kIOReturnError; 232 } 233 234 // Iterate until we find our matching driver 235 236 tempDriver = (AppleUSBCDCECMControl *)iterator->getNextObject(); 237 while (tempDriver) 238 { 239 XTRACEP(me, 0, tempDriver, "findControlDriverED - Control driver candidate"); 240 if (tempDriver->checkInterfaceNumber((AppleUSBCDCECMData *)me)) 241 { 242 XTRACEP(me, 0, tempDriver, "findControlDriverED - Found our control driver"); 243 me->fControlDriver = tempDriver; 244 break; 245 } 246 tempDriver = (AppleUSBCDCECMControl *)iterator->getNextObject(); 247 } 248 249 matchingDictionary->release(); 250 iterator->release(); 251 252 if (!me->fControlDriver) 253 { 254 XTRACE(me, 0, 0, "findControlDriverED - Failed"); 255 return kIOReturnError; 256 } 257 258 return kIOReturnSuccess; 259 260}/* end findControlDriverED */ 261 262#if LOG_DATA 263#define dumplen 32 // Set this to the number of bytes to dump and the rest should work out correct 264 265#define buflen ((dumplen*2)+dumplen)+3 266#define Asciistart (dumplen*2)+3 267 268/****************************************************************************************************/ 269// 270// Function: AppleUSBCDCECMData::USBLogData 271// 272// Inputs: Dir - direction 273// Count - number of bytes 274// buf - the data 275// 276// Outputs: 277// 278// Desc: Puts the data in the log. 279// 280/****************************************************************************************************/ 281 282void AppleUSBCDCECMData::USBLogData(UInt8 Dir, SInt32 Count, char *buf) 283{ 284 SInt32 wlen; 285 UInt8 tDir = Dir; 286 SInt32 llen, rlen; 287 SInt16 i, Aspnt, Hxpnt; 288 UInt8 wchr; 289 char LocBuf[buflen+1]; 290 291 XTRACE(0, 0, Count, "USBLogData >>>>"); 292 293 294 switch (tDir) 295 { 296 case kDataIn: 297 Log("AppleUSBCDCECMData: USBLogData - Read Complete, address = %8p, size = %8d\n", (void *)buf, (UInt)Count); 298 break; 299 case kDataOut: 300 Log("AppleUSBCDCECMData: USBLogData - Write, address = %8p, size = %8d\n", (void *)buf, (UInt)Count); 301 break; 302 case kDataOther: 303 Log("AppleUSBCDCECMData: USBLogData - Other, address = %8p, size = %8d\n", (void *)buf, (UInt)Count); 304 break; 305 case kDataNone: 306 tDir = kDataOther; 307 break; 308 } 309 310#if DUMPALL 311 wlen = Count; 312#else 313 if (Count > dumplen) 314 { 315 wlen = dumplen; 316 } else { 317 wlen = Count; 318 } 319#endif 320 321 if (wlen == 0) 322 { 323 Log("AppleUSBCDCECMData: USBLogData - No data, Count=0\n"); 324 return; 325 } 326 327 rlen = 0; 328 do 329 { 330 memset(LocBuf, 0x20, buflen); 331 332 if (wlen > dumplen) 333 { 334 llen = dumplen; 335 wlen -= dumplen; 336 } else { 337 llen = wlen; 338 wlen = 0; 339 } 340 Aspnt = Asciistart; 341 Hxpnt = 0; 342 for (i=1; i<=llen; i++) 343 { 344 wchr = buf[i-1]; 345 LocBuf[Hxpnt++] = Asciify(wchr >> 4); 346 LocBuf[Hxpnt++] = Asciify(wchr); 347 if ((wchr < 0x20) || (wchr > 0x7F)) // Non printable characters 348 { 349 LocBuf[Aspnt++] = 0x2E; // Replace with a period 350 } else { 351 LocBuf[Aspnt++] = wchr; 352 } 353 } 354 LocBuf[Aspnt] = 0x00; 355 356 Log("%s\n", LocBuf); 357#if USE_IOL 358 IOSleep(Sleep_Time); // Try and keep the log from overflowing 359#endif 360 rlen += llen; 361 buf = &buf[rlen]; 362 } while (wlen != 0); 363 364 XTRACE(0, Dir, Count, "USBLogData <<<<"); 365 366}/* end USBLogData */ 367 368/****************************************************************************************************/ 369// 370// Function: AppleUSBCDCECMData::dumpData 371// 372// Inputs: buf - the data 373// size - number of bytes 374// 375// Outputs: None 376// 377// Desc: Creats formatted data for the log (cannot be used at interrupt time) 378// 379/****************************************************************************************************/ 380 381void AppleUSBCDCECMData::dumpData(char *buf, SInt32 size) 382{ 383 SInt32 curr, len, dlen; 384 385 Log("AppleUSBCDCECMData: dumpData - Address = %8p, size = %8d\n", (void *)buf, (UInt)size); 386 387 dlen = 0; 388 len = size; 389 390 for (curr=0; curr<size; curr+=dumplen) 391 { 392 if (len > dumplen) 393 { 394 dlen = dumplen; 395 } else { 396 dlen = len; 397 } 398 Log("%8p ", (void *)&buf[curr]); 399 USBLogData(kDataNone, dlen, &buf[curr]); 400 len -= dlen; 401 } 402 403}/* end dumpData */ 404#endif 405 406/****************************************************************************************************/ 407// 408// Method: AppleUSBCDCECMData::dataReadComplete 409// 410// Inputs: obj - me 411// param - pool index 412// rc - return code 413// remaining - what's left 414// 415// Outputs: 416// 417// Desc: BulkIn pipe (Data interface) read completion routine 418// 419/****************************************************************************************************/ 420 421void AppleUSBCDCECMData::dataReadComplete(void *obj, void *param, IOReturn rc, UInt32 remaining) 422{ 423 AppleUSBCDCECMData *me = (AppleUSBCDCECMData*)obj; 424 IOReturn ior; 425 pipeInBuffers *pipeInBuff = (pipeInBuffers *)param; 426 427 XTRACE(me, 0, pipeInBuff->indx, "dataReadComplete"); 428 429 if (me->fTerminate) //rcs revisit for IOUSBFamily 2.0 430 return; 431 432 if (rc == kIOReturnSuccess) // If operation returned ok 433 { 434 XTRACE(me, 0, me->fControlDriver->fMax_Block_Size - remaining, "dataReadComplete - data length"); 435 436 meLogData(kDataIn, (me->fControlDriver->fMax_Block_Size - remaining), pipeInBuff->pipeInBuffer); 437 438 // If the link is down we're probably in the state where the device is not sending interrupts 439 // If we're in the ready state then we probably need to start things up 440 441 if (me->fLinkStatus == kLinkDown) 442 { 443 XTRACE(me, 0, me->fReady, "dataReadComplete - Link is down, checking ready state"); 444 if (me->fReady) 445 { 446 me->linkStatusChange(kLinkUp); 447 } 448 } 449 450 // Move the incoming bytes up the stack 451 452 me->receivePacket(pipeInBuff->pipeInBuffer, me->fControlDriver->fMax_Block_Size - remaining); 453 454 } else { 455 XTRACE(me, 0, rc, "dataReadComplete - Read completion io err"); 456 if (rc != kIOReturnAborted) 457 { 458 me->fDeferredClear = true; 459#if 0 460 rc = me->clearPipeStall(me->fInPipe); 461 if (rc != kIOReturnSuccess) 462 { 463 XTRACE(me, 0, rc, "dataReadComplete - clear stall failed (trying to continue)"); 464 } 465#endif 466 } 467 } 468 469 // Queue the next read, only if not aborted 470 471 if (rc != kIOReturnAborted) 472 { 473 ior = me->fInPipe->Read(pipeInBuff->pipeInMDP, &pipeInBuff->readCompletionInfo, NULL); 474 if (ior != kIOReturnSuccess) 475 { 476 XTRACE(me, 0, ior, "dataReadComplete - Failed to queue read"); 477 pipeInBuff->dead = true; 478 } 479 } else { 480 XTRACE(me, pipeInBuff->indx, 0, "dataReadComplete - Read terminated"); 481 pipeInBuff->dead = true; 482 } 483 484 return; 485 486}/* end dataReadComplete */ 487 488/****************************************************************************************************/ 489// 490// Method: AppleUSBCDCECMData::dataWriteComplete 491// 492// Inputs: obj - me 493// param - pool index 494// rc - return code 495// remaining - what's left 496// 497// Outputs: 498// 499// Desc: BulkOut pipe (Data interface) write completion routine 500// 501/****************************************************************************************************/ 502 503void AppleUSBCDCECMData::dataWriteComplete(void *obj, void *param, IOReturn rc, UInt32 remaining) 504{ 505 AppleUSBCDCECMData *me = (AppleUSBCDCECMData *)obj; 506 mbuf_t m; 507 UInt32 pktLen = 0; 508// UInt32 poolIndx = (UInt32)param; 509 pipeOutBuffers *pipeOutBuff = (pipeOutBuffers *)param; 510 511 if (rc == kIOReturnSuccess) // If operation returned ok 512 { 513 XTRACE(me, rc, pipeOutBuff->indx, "dataWriteComplete"); 514 515 if (pipeOutBuff->m != NULL) // Null means zero length write 516 { 517 m = pipeOutBuff->m; 518 while (m) 519 { 520 pktLen += mbuf_len(m); 521 m = mbuf_next(m); 522 } 523 524 me->freePacket(pipeOutBuff->m); // Free the mbuf 525 pipeOutBuff->m = NULL; 526 527 if ((pktLen % me->fOutPacketSize) == 0) // If it was a multiple of max packet size then we need to do a zero length write 528 { 529 XTRACE(me, rc, pktLen, "dataWriteComplete - writing zero length packet"); 530// pipeOutBuff->pipeOutMDP->setLength(0); 531 pipeOutBuff->writeCompletionInfo.parameter = (void *)pipeOutBuff; 532// me->fOutPipe->Write(pipeOutBuff->pipeOutMDP, &pipeOutBuff->writeCompletionInfo); 533 me->fOutPipe->Write(pipeOutBuff->pipeOutMDP, 2000, 5000, 0, &pipeOutBuff->writeCompletionInfo); 534 } else { 535 pipeOutBuff->avail = true; 536 if (me->fTxStalled) 537 { 538 me->fTxStalled = false; 539 me->fTransmitQueue->service(IOBasicOutputQueue::kServiceAsync); 540 } 541 } 542 } else { 543 pipeOutBuff->avail = true; // Make the buffer available again 544 if (me->fTxStalled) 545 { 546 me->fTxStalled = false; 547 me->fTransmitQueue->service(IOBasicOutputQueue::kServiceAsync); 548 } 549 } 550 } else { 551 XTRACE(me, rc, pipeOutBuff->indx, "dataWriteComplete - IO err"); 552 553 if (pipeOutBuff->m != NULL) 554 { 555 me->freePacket(pipeOutBuff->m); // Free the mbuf anyway 556 pipeOutBuff->m = NULL; 557 } 558 559 pipeOutBuff->avail = true; 560 if (me->fTxStalled) 561 { 562 me->fTxStalled = false; 563 me->fTransmitQueue->service(IOBasicOutputQueue::kServiceAsync); 564 } 565 566 if (rc != kIOReturnAborted) 567 { 568 me->fDeferredClear = true; 569#if 0 570 rc = me->clearPipeStall(me->fOutPipe); 571 if (rc != kIOReturnSuccess) 572 { 573 XTRACE(me, 0, rc, "dataWriteComplete - clear stall failed (trying to continue)"); 574 } 575#endif 576 } 577 } 578 579 return; 580 581}/* end dataWriteComplete */ 582 583/****************************************************************************************************/ 584// 585// Method: AppleUSBCDCECMData::init 586// 587// Inputs: properties - data (keys and values) used to match 588// 589// Outputs: Return code - true (init successful), false (init failed) 590// 591// Desc: Initialize the driver. 592// 593/****************************************************************************************************/ 594 595bool AppleUSBCDCECMData::init(OSDictionary *properties) 596{ 597 UInt32 i; 598 599 XTRACE(this, 0, 0, "init"); 600 601 if (super::init(properties) == false) 602 { 603 XTRACE(this, 0, 0, "init - initialize super failed"); 604 return false; 605 } 606 607 fAltInterface = -1; 608 fTerminate = false; 609 fResetState = kResetNormal; 610 fSleeping = false; 611 fDeferredClear = false; 612 613 fLinkStatus = kLinkDown; 614 fUpSpeed = 10000000; // Set to 10 until we know better (bits/sec) 615 fDownSpeed = 10000000; // Same here 616 617 fQueueStarted = false; // State of the IO output queue 618 fTxStalled = false; 619 620 for (i=0; i<kMaxOutBufPool; i++) 621 { 622 fPipeOutBuff[i].pipeOutMDP = NULL; 623 fPipeOutBuff[i].pipeOutBuffer = NULL; 624 fPipeOutBuff[i].m = NULL; 625 fPipeOutBuff[i].avail = false; 626 fPipeOutBuff[i].writeCompletionInfo.target = NULL; 627 fPipeOutBuff[i].writeCompletionInfo.action = NULL; 628 fPipeOutBuff[i].writeCompletionInfo.parameter = NULL; 629 fPipeOutBuff[i].indx = i; 630 } 631 fOutPoolIndex = 0; 632 633 for (i=0; i<kMaxInBufPool; i++) 634 { 635 fPipeInBuff[i].pipeInMDP = NULL; 636 fPipeInBuff[i].pipeInBuffer = NULL; 637 fPipeInBuff[i].dead = false; 638 fPipeInBuff[i].readCompletionInfo.target = NULL; 639 fPipeInBuff[i].readCompletionInfo.action = NULL; 640 fPipeInBuff[i].readCompletionInfo.parameter = NULL; 641 fPipeInBuff[i].indx = i; 642 } 643 644 return true; 645 646}/* end init*/ 647 648/****************************************************************************************************/ 649// 650// Method: AppleUSBCDCECMData::probe 651// 652// Inputs: provider - my provider 653// 654// Outputs: IOService - from super::probe, score - probe score 655// 656// Desc: Modify the probe score if necessary (we don't at the moment) 657// 658/****************************************************************************************************/ 659 660IOService* AppleUSBCDCECMData::probe(IOService *provider, SInt32 *score) 661{ 662 IOService *res; 663 664 // If our IOUSBInterface has a "do not match" property, it means that we should not match and need 665 // to bail. See rdar://3716623 666 667 OSBoolean *boolObj = OSDynamicCast(OSBoolean, provider->getProperty("kDoNotClassMatchThisInterface")); 668 if (boolObj && boolObj->isTrue()) 669 { 670 XTRACE(this, 0, 0, "probe - provider doesn't want us to match"); 671 return NULL; 672 } 673 674 res = super::probe(provider, score); 675 676 return res; 677 678}/* end probe */ 679 680/****************************************************************************************************/ 681// 682// Method: AppleUSBCDCECMData::start 683// 684// Inputs: provider - my provider 685// 686// Outputs: Return code - true (it's me), false (sorry it probably was me, but I can't configure it) 687// 688// Desc: This is called once it has beed determined I'm probably the best 689// driver for this device. 690// 691/****************************************************************************************************/ 692 693bool AppleUSBCDCECMData::start(IOService *provider) 694{ 695 IOReturn ret = kIOReturnSuccess; 696 UInt16 devDriverCount = 0; 697 OSNumber *bufNumber = NULL; 698 OSBoolean *enumerateOnWake; 699 UInt16 bufValue = 0; 700 IOUSBDevice *usbDevice; 701 702 703 XTRACE(this, 0, 0, "start"); 704 705 // Get my USB provider - the interface 706 707 fDataInterface = OSDynamicCast(IOUSBInterface, provider); 708 if(!fDataInterface) 709 { 710 ALERT(0, 0, "start - provider invalid"); 711 return false; 712 } 713 714 fDataInterfaceNumber = fDataInterface->GetInterfaceNumber(); 715 716 // See if we can find/wait for the CDC driver 717 718 while (1) 719 { 720 ret = findCDCDriverED(fDataInterface->GetDevice(), this, fDataInterfaceNumber); 721 if (ret == kIOReturnSuccess) 722 { 723 XTRACE (this, 0, 0, "start: Found the CDC device driver"); 724 break; 725 } else { 726 if (ret == kIOReturnNotReady) 727 { 728 devDriverCount++; 729 XTRACE(this, devDriverCount, fDataInterfaceNumber, "start - Waiting for CDC device driver..."); 730 if (devDriverCount > 9) 731 { 732 break; 733 } 734 IOSleep(100); 735 } else { 736 break; 737 } 738 } 739 } 740 741 // If we didn't find him then we have to bail 742 743 if (ret != kIOReturnSuccess) 744 { 745 ALERT(0, fDataInterfaceNumber, "start - Find CDC driver for ECM data interface failed"); 746 return false; 747 } 748 749 // Now we can start for real 750 751 if(!super::start(provider)) 752 { 753 ALERT(0, 0, "start - start super failed"); 754 return false; 755 } 756 757 // get workloop - check it first as createOutputQueue is called very early 758 759 if (!fWorkLoop) 760 { 761 fWorkLoop = getWorkLoop(); 762 if (!fWorkLoop) 763 { 764 ALERT(0, 0, "start - getWorkLoop failed"); 765 return false; 766 } 767 } 768 769 if (!configureData()) 770 { 771 ALERT(0, 0, "start - configureData failed"); 772 return false; 773 } 774 775 // Check for an input buffer pool override first 776 777 fInBufPool = 0; 778 fOutBufPool = 0; 779 780 bufNumber = (OSNumber *)provider->getProperty(inputTag); 781 if (bufNumber) 782 { 783 bufValue = bufNumber->unsigned16BitValue(); 784 XTRACE(this, 0, bufValue, "start - Number of input buffers override value"); 785 if (bufValue <= kMaxInBufPool) 786 { 787 fInBufPool = bufValue; 788 } else { 789 fInBufPool = kMaxInBufPool; 790 } 791 } else { 792 fInBufPool = 0; 793 } 794 795 // Now set up the real input buffer pool values (only if not overridden) 796 797 if (fInBufPool == 0) 798 { 799 bufNumber = NULL; 800 bufNumber = (OSNumber *)getProperty(inputTag); 801 if (bufNumber) 802 { 803 bufValue = bufNumber->unsigned16BitValue(); 804 XTRACE(this, 0, bufValue, "start - Number of input buffers requested"); 805 if (bufValue <= kMaxInBufPool) 806 { 807 fInBufPool = bufValue; 808 } else { 809 fInBufPool = kMaxInBufPool; 810 } 811 } else { 812 fInBufPool = kInBufPool; 813 } 814 } 815 816 // Check for an output buffer pool override 817 818 bufNumber = NULL; 819 bufNumber = (OSNumber *)provider->getProperty(outputTag); 820 if (bufNumber) 821 { 822 bufValue = bufNumber->unsigned16BitValue(); 823 XTRACE(this, 0, bufValue, "start - Number of output buffers override value"); 824 if (bufValue <= kMaxOutBufPool) 825 { 826 fOutBufPool = bufValue; 827 } else { 828 fOutBufPool = kMaxOutBufPool; 829 } 830 } else { 831 fOutBufPool = 0; 832 } 833 834 // Now set up the real output buffer pool values (only if not overridden) 835 836 if (fOutBufPool == 0) 837 { 838 bufNumber = NULL; 839 bufNumber = (OSNumber *)getProperty(outputTag); 840 if (bufNumber) 841 { 842 bufValue = bufNumber->unsigned16BitValue(); 843 XTRACE(this, 0, bufValue, "start - Number of output buffers requested"); 844 if (bufValue <= kMaxOutBufPool) 845 { 846 fOutBufPool = bufValue; 847 } else { 848 fOutBufPool = kMaxOutBufPool; 849 } 850 } else { 851 fOutBufPool = kOutBufPool; 852 } 853 } 854 855 856 //Do not automatically re-enumerate CDC ECM devices on wake 857 fEnumOnWake = FALSE; 858 UInt16 myVID = fDataInterface->GetDevice()->GetVendorID(); 859 UInt16 myPID = fDataInterface->GetDevice()->GetProductID(); 860 861 char vendorString[20]; 862 char productString[20]; 863 snprintf(vendorString, sizeof(vendorString), "0x%X", myVID); 864 snprintf(productString, sizeof(productString), "0x%X", myPID); 865 866 cdc_LogToMessageTracer(CDC_ASL_DOMAIN, "AppleUSBCDCECMData", vendorString, productString, 0, 0); 867 868 XTRACE(this, fInBufPool, fOutBufPool, "start - Buffer pools (input, output)"); 869 870 if (findControlDriverED(this) != kIOReturnSuccess) 871 { 872 ALERT(0, 0, "start - Find control driver failed"); 873 } 874 875 if (!createNetworkInterface()) 876 { 877 ALERT(0, 0, "start - createNetworkInterface failed"); 878 return false; 879 } 880 881 // Looks like we're ok (being defensive here) 882 883 if (fDataInterface) 884 fDataInterface->retain(); 885 if (fWorkLoop) 886 fWorkLoop->retain(); 887 if (fTransmitQueue) 888 fTransmitQueue->retain(); 889 890 // Ready to service interface requests 891 892//rcs radar://10369195 We now registerService in createNetworkInterface 893// if (fNetworkInterface) 894// fNetworkInterface->registerService(); 895 896 XTRACE(this, 0, 0, "start - successful"); 897 Log(DEBUG_NAME ": Version number - %s, Input buffers %d, Output buffers %d\n", VersionNumber, fInBufPool, fOutBufPool); 898 899 return true; 900 901}/* end start */ 902 903/****************************************************************************************************/ 904// 905// Method: AppleUSBCDCECMData::stop 906// 907// Inputs: provider - my provider 908// 909// Outputs: 910// 911// Desc: Stops the driver 912// 913/****************************************************************************************************/ 914 915void AppleUSBCDCECMData::stop(IOService *provider) 916{ 917 918 XTRACE(this, 0, 0, "stop"); 919 920 fReady = false; 921 922 // Release all resources 923 924 releaseResources(); 925 926 if (fDataInterface) 927 { 928 fDataInterface->close(this); 929 fDataInterface->release(); 930 fDataInterface = NULL; 931 } 932 933 if (fNetworkInterface) 934 { 935 detachInterface(fNetworkInterface, FALSE); 936 937 fNetworkInterface->release(); 938 fNetworkInterface = NULL; 939 } 940 941 if (fMediumDict) 942 { 943 fMediumDict->release(); 944 fMediumDict = NULL; 945 } 946 947 if (fWorkLoop) 948 { 949 fWorkLoop->release(); 950 fWorkLoop = NULL; 951 } 952 953 if (fTransmitQueue) 954 { 955 fTransmitQueue->release(); 956 fTransmitQueue = NULL; 957 } 958 959 super::stop(provider); 960 961 return; 962 963}/* end stop */ 964 965/****************************************************************************************************/ 966// 967// Method: AppleUSBCDCECMData::configureData 968// 969// Inputs: 970// 971// Outputs: return code - true (configure was successful), false (it failed) 972// 973// Desc: Finishes up the rest of the configuration 974// 975/****************************************************************************************************/ 976 977bool AppleUSBCDCECMData::configureData() 978{ 979 IOUSBFindInterfaceRequest req; 980 const IOUSBInterfaceDescriptor *altInterfaceDesc; 981 IOReturn ior = kIOReturnSuccess; 982 UInt16 numends = 0; 983 UInt16 alt; 984 985 XTRACE(this, 0, 0, "configureData."); 986 987 if (!fDataInterface) 988 { 989 XTRACE(this, 0, 0, "configureData - Data interface is NULL"); 990 return false; 991 } 992 993 if (!fDataInterface->open(this)) 994 { 995 XTRACE(this, 0, 0, "configureData - open data interface failed"); 996 return false; 997 } 998 999 // Check we have the correct interface (there maybe an alternate) 1000 1001 numends = fDataInterface->GetNumEndpoints(); 1002 if (numends < 2) 1003 { 1004 req.bInterfaceClass = kUSBDataClass; 1005 req.bInterfaceSubClass = 0; 1006 req.bInterfaceProtocol = 0; 1007 req.bAlternateSetting = kIOUSBFindInterfaceDontCare; 1008 altInterfaceDesc = fDataInterface->FindNextAltInterface(NULL, &req); 1009 if (!altInterfaceDesc) 1010 { 1011 XTRACE(this, 0, 0, "configureData - FindNextAltInterface failed"); 1012 return false; 1013 } 1014 while (altInterfaceDesc) 1015 { 1016 numends = altInterfaceDesc->bNumEndpoints; 1017 if (numends > 1) 1018 { 1019 alt = altInterfaceDesc->bAlternateSetting; 1020 XTRACE(this, numends, alt, "configureData - Data Class interface (alternate) found"); 1021 ior = fDataInterface->SetAlternateInterface(this, alt); 1022 if (ior == kIOReturnSuccess) 1023 { 1024 fAltInterface = alt; 1025 XTRACE(this, 0, 0, "configureData - Alternate set"); 1026 break; 1027 } else { 1028 XTRACE(this, 0, 0, "configureData - SetAlternateInterface failed"); 1029 return false; 1030 } 1031 } else { 1032 XTRACEP(this, 0, altInterfaceDesc, "configureData - No endpoints this alternate"); 1033 } 1034 altInterfaceDesc = fDataInterface->FindNextAltInterface(altInterfaceDesc, &req); 1035 } 1036 } 1037 1038 if (numends < 2) 1039 { 1040 XTRACE(this, 0, 0, "configureData - Could not find the correct interface"); 1041 return false; 1042 } 1043 1044 return true; 1045 1046}/* end configureData */ 1047 1048/****************************************************************************************************/ 1049// 1050// Method: AppleUSBCDCECMData::createNetworkInterface 1051// 1052// Inputs: 1053// 1054// Outputs: return Code - true (created and initialilzed ok), false (it failed) 1055// 1056// Desc: Creates and initializes the network interface 1057// 1058/****************************************************************************************************/ 1059 1060bool AppleUSBCDCECMData::createNetworkInterface() 1061{ 1062 1063 XTRACE(this, 0, 0, "createNetworkInterface"); 1064 1065 // Allocate memory for transmit queue 1066 1067 fTransmitQueue = (IOGatedOutputQueue *)getOutputQueue(); 1068 if (!fTransmitQueue) 1069 { 1070 ALERT(0, 0, "createNetworkInterface - Output queue initialization failed"); 1071 return false; 1072 } 1073 1074 // Allocate Timer event source 1075 1076 fTimerSource = IOTimerEventSource::timerEventSource(this, timerFired); 1077 if (fTimerSource == NULL) 1078 { 1079 ALERT(0, 0, "createNetworkInterface - Allocate Timer event source failed"); 1080 return false; 1081 } 1082 1083 if (fWorkLoop) 1084 { 1085 if (fWorkLoop->addEventSource(fTimerSource) != kIOReturnSuccess) 1086 { 1087 ALERT(0, 0, "createNetworkInterface - Add Timer event source failed"); 1088 return false; 1089 } 1090 } 1091 1092 // Attach an IOEthernetInterface client 1093 1094 XTRACE(this, 0, 0, "createNetworkInterface - attaching and registering interface"); 1095 1096//rcs radar://10369195 attach interface and register at the same time.. 1097// if (!attachInterface((IONetworkInterface **)&fNetworkInterface, false)) 1098 if (!attachInterface((IONetworkInterface **)&fNetworkInterface)) 1099 { 1100 ALERT(0, 0, "createNetworkInterface - attachInterface failed"); 1101 return false; 1102 } 1103 1104 XTRACE(this, 0, 0, "createNetworkInterface - Exiting, successful"); 1105 1106 return true; 1107 1108}/* end createNetworkInterface */ 1109 1110/****************************************************************************************************/ 1111// 1112// Method: AppleUSBCDCECMData::enable 1113// 1114// Inputs: netif - the interface being enabled 1115// 1116// Outputs: Return code - kIOReturnSuccess or kIOReturnIOError 1117// 1118// Desc: Called by IOEthernetInterface client to enable the controller. 1119// This method is always called while running on the default workloop 1120// thread 1121// 1122/****************************************************************************************************/ 1123 1124IOReturn AppleUSBCDCECMData::enable(IONetworkInterface *netif) 1125{ 1126 IOReturn ior = kIOReturnSuccess; 1127 1128 XTRACEP(this, 0, netif, "enable"); 1129 1130 IOSleep(5); // Just in case (to let start finish - on another thread) 1131 1132 // If an interface client has previously enabled us, 1133 // and we know there can only be one interface client 1134 // for this driver, then simply return success. 1135 1136 if (fNetifEnabled) 1137 { 1138 XTRACE(this, 0, 0, "enable - already enabled"); 1139 return kIOReturnSuccess; 1140 } 1141 1142 if (!fControlDriver) 1143 { 1144 if (findControlDriverED(this) != kIOReturnSuccess) 1145 { 1146 ALERT(0, 0, "enable - Find control driver failed"); 1147 return kIOReturnIOError; 1148 } 1149 } 1150 1151 if (!fReady) 1152 { 1153 if (!wakeUp()) 1154 { 1155 XTRACE(this, 0, fReady, "enable - wakeUp failed"); 1156 return kIOReturnIOError; 1157 } 1158 } 1159 1160 if (!fControlDriver->dataAcquired(fpNetStats, fpEtherStats)) 1161 { 1162 XTRACE(this, 0, 0, "enable - dataAcquired to Control failed"); 1163 return kIOReturnIOError; 1164 } 1165 1166 // Mark the controller as enabled by the interface. 1167 1168 setLinkStatusDown(); 1169 1170 1171 fNetifEnabled = true; 1172 1173 fControlDriver->USBSetPacketFilter(); 1174 XTRACE(this, 0, fControlDriver->fPacketFilter, "enable - packet filter applied+"); 1175 1176 return ior; 1177 1178}/* end enable */ 1179 1180/****************************************************************************************************/ 1181// 1182// Method: AppleUSBCDCECMData::disable 1183// 1184// Inputs: netif - the interface being disabled 1185// 1186// Outputs: Return code - kIOReturnSuccess 1187// 1188// Desc: Called by IOEthernetInterface client to disable the controller. 1189// This method is always called while running on the default workloop 1190// thread 1191// 1192/****************************************************************************************************/ 1193 1194IOReturn AppleUSBCDCECMData::disable(IONetworkInterface *netif) 1195{ 1196 UInt16 packetFilter; 1197 bool result; 1198 IOReturn err; 1199 1200 1201 XTRACE(this, 0, 0, "AppleUSBCDCECMData::disable"); 1202 1203 putToSleep(); 1204 1205 fNetifEnabled = false; 1206 fReady = false; 1207 1208 // Tell the Control driver the port's been disabled 1209 // If reset state's not normal then he already knows 1210 1211 if (fResetState == kResetNormal) 1212 { 1213 if (fControlDriver) 1214 { 1215 packetFilter = fControlDriver->fPacketFilter; //save the packet filter setting 1216 1217 fControlDriver->fPacketFilter = kPACKET_TYPE_DISABLED; //Per Realtech SetPacketFilter (0) 1218 result = fControlDriver->USBSetPacketFilter(); 1219 fControlDriver->dataReleased(); 1220 XTRACE(this, 0, result, "AppleUSBCDCECMData::disable USBSetPacketFilter"); 1221 1222 fControlDriver->fPacketFilter = packetFilter; 1223 } 1224 } 1225 1226// fDataInterface->GetDevice()->ReEnumerateDevice(0); 1227 1228 err = fDataInterface->SetAlternateInterface (this, kResetNormal); //Per Realtech set Alternate Interface setting 0 1229 1230 XTRACE(this, err, kResetNormal, "AppleUSBCDCECMData::disable -- SetAlternateInterface <<<"); 1231 1232 fDataInterface->GetDevice()->SuspendDevice(true); 1233 1234 XTRACE(this, 0, true, "AppleUSBCDCECMData::disable -- SuspendDevice <<<"); 1235 1236 1237 return kIOReturnSuccess; 1238 1239}/* end disable */ 1240 1241/****************************************************************************************************/ 1242// 1243// Method: AppleUSBCDCECMData::setWakeOnMagicPacket 1244// 1245// Inputs: active - true(wake), false(don't) 1246// 1247// Outputs: Return code - kIOReturnSuccess 1248// 1249// Desc: Set for wake on magic packet 1250// 1251/****************************************************************************************************/ 1252 1253IOReturn AppleUSBCDCECMData::setWakeOnMagicPacket(bool active) 1254{ 1255 IOUSBDevRequest devreq; 1256 IOReturn ior = kIOReturnSuccess; 1257 1258 XTRACE(this, 0, active, "setWakeOnMagicPacket"); 1259 1260 fWOL = active; 1261 1262 if (fConfigAttributes & kUSBAtrRemoteWakeup) 1263 { 1264 1265 // Set/Clear the Device Remote Wake feature depending upon the active flag 1266 1267 devreq.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBStandard, kUSBDevice); 1268 if (active) 1269 { 1270 devreq.bRequest = kUSBRqSetFeature; 1271 } else { 1272 devreq.bRequest = kUSBRqClearFeature; 1273 } 1274 devreq.wValue = kUSBFeatureDeviceRemoteWakeup; 1275 devreq.wIndex = 0; 1276 devreq.wLength = 0; 1277 devreq.pData = 0; 1278 1279 ior = fDataInterface->GetDevice()->DeviceRequest(&devreq); 1280 if (ior == kIOReturnSuccess) 1281 { 1282 XTRACE(this, 0, ior, "setWakeOnMagicPacket - Set/Clear remote wake up feature successful"); 1283 } else { 1284 XTRACE(this, 0, ior, "setWakeOnMagicPacket - Set/Clear remote wake up feature failed"); 1285 } 1286 } else { 1287 XTRACE(this, 0, 0, "setWakeOnMagicPacket - Remote wake up not supported"); 1288 } 1289 1290 1291 return kIOReturnSuccess; 1292 1293}/* end setWakeOnMagicPacket */ 1294 1295/****************************************************************************************************/ 1296// 1297// Method: AppleUSBCDCECMData::getPacketFilters 1298// 1299// Inputs: group - the filter group 1300// 1301// Outputs: Return code - kIOReturnSuccess and others 1302// filters - the capability 1303// 1304// Desc: Set the filter capability for the driver 1305// 1306/****************************************************************************************************/ 1307 1308IOReturn AppleUSBCDCECMData::getPacketFilters(const OSSymbol *group, UInt32 *filters) const 1309{ 1310 IOReturn rtn = kIOReturnSuccess; 1311 1312 XTRACEP(this, group, filters, "getPacketFilters"); 1313 1314 if (group == gIOEthernetWakeOnLANFilterGroup) 1315 { 1316 if (fConfigAttributes & kUSBAtrRemoteWakeup) 1317 { 1318 *filters = kIOEthernetWakeOnMagicPacket; 1319 } else { 1320 *filters = 0; 1321 } 1322 } else { 1323 if (group == gIONetworkFilterGroup) 1324 { 1325 *filters = kIOPacketFilterUnicast | kIOPacketFilterBroadcast | kIOPacketFilterMulticast | kIOPacketFilterMulticastAll | kIOPacketFilterPromiscuous; 1326 } else { 1327 rtn = super::getPacketFilters(group, filters); 1328 } 1329 } 1330 1331 if (rtn != kIOReturnSuccess) 1332 { 1333 XTRACE(this, 0, rtn, "getPacketFilters - failed"); 1334 } 1335 1336 return rtn; 1337 1338}/* end getPacketFilters */ 1339 1340/****************************************************************************************************/ 1341// 1342// Method: AppleUSBCDCECMData::getMaxPacketSize 1343// 1344// Inputs: 1345// 1346// Outputs: Return code - kIOReturnSuccess or kIOReturnIOError 1347// maxSize - the max size we currently support 1348// 1349// Desc: Set the max size from the descriptors of this device 1350// 1351/****************************************************************************************************/ 1352 1353IOReturn AppleUSBCDCECMData::getMaxPacketSize(UInt32 *maxSize) const 1354{ 1355 IOReturn rtn = kIOReturnSuccess; 1356 1357 XTRACE(this, 0, 0, "getMaxPacketSize"); 1358 1359 if (fControlDriver) 1360 { 1361 XTRACE(this, 0, fControlDriver->fMax_Block_Size, "getMaxPacketSize - Setting max size"); 1362 //The CDC Spec for fMax_Block_Size does not include the length of the CRC 1363 //IOEthernetController expects the CRC length to be included in the transfer size 1364 *maxSize = fControlDriver->fMax_Block_Size + kIOEthernetCRCSize; //JRW <rdar://problem/14756797> 1365 } else { 1366 rtn = kIOReturnIOError; // If we don't have a control driver by now we're in trouble... 1367 XTRACE(this, 0, 0, "getMaxPacketSize - No control driver???"); 1368 } 1369 1370 return rtn; 1371 1372}/* end getMaxPacketSize */ 1373 1374/****************************************************************************************************/ 1375// 1376// Method: AppleUSBCDCECMData::selectMedium 1377// 1378// Inputs: 1379// 1380// Outputs: 1381// 1382// Desc: Lets us know if someone is playing with ifconfig 1383// 1384/****************************************************************************************************/ 1385 1386IOReturn AppleUSBCDCECMData::selectMedium(const IONetworkMedium *medium) 1387{ 1388 IOMediumType mType; 1389 1390 XTRACE(this, 0, 0, "selectMedium"); 1391 1392 if (fTerminate) 1393 { 1394 XTRACE(this, 0, 0, "selectMedium - Device unplugged"); 1395 return kIOReturnIOError; 1396 } 1397 1398 if (!medium) 1399 { 1400 XTRACE(this, 0, 0, "selectMedium - No medium defined"); 1401 return kIOReturnError; 1402 } 1403 1404 mType = medium->getType(); 1405 XTRACE(this, 0, mType, "selectMedium - Type"); 1406 1407 if ((mType & kIOMediumNetworkTypeMask) != kIOMediumEthernet) 1408 { 1409 XTRACE(this, 0, 0, "selectMedium - Not ethernet medium"); 1410 return kIOReturnBadArgument; 1411 } 1412 1413 // Check the type (auto and none is really all we can accept) 1414 1415 switch (mType & (kIOMediumNetworkTypeMask | kIOMediumSubTypeMask)) 1416 { 1417 case kIOMediumEthernetNone: 1418 XTRACE(this, 0, 0, "selectMedium - None, link going down"); 1419 setSelectedMedium(medium); 1420 linkStatusChange(kLinkDown); 1421 1422 break; 1423 case kIOMediumEthernetAuto: 1424 XTRACE(this, 0, 0, "selectMedium - Auto, link going up"); 1425 setSelectedMedium(medium); 1426 linkStatusChange(kLinkUp); 1427 1428 break; 1429 default: 1430 XTRACE(this, 0, 0, "selectMedium - Unsupported"); 1431 return kIOReturnUnsupported; 1432 } 1433 1434 return kIOReturnSuccess; 1435 1436}/* end selectMedium */ 1437 1438/****************************************************************************************************/ 1439// 1440// Method: AppleUSBCDCECMData::getHardwareAddress 1441// 1442// Inputs: 1443// 1444// Outputs: Return code - kIOReturnSuccess or kIOReturnError 1445// ea - the address 1446// 1447// Desc: Get the ethernet address from the hardware (actually the descriptor) 1448// 1449/****************************************************************************************************/ 1450 1451IOReturn AppleUSBCDCECMData::getHardwareAddress(IOEthernetAddress *ea) 1452{ 1453 UInt32 i; 1454 1455 XTRACE(this, 0, 0, "getHardwareAddress"); 1456 1457 if (fControlDriver) 1458 { 1459 for (i=0; i<6; i++) 1460 { 1461 ea->bytes[i] = fControlDriver->fEaddr[i]; 1462 } 1463 } else { // Use cached address 1464 for (i=0; i<6; i++) 1465 { 1466 ea->bytes[i] = fEthernetaddr[i]; 1467 } 1468 } 1469 1470 return kIOReturnSuccess; 1471 1472}/* end getHardwareAddress */ 1473 1474/****************************************************************************************************/ 1475// 1476// Method: AppleUSBCDCECMData::newVendorString 1477// 1478// Inputs: 1479// 1480// Outputs: Return code - the vendor string 1481// 1482// Desc: Identifies the hardware vendor 1483// 1484/****************************************************************************************************/ 1485 1486const OSString* AppleUSBCDCECMData::newVendorString() const 1487{ 1488 1489 XTRACE(this, 0, 0, "newVendorString"); 1490 1491 return OSString::withCString((const char *)defaultName); // Maybe we should use the descriptors 1492 1493}/* end newVendorString */ 1494 1495/****************************************************************************************************/ 1496// 1497// Method: AppleUSBCDCECMData::newModelString 1498// 1499// Inputs: 1500// 1501// Outputs: Return code - the model string 1502// 1503// Desc: Identifies the hardware model 1504// 1505/****************************************************************************************************/ 1506 1507const OSString* AppleUSBCDCECMData::newModelString() const 1508{ 1509 1510 XTRACE(this, 0, 0, "newModelString"); 1511 1512 return OSString::withCString("USB"); // Maybe we should use the descriptors 1513 1514}/* end newModelString */ 1515 1516/****************************************************************************************************/ 1517// 1518// Method: AppleUSBCDCECMData::newRevisionString 1519// 1520// Inputs: 1521// 1522// Outputs: Return code - the revision string 1523// 1524// Desc: Identifies the hardware revision 1525// 1526/****************************************************************************************************/ 1527 1528const OSString* AppleUSBCDCECMData::newRevisionString() const 1529{ 1530 1531 XTRACE(this, 0, 0, "newRevisionString"); 1532 1533 return OSString::withCString(""); 1534 1535}/* end newRevisionString */ 1536 1537/****************************************************************************************************/ 1538// 1539// Method: AppleUSBCDCECMData::setMulticastMode 1540// 1541// Inputs: active - true (set it), false (don't) 1542// 1543// Outputs: Return code - kIOReturnSuccess 1544// 1545// Desc: Sets multicast mode 1546// 1547/****************************************************************************************************/ 1548 1549IOReturn AppleUSBCDCECMData::setMulticastMode(IOEnetMulticastMode active) 1550{ 1551 1552 XTRACE(this, 0, active, "setMulticastMode"); 1553 1554 if (!fReady) 1555 { 1556 return kIOReturnSuccess; 1557 } 1558 1559 if (fControlDriver) 1560 { 1561 if (active) 1562 { 1563 fControlDriver->fPacketFilter |= kPACKET_TYPE_MULTICAST; 1564 } else { 1565 fControlDriver->fPacketFilter &= ~kPACKET_TYPE_MULTICAST; 1566 } 1567 1568 fControlDriver->USBSetPacketFilter(); 1569 1570 return kIOReturnSuccess; 1571 } 1572 1573 return kIOReturnIOError; 1574 1575}/* end setMulticastMode */ 1576 1577/****************************************************************************************************/ 1578// 1579// Method: AppleUSBCDCECMData::setMulticastList 1580// 1581// Inputs: addrs - list of addresses 1582// count - number in the list 1583// 1584// Outputs: Return code - kIOReturnSuccess or kIOReturnIOError 1585// 1586// Desc: Sets multicast list 1587// 1588/****************************************************************************************************/ 1589 1590IOReturn AppleUSBCDCECMData::setMulticastList(IOEthernetAddress *addrs, UInt32 count) 1591{ 1592 bool uStat; 1593 1594 XTRACE(this, 0, count, "setMulticastList"); 1595 1596 if (!fReady) 1597 { 1598 return kIOReturnSuccess; 1599 } 1600 1601 if (fControlDriver) 1602 { 1603 1604 if (count > fControlDriver->fMcFilters) 1605 { 1606 fControlDriver->fPacketFilter |= kPACKET_TYPE_ALL_MULTICAST; 1607 } 1608 else 1609 { 1610 fControlDriver->fPacketFilter &= ~kPACKET_TYPE_ALL_MULTICAST; 1611 1612 } 1613 1614 fControlDriver->USBSetPacketFilter(); 1615 1616 uStat = fControlDriver->USBSetMulticastFilter(addrs, count); 1617 if (!uStat) 1618 { 1619 return kIOReturnIOError; 1620 } 1621 1622 return kIOReturnSuccess; 1623 } 1624 1625 return kIOReturnIOError; 1626 1627}/* end setMulticastList */ 1628 1629/****************************************************************************************************/ 1630// 1631// Method: AppleUSBCDCECMData::setPromiscuousMode 1632// 1633// Inputs: active - true (set it), false (don't) 1634// 1635// Outputs: Return code - kIOReturnSuccess 1636// 1637// Desc: Sets promiscuous mode 1638// 1639/****************************************************************************************************/ 1640 1641IOReturn AppleUSBCDCECMData::setPromiscuousMode(IOEnetPromiscuousMode active) 1642{ 1643 1644 XTRACE(this, 0, active, "setPromiscuousMode"); 1645 1646 if (!fReady) 1647 { 1648 return kIOReturnSuccess; 1649 } 1650 1651 if (fControlDriver) 1652 { 1653 if (active) 1654 { 1655 fControlDriver->fPacketFilter |= kPACKET_TYPE_PROMISCUOUS; 1656 } else { 1657 fControlDriver->fPacketFilter &= ~kPACKET_TYPE_PROMISCUOUS; 1658 } 1659 1660 fControlDriver->USBSetPacketFilter(); 1661 1662 return kIOReturnSuccess; 1663 } 1664 1665 return kIOReturnIOError; 1666 1667}/* end setPromiscuousMode */ 1668 1669/****************************************************************************************************/ 1670// 1671// Method: AppleUSBCDCECMData::createOutputQueue 1672// 1673// Inputs: 1674// 1675// Outputs: Return code - the output queue 1676// 1677// Desc: Creates the output queue 1678// 1679/****************************************************************************************************/ 1680 1681IOOutputQueue* AppleUSBCDCECMData::createOutputQueue() 1682{ 1683 1684 XTRACE(this, 0, 0, "createOutputQueue"); 1685 1686 if (!fWorkLoop) 1687 { 1688 fWorkLoop = getWorkLoop(); 1689 if (!fWorkLoop) 1690 { 1691 ALERT(0, 0, "createOutputQueue - getWorkLoop failed"); 1692 return NULL; 1693 } 1694 } 1695 1696 return IOGatedOutputQueue::withTarget(this, fWorkLoop, TRANSMIT_QUEUE_SIZE); 1697 1698}/* end createOutputQueue */ 1699 1700/****************************************************************************************************/ 1701// 1702// Method: AppleUSBCDCECMData::outputPacket 1703// 1704// Inputs: mbuf - the packet 1705// param - optional parameter 1706// 1707// Outputs: Return code - kIOReturnOutputSuccess or kIOReturnOutputStall 1708// 1709// Desc: Packet transmission. The BSD mbuf needs to be formatted correctly 1710// and transmitted 1711// 1712/****************************************************************************************************/ 1713 1714UInt32 AppleUSBCDCECMData::outputPacket(mbuf_t pkt, void *param) 1715{ 1716 UInt32 ior = kIOReturnSuccess; 1717 1718 XTRACEP(this, pkt, 0, "outputPacket"); 1719 1720 if (!fControlDriver) 1721 { 1722 XTRACE(this, 0, 0, "outputPacket - Control driver has gone"); 1723 freePacket(pkt); 1724 return kIOReturnOutputDropped; 1725 } 1726 1727 if (fLinkStatus == kLinkDown) 1728 { 1729 XTRACEP(this, pkt, 0, "outputPacket - link is down"); 1730 if (fControlDriver->fOutputErrsOK) 1731 fpNetStats->outputErrors++; 1732 freePacket(pkt); 1733 return kIOReturnOutputDropped; 1734 } 1735 1736 if (fResetState != kResetNormal) 1737 { 1738 XTRACEP(this, pkt, 0, "outputPacket - deferred reset"); 1739 if (fControlDriver->fOutputErrsOK) 1740 fpNetStats->outputErrors++; 1741 freePacket(pkt); 1742 if (fResetState == kResetNeeded) 1743 { 1744 fResetState = kResetDone; 1745 fDataInterface->GetDevice()->ReEnumerateDevice(0); 1746 } 1747 return kIOReturnOutputDropped; 1748 } 1749 1750 ior = USBTransmitPacket(pkt); 1751 if (ior != kIOReturnSuccess) 1752 { 1753 if (ior == kIOReturnOutputStall) 1754 { 1755 fTxStalled = true; 1756 } else { 1757 freePacket(pkt); 1758 ior = kIOReturnOutputDropped; 1759 } 1760 } 1761 1762 return ior; 1763 1764}/* end outputPacket */ 1765 1766/****************************************************************************************************/ 1767// 1768// Method: AppleUSBCDCECMData::configureInterface 1769// 1770// Inputs: netif - the interface being configured 1771// 1772// Outputs: Return code - true (configured ok), false (not) 1773// 1774// Desc: Finish the network interface configuration 1775// 1776/****************************************************************************************************/ 1777 1778bool AppleUSBCDCECMData::configureInterface(IONetworkInterface *netif) 1779{ 1780 IONetworkData *nd; 1781 1782 XTRACEP(this, IOThreadSelf(), netif, "configureInterface"); 1783 1784 if (super::configureInterface(netif) == false) 1785 { 1786 ALERT(0, 0, "configureInterface - super failed"); 1787 return false; 1788 } 1789 1790 // Get a pointer to the statistics structure in the interface 1791 1792 nd = netif->getNetworkData(kIONetworkStatsKey); 1793 if (!nd || !(fpNetStats = (IONetworkStats *)nd->getBuffer())) 1794 { 1795 ALERT(0, 0, "configureInterface - Invalid network statistics"); 1796 return false; 1797 } 1798 1799 // Get the Ethernet statistics structure 1800 1801 nd = netif->getParameter(kIOEthernetStatsKey); 1802 if (!nd || !(fpEtherStats = (IOEthernetStats*)nd->getBuffer())) 1803 { 1804 ALERT(0, 0, "configureInterface - Invalid ethernet statistics\n"); 1805 return false; 1806 } 1807 1808 return true; 1809 1810}/* end configureInterface */ 1811 1812/****************************************************************************************************/ 1813// 1814// Method: AppleUSBCDCECMData::wakeUp 1815// 1816// Inputs: 1817// 1818// Outputs: Return Code - true(we're awake), false(failed) 1819// 1820// Desc: Resumes the device it it was suspended and then gets all the data 1821// structures sorted out and all the pipes ready. 1822// 1823/****************************************************************************************************/ 1824 1825bool AppleUSBCDCECMData::wakeUp() 1826{ 1827 IOReturn rtn = kIOReturnSuccess; 1828 UInt32 i; 1829 bool readOK = false; 1830 1831 XTRACE(this, 0, 0, "wakeUp"); 1832 1833 if (fEnumOnWake) 1834 { 1835 if ((fSleeping) && (fDataInterface)) 1836 { 1837 fDataInterface->GetDevice()->ReEnumerateDevice(0); 1838 return false; 1839 } 1840 } 1841 1842 fDataInterface->GetDevice()->SuspendDevice(false); 1843 1844 fReady = false; 1845 1846 if (fTimerSource) 1847 { 1848 fTimerSource->cancelTimeout(); 1849 } 1850 1851 if (!allocateResources()) 1852 { 1853 ALERT(0, 0, "wakeUp - allocateResources failed"); 1854 return false; 1855 } 1856 1857 // Kick off the data-in bulk pipe reads 1858 1859 for (i=0; i<fInBufPool; i++) 1860 { 1861 if (fPipeInBuff[i].pipeInMDP) 1862 { 1863// fPipeInBuff[i].readCompletionInfo.parameter = (void *)i; 1864 fPipeInBuff[i].readCompletionInfo.parameter = (void *)&fPipeInBuff[i]; 1865 rtn = fInPipe->Read(fPipeInBuff[i].pipeInMDP, &fPipeInBuff[i].readCompletionInfo, NULL); 1866 if (rtn == kIOReturnSuccess) 1867 { 1868 readOK = true; 1869 } else { 1870 XTRACE(this, i, rtn, "wakeUp - Read failed"); 1871 } 1872 } 1873 } 1874 1875 if (!readOK) 1876 { 1877 1878 // We failed for some reason 1879 1880 ALERT(0, 0, "wakeUp - Starting the input pipe read(s) failed"); 1881 return false; 1882 } else { 1883 if (!fMediumDict) 1884 { 1885 if (!createMediumTables()) 1886 { 1887 ALERT(0, 0, "wakeUp - createMediumTables failed"); 1888 return false; 1889 } 1890 } 1891 1892 if (fTimerSource) 1893 { 1894 fTimerSource->setTimeoutMS(WATCHDOG_TIMER_MS); 1895 } 1896 fReady = true; 1897 } 1898 1899 fSleeping = false; 1900 1901 return true; 1902 1903}/* end wakeUp */ 1904 1905/****************************************************************************************************/ 1906// 1907// Method: AppleUSBCDCECMData::putToSleep 1908// 1909// Inputs: 1910// 1911// Outputs: Return Code - true(we're asleep), false(failed) 1912// 1913// Desc: Do clean up and suspend the device. 1914// 1915/****************************************************************************************************/ 1916 1917void AppleUSBCDCECMData::putToSleep() 1918{ 1919 XTRACE(this, 0, 0, "putToSleep >>>"); 1920 1921 if ( (!fReady) || (fTerminate == true)) // We've been here before... 1922 { 1923 return; 1924 } 1925 1926 fReady = false; 1927 1928 // Abort any outstanding I/O 1929 1930 if (fInPipe) 1931 fInPipe->Abort(); 1932 if (fOutPipe) 1933 fOutPipe->Abort(); 1934 1935 if (fTimerSource) 1936 { 1937 fTimerSource->cancelTimeout(); 1938 } 1939 1940 releaseResources(); 1941 linkStatusChange(kLinkDown); 1942 fSleeping = true; 1943 1944}/* end putToSleep */ 1945 1946/****************************************************************************************************/ 1947// 1948// Method: AppleUSBCDCECMData::createMediumTables 1949// 1950// Inputs: 1951// 1952// Outputs: Return code - true (tables created), false (not created) 1953// 1954// Desc: Creates the medium tables 1955// 1956/****************************************************************************************************/ 1957 1958bool AppleUSBCDCECMData::createMediumTables() 1959{ 1960 IONetworkMedium *medium; 1961 UInt64 maxSpeed; 1962 UInt32 i; 1963 1964 XTRACE(this, 0, 0, "createMediumTables"); 1965 1966 maxSpeed = 1000; 1967 fMediumDict = OSDictionary::withCapacity(sizeof(mediumTable) / sizeof(mediumTable[0])); 1968 if (fMediumDict == 0) 1969 { 1970 XTRACE(this, 0, 0, "createMediumTables - create dict. failed"); 1971 return false; 1972 } 1973 1974 for (i = 0; i < sizeof(mediumTable) / sizeof(mediumTable[0]); i++) 1975 { 1976 medium = IONetworkMedium::medium(mediumTable[i].type, mediumTable[i].speed); 1977 if (medium && (medium->getSpeed() <= maxSpeed)) 1978 { 1979 IONetworkMedium::addMedium(fMediumDict, medium); 1980 medium->release(); 1981 } 1982 } 1983 1984 if (publishMediumDictionary(fMediumDict) != true) 1985 { 1986 XTRACE(this, 0, 0, "createMediumTables - publish dict. failed"); 1987 return false; 1988 } 1989 1990 medium = IONetworkMedium::getMediumWithType(fMediumDict, kIOMediumEthernetAuto); 1991 setCurrentMedium(medium); 1992 1993 return true; 1994 1995}/* end createMediumTables */ 1996 1997/****************************************************************************************************/ 1998// 1999// Method: AppleUSBCDCECMData::allocateResources 2000// 2001// Inputs: 2002// 2003// Outputs: return code - true (allocate was successful), false (it failed) 2004// 2005// Desc: Gets all the endpoints open and buffers allocated etc. 2006// 2007/****************************************************************************************************/ 2008 2009bool AppleUSBCDCECMData::allocateResources() 2010{ 2011 IOUSBFindEndpointRequest epReq; 2012 UInt32 i; 2013 2014 XTRACE(this, 0, 0, "allocateResources."); 2015 2016 // Check things are still around (waking from sleep) 2017 2018 if (!fDataInterface) 2019 { 2020 XTRACE(this, 0, 0, "allocateResources - No data interface"); 2021 return false; 2022 } 2023 2024 if (!fControlDriver) 2025 { 2026 XTRACE(this, 0, 0, "allocateResources - No control driver"); 2027 return false; 2028 } 2029 2030 // Open all the end points 2031 2032 epReq.type = kUSBBulk; 2033 epReq.direction = kUSBIn; 2034 epReq.maxPacketSize = 0; 2035 epReq.interval = 0; 2036 fInPipe = fDataInterface->FindNextPipe(0, &epReq); 2037 if (!fInPipe) 2038 { 2039 XTRACE(this, 0, 0, "allocateResources - no bulk input pipe."); 2040 return false; 2041 } 2042 XTRACE(this, epReq.maxPacketSize << 16 |epReq.interval, 0, "allocateResources - bulk input pipe."); 2043 2044 epReq.direction = kUSBOut; 2045 fOutPipe = fDataInterface->FindNextPipe(0, &epReq); 2046 if (!fOutPipe) 2047 { 2048 XTRACE(this, 0, 0, "allocateResources - no bulk output pipe."); 2049 return false; 2050 } 2051 fOutPacketSize = epReq.maxPacketSize; 2052 XTRACE(this, epReq.maxPacketSize << 16 |epReq.interval, 0, "allocateResources - bulk output pipe."); 2053 2054 // Allocate Memory Descriptor Pointer with memory for the data-in bulk pipe 2055 2056 for (i=0; i<fInBufPool; i++) 2057 { 2058// fPipeInBuff[i].pipeInMDP = IOBufferMemoryDescriptor::withCapacity(fControlDriver->fMax_Block_Size, kIODirectionIn); 2059 fPipeInBuff[i].pipeInMDP = IOBufferMemoryDescriptor::withOptions(kIODirectionIn | kIOMemoryPhysicallyContiguous, fControlDriver->fMax_Block_Size, PAGE_SIZE); 2060 if (!fPipeInBuff[i].pipeInMDP) 2061 { 2062 XTRACE(this, 0, i, "allocateResources - Allocate input descriptor failed"); 2063 return false; 2064 } 2065 2066 fPipeInBuff[i].pipeInMDP->setLength(fControlDriver->fMax_Block_Size); 2067 fPipeInBuff[i].pipeInBuffer = (UInt8*)fPipeInBuff[i].pipeInMDP->getBytesNoCopy(); 2068 XTRACEP(this, fPipeInBuff[i].pipeInMDP, fPipeInBuff[i].pipeInBuffer, "allocateResources - input buffer"); 2069 fPipeInBuff[i].dead = false; 2070 fPipeInBuff[i].readCompletionInfo.target = this; 2071 fPipeInBuff[i].readCompletionInfo.action = dataReadComplete; 2072 fPipeInBuff[i].readCompletionInfo.parameter = NULL; 2073 } 2074 2075 // Allocate Memory Descriptor Pointers with memory for the data-out bulk pipe pool 2076 2077 for (i=0; i<fOutBufPool; i++) 2078 { 2079// fPipeOutBuff[i].pipeOutMDP = IOBufferMemoryDescriptor::withCapacity(fControlDriver->fMax_Block_Size, kIODirectionOut); 2080 fPipeOutBuff[i].pipeOutMDP = IOBufferMemoryDescriptor::withOptions(kIODirectionOut | kIOMemoryPhysicallyContiguous, fControlDriver->fMax_Block_Size, PAGE_SIZE); 2081 if (!fPipeOutBuff[i].pipeOutMDP) 2082 { 2083 XTRACE(this, 0, i, "allocateResources - Allocate output descriptor failed"); 2084 return false; 2085 } 2086 2087 fPipeOutBuff[i].pipeOutMDP->setLength(fControlDriver->fMax_Block_Size); 2088 fPipeOutBuff[i].pipeOutBuffer = (UInt8*)fPipeOutBuff[i].pipeOutMDP->getBytesNoCopy(); 2089 XTRACEP(this, fPipeOutBuff[i].pipeOutMDP, fPipeOutBuff[i].pipeOutBuffer, "allocateResources - output buffer"); 2090 fPipeOutBuff[i].avail = true; 2091 fPipeOutBuff[i].writeCompletionInfo.target = this; 2092 fPipeOutBuff[i].writeCompletionInfo.action = dataWriteComplete; 2093 fPipeOutBuff[i].writeCompletionInfo.parameter = NULL; // for now, filled in with pool index when sent 2094 } 2095 2096 return true; 2097 2098}/* end allocateResources */ 2099 2100/****************************************************************************************************/ 2101// 2102// Method: AppleUSBCDCECMData::releaseResources 2103// 2104// Inputs: 2105// 2106// Outputs: 2107// 2108// Desc: Frees up the resources allocated in allocateResources 2109// 2110/****************************************************************************************************/ 2111 2112void AppleUSBCDCECMData::releaseResources() 2113{ 2114 UInt32 i; 2115 2116 XTRACE(this, 0, 0, "releaseResources"); 2117 2118 for (i=0; i<fOutBufPool; i++) 2119 { 2120 if (fPipeOutBuff[i].pipeOutMDP) 2121 { 2122 fPipeOutBuff[i].pipeOutMDP->release(); 2123 fPipeOutBuff[i].pipeOutMDP = NULL; 2124 fPipeOutBuff[i].avail = false; 2125 fPipeOutBuff[i].writeCompletionInfo.target = NULL; 2126 fPipeOutBuff[i].writeCompletionInfo.action = NULL; 2127 fPipeOutBuff[i].writeCompletionInfo.parameter = NULL; 2128 } 2129 } 2130 fOutPoolIndex = 0; 2131 2132 for (i=0; i<fInBufPool; i++) 2133 { 2134 if (fPipeInBuff[i].pipeInMDP) 2135 { 2136 fPipeInBuff[i].pipeInMDP->release(); 2137 fPipeInBuff[i].pipeInMDP = NULL; 2138 fPipeInBuff[i].dead = false; 2139 fPipeInBuff[i].readCompletionInfo.target = NULL; 2140 fPipeInBuff[i].readCompletionInfo.action = NULL; 2141 fPipeInBuff[i].readCompletionInfo.parameter = NULL; 2142 } 2143 } 2144 2145}/* end releaseResources */ 2146 2147/****************************************************************************************************/ 2148// 2149// Method: AppleUSBCDCECMData::getOutputBuffer 2150// 2151// Inputs: bufIndx - index of an available buffer 2152// 2153// Outputs: Return code - True (got one), False (none available) 2154// 2155// Desc: Get an available buffer from the output buffer pool 2156// 2157/****************************************************************************************************/ 2158 2159bool AppleUSBCDCECMData::getOutputBuffer(UInt32 *bufIndx) 2160{ 2161 bool gotBuffer = false; 2162 UInt32 indx = 0; 2163 2164 XTRACE(this, 0, 0, "getOutputBuffer"); 2165 2166 // Get an ouput buffer (use the hint first then if that's not available look for one and then create one...) 2167 2168 indx = fOutPoolIndex; 2169 if (!fPipeOutBuff[indx].avail) 2170 { 2171 for (indx=0; indx<fOutBufPool; indx++) 2172 { 2173 if (fPipeOutBuff[indx].avail) 2174 { 2175 fOutPoolIndex = indx; 2176 gotBuffer = true; 2177 break; 2178 } 2179 } 2180 } else { 2181 gotBuffer = true; 2182 } 2183 2184 if (gotBuffer) 2185 { 2186 fPipeOutBuff[indx].avail = false; 2187 fOutPoolIndex++; 2188 if (fOutPoolIndex >= fOutBufPool) 2189 { 2190 fOutPoolIndex = 0; 2191 } 2192 } else { 2193 if (fOutBufPool >= kMaxOutBufPool) 2194 { 2195 ALERT(kMaxOutBufPool, fOutBufPool, "getOutputBuffer - Output buffer pool empty"); 2196 indx = 0; 2197 gotBuffer = false; 2198 } else { 2199 XTRACE(this, 0, fOutBufPool, "getOutputBuffer - Adding output buffer to pool"); 2200 2201 // Create a new one (should never really get here - maybe very very heavy transmit traffic) 2202 2203 indx = fOutBufPool; 2204 fPipeOutBuff[indx].pipeOutMDP = IOBufferMemoryDescriptor::withCapacity(fControlDriver->fMax_Block_Size, kIODirectionOut); 2205 if (!fPipeOutBuff[indx].pipeOutMDP) 2206 { 2207 XTRACE(this, 0, indx, "getOutputBuffer - Allocate output descriptor failed"); 2208 gotBuffer = false; 2209 indx = 0; 2210 } else { 2211 fPipeOutBuff[indx].pipeOutMDP->setLength(fControlDriver->fMax_Block_Size); 2212 fPipeOutBuff[indx].pipeOutBuffer = (UInt8*)fPipeOutBuff[indx].pipeOutMDP->getBytesNoCopy(); 2213 XTRACEP(this, fPipeOutBuff[indx].pipeOutMDP, fPipeOutBuff[indx].pipeOutBuffer, "getOutputBuffer - output buffer"); 2214 fPipeOutBuff[indx].avail = false; 2215 fPipeOutBuff[indx].writeCompletionInfo.target = this; 2216 fPipeOutBuff[indx].writeCompletionInfo.action = dataWriteComplete; 2217 fPipeOutBuff[indx].writeCompletionInfo.parameter = NULL; 2218 fPipeOutBuff[indx].indx = indx; 2219 fOutBufPool++; 2220 fOutPoolIndex = 0; 2221 gotBuffer = true; 2222 } 2223 } 2224 } 2225 2226 *bufIndx = indx; 2227 2228 return gotBuffer; 2229 2230}/* end getOutputBuffer */ 2231 2232/****************************************************************************************************/ 2233// 2234// Method: AppleUSBCDCECMData::USBTransmitPacket 2235// 2236// Inputs: packet - the packet 2237// 2238// Outputs: Return code - kIOReturnSuccess (transmit started), everything else (it didn't) 2239// 2240// Desc: Set up and then transmit the packet. 2241// 2242/****************************************************************************************************/ 2243 2244IOReturn AppleUSBCDCECMData::USBTransmitPacket(mbuf_t packet) 2245{ 2246 UInt32 numbufs = 0; // number of mbufs for this packet 2247 mbuf_t m; // current mbuf 2248 UInt32 total_pkt_length = 0; 2249 UInt32 rTotal = 0; 2250 IOReturn ior = kIOReturnSuccess; 2251 UInt32 indx; 2252 2253 XTRACEP(this, 0, packet, "USBTransmitPacket"); 2254 2255 if (fDeferredClear) 2256 { 2257 ior = clearPipeStall(fOutPipe); 2258 if (ior != kIOReturnSuccess) 2259 { 2260 XTRACE(this, 0, ior, "USBTransmitPacket - clear stall failed (trying to continue)"); 2261 } 2262 fDeferredClear = false; 2263 } 2264 2265 // Count the number of mbufs in this packet 2266 2267 m = packet; 2268 while (m) 2269 { 2270 if (mbuf_len(m) != 0) 2271 { 2272 total_pkt_length += mbuf_len(m); 2273 numbufs++; 2274 } 2275 m = mbuf_next(m); 2276 } 2277 2278 XTRACE(this, total_pkt_length, numbufs, "USBTransmitPacket - Total packet length and Number of mbufs"); 2279 2280 if (total_pkt_length > fControlDriver->fMax_Block_Size) 2281 { 2282 XTRACE(this, 0, 0, "USBTransmitPacket - Bad packet size"); // Note for now and revisit later 2283 if (fControlDriver->fOutputErrsOK) 2284 fpNetStats->outputErrors++; 2285 return kIOReturnOutputDropped; 2286 } 2287 2288 if (!getOutputBuffer(&indx)) 2289 { 2290 ALERT(fOutBufPool, fOutPoolIndex, "USBTransmitPacket - Output buffer unavailable"); 2291 return kIOReturnOutputStall; 2292 } 2293 2294 // Start filling in the send buffer 2295 2296 m = packet; // start with the first mbuf of the packet 2297 rTotal = 0; // running total 2298 do 2299 { 2300 if (mbuf_len(m) == 0) // Ignore zero length buffers 2301 continue; 2302 2303 bcopy(mbuf_data(m), &fPipeOutBuff[indx].pipeOutBuffer[rTotal], mbuf_len(m)); 2304 rTotal += mbuf_len(m); 2305 2306 } while ((m = mbuf_next(m)) != 0); 2307 2308 LogData(kDataOut, rTotal, fPipeOutBuff[indx].pipeOutBuffer); 2309 2310 fPipeOutBuff[indx].m = packet; 2311 fPipeOutBuff[indx].writeCompletionInfo.parameter = (void *)&fPipeOutBuff[indx]; 2312 2313 ior = fOutPipe->Write(fPipeOutBuff[indx].pipeOutMDP, 2000, 5000, rTotal, &fPipeOutBuff[indx].writeCompletionInfo); 2314 if (ior != kIOReturnSuccess) 2315 { 2316 XTRACE(this, 0, ior, "USBTransmitPacket - Write failed"); 2317 if (ior == kIOUSBPipeStalled) 2318 { 2319// fOutPipe->Reset(); 2320 clearPipeStall(fOutPipe); 2321 ior = fOutPipe->Write(fPipeOutBuff[indx].pipeOutMDP, 2000, 5000, rTotal, &fPipeOutBuff[indx].writeCompletionInfo); 2322 if (ior != kIOReturnSuccess) 2323 { 2324 XTRACE(this, 0, ior, "USBTransmitPacket - Write really failed"); 2325 if (fControlDriver->fOutputErrsOK) 2326 fpNetStats->outputErrors++; 2327 2328 fPipeOutBuff[indx].avail = true; 2329 return ior; 2330 } 2331 } else { 2332 if (fControlDriver->fOutputErrsOK) 2333 fpNetStats->outputErrors++; 2334 2335 fPipeOutBuff[indx].avail = true; 2336 return ior; 2337 } 2338 } 2339 2340 if (fControlDriver->fOutputPktsOK) 2341 fpNetStats->outputPackets++; 2342 2343 return ior; 2344 2345}/* end USBTransmitPacket */ 2346 2347/****************************************************************************************************/ 2348// 2349// Method: AppleUSBCDCECMData::clearPipeStall 2350// 2351// Inputs: thePipe - the pipe 2352// 2353// Outputs: 2354// 2355// Desc: Clear a stall on the specified pipe. 2356// 2357/****************************************************************************************************/ 2358 2359IOReturn AppleUSBCDCECMData::clearPipeStall(IOUSBPipe *thePipe) 2360{ 2361 IOReturn rtn = kIOReturnSuccess; 2362 2363 XTRACEP(this, 0, thePipe, "clearPipeStall"); 2364 2365// rtn = thePipe->GetPipeStatus(); 2366// if (rtn == kIOUSBPipeStalled) 2367// { 2368 rtn = thePipe->ClearPipeStall(true); 2369 if (rtn == kIOReturnSuccess) 2370 { 2371 XTRACE(this, 0, 0, "clearPipeStall - Successful"); 2372 } else { 2373 XTRACE(this, 0, rtn, "clearPipeStall - Failed"); 2374 } 2375// } else { 2376// XTRACE(this, 0, 0, "clearPipeStall - Pipe not stalled"); 2377 // } 2378 2379 return rtn; 2380 2381}/* end clearPipeStall */ 2382 2383/****************************************************************************************************/ 2384// 2385// Method: AppleUSBCDCECMData::receivePacket 2386// 2387// Inputs: packet - the packet 2388// size - Number of bytes in the packet 2389// 2390// Outputs: 2391// 2392// Desc: Build the mbufs and then send to the network stack. 2393// 2394/****************************************************************************************************/ 2395 2396void AppleUSBCDCECMData::receivePacket(UInt8 *packet, UInt32 size) 2397{ 2398 mbuf_t m; 2399 errno_t err; 2400 UInt32 submit; 2401 2402 XTRACE(this, 0, size, "receivePacket"); 2403 2404 if (!fControlDriver) 2405 { 2406 XTRACE(this, 0, 0, "receivePacket - Control driver has gone, packet dropped"); 2407 return; 2408 } 2409 2410 if (size > fControlDriver->fMax_Block_Size) 2411 { 2412 XTRACE(this, 0, 0, "receivePacket - Packet size error, packet dropped"); 2413 if (fControlDriver->fInputErrsOK) 2414 fpNetStats->inputErrors++; 2415 return; 2416 } 2417 2418 m = allocatePacket(size); 2419 if (m) 2420 { 2421 err = mbuf_copyback(m, 0, size, packet, MBUF_DONTWAIT); 2422 if (err) 2423 { 2424 XTRACE(this, 0, err, "receivePacket - Buffer copy failed, packet dropped"); 2425 if (fControlDriver->fInputErrsOK) 2426 fpNetStats->inputErrors++; 2427 freePacket(m); 2428 return; 2429 } 2430// bcopy(packet, mbuf_data(m), size); 2431 submit = fNetworkInterface->inputPacket(m, size); 2432 XTRACE(this, 0, submit, "receivePacket - Packets submitted"); 2433 if (fControlDriver->fInputPktsOK) 2434 fpNetStats->inputPackets++; 2435 } else { 2436 XTRACE(this, 0, 0, "receivePacket - Buffer allocation failed, packet dropped"); 2437 if (fControlDriver->fInputErrsOK) 2438 fpNetStats->inputErrors++; 2439 } 2440 2441}/* end receivePacket */ 2442 2443/****************************************************************************************************/ 2444// 2445// Method: AppleUSBCDCECMData::linkStatusChange 2446// 2447// Inputs: linkState - 0=down, 1=up 2448// 2449// Outputs: 2450// 2451// Desc: Notification from the control driver (or wherever) of the link state 2452// 2453/****************************************************************************************************/ 2454void AppleUSBCDCECMData::linkStatusChange(UInt8 linkState) 2455{ 2456 2457 XTRACE(this, 0, linkState, "linkStatusChange"); 2458 2459 // Check the state actually changed 2460 2461 if (fLinkStatus != linkState) 2462 { 2463 XTRACE(this, 0, linkState, "linkStatusChange - State has changed"); 2464 2465 fLinkStatus = linkState; 2466 2467 if (linkState == kLinkUp) 2468 { 2469 setLinkStatusUp(); 2470 2471 // Start our IOOutputQueue object if not already started 2472 2473 if (fTransmitQueue) 2474 { 2475 if (!fQueueStarted) 2476 { 2477 fTransmitQueue->setCapacity(TRANSMIT_QUEUE_SIZE); 2478 XTRACE(this, 0, TRANSMIT_QUEUE_SIZE, "linkStatusChange - capacity set"); 2479 2480 fTransmitQueue->start(); 2481 XTRACE(this, 0, 0, "linkStatusChange - transmit queue started"); 2482 2483 fQueueStarted = true; 2484 } 2485 } 2486 } else { 2487 if (fQueueStarted) 2488 { 2489 fTransmitQueue->stop(); 2490 2491 // Flush all packets currently in the output queue 2492 2493 fTransmitQueue->setCapacity(0); 2494 fTransmitQueue->flush(); 2495 2496 fQueueStarted = false; 2497 } 2498 setLinkStatusDown(); 2499 } 2500 } 2501 2502}/* end linkStatusChange */ 2503 2504/****************************************************************************************************/ 2505// 2506// Method: AppleUSBCDCECMData::linkSpeedChange 2507// 2508// Inputs: upSpeed - in bits/second (already converted to host format) 2509// downSpeed - in bits/second (already converted to host format) 2510// 2511// Outputs: 2512// 2513// Desc: Notification from the control driver of the link speed 2514// 2515/****************************************************************************************************/ 2516void AppleUSBCDCECMData::linkSpeedChange(UInt32 upSpeed, UInt32 downSpeed) 2517{ 2518 UInt32 speed; 2519 2520 XTRACE(this, upSpeed, downSpeed, "linkSpeedChange"); 2521 2522 fUpSpeed = upSpeed; 2523 fDownSpeed = downSpeed; 2524 2525 //IOEthernetController does not handle asymmetric speeds. So pick the min speed as worst case scenario for traffic shaping. 2526 speed = min(fDownSpeed,fUpSpeed); 2527 2528 if ((fLinkStatus != kLinkUp) && (speed != 0)) 2529 { 2530 linkStatusChange(kLinkUp); // force link up 2531 } 2532 2533}/* end linkSpeedChange */ 2534 2535/****************************************************************************************************/ 2536// 2537// Method: AppleUSBCDCECMData::setLinkStatusUp 2538// 2539// Inputs: 2540// 2541// Outputs: 2542// 2543// Desc: Set our link status to up 2544// 2545/****************************************************************************************************/ 2546void AppleUSBCDCECMData::setLinkStatusUp() 2547{ 2548 IONetworkMedium *medium; 2549 IOMediumType mediumType = 0; 2550 UInt64 speed; 2551 char line[256]; 2552 UInt32 linkSpeed; 2553 UInt16 regs[LinkUp_Phy_Count] = {0, 0, 0, 0, 0, 0}; 2554 LinkUpFlow flowState = kLinkUpFlow_None; 2555 bool fullduplex; 2556 char portNameBuffer[5]; 2557 OSNumber *usbPortNumber; 2558 char *portName = NULL; 2559 2560 XTRACE(this, fUpSpeed, fDownSpeed, "setLinkStatusUp"); 2561 2562 if (fLinkStatus != kLinkUp) 2563 { 2564 XTRACE(this, 0, 0, "setLinkStatusUp linkspeed is 0 +"); 2565 return; 2566 } 2567 2568 // We'll default to FDX and use the higher speed 2569 2570 mediumType = kIOMediumOptionFullDuplex; 2571 fullduplex = true; 2572 2573 speed = max(fUpSpeed,fDownSpeed); 2574 2575 linkSpeed = speed/1000000; // Need this in mbits 2576 2577 XTRACE(this, speed, linkSpeed, "speed, linkSpeed mbps+++"); 2578 2579 switch (linkSpeed) { 2580 2581 case 0: 2582 mediumType |= kIOMediumEthernetNone; 2583 fLinkStatus = kLinkDown; 2584 XTRACE(this, speed, linkSpeed, "setLinkStatusUp linkspeed is 0 +"); 2585 return; 2586 2587 case 10: 2588 mediumType |= kIOMediumEthernet10BaseT; 2589 break; 2590 2591 case 100: 2592 mediumType |= kIOMediumEthernet100BaseTX; 2593 break; 2594 2595 case 1000: 2596 mediumType |= kIOMediumEthernet1000BaseTX; 2597 break; 2598 2599 default: 2600 mediumType |= kIOMediumEthernet10BaseT; 2601 XTRACE(this, speed, linkSpeed, "default linkspeed+"); 2602 linkSpeed = 10; //Force to 10 Mbps 2603 speed = linkSpeed*1000000; //Corresponding value in bits per second 2604 break; 2605 } 2606 2607 2608 // Get the port number 2609 2610 usbPortNumber = OSDynamicCast(OSNumber, fDataInterface->GetDevice()->getProperty("PortNum")); 2611 if (usbPortNumber) 2612 { 2613 snprintf(portNameBuffer, sizeof(portNameBuffer), "%d", usbPortNumber->unsigned16BitValue()); 2614 portName = portNameBuffer; 2615 } 2616 2617 // Get some debug info. (none at the moment) 2618 2619 regs[0] = 0; 2620 regs[1] = 0; 2621 regs[2] = 0; 2622 regs[3] = 0; 2623 regs[4] = 0; 2624 regs[5] = 0; 2625 2626 // Now print it 2627 2628 ::LinkUpMessage(line, sizeof(line), // std link up msg to line buffer 2629 NULL, // get kext name from kmodinfo 2630 fNetworkInterface, // where to get the en name 2631 linkSpeed, // speed in mbits 2632 fullduplex, // boolean for full/half duplex 2633 flowState, // flow control type 2634 portName, // port name or NULL 2635 regs, // array of 6 useful registers to log 2636 NULL); // string of loopback type or NULL 2637#if USE_ELG 2638 Log("%s\n", line); // Above goes to IOLog, send a copy to firewire if debug enabled 2639#endif 2640 2641 2642 medium = IONetworkMedium::getMediumWithType(fMediumDict, mediumType); 2643 2644 XTRACE(this, 0, mediumType, "setLinkStatusUp - LinkStatus set"); 2645 2646 setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, medium, speed); 2647 2648}/* end setLinkStatusUp */ 2649 2650/****************************************************************************************************/ 2651// 2652// Method: AppleUSBCDCECMData::setLinkStatusDown 2653// 2654// Inputs: 2655// 2656// Outputs: 2657// 2658// Desc: Set our link status to down 2659// 2660/****************************************************************************************************/ 2661void AppleUSBCDCECMData::setLinkStatusDown() 2662{ 2663 2664 XTRACE(this, 0, 0, "setLinkStatusDown"); 2665 2666 // Set our status to inactive, with the current medium set to 'none' 2667 2668 setLinkStatus(kIONetworkLinkValid, IONetworkMedium::getMediumWithType(fMediumDict, kIOMediumEthernetNone)); 2669 2670 // Log it if we need to 2671 2672 if (fNetworkInterface) 2673 { 2674 Log("Ethernet [%s]: Link down on %s%d\n", DEBUG_NAME, fNetworkInterface->getNamePrefix(), fNetworkInterface->getUnitNumber()); 2675 } else { 2676 Log("Ethernet [%s]: Link down\n", DEBUG_NAME); 2677 } 2678 2679 fLinkStatus = kLinkDown; 2680 linkSpeedChange(0,0); //Force Link Speed to Zero 2681 2682}/* end setLinkStatusDown */ 2683 2684/****************************************************************************************************/ 2685// 2686// Method: AppleUSBCDCECMData::timerFired 2687// 2688// Inputs: 2689// 2690// Outputs: 2691// 2692// Desc: Static member function called when a timer event fires. 2693// 2694/****************************************************************************************************/ 2695void AppleUSBCDCECMData::timerFired(OSObject *owner, IOTimerEventSource *sender) 2696{ 2697 2698// XTRACE(this, 0, 0, "timerFired"); 2699 2700 if (owner) 2701 { 2702 AppleUSBCDCECMData* target = OSDynamicCast(AppleUSBCDCECMData, owner); 2703 2704 if (target) 2705 { 2706 target->timeoutOccurred(sender); 2707 } 2708 } 2709 2710}/* end timerFired */ 2711 2712/****************************************************************************************************/ 2713// 2714// Method: AppleUSBCDCECMData::timeoutOccurred 2715// 2716// Inputs: 2717// 2718// Outputs: 2719// 2720// Desc: Timeout handler, used for stats gathering. 2721// 2722/****************************************************************************************************/ 2723 2724void AppleUSBCDCECMData::timeoutOccurred(IOTimerEventSource * /*timer*/) 2725{ 2726 bool statsOK = false; 2727 2728// XTRACE(this, 0, 0, "timeoutOccurred"); 2729 2730 if (fControlDriver) 2731 { 2732 statsOK = fControlDriver->statsProcessing(); 2733 } 2734 2735 if (statsOK) 2736 { 2737 2738 // Restart the watchdog timer 2739 2740 fTimerSource->setTimeoutMS(WATCHDOG_TIMER_MS); 2741 } 2742 2743}/* end timeoutOccurred */ 2744 2745 2746 2747bool AppleUSBCDCECMData::willTerminate( IOService * provider, IOOptionBits options ) 2748{ 2749 bool result = true; 2750 Log(DEBUG_NAME ":willTerminate\n"); 2751 2752 fTerminate = true; 2753 return result; 2754} 2755 2756 2757/****************************************************************************************************/ 2758// 2759// Method: AppleUSBCDCECMData::message 2760// 2761// Inputs: type - message type 2762// provider - my provider 2763// argument - additional parameters 2764// 2765// Outputs: return Code - kIOReturnSuccess 2766// 2767// Desc: Handles IOKit messages. 2768// 2769/****************************************************************************************************/ 2770 2771IOReturn AppleUSBCDCECMData::message(UInt32 type, IOService *provider, void *argument) 2772{ 2773 UInt16 i; 2774 IOReturn ior; 2775 2776 XTRACE(this, 0, type, "message"); 2777 2778 switch (type) 2779 { 2780 case kIOMessageServiceIsTerminated: 2781 XTRACE(this, fReady, type, "message - kIOMessageServiceIsTerminated"); 2782#if 0 2783 // As a precaution abort any outstanding I/O 2784 2785 if (fInPipe) 2786 fInPipe->Abort(); 2787 if (fOutPipe) 2788 fOutPipe->Abort(); 2789#endif 2790 2791 if (fReady) 2792 { 2793 if (!fTerminate) // Check if we're already being terminated 2794 { 2795#if 0 2796 // NOTE! This call below depends on the hard coded path of this KEXT. Make sure 2797 // that if the KEXT moves, this path is changed! 2798 KUNCUserNotificationDisplayNotice( 2799 10, // Timeout in seconds 2800 0, // Flags (for later usage) 2801 "", // iconPath (not supported yet) 2802 "", // soundPath (not supported yet) 2803 "/System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBCDCECMData.kext", // localizationPath 2804 "Unplug Header", // the header 2805 "Unplug Notice", // the notice - look in Localizable.strings 2806 "OK"); 2807#endif 2808 } 2809 } 2810 2811 putToSleep(); 2812 2813// releaseResources(); 2814 2815 if (fDataInterface) 2816 { 2817 fDataInterface->close(this); 2818 fDataInterface->release(); 2819 fDataInterface = NULL; 2820 } 2821 fTerminate = true; // we're being terminated (unplugged) 2822 linkStatusChange(kLinkDown); // and of course we're offline 2823 return kIOReturnSuccess; 2824 case kIOMessageServiceIsSuspended: 2825 XTRACE(this, 0, type, "message - kIOMessageServiceIsSuspended"); 2826 break; 2827 case kIOMessageServiceIsResumed: 2828 XTRACE(this, 0, type, "message - kIOMessageServiceIsResumed"); 2829 break; 2830 case kIOMessageServiceIsRequestingClose: 2831 XTRACE(this, 0, type, "message - kIOMessageServiceIsRequestingClose"); 2832 break; 2833 case kIOMessageServiceWasClosed: 2834 XTRACE(this, 0, type, "message - kIOMessageServiceWasClosed"); 2835 break; 2836 case kIOMessageServiceBusyStateChange: 2837 XTRACE(this, 0, type, "message - kIOMessageServiceBusyStateChange"); 2838 break; 2839 case kIOUSBMessagePortHasBeenResumed: 2840 XTRACE(this, 0, type, "message - kIOUSBMessagePortHasBeenResumed"); 2841 2842 ior = fDataInterface->SetAlternateInterface(this, fAltInterface); 2843 if (ior != kIOReturnSuccess) 2844 { 2845 ALERT(0, 0, "AppleUSBCDCECMData::enable - SetAlternateInterface failed"); 2846 XTRACE(this, 0, 0, "enable - SetAlternateInterface failed"); 2847 } 2848 2849 for (i=0; i<fInBufPool; i++) 2850 { 2851 if (fPipeInBuff[i].dead) // If it's dead try and resurrect it 2852 { 2853 ior = fInPipe->Read(fPipeInBuff[i].pipeInMDP, &fPipeInBuff[i].readCompletionInfo, NULL); 2854 if (ior != kIOReturnSuccess) 2855 { 2856 XTRACE(this, 0, ior, "message - Read io error"); 2857 } else { 2858 fPipeInBuff[i].dead = false; 2859 } 2860 } 2861 } 2862 return kIOReturnSuccess; 2863 case kIOUSBMessageHubResumePort: 2864 XTRACE(this, 0, type, "message - kIOUSBMessageHubResumePort"); 2865 break; 2866 case kIOMessageServiceIsAttemptingOpen: 2867 XTRACE(this, 0, type, "message - kIOMessageServiceIsAttemptingOpen"); 2868 break; 2869 default: 2870 XTRACE(this, 0, type, "message - unknown message"); 2871 break; 2872 } 2873 2874 return super::message(type, provider, argument); 2875 2876}/* end message */ 2877 2878/****************************************************************************************************/ 2879// 2880// Method: AppleUSBCDCECMData::registerWithPolicyMaker 2881// 2882// Inputs: provider - my provider 2883// 2884// Outputs: return code - From policy maker 2885// 2886// Desc: Initialize the driver for power management and register ourselves with policy-maker. 2887// Called by superclass - not by Power Management. 2888// 2889/****************************************************************************************************/ 2890 2891IOReturn AppleUSBCDCECMData::registerWithPolicyMaker(IOService *policyMaker) 2892{ 2893 IOReturn ior; 2894 2895 XTRACE(this, 0, 0, "registerWithPolicyMaker"); 2896 2897 ior = policyMaker->registerPowerDriver(this, gOurPowerStates, kNumCDCStates); 2898 2899 return ior; 2900 2901}/* end registerWithPolicyMaker */ 2902