home *** CD-ROM | disk | FTP | other *** search
/ ftp.sustworks.com 2018 / ftp.sustworks.com.zip / ftp.sustworks.com / USBAx8817x_101.dmg / src / Source / USBAx8817x.cpp < prev    next >
C/C++ Source or Header  |  2005-10-08  |  94KB  |  3,103 lines

  1. /*
  2.     File:            USBAx8817x.cpp
  3.  
  4.     Description:     Driver for USBAx8817 USB-To-Ethernet devices
  5.  
  6.     Acknowledgements: This driver started out as a sample CDC
  7.                      USB-To-Ethernet driver, provided by Apple, and
  8.                      was slowly transformed into the Pegasus driver.
  9.                      It is partly based upon the linux Pegausus driver
  10.                      source.  Some constants from the linux header
  11.                      file were copied directly.  Also, a CRC function
  12.                      was copied almost directly from aue.c, the BSD
  13.                      Pegasus driver.
  14.  
  15.     Copyright:       Copyright 2005, Daniel Sumorok and Peter Sichel
  16.         
  17.     Disclaimer:      This program is free software; you can redistribute it
  18.                      and/or modify it under the terms of the GNU
  19.                      General Public License as published by the Free
  20.                      Software Foundation; either version 2, or (at
  21.                      your option) any later version.
  22.  
  23.                      This program is distributed in the hope that it
  24.                      will be useful, but WITHOUT ANY WARRANTY; without
  25.                      even the implied warranty of MERCHANTABILITY or
  26.                      FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  27.                      General Public License for more details.
  28.  
  29.                      You should have received a copy of the GNU
  30.                      General along with this program; if not, write to
  31.                      the Free Software Foundation, 59 Temple Place -
  32.                      Suite 330, Boston, MA 02111-1307, USA.  Change
  33.                      History (least recent first):
  34.         
  35.             <1>         03/25/05        USBPegasusEthernet source
  36.  
  37. */
  38.  
  39. /*
  40.  * Copyright (c) 1997, 1998, 1999, 2000-2003
  41.  *      Bill Paul <wpaul@windriver.com>.  All rights reserved.
  42.  *
  43.  * Redistribution and use in source and binary forms, with or without
  44.  * modification, are permitted provided that the following conditions
  45.  * are met:
  46.  * 1. Redistributions of source code must retain the above copyright
  47.  *    notice, this list of conditions and the following disclaimer.
  48.  * 2. Redistributions in binary form must reproduce the above copyright
  49.  *    notice, this list of conditions and the following disclaimer in the
  50.  *    documentation and/or other materials provided with the distribution.
  51.  * 3. All advertising materials mentioning features or use of this software
  52.  *    must display the following acknowledgement:
  53.  *      This product includes software developed by Bill Paul.
  54.  * 4. Neither the name of the author nor the names of any co-contributors
  55.  *    may be used to endorse or promote products derived from this software
  56.  *    without specific prior written permission.
  57.  *
  58.  */
  59.  
  60. #include "USBAx8817x_private.h"
  61. #include "USBAx8817x.h"
  62. #include "USBAx8817xEthernetInterface.h"
  63.  
  64. static IOPMPowerState  ourPowerStates[kNumPowerStates] = {
  65.   {1,0,0,0,0,0,0,0,0,0,0,0},
  66.   {1,IOPMDeviceUsable,IOPMPowerOn,IOPMPowerOn,0,0,0,0,0,0,0,0} 
  67. };
  68.     
  69. static struct MediumTable {
  70.   UInt32        type;
  71.   UInt32        speed;
  72. }
  73.  
  74. mediumTable[] = {
  75.   {kIOMediumEthernetNone, 0},
  76.   {kIOMediumEthernetAuto, 0},
  77.   {kIOMediumEthernet10BaseT    | kIOMediumOptionHalfDuplex, 10},
  78.   {kIOMediumEthernet10BaseT    | kIOMediumOptionFullDuplex, 10},
  79.   {kIOMediumEthernet100BaseTX  | kIOMediumOptionHalfDuplex, 100},
  80.   {kIOMediumEthernet100BaseTX  | kIOMediumOptionFullDuplex, 100}
  81. };
  82.  
  83. #define super IOEthernetController
  84. #define POSTEVENT(x) postEvent(this, (void *)(int)x, (void *)(int)true)
  85.  
  86. OSDefineMetaClassAndStructors(USBAx8817x, IOEthernetController);
  87.  
  88. #pragma mark -- Device Control --
  89.  
  90. /*****************************************************************************/
  91. //
  92. //              Method:         USBAx8817x::axCmd
  93. //
  94. //              Inputs:         cmd   - AX Command (see USBAx8817x.h)
  95. //                              index - 
  96. //                              val   -
  97. //                              buf   -
  98. //
  99. //              Outputs:        Return code - true means success
  100. //                                            false means failure
  101. //
  102. //              Desc:           Reads or writes a to a register.  The
  103. //                              cmd input encapsulates whether the
  104. //                              operation is a read or a write, and
  105. //                              the register being accessed.
  106. //
  107. /****************************************************************************/
  108. bool USBAx8817x::axCmd(UInt16 cmd, UInt16 index, UInt16 val, void *buf) {
  109.   IOUSBDevRequest request;
  110.   IOReturn ior;
  111.  
  112.   if(fCntlPipe == NULL) {
  113.     IOLog("USBAx8817x::axCmd: fCntlPipe is NULL\n");
  114.     return false;
  115.   }
  116.  
  117.   if(AXE_CMD_DIR(cmd)) {
  118.     request.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBVendor,
  119.                                                  kUSBDevice);
  120.   } else {
  121.     request.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBVendor,
  122.                                                  kUSBDevice);
  123.   }
  124.  
  125.   request.bRequest = AXE_CMD_CMD(cmd);
  126.   request.wValue = val;
  127.   request.wIndex = index;
  128.   request.wLength = AXE_CMD_LEN(cmd);
  129.   request.pData = buf;
  130.   request.wLenDone = 0;
  131.  
  132.   ior = fCntlPipe->ControlRequest(&request, 0);
  133.  
  134.   if(ior != kIOReturnSuccess) {
  135.     IOLog("USBAx8817x::axCmd: Control request failed.\n");
  136.     return false;
  137.   }
  138.  
  139.   if((int)request.wLenDone != AXE_CMD_LEN(cmd)) {
  140.     IOLog("USBAx8817x::axCmd: Control request failed!  size = %d, wLenDone = %d\n",
  141.           (int)AXE_CMD_LEN(cmd), (int)request.wLenDone);
  142.     return false;
  143.   }
  144.  
  145.   return true;
  146. }
  147.  
  148. /*****************************************************************************/
  149. //
  150. //              Method:         USBAx8817x::axCmdAsync
  151. //
  152. //              Inputs:         cmd   - AX Command (see USBAx8817x.h)
  153. //                              index - 
  154. //                              val   -
  155. //                              buf   -
  156. //
  157. //              Outputs:        Return code - true means success
  158. //                                            false means failure
  159. //
  160. //              Desc:           Asynchonously Reads or writes a to a
  161. //                              register.  The cmd input encapsulates
  162. //                              whether the operation is a read or a
  163. //                              write, and the register being
  164. //                              accessed.  The callback sends an event
  165. //                              to the setState() method.
  166. //
  167. /****************************************************************************/
  168. IOReturn USBAx8817x::axCmdAsync(UInt16 cmd, UInt16 index, UInt16 val) {
  169.  
  170.   IOReturn ior;
  171.  
  172.   if(AXE_CMD_DIR(cmd)) {
  173.     fCtrlRead.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBVendor,
  174.                                                    kUSBDevice);
  175.   } else {
  176.     fCtrlRead.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBVendor,
  177.                                                    kUSBDevice);
  178.   }
  179.  
  180.   fCtrlRead.bRequest = AXE_CMD_CMD(cmd);
  181.   fCtrlRead.wValue = val;
  182.   fCtrlRead.wIndex = index;
  183.   fCtrlRead.wLength = AXE_CMD_LEN(cmd);
  184.  
  185.   ior = fCntlPipe->ControlRequest(&fCtrlRead, &fCtrlCompletionInfo);
  186.  
  187.   return ior;
  188. } /* end axCmdAsync */
  189.  
  190. /*****************************************************************************/
  191. //
  192. //              Method:         USBAx8817x::readMiiWord
  193. //
  194. //              Inputs:         phy  - The phy address
  195. //                              inx  - The MII register number
  196. //                              regd - The value to be written
  197. //
  198. //              Outputs:        Return code - true means success
  199. //                                            false means failure
  200. //
  201. //              Desc:           Reads a media independent interface
  202. //                              register.
  203. //
  204. /****************************************************************************/
  205. bool USBAx8817x::readMiiWord(UInt8 phyIn, UInt8 indx, UInt16 *regd) {
  206.   if(!axCmd(AXE_CMD_MII_OPMODE_SW, 0, 0, NULL)) {
  207.     IOLog("USBAx8817x: readMiiWord: Failed to set SW MII mode.\n");
  208.     return false;
  209.   }
  210.   
  211.   if(!axCmd(AXE_CMD_MII_READ_REG, indx, phyIn, regd)) {
  212.     IOLog("USBAx8817x: readMiiWord: Failed to read MII register.\n");
  213.     return false;
  214.   }
  215.  
  216.   if(!axCmd(AXE_CMD_MII_OPMODE_HW, 0, 0, NULL)) {
  217.     IOLog("USBAx8817x: readMiiWord: Failed to set HW MII mode.\n");
  218.     return false;
  219.   }
  220.  
  221.   *regd = USBToHostWord(*regd);
  222.   return true;
  223. } /* end readMiiWord */
  224.  
  225. /*****************************************************************************/
  226. //
  227. //              Method:         USBAx8817x::writeMiiWord
  228. //
  229. //              Inputs:         phy  - The phy address
  230. //                              inx  - The MII register number
  231. //                              regd - The value to be written
  232. //
  233. //              Outputs:        Return code - true means success
  234. //                                            false means failure
  235. //
  236. //              Desc:           Writes a media independent interface
  237. //                              register.
  238. //
  239. /****************************************************************************/
  240. bool USBAx8817x::writeMiiWord(UInt8 phyIn, UInt8 indx, UInt16 regd) {
  241.   UInt16 data16;
  242.  
  243.   if(!axCmd(AXE_CMD_MII_OPMODE_SW, 0, 0, NULL)) {
  244.     IOLog("USBAx8817x: readMiiWord: Failed to set SW MII mode.\n");
  245.     return false;
  246.   }
  247.  
  248.   data16 = HostToUSBWord(regd);
  249.   if(!axCmd(AXE_CMD_MII_WRITE_REG, indx, phyIn, &data16)) {
  250.     IOLog("USBAx8817x: readMiiWord: Failed to read MII register.\n");
  251.     return false;
  252.   }
  253.  
  254.   if(!axCmd(AXE_CMD_MII_OPMODE_HW, 0, 0, NULL)) {
  255.     IOLog("USBAx8817x: readMiiWord: Failed to set HW MII mode.\n");
  256.     return false;
  257.   }
  258.  
  259.   return true;
  260. } /* end writeMiiWord */
  261.  
  262. /*****************************************************************************/
  263. //
  264. //              Method:         USBAx8817x::readMiiWordAsync
  265. //
  266. //              Inputs:         inx  - The MII register number
  267. //
  268. //              Outputs:        Return code - IOReturnSuccess on success
  269. //                                            failure otherwise
  270. //
  271. //              Desc:           Reads a media independent interface
  272. //                              register asynchonously.
  273. //
  274. /****************************************************************************/
  275. IOReturn USBAx8817x::readMiiWordAsync(UInt8 indx) {
  276.   IOReturn ior;
  277.  
  278.   ior = axCmdAsync(AXE_CMD_MII_OPMODE_SW, 0, 0);
  279.   if(ior == kIOReturnSuccess) {
  280.     miiState = miiStateRead;
  281.     miiIndx = indx;
  282.   }
  283.  
  284.   return ior;
  285. } /* end readMiiWordAsync */
  286.  
  287. /*****************************************************************************/
  288. //
  289. //              Method:         USBAx8817x::writeMiiWordAsync
  290. //
  291. //              Inputs:         indx - The MII register number
  292. //                              data - The value to be written
  293. //
  294. //              Outputs:        Return code - IOReturnSuccess on success
  295. //                                            failure otherwise
  296. //
  297. //              Desc:           Writes a media independent interface
  298. //                              register.
  299. //
  300. /****************************************************************************/
  301. IOReturn USBAx8817x::writeMiiWordAsync(UInt8 indx, UInt16 data) {
  302.   IOReturn ior;
  303.  
  304.   ior = axCmdAsync(AXE_CMD_MII_OPMODE_SW, 0, 0);
  305.   if(ior == kIOReturnSuccess) {
  306.     miiState = miiStateWrite;
  307.     miiIndx = indx;
  308.     miiData = USBToHostWord(data);
  309.   }
  310.  
  311.   return ior;
  312. } /* end writeMiiWordAsync */
  313.  
  314. #pragma mark -- Initialization --
  315.  
  316. /*****************************************************************************/
  317. //
  318. //      Method:         USBAx8817x::init
  319. //
  320. //      Inputs:         properties - data (keys and values) used to match
  321. //
  322. //      Outputs:        Return code - true (init successful), false 
  323. //                      (init failed)
  324. //
  325. //      Desc:           Initialize the driver.
  326. //
  327. /*****************************************************************************/
  328. bool USBAx8817x::init(OSDictionary *properties) {
  329.   OSNumber *numberTest;
  330.   int i;
  331.  
  332.   if (super::init(properties) == false) {
  333.     IOLog("USBAx8817x::init: initialize super failed");
  334.     return false;
  335.   }
  336.  
  337.   numberTest = OSDynamicCast(OSNumber, getProperty("gpioBits"));
  338.   if(numberTest) {
  339.     gpioBits = numberTest->unsigned32BitValue();
  340.   } else {
  341.     gpioBits =  0x00130103;
  342.   }
  343.  
  344.   for(i=0; i<TX_RING_SIZE; ++i) {
  345.     txRing[i].mdp = NULL;
  346.   }
  347.  
  348.   for(i=0; i<NUM_RX_BUFFERS; ++i) {
  349.     rxMDPList[i] = NULL;
  350.   }
  351.  
  352.   readActive = false;
  353.   supports1000BaseT = false;
  354.   txQueueStopped = false;
  355.   readThreadCmd = 0;
  356.   writePipeStalled = false;
  357.   writeStallCleared = false;
  358.   pktQueueLen = 0;
  359.   debugFlags = 0;
  360.   txInProgress = 0;
  361.   txQueueLock = NULL;
  362.   txLock = NULL;
  363.   rxQueueLock = NULL;
  364.   rxThread = NULL;
  365.   txSpots = TX_RING_SIZE;
  366.   txPkt = NULL;
  367.   recursionLevel = 0;
  368.   started = false;
  369.   awake = false;
  370.   callbackPending = false;
  371.   checkLinkPending = false;
  372.   miiPending = false;
  373.   interruptPending = false;
  374.   readingInterrupt = false;
  375.   fNetworkInterface = NULL;
  376.   fDataInterface = NULL;
  377.   fpDevice = NULL;
  378.   fMediumDict = NULL;
  379.   fTransmitQueue = NULL;
  380.   fTimerSource = NULL;
  381.   timerPending = false;
  382.   fTerminate = false;
  383.   fNetifEnabled = false;
  384.   fNetifRequestEnabled = false;
  385.   fInPipe = NULL;
  386.   fOutPipe = NULL;
  387.   fCntlPipe = NULL;
  388.   fInterruptPipe = NULL;
  389.   fPipeInterruptMDP = NULL;
  390.   modelStr[0] = '\0';
  391.   vendorStr[0] = '\0';
  392.   revisionStr[0] = '\0';
  393.   ourPolicyMaker = NULL;
  394.   powerUpThread = NULL;
  395.   powerDownThread = NULL;
  396.   fpEtherStats = NULL;
  397.   fpNetStats = NULL;
  398.   promiscMode = false;
  399.   promiscRequest = false;
  400.   fMulticastEnable = false;
  401.   ethCtrl0Val = 0x08;
  402.   ethCtrl1Val = 0x00;
  403.   ethCtrl2Val = 0x03;
  404.   rxCtrlVal = 0x00;
  405.   fLinkUp = false;
  406.   rcvdLinkStatus = false;
  407.   mcBytesToWrite = 0;
  408.   setMc = false;
  409.   txDone = false;
  410.   suspendPending = false;
  411.   resumePending = false;
  412.   ackPowerPending = false;
  413.   cState = ctrlStateSuspend;
  414.   miiState = miiStateIdle;
  415.   selectedMedium = kIOMediumEthernetNone;
  416.   requestedMedium = kIOMediumEthernetAuto;
  417.  
  418.   IOLog("USBAx8817x: This product includes software developed by Bill Paul.\n");
  419.   return true;
  420. } /* end init */
  421.  
  422. /*****************************************************************************/
  423. //
  424. //              Method:         USBAx8817x::probe
  425. //
  426. //              Inputs:         provider - my provider
  427. //                              score    - a score indicating how well
  428. //                                         this driver is matched to
  429. //                                         the device.
  430. //
  431. //              Outputs:        this (I think I can drive this device),
  432. //                              NULL (I don't recognize the device)
  433. //
  434. //              Desc:           This is called to let the driver probe
  435. //                              the device to see if the driver is
  436. //                              compatible with the device.
  437. //
  438. /****************************************************************************/
  439. IOService * USBAx8817x::probe(IOService *provider, SInt32 *score ) {
  440.   if(!super::probe(provider, score)) {
  441.     return NULL;
  442.   }
  443.  
  444.   return this;
  445. } /* end probe */
  446.  
  447. /*****************************************************************************/
  448. //
  449. //              Method:         USBAx8817x::start
  450. //
  451. //              Inputs:         provider - my provider
  452. //
  453. //              Outputs:        Return code - true (it's me), 
  454. //                              false (sorry it probably was me, but I can't 
  455. //                              configure it)
  456. //
  457. //              Desc:           This is called once it has beed determined I'm 
  458. //                              probably the best driver for this device.
  459. //
  460. /****************************************************************************/
  461. bool USBAx8817x::start(IOService *provider) {
  462.   if(!super::start(provider)) {
  463.     IOLog("USBAx8817x::start: Failed to start provider.\n");
  464.     return false;
  465.   }
  466.  
  467.   if(openUSB(provider) == false) {
  468.     stop(provider);
  469.     return false;
  470.   }
  471.  
  472.   if(allocateBuffers() == false) {
  473.     stop(provider);
  474.     return false;
  475.   }
  476.  
  477.   if(resetMAC() == false) {
  478.     stop(provider);
  479.     return false;
  480.   }
  481.  
  482.   if(createNetworkInterface() == false) {
  483.     stop(provider);
  484.     return false;
  485.   }
  486.  
  487.   if(createMediumTables() == false) {
  488.     stop(provider);
  489.     return false;
  490.   }
  491.  
  492.   if(startIO() == false) {
  493.     stop(provider);
  494.     return false;
  495.   }
  496.  
  497.   postEvent(this, (void *)(int)ctrlEventStart);
  498.   return true;          
  499. } /* end start */
  500.  
  501. /*****************************************************************************/
  502. //
  503. //      Method:         USBAx8817x::openUSB
  504. //
  505. //      Inputs:         None
  506. //
  507. //      Outputs:        true if successful, false otherwise
  508. //
  509. //      Desc:           Opens the USB device and all the points.
  510. //
  511. /*****************************************************************************/
  512. bool USBAx8817x::openUSB(IOService *provider) {
  513.   IOUSBFindInterfaceRequest             req; // device request
  514.   IOReturn                              ior = kIOReturnSuccess;
  515.   UInt16                                numends;
  516.   bool                                  goodCall;
  517.   IOUSBFindEndpointRequest              epReq; // endPoint request struct
  518.   const IOUSBEndpointDescriptor         *epDesc;
  519.   UInt8                                 strIndex, config;
  520.   const IOUSBConfigurationDescriptor    *cd = NULL; // configuration descriptor
  521.  
  522.   // Get my USB device provider - the device
  523.   fpDevice = OSDynamicCast(IOUSBDevice, provider);
  524.   if(!fpDevice) {
  525.     IOLog("USBAx8817x::openUSB: Unable to get provider device.\n");
  526.     stop(provider);
  527.     return false;
  528.   }
  529.  
  530.   if(!fpDevice->open(this)) {
  531.     IOLog("USBAx8817x::openUSB: failed to open provider.\n");
  532.     fpDevice = NULL;
  533.     return false;
  534.   }
  535.   fpDevice->retain();
  536.  
  537.   /* The USB-Ethernet device only has one configuraion (as far as I
  538.      know). If this device has more configurations, I assume it is a
  539.      different type of device.*/
  540.   if(fpDevice->GetNumConfigurations() != 1) {
  541.     IOLog("USBAx8817x::openUSB: Wrong number of configurations.\n");
  542.     return false;
  543.   }
  544.  
  545.   /* Open USB Pipes */
  546.   cd = fpDevice->GetFullConfigurationDescriptor(0);
  547.   if (!cd) {
  548.     IOLog("USBAx8817x::openUSB: GetFullConfigurationDescriptor() failed.\n");
  549.     return false;
  550.   }
  551.   
  552.   config = cd->bConfigurationValue;
  553.   ior = fpDevice->SetConfiguration(this, config);
  554.   if (ior != kIOReturnSuccess) {
  555.     IOLog("USBAx8817x::openUSB: SetConfiguratoin() failed.\n");
  556.     return false;
  557.   }
  558.  
  559.   strIndex = fpDevice->GetManufacturerStringIndex();
  560.   if(strIndex != 0) {
  561.     fpDevice->GetStringDescriptor(strIndex, vendorStr, 32);
  562.   }
  563.  
  564.   strIndex = fpDevice->GetProductStringIndex();
  565.   if(strIndex != 0) {
  566.     fpDevice->GetStringDescriptor(strIndex, modelStr, 32);
  567.   }
  568.   strIndex = fpDevice->GetSerialNumberStringIndex();
  569.   if(strIndex != 0) {
  570.     fpDevice->GetStringDescriptor(strIndex, revisionStr, 32);
  571.   }
  572.  
  573.   req.bInterfaceClass   = kIOUSBFindInterfaceDontCare;
  574.   req.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
  575.   req.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
  576.   req.bAlternateSetting = kIOUSBFindInterfaceDontCare;
  577.  
  578.   /* Hopefully this will find interface zero... */    
  579.   fDataInterface = fpDevice->FindNextInterface(NULL, &req);
  580.   if (fDataInterface == NULL) {
  581.     IOLog("USBAx8817x::openUSB: FindNextInterfaceDescriptor() failed.\n");
  582.     return false;
  583.   }
  584.  
  585.   goodCall = fDataInterface->open(this);
  586.   if (!goodCall) {
  587.     fDataInterface = NULL;
  588.     IOLog("USBAx8817x::openUSB: Open Data Interface failed.\n");
  589.     return false;
  590.   }
  591.   fDataInterface->retain();
  592.     
  593.   numends = fDataInterface->GetNumEndpoints();    
  594.   if (numends != 3) {
  595.     IOLog("USBAx8817x::openUSB: Number of endpoints (%d) is not 3.\n", numends);
  596.     return false;
  597.   }
  598.  
  599.   // Open all the end points
  600.   fCntlPipe = fpDevice->GetPipeZero();
  601.  
  602.   if(fCntlPipe == NULL) {
  603.     IOLog("USBAx8817x::openUSB: Failed to find control pipe.\n");
  604.     return false;
  605.   }
  606.  
  607.   epReq.type = kUSBInterrupt;
  608.   epReq.direction = kUSBIn;
  609.   epReq.maxPacketSize = 0;
  610.   epReq.interval = 0;
  611.   fInterruptPipe = fDataInterface->FindNextPipe(NULL, &epReq);
  612.   if(fInterruptPipe == NULL) {
  613.     IOLog("USBAx8817x::openUSB: Failed to find interrupt pipe.\n");
  614.     return false;
  615.   }
  616.  
  617.   epReq.type = kUSBBulk;
  618.   epReq.direction = kUSBIn;
  619.   epReq.maxPacketSize = 0;
  620.   epReq.interval = 0;
  621.   fInPipe = fDataInterface->FindNextPipe(NULL, &epReq);
  622.  
  623.   if(fInPipe == NULL) {
  624.     IOLog("USBAx8817x::openUSB: Failed to find bulk incoming pipe.\n");
  625.     return false;
  626.   }
  627.  
  628.   epDesc = fInPipe->GetEndpointDescriptor();
  629.  
  630.   epReq.direction = kUSBOut;
  631.   fOutPipe = fDataInterface->FindNextPipe(NULL, &epReq);
  632.   if(fOutPipe == NULL) {
  633.     IOLog("USBAx8817x::openUSB: Failed to find bulk outgoing pipe.\n");
  634.     return false;
  635.   }
  636.  
  637.   maxPacketSize = USBToHostWord(epDesc->wMaxPacketSize);
  638.  
  639.   return true;
  640. } /* end openUSB */
  641.  
  642. /*****************************************************************************/
  643. //
  644. //              Method:         USBAx8817x::allocateBuffers
  645. //
  646. //              Inputs:         provider - none
  647. //
  648. //              Outputs:        Return code - true means success
  649. //                                            false meand failure
  650. //
  651. //              Desc:           Allocates the buffers for asynchronous I/O.
  652. //
  653. /****************************************************************************/
  654. bool USBAx8817x::allocateBuffers() {
  655.   int i;
  656.  
  657.   for(i=0; i<NUM_RX_BUFFERS; ++i) {
  658.     rxMDPList[i] = 
  659.       IOBufferMemoryDescriptor::withCapacity(BUFSIZE, kIODirectionIn);
  660.     if(!rxMDPList[i]) {
  661.       IOLog("USBAx8817x::allocateBuffers: Failed to allocate input buffer %d.\n",
  662.             i);
  663.       return false;
  664.     }
  665.     rxMDPList[i]->setLength(BUFSIZE);
  666.   }
  667.  
  668.   fPipeInterruptMDP = 
  669.     IOBufferMemoryDescriptor::withCapacity(8, kIODirectionIn);
  670.   if(!fPipeInterruptMDP) {
  671.     IOLog("USBAx8817x::allocateBuffers: Failed to allocate interrupt buffer.\n");
  672.     return false;
  673.   }
  674.   fPipeInterruptMDP->setLength(8);
  675.   fInterruptPipeBuffer = (UInt8 *)fPipeInterruptMDP->getBytesNoCopy();
  676.  
  677.   fPipeCtrlMDP = IOBufferMemoryDescriptor::withCapacity(8, kIODirectionIn);
  678.   if(!fPipeCtrlMDP) {
  679.     IOLog("USBAx8817x::allocateBuffers: Failed to allocate control buffer.\n");
  680.     return false;
  681.   }
  682.   fPipeCtrlMDP->setLength(8);
  683.   fCtrlPipeBuffer = (UInt8 *)fPipeCtrlMDP->getBytesNoCopy();
  684.  
  685.   /* Allocate Trsnsmit Ring buffers. */
  686.   for(i=0; i<TX_RING_SIZE; ++i) {
  687.     txRing[i].mdp = IOBufferMemoryDescriptor::withCapacity(BUFSIZE, 
  688.                                                            kIODirectionOut);
  689.     if(!txRing[i].mdp) {
  690.       IOLog("USBAx8817x::allocateBuffers: Failed to allocate output buffer %d.\n",
  691.             i);
  692.       return false;
  693.     }
  694.  
  695.     txRing[i].buffer = (UInt8 *)txRing[i].mdp->getBytesNoCopy();
  696.     txRing[i].packet = NULL;
  697.     txRing[i].flags = 0;
  698.   }
  699.  
  700.   /* Connect Transmit Ring. */
  701.   for(i=0; i<(TX_RING_SIZE-1); ++i) {
  702.     txRing[i].next = &txRing[i+1];
  703.   }
  704.   txRing[i].next = &txRing[0];
  705.  
  706.   /* Connect Receive Ring. */
  707.   for(i=0; i<(NUM_RX_BUFFERS-1); ++i) {
  708.     readComp[i].next = &readComp[i+1];
  709.   }
  710.   readComp[i].next = &readComp[0];
  711.  
  712.   txProducePtr = &txRing[0];
  713.   txConsumePtr = &txRing[0];
  714.   rxRing = &readComp[0];
  715.  
  716.   return true;
  717. } /* end allocateBuffers */
  718.  
  719. /*****************************************************************************/
  720. //
  721. //      Method:         USBAx8817x::resetMAC
  722. //
  723. //      Inputs:         None
  724. //
  725. //      Outputs:        true if successful, false otherwise
  726. //
  727. //      Desc:           Tries to reset the MAC and the phy, and read
  728. //                      the ethernet address.
  729. //
  730. /*****************************************************************************/
  731. bool USBAx8817x::resetMAC() {
  732.   UInt8 ipgs[4];
  733.   UInt16 data16;
  734.   int i;
  735.   bool ret;
  736.  
  737.   IOLog("USBAx8817x: Version 1.0.1.\n");
  738.  
  739.   /* Toggle the GPIOs in a manufacturer/model specific way */
  740.   /* Taken from usbnet.c linux driver.*/
  741.   for (i = 2; i >= 0; i--) {
  742.     if(!axCmd(AXE_CMD_WRITE_GPIO, 0,(gpioBits >> (i * 8)) & 0xff, NULL)) {
  743.       IOLog("USBAx8817x: resetMAC: Failed to write GPIO bits.\n");
  744.       return false;
  745.     }
  746.     IOSleep(5);
  747.   }
  748.  
  749.   /*
  750.    * Get station address.
  751.    */
  752.   bzero(fEaddr, 6);
  753.   if(!axCmd(AXE_CMD_READ_NODEID, 0, 0, &fEaddr)) {
  754.     IOLog("USBAx8817x: resetMAC: Failed to read Node ID.\n");
  755.     return false;
  756.   }
  757.  
  758.   /* Disable flow control */
  759.   mediumStatus = 0;
  760.   if(!axCmd(AXE_CMD_WRITE_MEDIA, 0, mediumStatus, NULL)) {
  761.     IOLog("USBAx8817x: resetMAC: Failed to write medium status.\n");
  762.     return false;
  763.   }
  764.  
  765.   rxCtrlVal = AXE_RXCMD_BROADCAST | AXE_RXCMD_UNICAST | 
  766.     AXE_RXCMD_MULTICAST;
  767.   if(!axCmd(AXE_CMD_RXCTL_WRITE, 0, rxCtrlVal, NULL)) {
  768.       IOLog("USBAx8817x: resetMAC: Failed to write rx control.\n");
  769.       return false;
  770.   }
  771.  
  772.   axCmd(AXE_CMD_READ_IPG012, 0, 0, ipgs);
  773.   if(!axCmd(AXE_CMD_WRITE_IPG0, 0, ipgs[0], NULL)) {
  774.     IOLog("USBAx8817x: resetMAC: Failed to write IPG Register 0.\n");
  775.     return false;
  776.   }
  777.  
  778.   if(!axCmd(AXE_CMD_WRITE_IPG1, 0, ipgs[1], NULL)) {
  779.     IOLog("USBAx8817x: resetMAC: Failed to write IPG Register 1.\n");
  780.     return false;
  781.   }
  782.  
  783.   if(!axCmd(AXE_CMD_WRITE_IPG2, 0, ipgs[2], NULL)) {
  784.     IOLog("USBAx8817x: resetMAC: Failed to write IPG Register 2.\n");
  785.     return false;
  786.   }
  787.  
  788.   phy = -1;
  789.   for(i=0; i<32; ++i) {
  790.     data16 = 0;
  791.     ret = readMiiWord(i, 1, &data16);
  792.  
  793.     if(ret && (data16 != 0xffff) && (data16 & 0x7800) ) {
  794.       phy = i;
  795.       break;
  796.     }
  797.   }
  798.  
  799.   if(phy == -1) {
  800.     IOLog("USBAx8817x: resetMAC: Could not located the ethernet phy.\n");
  801.     return false;
  802.   }
  803.  
  804.   if(data16 & 0x0100) {
  805.     supports1000BaseT = true;
  806.     IOLog("USBAx8817x: Found 1000BaseT capable phy.\n");
  807.     readMiiWord(phy, 15, &data16);
  808.     IOLog("USBAx8817x: MII register 15 = 0x%X.\n", data16);
  809.   }
  810.   
  811.   data16=0;
  812.   if(axCmd(AXE_CMD_SROM_READ, 0, 0x10, &data16)) {
  813.     deviceFlag = USBToHostWord(data16);
  814.     IOLog("USBAx8817x: Max packet size is = %d.\n", deviceFlag);
  815.   }
  816.  
  817.   data16=0;
  818.   if(axCmd(AXE_CMD_SROM_READ, 0, 0x01, &data16)) {
  819.     data16 = USBToHostWord(data16);
  820.     IOLog("USBAx8817x: flags = 0x%X.\n", data16);
  821.   }
  822.  
  823.   return true;
  824. } /* end resetMAC */
  825.  
  826. /***************************************************************************/
  827. //
  828. //      Method:    USBAx8817x::registerWithPolicyMaker
  829. //
  830. //      Inputs:    policyMaker - Power Policy Maker object
  831. //
  832. //      Outputs:   IOReturnSuccess if succesful
  833. //
  834. //      Desc:      This function is based on the registerWithPolicyMaker()
  835. //                 in i82557PM.c from the Darwin source code.  Register
  836. //                 with the power management policy maker.
  837. //   
  838. /****************************************************************************/
  839. IOReturn USBAx8817x::registerWithPolicyMaker(IOService *policyMaker) {
  840.   currentPowerState = kUSBEthernetOffState;
  841.   ourPolicyMaker = policyMaker;
  842.  
  843.   powerDownThread = 
  844.     thread_call_allocate((thread_call_func_t)  handleSetPowerStateOff, 
  845.                          (thread_call_param_t) this );
  846.   
  847.   powerUpThread  = 
  848.     thread_call_allocate((thread_call_func_t)  handleSetPowerStateOn,
  849.                          (thread_call_param_t) this );
  850.  
  851.   return policyMaker->registerPowerDriver(this, ourPowerStates, 
  852.                                           kNumPowerStates);
  853. } /* end registerWithPolicyMaker */
  854.  
  855.  
  856. /*****************************************************************************/
  857. //
  858. //      Method:         USBAx8817x::createNetworkInterface
  859. //
  860. //      Inputs:         
  861. //
  862. //      Outputs:        return Code - true (created and initialilzed ok), 
  863. //                                    false (it failed)
  864. //
  865. //      Desc:           Creates and initializes the network interface
  866. //
  867. /*****************************************************************************/
  868. bool USBAx8817x::createNetworkInterface() {
  869.   fTransmitQueue = (AxOutputQueue *)getOutputQueue();
  870.   //fTransmitQueue = (IOBasicOutputQueue *)getOutputQueue();
  871.   if (!fTransmitQueue)  {
  872.  
  873.     IOLog("USBAx8817x::createNetworkInterface: Failed to get output queue.\n");
  874.     return false;
  875.   }
  876.   fTransmitQueue->retain();
  877.  
  878.   fWorkLoop = getWorkLoop();  
  879.   if(!fWorkLoop) {
  880.     IOLog("USBAx8817x::createNetworkInterface: Failed to get work loop.\n");
  881.     return false;
  882.   }
  883.  
  884.   fTimerSource = IOTimerEventSource::timerEventSource(this, timerFired);
  885.   if (fTimerSource == NULL) {
  886.     IOLog("USBAx8817x::createNetworkInterface: Failed to allocate timer.\n");
  887.     return false;
  888.   }
  889.   fTimerSource->retain();
  890.     
  891.   if (fWorkLoop->addEventSource(fTimerSource) != kIOReturnSuccess) {
  892.     IOLog("USBAx8817x::createNetworkInterface: Failed to add timer event.\n");
  893.     return false;
  894.   }
  895.  
  896.   if (!attachInterface((IONetworkInterface **)&fNetworkInterface, true)) {
  897.     IOLog("USBAx8817x::createNetworkInterface: Failed to attach network interface.\n");
  898.     return false;
  899.   }
  900.  
  901.   //retain();
  902.   return true;
  903.         
  904. }/* end createNetworkInterface */
  905.  
  906. /****************************************************************************/
  907. //
  908. //      Method:         USBAx8817x::createMediumTables
  909. //
  910. //      Inputs:         
  911. //
  912. //      Outputs:        Return code - true (tables created), false (not 
  913. //                                    created)
  914. //
  915. //      Desc:           Creates the medium tables
  916. //
  917. /****************************************************************************/
  918. bool USBAx8817x::createMediumTables() {
  919.   IONetworkMedium       *medium;
  920.   UInt32                i;
  921.  
  922.   fMediumDict = OSDictionary::withCapacity(sizeof(mediumTable) / 
  923.                                            sizeof(mediumTable[0]));
  924.   if(fMediumDict == NULL) {
  925.     IOLog("USBAx8817x::createMediumTables: Failed to create dictionary.\n");
  926.     return false;
  927.   }
  928.  
  929.   for(i = 0; i < sizeof(mediumTable) / sizeof(mediumTable[0]); i++ ) {
  930.     medium = IONetworkMedium::medium(mediumTable[i].type, 
  931.                                      mediumTable[i].speed);
  932.     IONetworkMedium::addMedium(fMediumDict, medium);
  933.     medium->release();
  934.   }
  935.  
  936.   if(supports1000BaseT) {
  937.     medium = IONetworkMedium::medium(kIOMediumEthernet1000BaseTX |
  938.                                      kIOMediumOptionFullDuplex, 1000);
  939.     IONetworkMedium::addMedium(fMediumDict, medium);
  940.     medium->release();
  941.  
  942.     medium = IONetworkMedium::medium(kIOMediumEthernet1000BaseTX |
  943.                                      kIOMediumOptionHalfDuplex, 1000);
  944.     IONetworkMedium::addMedium(fMediumDict, medium);
  945.     medium->release();
  946.   }
  947.  
  948.   if(publishMediumDictionary(fMediumDict) != true) {
  949.     IOLog("USBAx8817x::createMediumTables: Failed to publish medium dictionary.\n");
  950.     return false;
  951.   }
  952.  
  953.   medium = 
  954.     IONetworkMedium::getMediumWithType(fMediumDict, kIOMediumEthernetAuto);
  955.   setSelectedMedium(medium);
  956.  
  957.   medium = 
  958.     IONetworkMedium::getMediumWithType(fMediumDict, kIOMediumEthernetNone);
  959.   setLinkStatus(kIONetworkLinkValid, medium);
  960.   fLinkUp = false;
  961.  
  962.   return true;    
  963. } /* end createMediumTables */
  964.  
  965. /****************************************************************************/
  966. //
  967. //      Method:         USBAx8817x::createMediumTables
  968. //
  969. //      Inputs:         none
  970. //
  971. //      Outputs:        Return code - true (success), false (failure)
  972. //
  973. //      Desc:           Initializes asychronous I/O
  974. //
  975. /****************************************************************************/
  976. bool USBAx8817x::startIO() {
  977.   //IOReturn ior;
  978.   int i;
  979.  
  980.   fCtrlRead.pData = fPipeCtrlMDP;
  981.   fCtrlWrite.pData = fPipeCtrlMDP;
  982.  
  983.   fCtrlCompletionInfo.target = this;
  984.   fCtrlCompletionInfo.action = ctrlComplete;
  985.   fCtrlCompletionInfo.parameter = NULL;
  986.  
  987.   fInterruptCompletionInfo.target = this;
  988.   fInterruptCompletionInfo.action = interruptComplete;
  989.   fInterruptCompletionInfo.parameter = NULL;
  990.  
  991.   for(i=0; i<NUM_RX_BUFFERS; ++i) {
  992.     fReadCompletionInfo[i].target = this;
  993.     fReadCompletionInfo[i].action = dataReadComplete;
  994.     fReadCompletionInfo[i].parameter = (void *)&readComp[i];
  995.     readComp[i].completion = &fReadCompletionInfo[i];
  996.     readComp[i].mdp = rxMDPList[i];
  997.     readComp[i].flags = 0;
  998.     readComp[i].packetLength = 0;
  999.   }
  1000.  
  1001.   for(i=0; i<TX_RING_SIZE; ++i) {
  1002.     txRing[i].writeCompletionInfo.target = this;
  1003.     txRing[i].writeCompletionInfo.action = dataWriteComplete;
  1004.     txRing[i].writeCompletionInfo.parameter = &txRing[i];
  1005.  
  1006.     txRing[i].writeZeroCompletionInfo.target = this;
  1007.     txRing[i].writeZeroCompletionInfo.action = dataWriteZeroComplete;
  1008.     txRing[i].writeZeroCompletionInfo.parameter = NULL;
  1009.   }
  1010.  
  1011.   txLock = IOLockAlloc();
  1012.  
  1013.   txQueueLock = IOLockAlloc();
  1014.   if(txQueueLock == NULL) {
  1015.     IOLog("USBAx8817x: startIO: Failed to allocate txQueueLock.\n");
  1016.     return false;
  1017.   }
  1018.  
  1019.   rxQueueLock = IOLockAlloc();
  1020.   if(rxQueueLock == NULL) {
  1021.     IOLog("USBAx8817x: startIO: Failed to allocate rxQueueLock.\n");
  1022.     return false;
  1023.   }
  1024.  
  1025.   rxThread = IOCreateThread(rxThreadEntry, this);
  1026.   if(rxThread == NULL) {
  1027.     IOLog("USBAx8817x: startIO: Failed to start rx thread.\n");
  1028.     return false;
  1029.   }
  1030.  
  1031.   return true;
  1032. } /* end startIO */
  1033.  
  1034. /*****************************************************************************/
  1035. //
  1036. //      Method:         USBAx8817x::createOutputQueue
  1037. //
  1038. //      Inputs:         
  1039. //
  1040. //      Outputs:        Return code - the output queue
  1041. //
  1042. //      Desc:           Creates the output queue
  1043. //
  1044. /*****************************************************************************/
  1045. IOOutputQueue* USBAx8817x::createOutputQueue() {
  1046.   return AxOutputQueue::withTarget(this, TRANSMIT_QUEUE_SIZE);
  1047.   //return IOBasicOutputQueue::withTarget(this, TRANSMIT_QUEUE_SIZE);
  1048. } /* end createOutputQueue */
  1049.  
  1050.  
  1051. /* 
  1052.  * configureInterface() - Ripped off from UniNEnet.cpp
  1053.  *  
  1054.  */
  1055. bool USBAx8817x::configureInterface( IONetworkInterface *netif ) {
  1056.   IONetworkData *nd;
  1057.  
  1058.   if ( super::configureInterface( netif ) == false ) {
  1059.     return false;
  1060.   }
  1061.  
  1062.   /* Grab a pointer to the statistics structure in the interface:       */
  1063.  
  1064.   nd = netif->getNetworkData( kIONetworkStatsKey );
  1065.   if ( !nd || !(fpNetStats = (IONetworkStats*)nd->getBuffer()) ) {
  1066.     IOLog( "USBAx8817x::configureInterface invalid network statistics.\n" );
  1067.     return false;
  1068.   }
  1069.   fpNetStats->outputPackets = 0;
  1070.   fpNetStats->inputPackets = 0;
  1071.  
  1072.   // Get the Ethernet statistics structure:
  1073.   nd = netif->getParameter( kIOEthernetStatsKey );
  1074.   if ( !nd || !(fpEtherStats = (IOEthernetStats*)nd->getBuffer()) ) {
  1075.     IOLog( "USBAx8817x::configureInterface - invalid ethernet statistics\n" );
  1076.     return false;
  1077.   }
  1078.  
  1079.   return true;
  1080. } /* end configureInterface */
  1081.  
  1082. /****************************************************************************/
  1083. //
  1084. //      Method:         USBAx8817x::createInterface
  1085. //
  1086. //      Inputs:         none
  1087. //
  1088. //      Outputs:        Return Value - Pointer to IONetworkInterface
  1089. //
  1090. //      Desc:           Creates the network interface object. A custom
  1091. //                      network interface object is created that
  1092. //                      removes the IFF_RUNNING flag when it is
  1093. //                      destroyed.  This seems to help destroy the bsd
  1094. //                      network interface when the device is unplugged.
  1095. //
  1096. /*****************************************************************************/
  1097. IONetworkInterface * USBAx8817x::createInterface() {
  1098.   USBAx8817xEthernetInterface * netif = new USBAx8817xEthernetInterface;
  1099.  
  1100.   if(netif && (netif->init(this) == false) ) {
  1101.     netif->release();
  1102.     netif = NULL;
  1103.   }
  1104.  
  1105.   return netif;
  1106. } /* end createInterface */
  1107.  
  1108. /*****************************************************************************/
  1109. //
  1110. //      Method:         USBAx8817x::getPacketFilters
  1111. //
  1112. //      Inputs:         group - the filter group
  1113. //
  1114. //      Outputs:        Return code - kIOReturnSuccess and others
  1115. //                      filters - the capability
  1116. //
  1117. //      Desc:           Set the filter capability for the driver
  1118. //
  1119. /*****************************************************************************/
  1120. IOReturn USBAx8817x::getPacketFilters(const OSSymbol *group, 
  1121.                                       UInt32 *filters) const {
  1122.   IOReturn      rtn = kIOReturnSuccess;
  1123.     
  1124.   if (group == gIONetworkFilterGroup) {
  1125.     *filters = kIOPacketFilterUnicast | kIOPacketFilterBroadcast | 
  1126.       kIOPacketFilterPromiscuous | kIOPacketFilterMulticast;
  1127.  
  1128.   } else {
  1129.     rtn = super::getPacketFilters(group, filters);
  1130.   }
  1131.     
  1132.   if (rtn != kIOReturnSuccess) {
  1133.     IOLog("USBAx8817x::getPacketFilters: Failed to get packet filters\n");
  1134.   }
  1135.     
  1136.   return rtn;    
  1137. } /* end getPacketFilters */
  1138.  
  1139. void USBAx8817x::rxThreadEntry(void *ob) {
  1140.   USBAx8817x *me;
  1141.  
  1142.   me = (USBAx8817x *)ob;
  1143.   if(me != NULL) {
  1144.     me->rxLoop();
  1145.   }
  1146.  
  1147.   IOExitThread();
  1148. } /* end rxThreadEntry */
  1149.  
  1150. #pragma mark -- Upper Layer Events --
  1151.  
  1152. /****************************************************************************/
  1153. //
  1154. //      Method:         USBAx8817x::enable
  1155. //
  1156. //      Inputs:         netif - the interface being enabled
  1157. //
  1158. //      Outputs:        Return code - kIOReturnSuccess or kIOReturnIOError
  1159. //
  1160. //      Desc:           Called by IOEthernetInterface client to enable the
  1161. //                      controller.
  1162. //
  1163. //                      This method is always called while running on the 
  1164. //                      default workloop thread.
  1165. //
  1166. /*****************************************************************************/
  1167. IOReturn USBAx8817x::enable(IONetworkInterface *netif) {
  1168.   fTransmitQueue->setCapacity(TRANSMIT_QUEUE_SIZE);
  1169.   fTransmitQueue->start();
  1170.  
  1171.   //POSTEVENT(ctrlEventEnable);
  1172.  
  1173.    IOLockLock(rxQueueLock);
  1174.    readThreadCmd &= ~RXTHREAD_CLOSE;
  1175.    readThreadCmd |= RXTHREAD_OPEN;
  1176.    IOLockWakeup(rxQueueLock, NO_EVENT, true);
  1177.    IOLockUnlock(rxQueueLock);
  1178.  
  1179.   return kIOReturnSuccess;
  1180. } /* end enable */
  1181.  
  1182. /*****************************************************************************/
  1183. //
  1184. //      Method:         USBAx8817x::disable
  1185. //
  1186. //      Inputs:         netif - the interface being disabled
  1187. //
  1188. //      Outputs:        Return code - kIOReturnSuccess
  1189. //
  1190. //      Desc:           Called by IOEthernetInterface client to disable the 
  1191. //                      controller.
  1192. //
  1193. //                      This method is always called while running on the 
  1194. //                      default workloop thread.
  1195. //
  1196. /****************************************************************************/
  1197.  IOReturn USBAx8817x::disable(IONetworkInterface * /*netif*/) {
  1198.    fTransmitQueue->stop();
  1199.    fTransmitQueue->setCapacity(0);
  1200.    fTransmitQueue->flush();
  1201.  
  1202.    IOLockLock(rxQueueLock);
  1203.    readThreadCmd &= ~RXTHREAD_OPEN;
  1204.    readThreadCmd |= RXTHREAD_CLOSE;
  1205.    IOLockWakeup(rxQueueLock, NO_EVENT, true);
  1206.    IOLockUnlock(rxQueueLock);
  1207.  
  1208.    return kIOReturnSuccess;
  1209. } /* end disable */
  1210.  
  1211.  
  1212. /*****************************************************************************/
  1213. //
  1214. //      Method:         USBAx8817x::outputPacket
  1215. //
  1216. //      Inputs:         mbuf - the packet
  1217. //                      param - optional parameter
  1218. //
  1219. //      Outputs:        Return code - kIOReturnOutputSuccess or 
  1220. //                                    kIOReturnOutputStall
  1221. //
  1222. //      Desc:           Packet transmission. The BSD mbuf needs to be 
  1223. //                      formatted correctly and transmitted
  1224. //                              
  1225. //
  1226. /*****************************************************************************/
  1227. UInt32 USBAx8817x::outputPacket(mbuf_t pkt, void *param) {
  1228.   mbuf_t m;
  1229.   int total_pkt_length;
  1230.   UInt8 *pipeBuffer;
  1231.   int txCount;
  1232.   int queueLen;
  1233.   IOBufferMemoryDescriptor *pipeMDP;
  1234.  
  1235.   if(!pkt) {
  1236.     return kIOReturnSuccess;
  1237.   }
  1238.  
  1239.   IOLockLock(txQueueLock);
  1240.   queueLen = --txSpots;
  1241.   if(queueLen == 0) {
  1242.     txQueueStopped = true;
  1243.   }
  1244.   IOLockUnlock(txQueueLock);
  1245.  
  1246.   if(queueLen < 0) {
  1247.     IOLockLock(txQueueLock);
  1248.     ++txSpots;
  1249.     IOLockUnlock(txQueueLock);
  1250.     IOLog("USBAx8817x: outputPacket: No buffers.  Requeuing packet.\n");
  1251.     return kIOOutputStatusRetry | kIOOutputCommandStall;
  1252.   }
  1253.  
  1254.   m = pkt;
  1255.   total_pkt_length = 0;
  1256.   while(m) {
  1257.     total_pkt_length += mbuf_len(m);
  1258.     m = mbuf_next(m);
  1259.   }
  1260.     
  1261.   if(total_pkt_length > kIOEthernetMaxPacketSize) {
  1262.     total_pkt_length = kIOEthernetMaxPacketSize;
  1263.   }
  1264.  
  1265.   txProducePtr = txProducePtr->next;
  1266.   pipeBuffer = txProducePtr->buffer;
  1267.   pipeMDP = txProducePtr->mdp;
  1268. #if 0
  1269.   m = pkt;
  1270.   txCount = 0;
  1271.  
  1272.   while(m) {
  1273.     if(mbuf_len(m) > 0) {
  1274.       bcopy(mbuf_data(m), &pipeBuffer[txCount], mbuf_len(m));
  1275.       txCount += mbuf_len(m);
  1276.     }
  1277.     m = mbuf_next(m);
  1278.   }
  1279.  
  1280.   /* Minimum packet is 60 bytes */
  1281.   if(txCount < 60) {
  1282.     bzero(&pipeBuffer[txCount], 60 - txCount);
  1283.     txCount = 60;
  1284.   }
  1285. #endif
  1286.   txCount = copyPktToBuffer(pkt, pipeBuffer, total_pkt_length);
  1287.   pipeMDP->setLength(txCount);
  1288.   postEvent(this, (void *)ctrlEventTransmit);
  1289.   freePacket(pkt);
  1290.  
  1291.   if(queueLen > 0) {
  1292.     return kIOOutputStatusAccepted | kIOOutputCommandNone;
  1293.   } else {
  1294.     return kIOOutputStatusAccepted | kIOOutputCommandStall;
  1295.   }
  1296.  
  1297. } /* end outputPacket */
  1298.  
  1299. int USBAx8817x::copyPktToBuffer(mbuf_t m, UInt8 *buf, int len) {
  1300.   while(m) {
  1301.     if(mbuf_len(m) > 0) {
  1302.       bcopy(mbuf_data(m), buf, mbuf_len(m));
  1303.       buf += mbuf_len(m);
  1304.     }
  1305.     m = mbuf_next(m);
  1306.   }
  1307.  
  1308.   /* Minimum packet is 60 bytes */
  1309.   if(len < 60) {
  1310.     bzero(buf, 60 - len);
  1311.     len = 60;
  1312.   }
  1313.  
  1314.   return len;
  1315. }
  1316.  
  1317. /*****************************************************************************/
  1318. //
  1319. //      Method:         USBAx8817x::timerFired
  1320. //
  1321. //      Inputs:         
  1322. //
  1323. //      Outputs:        
  1324. //
  1325. //      Desc:           Static member function called when a timer event fires.
  1326. //
  1327. /****************************************************************************/
  1328. void USBAx8817x::timerFired(OSObject *owner,
  1329.                             IOTimerEventSource *sender) {
  1330.   if(owner) {
  1331.     USBAx8817x* target = OSDynamicCast(USBAx8817x, owner);
  1332.     if(target) {
  1333.       postEvent(owner, (void *)(int)ctrlEventTimer);
  1334.     }
  1335.   }
  1336. } /* end timerFired */
  1337.  
  1338. /*****************************************************************************/
  1339. //
  1340. //      Method:         USBAx8817x::selectMedium
  1341. //
  1342. //      Inputs:
  1343. //
  1344. //      Outputs:
  1345. //
  1346. //      Desc:           Lets us know if someone is playing with ifconfig
  1347. //
  1348. /*****************************************************************************/
  1349. IOReturn USBAx8817x::selectMedium(const IONetworkMedium *medium) {
  1350.   if(!medium) {
  1351.     return kIOReturnError;
  1352.   }
  1353.  
  1354.   switch(medium->getType()) {
  1355.   case kIOMediumEthernet1000BaseTX  | kIOMediumOptionHalfDuplex:
  1356.   case kIOMediumEthernet1000BaseTX  | kIOMediumOptionFullDuplex:
  1357.     if(!supports1000BaseT) {
  1358.       IOLog("USBAx8817x: selectMedium: 1000BaseTx mode is not supported.\n");
  1359.       return kIOReturnError;
  1360.     }
  1361.   case kIOMediumEthernet10BaseT | kIOMediumOptionHalfDuplex:
  1362.   case kIOMediumEthernet10BaseT | kIOMediumOptionFullDuplex:
  1363.   case kIOMediumEthernet100BaseTX  | kIOMediumOptionHalfDuplex:
  1364.   case kIOMediumEthernet100BaseTX  | kIOMediumOptionFullDuplex:
  1365.   case kIOMediumEthernetAuto:
  1366.     requestedMedium = medium->getType();
  1367.     break;
  1368.   case kIOMediumEthernetNone:
  1369.     requestedMedium = kIOMediumEthernetAuto;
  1370.     break;
  1371.   default:
  1372.     IOLog("USBAx8817x: selectMedium: Medium 0x%X does not exist.\n",
  1373.           (int)medium->getType());
  1374.     return kIOReturnError;
  1375.   }
  1376.  
  1377.   POSTEVENT(ctrlEventNudge);
  1378.     
  1379.   return kIOReturnSuccess;
  1380. } /* end selectMedium */
  1381.  
  1382. /*****************************************************************************/
  1383. //
  1384. //      Method:         USBAx8817x::getHardwareAddress
  1385. //
  1386. //      Inputs:         
  1387. //
  1388. //      Outputs:        Return code - kIOReturnSuccess or kIOReturnError
  1389. //                      ea - the address
  1390. //
  1391. //      Desc:           Get the ethernet address from the hardware (actually 
  1392. //                      the descriptor)
  1393. //
  1394. /*****************************************************************************/
  1395. IOReturn USBAx8817x::getHardwareAddress(IOEthernetAddress *ea) {
  1396.   UInt32      i;
  1397.      
  1398.   for (i=0; i<6; i++) {
  1399.     ea->bytes[i] = fEaddr[i];
  1400.   }
  1401.  
  1402.   return kIOReturnSuccess;
  1403. } /* end getHardwareAddress */
  1404.  
  1405. /*****************************************************************************/
  1406. //
  1407. //      Method:         USBAx8817x::newVendorString
  1408. //
  1409. //      Inputs:         
  1410. //
  1411. //      Outputs:        Return code - the vendor string
  1412. //
  1413. //      Desc:           Identifies the hardware vendor
  1414. //
  1415. /****************************************************************************/
  1416. const OSString* USBAx8817x::newVendorString() const {
  1417.   return OSString::withCString(vendorStr);
  1418. } /* end newVendorString */
  1419.  
  1420. /*****************************************************************************/
  1421. //
  1422. //      Method:         USBAx8817x::newModelString
  1423. //
  1424. //      Inputs:         
  1425. //
  1426. //      Outputs:        Return code - the model string
  1427. //
  1428. //      Desc:           Identifies the hardware model
  1429. //
  1430. /****************************************************************************/
  1431. const OSString* USBAx8817x::newModelString() const {
  1432.   return OSString::withCString(modelStr);
  1433. } /* end newModelString */
  1434.  
  1435. /****************************************************************************/
  1436. //
  1437. //      Method:         USBAx8817x::newRevisionString
  1438. //
  1439. //      Inputs:         
  1440. //
  1441. //      Outputs:        Return code - the revision string
  1442. //
  1443. //      Desc:           Identifies the hardware revision
  1444. //
  1445. /*****************************************************************************/
  1446. const OSString* USBAx8817x::newRevisionString() const {
  1447.   return OSString::withCString(revisionStr);
  1448. } /* end newRevisionString */
  1449.  
  1450. /*****************************************************************************/
  1451. //
  1452. //              Method:         USBAx8817x::setMulticastMode
  1453. //
  1454. //              Inputs:         active - true (set it), false (don't)
  1455. //
  1456. //              Outputs:        Return code - kIOReturnSuccess
  1457. //
  1458. //              Desc:           Sets multicast mode
  1459. //
  1460. /*****************************************************************************/
  1461. IOReturn USBAx8817x::setMulticastMode(bool active) {
  1462.   if(active) {
  1463.     fMulticastEnable = true;
  1464.   } else {
  1465.     setMulticastList(NULL, 0);
  1466.     fMulticastEnable = false;
  1467.   }
  1468.  
  1469.   return kIOReturnSuccess;
  1470. } /* end setMulticastMode */
  1471.  
  1472.  
  1473. /* The following was taked from crc32.h, in the linux source code. */
  1474. static unsigned const ethernet_polynomial = 0x04c11db7U;
  1475. static inline UInt32 ether_crc(int length, unsigned char *data) {
  1476.   int crc = -1;
  1477.   while (--length >= 0) {
  1478.     unsigned char current_octet = *data++;
  1479.     int bit;
  1480.     for (bit = 0; bit < 8; bit++, current_octet >>= 1) {
  1481.       crc = (crc << 1) ^
  1482.         ((crc < 0) ^ (current_octet & 1) ?
  1483.          ethernet_polynomial : 0);
  1484.     }
  1485.   }
  1486.   return crc;
  1487. }
  1488.  
  1489. /*****************************************************************************/
  1490. //
  1491. //      Method:         USBAx8817x::setMulticastList
  1492. //
  1493. //      Inputs:         addrs - list of addresses
  1494. //                      count - number in the list
  1495. //
  1496. //      Outputs:        Return code - kIOReturnSuccess or kIOReturnIOError
  1497. //
  1498. //      Desc:           Sets multicast list
  1499. //
  1500. /*****************************************************************************/
  1501. IOReturn USBAx8817x::setMulticastList(IOEthernetAddress *addrs, 
  1502.                                       UInt32 count) {
  1503.   UInt32 i;
  1504.   UInt32 index, byteIndex, bitIndex;
  1505.   UInt32 hash;
  1506.  
  1507.   if(fMulticastEnable == false) {
  1508.     return kIOReturnSuccess;
  1509.   }
  1510.  
  1511.   for(i=0; i<8; ++i) {
  1512.     mHashTable[i] = 0;
  1513.   }
  1514.  
  1515.   if(addrs != NULL) {
  1516.     for(i=0; i<count; ++i) {
  1517.       hash = ether_crc(6, addrs->bytes);
  1518.       index = hash >> 26;
  1519.       byteIndex = index >> 3;
  1520.       bitIndex = index & 0x07;
  1521.       mHashTable[byteIndex] |= (1 << bitIndex);
  1522.       
  1523.       ++addrs;
  1524.     }
  1525.   }
  1526.  
  1527.   POSTEVENT(ctrlEventSetMulticast);
  1528.  
  1529.   return kIOReturnSuccess;
  1530. } /* end setMulticastList */
  1531.  
  1532. /*****************************************************************************/
  1533. //
  1534. //      Method:         USBAx8817x::setPromiscuousMode
  1535. //
  1536. //      Inputs:         active - true (set it), false (don't)
  1537. //
  1538. //      Outputs:        Return code - kIOReturnSuccess
  1539. //
  1540. //      Desc:           Sets promiscuous mode
  1541. //
  1542. /*****************************************************************************/
  1543. IOReturn USBAx8817x::setPromiscuousMode(bool active) {
  1544.   if(active) {
  1545.     promiscRequest = true;
  1546.   } else {
  1547.     promiscRequest = false;
  1548.   }
  1549.  
  1550.   POSTEVENT(ctrlEventNudge);
  1551.  
  1552.   return kIOReturnSuccess;
  1553. } /* end setPromiscuousMode */
  1554.  
  1555. /***************************************************************************/
  1556. //
  1557. //      Method:    USBAx8817x::setPowerState
  1558. //
  1559. //      Inputs:    powerStateOrdinal - Power state to change to.
  1560. //                 whatdevice        - not used
  1561. //
  1562. //      Outputs:   IOReturnSuccess if succesful
  1563. //
  1564. //      Desc:      Change our current power state.  Either sleep (off) or
  1565. //                 wake up (on).
  1566. //   
  1567. /****************************************************************************/
  1568. IOReturn USBAx8817x::setPowerState(unsigned long powerStateOrdinal,
  1569.                                    IOService *whatDevice) {
  1570.   IOReturn result = IOPMAckImplied;
  1571.  
  1572.   if(currentPowerState == powerStateOrdinal) {
  1573.     return result;
  1574.   }
  1575.  
  1576.   currentPowerState = powerStateOrdinal;
  1577.   switch(powerStateOrdinal) {
  1578.   case kUSBEthernetOffState:
  1579.     if(powerDownThread) {
  1580.       retain();
  1581.       if( thread_call_enter(powerDownThread) == TRUE ) {
  1582.         release();
  1583.       }
  1584.       result = 3 * 1000 * 1000;  /* 3 seconds */
  1585.     }
  1586.  
  1587.     break;
  1588.   case kUSBEthernetOnState:
  1589.     if( powerUpThread ) {
  1590.       retain();
  1591.       if ( thread_call_enter(powerUpThread) == TRUE ) {
  1592.         release();
  1593.       }
  1594.       result = 3 * 1000 * 1000;  /* 3 seconds */
  1595.     }
  1596.     break;
  1597.   }
  1598.  
  1599.   return result;
  1600. } /* end setPowerState */
  1601.  
  1602. void USBAx8817x::rxLoop() {
  1603.   IOLockLock(rxQueueLock);
  1604.  
  1605.   while(true) {
  1606.     /* Check for event */
  1607.  
  1608.     while(rxRing->flags & RX_FLAG_FULL) {
  1609.       rxRing->flags &= ~RX_FLAG_FULL;
  1610.       IOLockUnlock(rxQueueLock);
  1611.  
  1612.       /* Send packet up! */
  1613.       receivePacket(rxRing->packetLength, rxRing->mdp, rxRing->completion);
  1614.       rxRing = rxRing->next;
  1615.  
  1616.       IOLockLock(rxQueueLock);
  1617.  
  1618.       if(readThreadCmd) {
  1619.         if(handleRxThreadCmd()) {
  1620.           return;
  1621.         }
  1622.       }
  1623.     }
  1624.  
  1625.     IOLockUnlock(rxQueueLock);
  1626.     fNetworkInterface->flushInputQueue();
  1627.     IOLockLock(rxQueueLock);
  1628.  
  1629.     if(readThreadCmd) {
  1630.       if(handleRxThreadCmd()) {
  1631.         return;
  1632.       }
  1633.     } else {
  1634.       IOLockSleep(rxQueueLock, NO_EVENT, THREAD_ABORTSAFE);
  1635.       if(readThreadCmd) {
  1636.         if(handleRxThreadCmd()) {
  1637.           return;
  1638.         }
  1639.       }
  1640.     }
  1641.   }
  1642. } /* end rxThreadEntry */
  1643.  
  1644. bool USBAx8817x::handleRxThreadCmd() {
  1645.   IOReturn ior;
  1646.   int i;
  1647.  
  1648.   if(readThreadCmd & RXTHREAD_STOP) {
  1649.     IOLockUnlock(rxQueueLock);
  1650.  
  1651.     if(fNetworkInterface) {
  1652.       detachInterface(fNetworkInterface, true);
  1653.       fNetworkInterface->release();
  1654.       fNetworkInterface = NULL;
  1655.     }
  1656.  
  1657.     if(fpDevice) {
  1658.       fpDevice->close(this);
  1659.       fpDevice->release();
  1660.       fpDevice = NULL;
  1661.     }
  1662.  
  1663.     IOLockLock(rxQueueLock);
  1664.     readThreadCmd |= RXTHREAD_STOPPED;
  1665.     IOLockWakeup(rxQueueLock, NO_EVENT, true);
  1666.     IOLockUnlock(rxQueueLock);
  1667.     return true;
  1668.   }
  1669.  
  1670.   if(readThreadCmd & RXTHREAD_CLOSE) {
  1671.     readActive = false;
  1672.     readThreadCmd &= ~RXTHREAD_CLOSE;
  1673.     readThreadCmd &= ~RXTHREAD_READSTALLED;
  1674.     IOLockUnlock(rxQueueLock);
  1675.     fInPipe->ClearPipeStall(true);
  1676.     fInterruptPipe->ClearPipeStall(true);
  1677.     postEvent(this, (void *)(int)ctrlEventDisable);
  1678.     IOLockLock(rxQueueLock);
  1679.   }
  1680.  
  1681.   if(readThreadCmd & RXTHREAD_OPEN) {
  1682.     readThreadCmd &= ~RXTHREAD_OPEN;
  1683.     readThreadCmd &= ~RXTHREAD_READSTALLED;
  1684.     IOLockUnlock(rxQueueLock);
  1685.     fInPipe->ClearPipeStall(true);
  1686.     fInterruptPipe->ClearPipeStall(true);
  1687.     for(i=0; i<NUM_RX_BUFFERS; ++i) {
  1688.       rxRing->flags &= ~RX_FLAG_FULL;
  1689.       ior = fInPipe->Read(rxRing->mdp, 0, 0, BUFSIZE, 
  1690.                           rxRing->completion, NULL);
  1691.       if(ior != kIOReturnSuccess) {
  1692.         IOLog("USBAx8817x::handleRxThreadCmd: Read %d failed.\n", i);
  1693.         fInPipe->ClearPipeStall(true);
  1694.         IOLockLock(rxQueueLock);
  1695.         return false;
  1696.       }
  1697.       rxRing = rxRing->next;
  1698.     }
  1699.     ior = fInterruptPipe->Read(fPipeInterruptMDP, 0, 0, 8, 
  1700.                                &fInterruptCompletionInfo, NULL);
  1701.     if(ior != kIOReturnSuccess) {
  1702.       IOLog("USBAx8817x::handleRxThreadCmd: Interrupt read failed.\n");
  1703.     }
  1704.     postEvent(this, (void *)(int)ctrlEventEnable);
  1705.     readActive = true;
  1706.     IOLockLock(rxQueueLock);
  1707.   }
  1708.  
  1709.   if(readThreadCmd & RXTHREAD_READSTALLED) {
  1710.     readThreadCmd &= ~RXTHREAD_READSTALLED;
  1711.     IOLockUnlock(rxQueueLock);
  1712.     fInPipe->ClearPipeStall(true);
  1713.     if(readActive == true) {
  1714.       for(i=0; i<NUM_RX_BUFFERS; ++i) {
  1715.         rxRing->flags &= ~RX_FLAG_FULL;
  1716.         ior = fInPipe->Read(rxRing->mdp, 0, 0, BUFSIZE, 
  1717.                             rxRing->completion, NULL);
  1718.         if(ior != kIOReturnSuccess) {
  1719.           IOLog("USBAx8817x::handleRxThreadCmd: Read %d failed.\n", i);
  1720.           fInPipe->ClearPipeStall(true);
  1721.           IOLockLock(rxQueueLock);
  1722.           return false;
  1723.         }
  1724.         rxRing = rxRing->next;
  1725.       }
  1726.     }
  1727.     IOLockLock(rxQueueLock);
  1728.   }
  1729.  
  1730.   if(readThreadCmd & RXTHREAD_WRITESTALLED) {
  1731.     readThreadCmd &= ~RXTHREAD_WRITESTALLED;
  1732.     IOLockUnlock(rxQueueLock);
  1733.     IOLog("USBAx8817x: Clearing Write Pipe.\n");
  1734.     fOutPipe->ClearPipeStall(true);
  1735.     postEvent(this, (void *)(int)ctrlEventClearedWriteStall);
  1736.     IOLockLock(rxQueueLock);
  1737.   }
  1738.  
  1739.   if(readThreadCmd & RXTHREAD_INTRSTALLED) {
  1740.     readThreadCmd &= ~RXTHREAD_INTRSTALLED;
  1741.  
  1742.     IOLockUnlock(rxQueueLock);
  1743.     IOLog("USBAx8817x: Interrupt Pipe stalled!\n");
  1744.     ior = fInterruptPipe->ClearPipeStall(true);
  1745.     if(ior == kIOReturnSuccess) {
  1746.       if(readActive) {
  1747.         IOLog("USBAx8817x: Interrupt Pipe stall cleared.\n");
  1748.         ior = fInterruptPipe->Read(fPipeInterruptMDP, 0, 0, 8, 
  1749.                                    &fInterruptCompletionInfo, NULL);
  1750.         if(ior != kIOReturnSuccess) {
  1751.           IOLog("USBAx8817x: interrupt read failed. error = 0x%X.\n",
  1752.                 ior);
  1753.         }
  1754.       }
  1755.     } else {
  1756.       IOLog("USBAx8817x: Failed to clear interrupt pipe.\n");
  1757.     }
  1758.     IOLockLock(rxQueueLock);
  1759.   }
  1760.  
  1761.   if(readThreadCmd & RXTHREAD_CTRLSTALLED) {
  1762.     readThreadCmd &= ~RXTHREAD_CTRLSTALLED;
  1763.  
  1764.     IOLockUnlock(rxQueueLock);
  1765.     IOLog("USBAx8817x: Control pipe stalled.\n");
  1766.     ior = fCntlPipe->ClearPipeStall(true);
  1767.     if(ior == kIOReturnSuccess) {
  1768.       IOLog("USBAx8817x: Control pipe stall cleared.\n");
  1769.       ior = fCntlPipe->ControlRequest(&fCtrlRead, &fCtrlCompletionInfo);
  1770.       if(ior != kIOReturnSuccess) {
  1771.         IOLog("USBAx8817x: control request failed. error = 0x%X.\n",
  1772.               ior);
  1773.       }    
  1774.     } else {
  1775.       IOLog("USBAx8817x: ctrlComplete: failed to clear control pipe.\n");
  1776.     }
  1777.     IOLockLock(rxQueueLock);
  1778.  
  1779.   } 
  1780.  
  1781.   return false;
  1782. }
  1783.  
  1784. #pragma mark -- Lower Layer Events -- 
  1785.  
  1786. /***************************************************************************/
  1787. //
  1788. //      Method:         USBAx8817x::dataReadComplete
  1789. //
  1790. //      Inputs:         obj - me
  1791. //                      param - unused
  1792. //                      rc - return code
  1793. //                      remaining - what's left
  1794. //
  1795. //      Outputs:        None
  1796. //
  1797. //      Desc:           BulkIn pipe (Data interface) read completion
  1798. //                      routine. This function get called after a
  1799. //                      paket was transmitted.  If all is good,
  1800. //                      recievePacket() is called.  Otherwise, the
  1801. //                      network interface is released.
  1802. //         
  1803. //
  1804. /****************************************************************************/
  1805. void USBAx8817x::dataReadComplete(void *obj, void *param, IOReturn rc, 
  1806.                                   UInt32 remaining) {
  1807.   USBAx8817x  *me = (USBAx8817x*)obj;
  1808.   ax8817xCompletion_t *comp;
  1809.   IOBufferMemoryDescriptor    *inMDP;
  1810.   IOUSBCompletion *completion;
  1811.  
  1812.   if(param == NULL) {
  1813.     IOLog("USBAx8817x::dataReadComplete: param == NULL.\n");
  1814.     return;
  1815.   }
  1816.  
  1817.   comp = (ax8817xCompletion_t *)param;
  1818.   completion = comp->completion;
  1819.   inMDP = comp->mdp;
  1820.  
  1821.   if(!me) {
  1822.     IOLog("USBAx8817x::dataReadComplete: me is NULL.\n");
  1823.     return;
  1824.   }
  1825.  
  1826.   if(rc == kIOReturnSuccess) {
  1827.     comp->packetLength = BUFSIZE - remaining;
  1828.  
  1829.     IOLockLock(me->rxQueueLock);
  1830.     if(!(me->readThreadCmd & RXTHREAD_STOP)) {
  1831.       comp->flags |= RX_FLAG_FULL;
  1832.       IOLockWakeup(me->rxQueueLock, NO_EVENT, true);
  1833.     }
  1834.     IOLockUnlock(me->rxQueueLock);
  1835.  
  1836.   } else if (rc != kIOReturnAborted){
  1837.     if((me->fInPipe->GetPipeStatus()) == kIOUSBPipeStalled) {
  1838.       IOLog("USBAx8817x::dataReadComplete: return code = 0x%x.\n", rc);
  1839.       IOLockLock(me->rxQueueLock);
  1840.       me->readThreadCmd |= RXTHREAD_READSTALLED;
  1841.       IOLockWakeup(me->rxQueueLock, NO_EVENT, true);
  1842.       IOLockUnlock(me->rxQueueLock);
  1843.     } 
  1844.   }
  1845. } /* end dataReadComplete */
  1846.  
  1847. /***************************************************************************/
  1848. //
  1849. //      Method:         USBAx8817x::receivePacket
  1850. //
  1851. //      Inputs:         completion - pointer to read completion routine
  1852. //                      inMDP - MDP where received data is
  1853. //                      remaining - BUFSIZE minus length of received packet
  1854. //
  1855. //      Outputs:        None
  1856. //
  1857. //      Desc:           Receives a packet.  Allocates a buffer, copies
  1858. //                      the received packet to the buffer, and sends
  1859. //                      the buffer up the network stack.  Then another
  1860. //                      read command is issued.  If the read command
  1861. //                      fails, the network interface is freed.
  1862. //         
  1863. //
  1864. /****************************************************************************/
  1865. void USBAx8817x::receivePacket(UInt32 packetLength,
  1866.                                IOBufferMemoryDescriptor *inMDP,
  1867.                                IOUSBCompletion *completion) {
  1868.   UInt8            *dataInPtr;
  1869.   UInt16       length;
  1870.   mbuf_t                rcvd;
  1871.   IOReturn     ior;
  1872.  
  1873.   if(packetLength > (14 + 6) ) {
  1874.     dataInPtr = (UInt8 *)inMDP->getBytesNoCopy();
  1875.     
  1876.     if(deviceFlag & 0x0040) {
  1877.       length = packetLength;
  1878.     } else {
  1879.       length = packetLength - 4; /* Device appended CRC to frame. */
  1880.     }
  1881.  
  1882.     rcvd = allocatePacket(length);
  1883.     if(!rcvd) {
  1884.       IOLog("USBAx8817x::receivePacket: Failed to allocate packet.\n");
  1885.       return;
  1886.     }
  1887.  
  1888.     bcopy(dataInPtr, mbuf_data(rcvd), length);
  1889.  
  1890.     fNetworkInterface->inputPacket(rcvd, length, 0x01);
  1891.     if(fpNetStats) {
  1892.       ++fpNetStats->inputPackets;
  1893.     }
  1894.   } else {
  1895.     IOLog("USBAx8817x::receivePacket: Packet length (%d) is too short.\n",
  1896.           (int)packetLength);
  1897.   }
  1898.  
  1899.   /* Read next packet. */
  1900.   inMDP->setLength(BUFSIZE);
  1901.   ior = fInPipe->Read(inMDP, 0, 0, BUFSIZE, completion, NULL);
  1902.   if(ior != kIOReturnSuccess) {
  1903.     if((fInPipe->GetPipeStatus()) == kIOUSBPipeStalled) {
  1904.       IOLog("USBAx8817x::receivePacket: return code = 0x%x.\n", ior);
  1905.       IOLockLock(rxQueueLock);
  1906.       readThreadCmd |= RXTHREAD_READSTALLED;
  1907.       IOLockWakeup(rxQueueLock, NO_EVENT, true);
  1908.       IOLockUnlock(rxQueueLock);
  1909.     } else {
  1910.       IOLog("USBAx8817x::receivePacket: Failed to read next packet.\n");
  1911.     }
  1912.   }
  1913.  
  1914. } /* end receivePacket */
  1915.  
  1916. /****************************************************************************/
  1917. //
  1918. //      Method:         USBAx8817x::dataWriteComplete
  1919. //
  1920. //      Inputs:         obj       - me (this)
  1921. //                      param     - parameter block(the mbuf)
  1922. //                      rc        - return code
  1923. //                      remaining - what's left
  1924. //
  1925. //      Outputs:        None
  1926. //
  1927. //      Desc:           BulkOut pipe (Data interface) write completion
  1928. //                      routine.  If the write length was a multiple
  1929. //                      of 64, a zero length packet is written.
  1930. //                      Otherwise, "transmit complete" event is posted.
  1931. //
  1932. /****************************************************************************/
  1933. void USBAx8817x::dataWriteZeroComplete(void *obj, void *param, 
  1934.                                         IOReturn rc, UInt32 remaining) {
  1935. }
  1936.  
  1937. void USBAx8817x::dataWriteComplete(void *obj, void *param, 
  1938.                                    IOReturn rc, UInt32 remaining) {
  1939.   int txQueueLen;
  1940.   USBAx8817x *me;
  1941.   ax8817xTxRing_t *transmitInfo;
  1942.   bool restartQueue = false;
  1943.   bool writeStalled = false;
  1944.  
  1945.   me = (USBAx8817x *)obj;
  1946.   if(!me) {
  1947.     return;
  1948.   }
  1949.  
  1950.   transmitInfo = (ax8817xTxRing_t *)param;
  1951.  
  1952.   IOLockLock(me->txQueueLock);
  1953.   txQueueLen = ++me->txSpots;
  1954.  
  1955.   if(me->txQueueStopped && (txQueueLen == TX_QUEUE_RESTART)) {
  1956.     restartQueue = true;
  1957.     me->txQueueStopped = false;
  1958.   }
  1959.  
  1960.   IOLockUnlock(me->txQueueLock);
  1961.  
  1962.   if(rc == kIOReturnSuccess) {
  1963.     ++me->fpNetStats->outputPackets;
  1964.   } else if(rc != kIOReturnAborted) {
  1965.     IOLog("USBAx8817x::dataWriteComplete: write failed: 0x%X\n", rc);
  1966.     if((me->fOutPipe->GetPipeStatus()) == kIOUSBPipeStalled) {
  1967.       writeStalled = true;
  1968.     }
  1969.   }
  1970.  
  1971.   if(writeStalled) {
  1972.     IOLog("USBAxx8817x: dataWriteComplete: Write pipe stalled!\n");
  1973.     postEvent(me, (void *)(int)ctrlEventWriteStalled);
  1974.   }
  1975.  
  1976.   if(restartQueue) {
  1977.     postEvent(me, (void *)(int)ctrlEventServiceQueue);
  1978.   }
  1979.  
  1980.   if(transmitInfo->packet) {
  1981.     me->freePacket(transmitInfo->packet);
  1982.     transmitInfo->packet = NULL;
  1983.   }
  1984.  
  1985.   postEvent(me, (void *)(int)ctrlEventTxDone);
  1986. } /* end dataWriteComplete */
  1987.  
  1988. /****************************************************************************/
  1989. //
  1990. //      Method:         USBAx8817x::ctrlComplete
  1991. //
  1992. //      Inputs:         obj       - me (this)
  1993. //                      param     - not used
  1994. //                      rc        - return code
  1995. //                      remaining - not used
  1996. //
  1997. //      Outputs:        None
  1998. //
  1999. //      Desc:           Completion routine for reads and writes to
  2000. //                      the control pipe.  This function simply posts
  2001. //                      a "control I/O done" event.
  2002. //
  2003. /****************************************************************************/
  2004. void USBAx8817x::ctrlComplete(void *obj, void *param, IOReturn rc, 
  2005.                               UInt32 remaining) {
  2006.   USBAx8817x    *me;
  2007.  
  2008.   me = (USBAx8817x *)obj;
  2009.   if(me) {
  2010.     if(rc == kIOReturnSuccess) {
  2011.       postEvent(me, (void *)(int)ctrlEventCallback);
  2012.     } else if((me->fCntlPipe->GetPipeStatus()) == kIOUSBPipeStalled) {
  2013.       IOLockLock(me->rxQueueLock);
  2014.       me->readThreadCmd |= RXTHREAD_INTRSTALLED;
  2015.       IOLockWakeup(me->rxQueueLock, NO_EVENT, true);    
  2016.       IOLockUnlock(me->rxQueueLock);      
  2017.  
  2018.     } else if(rc != kIOReturnAborted) {
  2019.       IOLog("USBAx8817x: ctrlComplete: error = 0x%X.\n", rc);
  2020.     }
  2021.   }
  2022. } /* end ctrlComplete */
  2023.  
  2024. /****************************************************************************/
  2025. //
  2026. //      Method:         USBAx8817x::interruptComplete
  2027. //
  2028. //      Inputs:         obj       - me (this)
  2029. //                      param     - not used
  2030. //                      rc        - return code
  2031. //                      remaining - not used
  2032. //
  2033. //      Outputs:        None
  2034. //
  2035. //      Desc:           Comlpletion routine for reads and writes to
  2036. //                      the interrupt pipe.  This function simply posts
  2037. //                      an "interrupt is pending" event.
  2038. //
  2039. /****************************************************************************/
  2040. void USBAx8817x::interruptComplete(void *obj, void *param,
  2041.                                    IOReturn rc, UInt32 remaining) {
  2042.   USBAx8817x    *me;
  2043.  
  2044.   me = (USBAx8817x *)obj;
  2045.  
  2046.   if(me) {
  2047.     if(rc == kIOReturnSuccess) {
  2048.       if(me->rcvdLinkStatus == true) {
  2049.         if(!(me->fInterruptPipeBuffer[2] & 0x03)) {
  2050.           me->rcvdLinkStatus = false;
  2051.           postEvent(me, (void *)(int)ctrlEventLinkDown);
  2052.         }
  2053.       } else {
  2054.         if(me->fInterruptPipeBuffer[2] & 0x03) {
  2055.           me->rcvdLinkStatus = true;
  2056.           postEvent(me, (void *)(int)ctrlEventLinkUp);
  2057.         }
  2058.       }
  2059.       me->fInterruptPipe->Read(me->fPipeInterruptMDP, 0, 0, 8, 
  2060.                                &me->fInterruptCompletionInfo, NULL);
  2061.     } else if((me->fInterruptPipe->GetPipeStatus()) == kIOUSBPipeStalled) {
  2062.       IOLockLock(me->rxQueueLock);
  2063.       me->readThreadCmd |= RXTHREAD_INTRSTALLED;
  2064.       IOLockWakeup(me->rxQueueLock, NO_EVENT, true);    
  2065.       IOLockUnlock(me->rxQueueLock);      
  2066.     } else if(rc != kIOReturnAborted) {
  2067.       IOLog("USBAx8817x::interruptComplete: Interrupt read failed.");
  2068.       IOLog(" Error code = 0x%X.\n", rc);
  2069.     }
  2070.   }
  2071. } /* end interruptComplete */
  2072.  
  2073. /****************************************************************************/
  2074. //
  2075. //      Method:         USBAx8817x::willTerminate
  2076. //
  2077. //      Inputs:         provider      - Pointer to my provider.
  2078. //                      IOOptionsBits - ignored
  2079. //
  2080. //      Outputs:        None
  2081. //
  2082. //      Desc:           A message from below indicating that the lower
  2083. //                      layer is about to terminate.  This is usually
  2084. //                      due to the device being unplugged.  It is
  2085. //                      important to close the provider at this
  2086. //                      point.  Shortly after we close the driver, our
  2087. //                      stop() method will be called, and then this
  2088. //                      driver will be unloaded.
  2089. //
  2090. /****************************************************************************/
  2091. bool USBAx8817x::willTerminate(IOService * provider,
  2092.                                IOOptionBits options) {
  2093.   setLinkStatus(kIONetworkLinkValid, 0);
  2094.   setLinkStatus(0, 0);
  2095.   
  2096.   postEvent(this, (void *)(int)ctrlEventTerminate);
  2097.  
  2098.   if(rxQueueLock != NULL) {
  2099.  
  2100.     IOLockLock(rxQueueLock);
  2101.  
  2102.     readThreadCmd |= RXTHREAD_STOP;
  2103.     IOLockWakeup(rxQueueLock, NO_EVENT, true);    
  2104.     IOLockUnlock(rxQueueLock);
  2105.     return true;
  2106.  
  2107.     while(!(readThreadCmd & RXTHREAD_STOPPED)) {
  2108.       readThreadCmd |= RXTHREAD_STOP;
  2109.       IOLockWakeup(rxQueueLock, NO_EVENT, true);    
  2110.       IOLockSleep(rxQueueLock, NO_EVENT, THREAD_ABORTSAFE);
  2111.     }
  2112.  
  2113.     IOLockUnlock(rxQueueLock);
  2114.     IOLockFree(rxQueueLock);
  2115.     rxQueueLock = NULL;
  2116.   }
  2117.  
  2118.   if(fNetworkInterface) {
  2119.     IOLog("USBAx8817x: willTerminate: Detaching network interface.\n");
  2120.     detachInterface(fNetworkInterface, true);
  2121.     fNetworkInterface->release();
  2122.     fNetworkInterface = NULL;
  2123.   }
  2124.  
  2125.   if(fCntlPipe) {
  2126.     fCntlPipe = NULL;
  2127.   }
  2128.  
  2129.   if(fInPipe) {
  2130.     fInPipe = NULL;
  2131.   }
  2132.  
  2133.   if(fOutPipe) {
  2134.     fOutPipe = NULL;
  2135.   }
  2136.   
  2137.   if(fInterruptPipe) {
  2138.     //fInterruptPipe->release();
  2139.     fInterruptPipe = NULL;
  2140.   }
  2141.  
  2142.   if(fDataInterface)  { 
  2143.     fDataInterface->close(this);        
  2144.     fDataInterface->release();
  2145.     fDataInterface = NULL;
  2146.   }
  2147.   
  2148.   if(fpDevice) {
  2149.     fpDevice->close(this);
  2150.     fpDevice->release();
  2151.     fpDevice = NULL;
  2152.   }
  2153.  
  2154.   return true;
  2155. } /* end willTerminate */
  2156.  
  2157. #pragma mark -- Event Handling --
  2158.  
  2159. /****************************************************************************/
  2160. //
  2161. //      Method:         USBAx8817x::postEvent
  2162. //
  2163. //      Inputs:         target  - me (this)
  2164. //                      evt     - Event to be posted
  2165. //                      result  - not used
  2166. //                      gotLock - true if we have the workloop thread.
  2167. //
  2168. //      Outputs:        kIOReturnSuccess (always)
  2169. //
  2170. //      Desc:           Post an event.  This method calls itself through
  2171. //                      the workloop, and then calls setState().
  2172. //
  2173. /****************************************************************************/
  2174. IOReturn  USBAx8817x::postEvent(OSObject *target, void *evt, void *result, 
  2175.                                 void *gotLock, void *arg3) {
  2176.   USBAx8817x *me;
  2177.   IOWorkLoop *workLoop;
  2178.  
  2179.   if(target == NULL) {
  2180.     return kIOReturnSuccess;
  2181.   }
  2182.  
  2183.   me = (USBAx8817x *)target;
  2184.  
  2185.   if( gotLock == (void *)false) {
  2186.     workLoop = me->getWorkLoop();
  2187.     if(workLoop) {
  2188.       return workLoop->runAction(postEvent, target, evt, 
  2189.                                  (void *)result,
  2190.                                  (void *)true);
  2191.     } else {
  2192.       IOLog("USBAx8817x::postEvent: Failed to get work loop.\n");
  2193.       return kIOReturnSuccess;
  2194.     }
  2195.   }
  2196.  
  2197.   ++me->recursionLevel;
  2198.   me->setState((ctrlEvent_t) (int)evt);
  2199.   --me->recursionLevel;
  2200.  
  2201.   return kIOReturnSuccess;
  2202. } /* end postEvent */
  2203.  
  2204. /****************************************************************************/
  2205. //
  2206. //      Method:         USBAx8817x::setState
  2207. //
  2208. //      Inputs:         target  - me (this)
  2209. //                      evt     - Event to be posted
  2210. //
  2211. //      Outputs:        none
  2212. //
  2213. //      Desc:           Posts an event, and makes asynchronous I/O
  2214. //                      calls.  This method must always by synchronized
  2215. //                      by the work loop.  Almost all asynchonous I/O
  2216. //                      calls, particularly control calls, are made
  2217. //                      from this method.  This records the event, and
  2218. //                      implements three state machines.  The first
  2219. //                      one, miiState, controls access to the Media
  2220. //                      Independent Interface (MII) registers.  This
  2221. //                      state machine runs at highest priority if it
  2222. //                      is not idle.  The next state machine,
  2223. //                      ethState, writes to ethernet control registers
  2224. //                      0, 1 and 2.  Finally, the third state machine,
  2225. //                      ctrlState, handles other control calls, such
  2226. //                      as checking if the cable was unplugged,
  2227. //                      setting promiscuous mode, multicast filters,
  2228. //                      etc.
  2229. //
  2230. /****************************************************************************/
  2231. void USBAx8817x::setState(ctrlEvent_t event) {
  2232.   IOReturn ior;
  2233.   UInt16 data16;
  2234.   IONetworkMedium *medium;
  2235.   int txLen;
  2236.  
  2237.   if(fTerminate == true) {
  2238.     return;
  2239.   }
  2240.  
  2241.   /* First, record the event. */
  2242.   switch(event) {
  2243.   case ctrlEventServiceQueue:
  2244.     fTransmitQueue->service();
  2245.     break;
  2246.   case ctrlEventTimer:
  2247.     timerPending = true;
  2248.     break;
  2249.   case ctrlEventEnable:
  2250.     fNetifRequestEnabled = true;
  2251.     break;
  2252.   case ctrlEventDisable:
  2253.     fNetifRequestEnabled = false;
  2254.     break;
  2255.   case ctrlEventTxDone:
  2256.     --txInProgress;
  2257.     break;
  2258.   case ctrlEventTransmit:
  2259.     ++pktQueueLen;
  2260.     break;
  2261.   case ctrlEventSetMulticast:
  2262.     setMc = true;
  2263.     break;
  2264.   case ctrlEventSuspend:
  2265.     suspendPending = true;
  2266.     break;
  2267.   case ctrlEventResume:
  2268.     awake = true;
  2269.     resumePending = true;
  2270.     break;
  2271.   case ctrlEventStart:
  2272.     started = true;
  2273.     resumePending = true;
  2274.     break;
  2275.   case ctrlEventCallback:
  2276.     callbackPending = true;
  2277.     break;
  2278.   case ctrlEventTerminate:
  2279.     if(fTransmitQueue) {
  2280.       fTransmitQueue->stop();
  2281.       fTransmitQueue->setCapacity(0);
  2282.       fTransmitQueue->flush();
  2283.     }
  2284.     fTerminate = true;
  2285.     return;
  2286.   case ctrlEventLinkUp:
  2287.     checkLinkPending = true;
  2288.     fLinkUp = false; /* This is intentionally reversed. */
  2289.     break;
  2290.   case ctrlEventLinkDown:
  2291.     checkLinkPending = true;
  2292.     fLinkUp = true; /* This is intentionally reversed. */
  2293.     break;
  2294.   case ctrlEventWriteStalled:
  2295.     writePipeStalled = true;
  2296.     break;
  2297.   case ctrlEventClearedWriteStall:
  2298.     writeStallCleared = true;
  2299.     break;
  2300.   default:
  2301.     break;
  2302.   }
  2303.  
  2304.   /* If this method has called itself recursively with a new event,
  2305.      exit now that the event has been recorded. */
  2306.   if(recursionLevel > 1) {
  2307.     return;
  2308.   }
  2309.  
  2310.   /* Run the mii state mathine. */
  2311.   switch(miiState) {
  2312.   case miiStateRead:
  2313.     if(callbackPending == true) {
  2314.       callbackPending = false;
  2315.       ior = axCmdAsync(AXE_CMD_MII_READ_REG, miiIndx, phy);
  2316.       if(ior == kIOReturnSuccess) {
  2317.         miiState = miiStateFinish1;
  2318.       } else {
  2319.         IOLog("USBAx8817x: miiStateRead1: axCmdAsync failed!\n");
  2320.       }
  2321.     }
  2322.     return;
  2323.   case miiStateWrite:
  2324.     if(callbackPending == true) {
  2325.       callbackPending = false;
  2326.       *( (UInt16 *)fCtrlPipeBuffer) = miiData;
  2327.       ior = axCmdAsync(AXE_CMD_MII_WRITE_REG, miiIndx, phy);
  2328.       if(ior == kIOReturnSuccess) {
  2329.         miiState = miiStateFinish1;
  2330.       }
  2331.     }
  2332.     return;
  2333.   case miiStateFinish1:
  2334.     if(callbackPending == true) {
  2335.       callbackPending = false;
  2336.  
  2337.       miiData = USBToHostWord( *( (UInt16 *)fCtrlPipeBuffer) );
  2338.       ior = axCmdAsync(AXE_CMD_MII_OPMODE_HW, 0, 0);
  2339.       if(ior == kIOReturnSuccess) {
  2340.         miiState = miiStateFinish2;
  2341.       } else {
  2342.         IOLog("USBAx8817x: miiStateRead2: axCmdAsync failed!\n");
  2343.       }
  2344.     }
  2345.     return;
  2346.   case miiStateFinish2:
  2347.     if(callbackPending == true) {
  2348.       callbackPending = false;
  2349.       miiPending = true;
  2350.       break;
  2351.     }
  2352.     return;
  2353.   default:
  2354.     break;
  2355.   } /* switch(miiState) */
  2356.   miiState = miiStateIdle;
  2357.  
  2358.   /* Run the control state mathine. */
  2359.   switch(cState) {
  2360.   case ctrlStateLinkStatus:
  2361.     if(miiPending == true) {
  2362.       miiPending = false;
  2363.  
  2364.       if(fLinkUp == false) {
  2365.         if(selectedMedium == kIOMediumEthernetAuto) {
  2366.           if( (miiData & 0x0004) == 0x0004) { /* Link went up */
  2367.             ior = readMiiWordAsync(6);
  2368.             /* Does partner support autonegotiation? */
  2369.             if(ior == kIOReturnSuccess) {
  2370.               cState = ctrlStateAutoDone1;
  2371.               return;
  2372.             }
  2373.           }
  2374.         } else if(miiData & 0x0004) { /* User selected medium type */
  2375.           /* Link is up! */
  2376.           medium = IONetworkMedium::getMediumWithType(fMediumDict,
  2377.                                                       selectedMedium);
  2378.           setLinkStatus(kIONetworkLinkValid | kIONetworkLinkActive, medium);
  2379.           fLinkUp = true;
  2380.         }
  2381.       } else { /* Linkup == true */
  2382.         if( !(miiData & 0x0004) ) { /* link went down */
  2383.           if(requestedMedium == kIOMediumEthernetAuto) {
  2384.             medium = /* Autonegotion */
  2385.               IONetworkMedium::getMediumWithType(fMediumDict, 
  2386.                                                  kIOMediumEthernetNone);
  2387.           } else {
  2388.             medium = /* User picked medium */
  2389.               IONetworkMedium::getMediumWithType(fMediumDict, 
  2390.                                                  selectedMedium);
  2391.           }
  2392.           setLinkStatus(kIONetworkLinkValid, medium);
  2393.           fLinkUp = false;
  2394.         }
  2395.       }
  2396.       break;
  2397.     }
  2398.     return;
  2399.   case ctrlStateAutoDone1:
  2400.     if(miiPending == true) {
  2401.       miiPending = false;
  2402.  
  2403.       if(miiData & 0x01) {
  2404.         /* Autonegotiation succeeded! */
  2405.         /* Figure out medium settings. */
  2406.         if(supports1000BaseT) {
  2407.           /* Check for 1000BaseT connection */
  2408.           ior = readMiiWordAsync(10);
  2409.           if(ior == kIOReturnSuccess) {
  2410.             cState = ctrlStateCheckGiga;
  2411.           }
  2412.           return;
  2413.         } else {
  2414.           ior = readMiiWordAsync(5);
  2415.           if(ior == kIOReturnSuccess) {
  2416.             cState = ctrlStateAutoDone2;
  2417.             return;
  2418.           }
  2419.         }
  2420.       } else {
  2421.         /* Autonegotiation failed. */
  2422.         /* Assume medium is 10BaseT, half-duplex. */
  2423.         medium = 
  2424.           IONetworkMedium::getMediumWithType(fMediumDict, 
  2425.                                              kIOMediumEthernet10BaseT |
  2426.                                              kIOMediumOptionHalfDuplex);
  2427.         setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, medium, 
  2428.                       10 * 1000000);
  2429.         fLinkUp = true;
  2430.         //mediumStatus &= ~AXE_MEDIA_FULL_DUPLEX;
  2431.     setMediumStatus(kIOMediumEthernet10BaseT |
  2432.             kIOMediumOptionHalfDuplex);
  2433.  
  2434.         ior = axCmdAsync(AXE_CMD_WRITE_MEDIA, 0, mediumStatus);
  2435.         if(ior == kIOReturnSuccess) {
  2436.           cState = ctrlStateWaitEth;
  2437.         }
  2438.         return;
  2439.       }
  2440.     }
  2441.     return;
  2442.   case ctrlStateCheckGiga:
  2443.     if(miiPending == true) {
  2444.       miiPending = false;
  2445.  
  2446.       IOLog("USBAx8817x: mii register 10 = 0x%X.\n", miiData);
  2447.       if(miiData & 0x0800) {
  2448.         medium = 
  2449.           IONetworkMedium::getMediumWithType(fMediumDict, 
  2450.                                              kIOMediumEthernet1000BaseTX |
  2451.                                              kIOMediumOptionFullDuplex);
  2452.         setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, medium, 
  2453.                       1000 * 1000000);
  2454.         //mediumStatus |= AXE_MEDIA_FULL_DUPLEX;
  2455.     setMediumStatus(kIOMediumEthernet1000BaseTX |
  2456.             kIOMediumOptionFullDuplex);
  2457.  
  2458.         fLinkUp = true;
  2459.  
  2460.         ior = axCmdAsync(AXE_CMD_WRITE_MEDIA, 0, mediumStatus);
  2461.         if(ior == kIOReturnSuccess) {
  2462.         }
  2463.         cState = ctrlStateWaitEth;
  2464.       } else if(miiData & 0x0400) {
  2465.         medium = 
  2466.           IONetworkMedium::getMediumWithType(fMediumDict, 
  2467.                                              kIOMediumEthernet1000BaseTX |
  2468.                                              kIOMediumOptionHalfDuplex);
  2469.         setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, medium, 
  2470.                       1000 * 1000000);
  2471.         //mediumStatus &= ~AXE_MEDIA_FULL_DUPLEX;
  2472.     setMediumStatus(kIOMediumEthernet1000BaseTX |
  2473.             kIOMediumOptionHalfDuplex);
  2474.         fLinkUp = true;
  2475.  
  2476.         ior = axCmdAsync(AXE_CMD_WRITE_MEDIA, 0, mediumStatus);
  2477.         if(ior == kIOReturnSuccess) {
  2478.           cState = ctrlStateWaitEth;
  2479.         }
  2480.       } else {
  2481.         IOLog("USBAx8817x: Link partner is NOT 1000BaseT HD capbable.\n");
  2482.         ior = readMiiWordAsync(5);
  2483.         if(ior == kIOReturnSuccess) {
  2484.           cState = ctrlStateAutoDone2;
  2485.         }
  2486.       }
  2487.     }
  2488.     return;
  2489.   case ctrlStateAutoDone2:
  2490.     if(miiPending == true) {
  2491.       miiPending = false;
  2492.       if( !(miiData & 0x001f) == 0x0001 ) {
  2493.         /* Autonegotiation failed.  Set link to 10BaseT, Half Duplex */
  2494.         medium = 
  2495.           IONetworkMedium::getMediumWithType(fMediumDict,
  2496.                                              kIOMediumEthernet10BaseT |
  2497.                                              kIOMediumOptionHalfDuplex);
  2498.         setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, medium,
  2499.                       10 * 1000000);
  2500.         //mediumStatus &= ~AXE_MEDIA_FULL_DUPLEX;
  2501.     setMediumStatus(kIOMediumEthernet10BaseT |
  2502.             kIOMediumOptionHalfDuplex);
  2503.       } else if(miiData & 0x0100) {
  2504.         /* 100BaseT, Full Duplex */
  2505.         medium = 
  2506.           IONetworkMedium::getMediumWithType(fMediumDict, 
  2507.                                              kIOMediumEthernet100BaseTX |
  2508.                                              kIOMediumOptionFullDuplex);
  2509.         setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, medium, 
  2510.                       100 * 1000000);
  2511.         //mediumStatus |= AXE_MEDIA_FULL_DUPLEX;
  2512.     setMediumStatus(kIOMediumEthernet100BaseTX |
  2513.             kIOMediumOptionFullDuplex);
  2514.       } else if(miiData & 0x0080) {
  2515.         /* 100BaseT, Half Duplex */
  2516.         medium = 
  2517.           IONetworkMedium::getMediumWithType(fMediumDict, 
  2518.                                              kIOMediumEthernet100BaseTX |
  2519.                                              kIOMediumOptionHalfDuplex);
  2520.         setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, medium, 
  2521.                       100 * 1000000);
  2522.         //mediumStatus &= ~AXE_MEDIA_FULL_DUPLEX;
  2523.     setMediumStatus(kIOMediumEthernet100BaseTX |
  2524.             kIOMediumOptionHalfDuplex);
  2525.       } else if(miiData & 0x0040) {
  2526.         /* 10BaseT, Full Duplex */
  2527.         medium = 
  2528.           IONetworkMedium::getMediumWithType(fMediumDict, 
  2529.                                              kIOMediumEthernet10BaseT |
  2530.                                              kIOMediumOptionFullDuplex);
  2531.         setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, medium, 
  2532.                       10 * 1000000);
  2533.         //mediumStatus |= AXE_MEDIA_FULL_DUPLEX;
  2534.     setMediumStatus(kIOMediumEthernet10BaseT |
  2535.             kIOMediumOptionFullDuplex);
  2536.       } else if(miiData & 0x0020) {
  2537.         /* 10BaseT, Half Duplex */
  2538.         medium = 
  2539.           IONetworkMedium::getMediumWithType(fMediumDict, 
  2540.                                              kIOMediumEthernet10BaseT |
  2541.                                              kIOMediumOptionHalfDuplex);
  2542.         setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, medium, 
  2543.                       10 * 1000000);
  2544.         //mediumStatus &= ~AXE_MEDIA_FULL_DUPLEX;
  2545.     setMediumStatus(kIOMediumEthernet10BaseT |
  2546.             kIOMediumOptionHalfDuplex);
  2547.       } else {
  2548.         /* Default: set to 10BaseT, Half duplex */
  2549.         medium = 
  2550.           IONetworkMedium::getMediumWithType(fMediumDict,
  2551.                                              kIOMediumEthernet10BaseT |
  2552.                                              kIOMediumOptionHalfDuplex);
  2553.         setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, medium,
  2554.                       10 * 1000000);
  2555.         //mediumStatus &= ~AXE_MEDIA_FULL_DUPLEX;
  2556.     setMediumStatus(kIOMediumEthernet10BaseT |
  2557.             kIOMediumOptionHalfDuplex);
  2558.       }
  2559.  
  2560.       fLinkUp = true;
  2561.       ior = axCmdAsync(AXE_CMD_WRITE_MEDIA, 0, mediumStatus);
  2562.       if(ior == kIOReturnSuccess) {
  2563.         cState = ctrlStateWaitEth;
  2564.       }
  2565.       return;
  2566.     }
  2567.     return;
  2568.   case ctrlStateWaitEth:
  2569.     if(callbackPending == true) {
  2570.       callbackPending = false;
  2571.       break;
  2572.     }
  2573.     return;
  2574.   case ctrlStateSetMedium:
  2575.     if(miiPending == true) {
  2576.       miiPending = false;
  2577.       ior = axCmdAsync(AXE_CMD_WRITE_MEDIA, 0, mediumStatus);
  2578.       if(ior == kIOReturnSuccess) {
  2579.         cState = ctrlStateWaitEth;
  2580.       }
  2581.     }
  2582.     return;
  2583.   case ctrlStateWaitMii:
  2584.     if(miiPending == true) {
  2585.       miiPending = false;
  2586.       break;
  2587.     }
  2588.     return;
  2589.   case ctrlStateDisable:
  2590.     if(callbackPending == true) {
  2591.       callbackPending = false;
  2592.  
  2593.       /* This will cause the phy to be set to requestedMedium on resume. */
  2594.       selectedMedium = kIOMediumEthernetNone;
  2595.       medium = 
  2596.         IONetworkMedium::getMediumWithType(fMediumDict, selectedMedium);
  2597.         
  2598.       if(medium != NULL) {
  2599.         if(requestedMedium != kIOMediumEthernetAuto) {
  2600.           setSelectedMedium(medium);
  2601.         }
  2602.         setLinkStatus(kIONetworkLinkValid, medium);
  2603.         fLinkUp = false;
  2604.       }
  2605.  
  2606.       /* Turn off phy. */
  2607.       ior = writeMiiWordAsync(0, 0x0800);
  2608.       if(ior == kIOReturnSuccess) {
  2609.         cState = ctrlStateWaitMii;
  2610.       }
  2611.     }
  2612.     return;
  2613.   case ctrlStateSuspend:
  2614.     if(resumePending == true) {
  2615.       resumePending = false;
  2616.       if( (awake == true) && (started == true) ) {
  2617.         break;
  2618.       }
  2619.     }
  2620.     return;
  2621.   case ctrlStateClearWriteStall:
  2622.     if(writeStallCleared == true) {
  2623.       writeStallCleared = false;
  2624.       break;
  2625.     }
  2626.     return;
  2627.   case ctrlStateIdle:
  2628.     break;
  2629.   } /* switch(cState) */
  2630.  
  2631.   cState = ctrlStateIdle;
  2632.  
  2633.   if(checkLinkPending == true) {
  2634.     if(txInProgress > 0) {
  2635.       return;
  2636.     }
  2637.  
  2638.     checkLinkPending = false;
  2639.  
  2640.     if(fNetifEnabled == true) {
  2641.       ior = readMiiWordAsync(1);
  2642.       if(ior == kIOReturnSuccess) {
  2643.         cState = ctrlStateLinkStatus;
  2644.         return;
  2645.       }
  2646.     }
  2647.   }
  2648.  
  2649.   if((suspendPending == true) && (fNetifEnabled == false)) {
  2650.     if(txInProgress > 0) {
  2651.       return;
  2652.     }
  2653.  
  2654.     suspendPending = false;
  2655.  
  2656.     cState = ctrlStateSuspend;
  2657.     ourPolicyMaker->acknowledgeSetPowerState();
  2658.     return;
  2659.   }
  2660.  
  2661.   if( (fNetifRequestEnabled == true) && (fNetifEnabled == false) ) {
  2662.     if(txInProgress > 0) {
  2663.       return;
  2664.     }
  2665.     fNetifEnabled = true;
  2666.     
  2667.     /* Walk past any transmit requests that didn't make it out before
  2668.        the driver was last disabled. */
  2669.     while(pktQueueLen > 0) {
  2670.       --pktQueueLen;
  2671.       if(txConsumePtr->packet) {
  2672.         freePacket(txConsumePtr->packet);
  2673.         txConsumePtr->packet = NULL;
  2674.       }
  2675.       txConsumePtr->flags = 0;
  2676.       txConsumePtr = txConsumePtr->next;
  2677.     }
  2678.  
  2679.     txInProgress = 0;
  2680.     rxCtrlVal |= AXE_RXCMD_ENABLE;
  2681.  
  2682.     ior = axCmdAsync(AXE_CMD_RXCTL_WRITE, 0, rxCtrlVal);
  2683.     if(ior == kIOReturnSuccess) {
  2684.       cState = ctrlStateWaitEth;
  2685.       return;
  2686.     }
  2687.   }
  2688.  
  2689.   if(fNetifEnabled == false) {
  2690.     return;
  2691.   }
  2692.  
  2693.   if(fNetifRequestEnabled == false) {
  2694.     if(txInProgress > 0) {
  2695.       return;
  2696.     }
  2697.  
  2698.     fNetifEnabled = false;
  2699.     rxCtrlVal &= ~AXE_RXCMD_ENABLE;
  2700.  
  2701.     ior = axCmdAsync(AXE_CMD_RXCTL_WRITE, 0, rxCtrlVal);
  2702.     if(ior == kIOReturnSuccess) {
  2703.       cState = ctrlStateDisable;
  2704.     }
  2705.     return;
  2706.   }
  2707.  
  2708.   if(selectedMedium != requestedMedium) {
  2709.     if(txInProgress > 0) {
  2710.       return;
  2711.     }
  2712.  
  2713.     selectedMedium = requestedMedium;
  2714.  
  2715.     medium = 
  2716.       IONetworkMedium::getMediumWithType(fMediumDict, selectedMedium);
  2717.     if(medium) {
  2718.       setSelectedMedium(medium);
  2719.       if(selectedMedium == kIOMediumEthernetAuto) {
  2720.         medium = IONetworkMedium::getMediumWithType(fMediumDict, 
  2721.                                                     kIOMediumEthernetNone);
  2722.         
  2723.       }
  2724.       setLinkStatus(kIONetworkLinkValid, medium);
  2725.       fLinkUp = false;
  2726.     }
  2727.  
  2728.     checkLinkPending = true;
  2729.     switch(selectedMedium) {
  2730.     case kIOMediumEthernet10BaseT | kIOMediumOptionHalfDuplex:
  2731.       data16 = 0x0000;
  2732.       //mediumStatus &= ~AXE_MEDIA_FULL_DUPLEX;
  2733.       setMediumStatus(selectedMedium);
  2734.       break;
  2735.     case kIOMediumEthernet10BaseT | kIOMediumOptionFullDuplex:
  2736.       data16 = 0x0100;
  2737.       //mediumStatus |= AXE_MEDIA_FULL_DUPLEX;
  2738.       setMediumStatus(selectedMedium);
  2739.       break;
  2740.     case kIOMediumEthernet100BaseTX  | kIOMediumOptionHalfDuplex:
  2741.       data16 = 0x2000;
  2742.       //mediumStatus &= ~AXE_MEDIA_FULL_DUPLEX;
  2743.       setMediumStatus(selectedMedium);
  2744.       break;
  2745.     case kIOMediumEthernet100BaseTX  | kIOMediumOptionFullDuplex:
  2746.       data16 = 0x2100;
  2747.       //mediumStatus |= AXE_MEDIA_FULL_DUPLEX;
  2748.       setMediumStatus(selectedMedium);
  2749.       break;
  2750.     case kIOMediumEthernet1000BaseTX  | kIOMediumOptionHalfDuplex:
  2751.       data16 = 0x0040;
  2752.       //mediumStatus |= AXE_MEDIA_FULL_DUPLEX;
  2753.       setMediumStatus(selectedMedium);
  2754.       break;
  2755.     case kIOMediumEthernet1000BaseTX  | kIOMediumOptionFullDuplex:
  2756.       data16 = 0x0140;
  2757.       //mediumStatus |= AXE_MEDIA_FULL_DUPLEX;
  2758.       setMediumStatus(selectedMedium);
  2759.       break;
  2760.     case kIOMediumEthernetAuto:
  2761.       data16 = 0x1200;
  2762.       ior = writeMiiWordAsync(0, data16);
  2763.       if(ior == kIOReturnSuccess) {
  2764.         cState = ctrlStateWaitMii;
  2765.       }
  2766.       return;
  2767.     default:
  2768.       data16 = 0x0000;
  2769.       //mediumStatus &= ~AXE_MEDIA_FULL_DUPLEX;
  2770.       setMediumStatus(kIOMediumEthernet10BaseT |
  2771.               kIOMediumOptionHalfDuplex);
  2772.       break;
  2773.     }
  2774.  
  2775.     ior = writeMiiWordAsync(0, data16);
  2776.     if(ior == kIOReturnSuccess) {
  2777.       cState = ctrlStateSetMedium;
  2778.     }
  2779.     return;
  2780.   }
  2781.  
  2782.   if(promiscMode != promiscRequest) {
  2783.     if(txInProgress > 0) {
  2784.       return;
  2785.     }
  2786.  
  2787.     promiscMode = promiscRequest;
  2788.     if(promiscMode) {
  2789.       rxCtrlVal |= AXE_RXCMD_PROMISC;
  2790.     } else {
  2791.       rxCtrlVal &= ~AXE_RXCMD_PROMISC;
  2792.     }
  2793.  
  2794.     ior = axCmdAsync(AXE_CMD_RXCTL_WRITE, 0, rxCtrlVal);
  2795.     if(ior == kIOReturnSuccess) {
  2796.       cState = ctrlStateWaitEth;
  2797.     }
  2798.     return;
  2799.   }
  2800.  
  2801.   if(setMc == true) {
  2802.     if(txInProgress > 0) {
  2803.       return;
  2804.     }
  2805.  
  2806.     setMc = false;
  2807.     mcBytesToWrite = 0;
  2808.  
  2809.     /* The following two lines just copy 8 bytes from mHashTable to
  2810.        fCtrlPipeBuffer.*/
  2811.     *( (UInt32 *)fCtrlPipeBuffer) = *( (UInt32 *)mHashTable);
  2812.     *( ((UInt32 *)fCtrlPipeBuffer) + 1) = *(((UInt32 *)mHashTable) + 1);
  2813.  
  2814.     ior = axCmdAsync(AXE_CMD_WRITE_MCAST, 0, 0);
  2815.     if(ior == kIOReturnSuccess) {
  2816.       cState = ctrlStateWaitEth;
  2817.     }
  2818.     return;
  2819.   }
  2820.  
  2821.   while((writePipeStalled == false) && (pktQueueLen > 0)) {
  2822.  
  2823. #if ONE_TX_AT_A_TIME 
  2824.     if(txInProgress > 0) {
  2825.       return;
  2826.     }
  2827. #endif
  2828.  
  2829.     --pktQueueLen;
  2830.     txConsumePtr = txConsumePtr->next;
  2831.  
  2832.     txLen = txConsumePtr->mdp->getLength();
  2833.     if( txLen && !(txLen & (maxPacketSize - 1)) ) {
  2834.       ior = fOutPipe->Write(txConsumePtr->mdp, 0, 0, txLen,
  2835.                             &txConsumePtr->writeZeroCompletionInfo);
  2836.       if(ior == kIOReturnSuccess) {
  2837.                                 /* Written packet was a multiple of maxPacketSize */
  2838.                                 ior = fOutPipe->Write(txConsumePtr->mdp, 0, 0, 0,
  2839.                                                                                                                         &txConsumePtr->writeCompletionInfo);
  2840.       }
  2841.     
  2842.     } else {
  2843.       ior = fOutPipe->Write(txConsumePtr->mdp, 0, 0, txLen,
  2844.                             &txConsumePtr->writeCompletionInfo);
  2845.     }
  2846.  
  2847.     if(ior == kIOReturnSuccess) {
  2848.       ++txInProgress;
  2849.     } else {
  2850.       if((fOutPipe->GetPipeStatus()) == kIOUSBPipeStalled) {
  2851.         writePipeStalled = true;
  2852.         IOLog("USBAxx8817x: setState: Write pipe stalled!\n");
  2853.       } else {
  2854.         IOLog("USBAx8817x::setState: write return code = 0x%x.\n", ior);
  2855.       }
  2856.     }
  2857.   }
  2858.  
  2859.   if((txInProgress == 0) && (writePipeStalled == true) ) {
  2860.     writePipeStalled = false;
  2861.     IOLog("USBAxx8817x: setState: Clearing write stall!\n");
  2862.     IOLockLock(rxQueueLock);
  2863.     readThreadCmd |= RXTHREAD_WRITESTALLED;
  2864.     IOLockWakeup(rxQueueLock, NO_EVENT, true);
  2865.     IOLockUnlock(rxQueueLock);
  2866.     cState = ctrlStateClearWriteStall;
  2867.   }
  2868. } /* End setState */
  2869.  
  2870. /*****************************************************************************/
  2871. //
  2872. //              Method:         USBAx8817x::setMediumStatus
  2873. //
  2874. //              Inputs:         selectedMedium - Medium to select
  2875. //
  2876. //              Outputs:        Return code - none
  2877. //
  2878. //              Desc:           The mediumStatus tells the MAC what medium is
  2879. //                              currently selected.
  2880. //
  2881. /****************************************************************************/
  2882. void USBAx8817x::setMediumStatus(UInt32 selectedMedium) {
  2883.   if(mediumStatus & kIOMediumOptionFullDuplex) {
  2884.     mediumStatus |= AXE_MEDIA_FULL_DUPLEX;
  2885.   } else {
  2886.     mediumStatus &= ~AXE_MEDIA_FULL_DUPLEX;
  2887.   }
  2888. }
  2889.  
  2890. /*****************************************************************************/
  2891. //
  2892. //              Method:         USBAx8817x::handleSetPowerStateOn
  2893. //
  2894. //              Inputs:         param0 - pointer to driver object
  2895. //                              param1 - not used
  2896. //
  2897. //              Outputs:        Return code - none
  2898. //
  2899. //              Desc:           Called to indicate a power "OFF" event.
  2900. //
  2901. /****************************************************************************/
  2902. void USBAx8817x::handleSetPowerStateOff(thread_call_param_t param0, 
  2903.                                         thread_call_param_t param1 ) {
  2904.   USBAx8817x *me;
  2905.  
  2906.   me = (USBAx8817x *)param0;
  2907.   if(!me) {
  2908.     IOLog("USBAx8817x::handleSetPowerStateOff: me == NULL!\n");
  2909.     return;
  2910.   }
  2911.  
  2912.   postEvent(me, (void *)(int)ctrlEventSuspend);
  2913.   if(me->ourPolicyMaker) {
  2914.     //me->ourPolicyMaker->acknowledgeSetPowerState();
  2915.   }
  2916.   me->release();
  2917. } /* end handleSetPowerStateOff */
  2918.  
  2919. /*****************************************************************************/
  2920. //
  2921. //              Method:         USBAx8817x::handleSetPowerStateOn
  2922. //
  2923. //              Inputs:         param0 - pointer to driver object
  2924. //                              param1 - not used
  2925. //
  2926. //              Outputs:        Return code - none
  2927. //
  2928. //              Desc:           Called to indicate a power "ON" event.
  2929. //
  2930. /****************************************************************************/
  2931. void USBAx8817x::handleSetPowerStateOn(thread_call_param_t param0, 
  2932.                                        thread_call_param_t param1 ) {
  2933.   USBAx8817x *me;
  2934.  
  2935.   me = (USBAx8817x *)param0;
  2936.   if(!me) {
  2937.     IOLog("USBAx8817x::handleSetPowerStateOn: me == NULL!\n");
  2938.     return;
  2939.   }
  2940.  
  2941.   postEvent(me, (void *)(int)ctrlEventResume);
  2942.   if(me->ourPolicyMaker) {
  2943.     me->ourPolicyMaker->acknowledgeSetPowerState();
  2944.   }
  2945.  
  2946.   me->release();
  2947. } /* end handleSetPowerStateOn */
  2948.  
  2949. #pragma mark -- Shutdown --
  2950.  
  2951. /*****************************************************************************/
  2952. //
  2953. //      Method:         USBAx8817x::cleanUp
  2954. //
  2955. //      Inputs:         None
  2956. //
  2957. //      Outputs:        None
  2958. //
  2959. //      Desc:           Releases all allocated resources.
  2960. //
  2961. /*****************************************************************************/
  2962. void USBAx8817x::cleanUp() {
  2963.   int i;
  2964.  
  2965.   if(rxQueueLock != NULL) {
  2966.     IOLockLock(rxQueueLock);
  2967.     while(!(readThreadCmd & RXTHREAD_STOPPED)) {
  2968.       readThreadCmd |= RXTHREAD_STOP;
  2969.       IOLockWakeup(rxQueueLock, NO_EVENT, true);    
  2970.       IOLockSleep(rxQueueLock, NO_EVENT, THREAD_ABORTSAFE);
  2971.     }
  2972.  
  2973.     IOLockUnlock(rxQueueLock);
  2974.     IOLockFree(rxQueueLock);
  2975.     rxQueueLock = NULL;
  2976.   }
  2977.  
  2978.   if(fNetworkInterface) {
  2979.     detachInterface(fNetworkInterface, false);
  2980.     fNetworkInterface->release();
  2981.     fNetworkInterface = NULL;
  2982.   }
  2983.  
  2984.   if(fTransmitQueue) {
  2985.     fTransmitQueue->stop();
  2986.     fTransmitQueue->setCapacity(0);
  2987.     fTransmitQueue->flush();
  2988.     fTransmitQueue->release();
  2989.     fTransmitQueue = NULL;
  2990.   }
  2991.  
  2992.   if(fTimerSource) {
  2993.     fTimerSource->cancelTimeout();
  2994.     fTimerSource->release();
  2995.     fTimerSource = NULL;
  2996.   }
  2997.  
  2998.   if(fPipeInterruptMDP) {
  2999.     fPipeInterruptMDP->release();
  3000.     fPipeInterruptMDP = NULL;
  3001.   }
  3002.  
  3003.   if(fPipeCtrlMDP) { 
  3004.     fPipeCtrlMDP->release();    
  3005.     fPipeCtrlMDP = NULL; 
  3006.   }
  3007.  
  3008.   for(i=0; i<TX_RING_SIZE; ++i) {
  3009.     if(txRing[i].mdp) { 
  3010.       txRing[i].mdp->release();    
  3011.       txRing[i].mdp = NULL; 
  3012.     }
  3013.     if(txRing[i].packet) {
  3014.       freePacket(txRing[i].packet);
  3015.       txRing[i].packet = NULL;
  3016.     }
  3017.   }
  3018.  
  3019.   for(i=0; i<NUM_RX_BUFFERS; ++i) {
  3020.     if(rxMDPList[i]) {
  3021.       rxMDPList[i]->release();
  3022.       rxMDPList[i] = NULL;
  3023.     }
  3024.   }
  3025.  
  3026.   if(fInterruptPipe) {
  3027.     //fInterruptPipe->release();
  3028.     fInterruptPipe = NULL;
  3029.   }
  3030.  
  3031.   if(fCntlPipe) {
  3032.     //fCntlPipe->release();
  3033.     fCntlPipe = NULL;
  3034.   }
  3035.  
  3036.   if(fInPipe) {
  3037.     //fInPipe->release();
  3038.     fInPipe = NULL;
  3039.   }
  3040.  
  3041.   if(fOutPipe) {
  3042.     //fOutPipe->release();
  3043.     fOutPipe = NULL;
  3044.   }
  3045.  
  3046.   if(fDataInterface) { 
  3047.     fDataInterface->close(this);        
  3048.     fDataInterface->release();
  3049.     fDataInterface = NULL;      
  3050.   }
  3051.  
  3052.   if(fpDevice) {
  3053.     fpDevice->close(this);
  3054.     fpDevice->release();
  3055.     fpDevice = NULL;
  3056.   }
  3057.  
  3058.   if(fMediumDict) {
  3059.     fMediumDict->release();
  3060.     fMediumDict = NULL;
  3061.   }
  3062.  
  3063.   if(powerUpThread) {
  3064.     thread_call_free(powerUpThread);
  3065.     powerUpThread = NULL;
  3066.   }
  3067.  
  3068.   if(powerDownThread) {
  3069.     thread_call_free(powerDownThread);
  3070.     powerDownThread = NULL;
  3071.   }
  3072.  
  3073.   if(txQueueLock) {
  3074.     IOLockFree(txQueueLock);
  3075.     txQueueLock = NULL;
  3076.   }
  3077.  
  3078.   if(txLock) {
  3079.     IOLockFree(txLock);
  3080.     txLock = NULL;
  3081.   }
  3082.  
  3083. } /* end cleanUp */
  3084.  
  3085. /*****************************************************************************/
  3086. //
  3087. //      Method:         USBAx8817x::stop
  3088. //
  3089. //      Inputs:         provider - my provider
  3090. //
  3091. //      Outputs:        None
  3092. //
  3093. //      Desc:           Stops
  3094. //
  3095. /*****************************************************************************/
  3096. void USBAx8817x::stop(IOService *provider) {
  3097.   cleanUp();
  3098.   super::stop(provider);
  3099.  
  3100.   IOLog("USBAx8817x: Stopped.\n");
  3101.   return;
  3102. } /* end stop */
  3103.