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

  1. /*
  2.     File:            USBAx88772.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 "USBAx88772_private.h"
  61. #include "USBAx8817x.h"
  62. #include "USBAx88772.h"
  63. #include "USBAx8817xEthernetInterface.h"
  64.  
  65. #define super USBAx8817x
  66. #define POSTEVENT(x) postEvent(this, (void *)(int)x, (void *)(int)true)
  67.  
  68. OSDefineMetaClassAndStructors(USBAx88772, USBAx8817x);
  69.  
  70. #define AX_SWRESET_CLEAR        0x00
  71. #define AX_SWRESET_RR            0x01
  72. #define AX_SWRESET_RT            0x02
  73. #define AX_SWRESET_PRTE            0x04
  74. #define AX_SWRESET_PRL            0x08
  75. #define AX_SWRESET_BZ            0x10
  76. #define AX_SWRESET_IPRL            0x20
  77. #define AX_SWRESET_IPPD            0x40
  78.  
  79. #pragma mark -- Initialization --
  80. /*****************************************************************************/
  81. //
  82. //      Method:         USBAx88772::resetMAC
  83. //
  84. //      Inputs:         None
  85. //
  86. //      Outputs:        true if successful, false otherwise
  87. //
  88. //      Desc:           Tries to reset the MAC and the phy, and read
  89. //                      the ethernet address.
  90. //
  91. /*****************************************************************************/
  92. bool USBAx88772::resetMAC() {
  93.   UInt8 ipgs[4];
  94.   UInt16 data16;
  95.   /*
  96.    *  Reset
  97.    */
  98.  
  99.   IOLog("USBAx88772: Version 1.0.1.\n");
  100.  
  101.   if(!axCmd(AXE_CMD_WRITE_GPIO, 0, 0x00b0, NULL)) {
  102.     IOLog("USBAx88772: resetMAC: Failed to write GPIO bits.\n");
  103.     return false;
  104.   }
  105.   IOSleep(5);
  106.  
  107.   if(!axCmd(AXE_CMD_SW_PHY_SELECT, 0, 1, NULL)) { 
  108.     IOLog("USBAx88772: resetMAC: Failed to select phy 1.\n");
  109.     return false;
  110.   }
  111.  
  112.   if(!axCmd(AXE_CMD_RESET, 0, AX_SWRESET_IPPD, NULL)) {
  113.     IOLog("USBAx8877x: resetMAC: Failed to power down internal PHY.\n");
  114.     return false;
  115.   }
  116.   IOSleep(150);
  117.  
  118.   if(!axCmd(AXE_CMD_RESET, 0, AX_SWRESET_CLEAR, NULL)) {
  119.     IOLog("USBAx88772: resetMAC: Failed to perform software reset.\n");
  120.     return false;
  121.   }
  122.   IOSleep(150);
  123.  
  124.   if(!axCmd(AXE_CMD_RESET, 0, AX_SWRESET_IPRL | AX_SWRESET_PRL,
  125.         NULL) ) {
  126.     IOLog("USBAx88772: resetMAC: Failed to set Internal/External ");
  127.     IOLog("PHY reset control.\n");
  128.     return false;
  129.   }
  130.   IOSleep(150);
  131.  
  132.   /*
  133.    * Get station address.
  134.    */
  135.   bzero(fEaddr, 6);
  136.   if(!axCmd(AXE_CMD_READ_NODEID, 0, 0, &fEaddr)) {
  137.     IOLog("USBAx88772: resetMAC: Failed to read Node ID.\n");
  138.     return false;
  139.   }
  140.  
  141.   if(!axCmd(AXE_CMD_READ_MEDIA, 0, 0, &mediumStatus)) {
  142.     IOLog("USBAx88772: resetMAC: Failed to read medium status.\n");
  143.     return false;
  144.   }
  145.   mediumStatus = USBToHostWord(mediumStatus);
  146.  
  147.   mediumStatus |= AXE_MEDIA_RECEIVE_ENABLE;
  148.   if(!axCmd(AXE_CMD_WRITE_MEDIA, 0, mediumStatus, 0)) {
  149.     IOLog("USBAx88772: resetMAC: Failed to write medium status.\n");
  150.     return false;
  151.   }
  152.  
  153.   data16 = 0;
  154.   if(!axCmd(AXE_CMD_RXCTL_READ, 0, 0, &data16)) {
  155.     IOLog("USBAx88772: resetMAC: Failed to read rx control.\n");
  156.     return false;
  157.   }
  158.  
  159.   rxCtrlVal = USBToHostWord(data16);
  160.   rxCtrlVal &= ~USB_BURST_MASK;
  161.   rxCtrlVal |= USB_BURST_2048;
  162.   rxCtrlVal &= ~AXE_RXCMD_ENABLE;
  163.   rxCtrlVal |= (AXE_RXCMD_MULTICAST | AXE_RXCMD_BROADCAST);
  164.   if(!axCmd(AXE_CMD_RXCTL_WRITE, 0, rxCtrlVal, NULL)){
  165.     IOLog("USBAx88772: resetMAC: Failed to write rx control.\n");
  166.     return false;
  167.   }
  168.  
  169.   if(!axCmd(AXE_CMD_READ_IPG012, 0, 0, ipgs)) {
  170.     IOLog("USBAx88772: resetMAC: Failed to read ipg values.\n");
  171.     return false;
  172.   }
  173.   data16 = (((UInt16)ipgs[1]) << 8) | ((UInt16)ipgs[0]);
  174.  
  175.   if(!axCmd(AXE_CMD_WRITE_IPG012, ipgs[2], data16, NULL)) {
  176.     IOLog("USBAx88772: resetMAC: Failed to write IPG values.\n");
  177.     return false;
  178.   }
  179.  
  180.   phy = 0xf0;
  181.   data16 = 0;
  182.   if(!readMiiWord(phy, 1, &data16)) {
  183.     IOLog("USBAx88772: resetMAC: Failed to read mii register 1.\n");
  184.     return false;
  185.   }
  186.  
  187.   if( (data16 == 0xffff) || (data16 == 0) ) {
  188.     IOLog("USBAx88772: resetMAC: MII register 1 was read back as %d.\n",
  189.       (int)data16);
  190.     return false;
  191.   }
  192.  
  193.   if(data16 & 0x0100) {
  194.     supports1000BaseT = true;
  195.     IOLog("USBAx88772: Found 1000BaseT capable phy.\n");
  196.     readMiiWord(phy, 15, &data16);
  197.     IOLog("USBAx88772: MII register 15 = 0x%X.\n", data16);
  198.   }
  199.   
  200.   data16=0;
  201.   if(axCmd(AXE_CMD_SROM_READ, 0, 0x10, &data16)) {
  202.     data16 = USBToHostWord(data16);
  203.     IOLog("USBAx88772: Max packet size is = %d.\n", data16);
  204.   }
  205.  
  206.   data16=0;
  207.   if(!axCmd(AXE_CMD_SROM_READ, 0, 0x01, &data16)) {
  208.     IOLog("USBAx88772: Failed to read flags.\n");
  209.     return false;
  210.   }
  211.  
  212.   deviceFlag = USBToHostWord(data16);
  213.   IOLog("USBAx88772: flags = 0x%X.\n", deviceFlag);
  214.  
  215.   /* Turn off phy. */
  216.   writeMiiWord(phy, 0, 0x0800);
  217.  
  218.   return true;
  219. } /* end resetMAC */
  220.  
  221. int USBAx88772::copyPktToBuffer(mbuf_t m, UInt8 *buf, int len) {
  222.   UInt16 *frameHdr;
  223.   UInt16 USBLen;
  224.  
  225.   frameHdr = (UInt16 *)buf;
  226.   USBLen = HostToUSBWord(len);
  227.   frameHdr[0] = USBLen;
  228.   frameHdr[1] = ~USBLen;
  229.   buf += 4;
  230.  
  231.   while(m) {
  232.     if(mbuf_len(m) > 0) {
  233.       bcopy(mbuf_data(m), buf, mbuf_len(m));
  234.       buf += mbuf_len(m);
  235.     }
  236.     m = mbuf_next(m);
  237.   }
  238.  
  239.   /* Minimum packet is 60 bytes */
  240.   if(len < 60) {
  241.     bzero(buf, 60 - len);
  242.     len = 60;
  243.   }
  244.  
  245.   return len + 4;
  246. }
  247.  
  248. /***************************************************************************/
  249. //
  250. //      Method:         USBAx88772::receivePacket
  251. //
  252. //      Inputs:         completion - pointer to read completion routine
  253. //                      inMDP - MDP where received data is
  254. //                      remaining - BUFSIZE minus length of received packet
  255. //
  256. //      Outputs:        None
  257. //
  258. //      Desc:           Receives a packet.  Allocates a buffer, copies
  259. //                      the received packet to the buffer, and sends
  260. //                      the buffer up the network stack.  Then another
  261. //                      read command is issued.  If the read command
  262. //                      fails, the network interface is freed.
  263. //         
  264. //
  265. /****************************************************************************/
  266. void USBAx88772::receivePacket(UInt32 packetLength,
  267.                                IOBufferMemoryDescriptor *inMDP,
  268.                                IOUSBCompletion *completion) {
  269.   UInt8        *dataInPtr;
  270.   mbuf_t       rcvd;
  271.   IOReturn     ior;
  272.   UInt16       frameLen;
  273.   UInt16       *frameHdr;
  274.   UInt32       lenOrig;
  275.   int itr;
  276.  
  277.   lenOrig = packetLength;
  278.   dataInPtr = (UInt8 *)inMDP->getBytesNoCopy();
  279.   itr = 0;
  280.   while(packetLength > 4) {
  281.     ++itr;
  282.     frameHdr = (UInt16 *)dataInPtr;
  283.     if(frameHdr[0] != (UInt16)~(frameHdr[1])) {
  284.       IOLog("USBAx88772::receivePacket: Bad frame header.  itr = %d\n",
  285.         itr);
  286.       break;
  287.     }
  288.     packetLength -= 4;
  289.     dataInPtr += 4;
  290.  
  291.     frameLen = USBToHostWord(frameHdr[0]);
  292.     if(frameLen > packetLength) {
  293.       IOLog("USBAx88772::receivePacket: Famelen = %d, ",
  294.         (int)frameLen);
  295.       IOLog("lenOrig = %d, lenNow = %d.\n",
  296.         (int)lenOrig, (int)packetLength);
  297.       break;
  298.     }
  299.     rcvd = allocatePacket(frameLen);
  300.     if(!rcvd) {
  301.       IOLog("USBAx88772::receivePacket: Failed to allocate packet.\n");
  302.       return;
  303.     }
  304.  
  305.     bcopy(dataInPtr, mbuf_data(rcvd), frameLen);
  306.  
  307.     fNetworkInterface->inputPacket(rcvd, frameLen, 0x01);
  308.     if(fpNetStats) {
  309.       ++fpNetStats->inputPackets;
  310.     }
  311.  
  312.     /* Round up frameLen to the nearest multiple of 2. */
  313.     frameLen = (frameLen + 1) & 0xfffe;
  314.     packetLength -= frameLen;
  315.     dataInPtr += frameLen;
  316.   }
  317.  
  318.   /* Read next packet. */
  319.   inMDP->setLength(BUFSIZE);
  320.   ior = fInPipe->Read(inMDP, 0, 0, BUFSIZE, completion, NULL);
  321.   if(ior != kIOReturnSuccess) {
  322.     if((fInPipe->GetPipeStatus()) == kIOUSBPipeStalled) {
  323.       IOLog("USBAx88772::receivePacket: return code = 0x%x.\n", ior);
  324.       IOLockLock(rxQueueLock);
  325.       readThreadCmd |= RXTHREAD_READSTALLED;
  326.       IOLockWakeup(rxQueueLock, NO_EVENT, true);
  327.       IOLockUnlock(rxQueueLock);
  328.     } else {
  329.       IOLog("USBAx88772::receivePacket: Failed to read next packet.\n");
  330.     }
  331.   }
  332.  
  333. } /* end receivePacket */
  334.  
  335. /*****************************************************************************/
  336. //
  337. //              Method:         USBAx88772::setMediumStatus
  338. //
  339. //              Inputs:         selectedMedium - Medium to select
  340. //
  341. //              Outputs:        Return code - none
  342. //
  343. //              Desc:           The mediumStatus tells the MAC what medium is
  344. //                              currently selected.
  345. //
  346. /****************************************************************************/
  347. void USBAx88772::setMediumStatus(UInt32 selectedMedium) {
  348.     switch(selectedMedium) {
  349.     case kIOMediumEthernet10BaseT | kIOMediumOptionHalfDuplex:
  350.       mediumStatus &= ~AXE_MEDIA_FULL_DUPLEX;
  351.       mediumStatus &= ~AXE_MEDIA_100_MODE;
  352.       mediumStatus &= ~AXE_MEDIA_GMII_MODE;
  353.       break;
  354.     case kIOMediumEthernet10BaseT | kIOMediumOptionFullDuplex:
  355.       mediumStatus |= AXE_MEDIA_FULL_DUPLEX;
  356.       mediumStatus &= ~AXE_MEDIA_100_MODE;
  357.       mediumStatus &= ~AXE_MEDIA_GMII_MODE;
  358.       break;
  359.     case kIOMediumEthernet100BaseTX  | kIOMediumOptionHalfDuplex:
  360.       mediumStatus &= ~AXE_MEDIA_FULL_DUPLEX;
  361.       mediumStatus |= AXE_MEDIA_100_MODE;
  362.       mediumStatus &= ~AXE_MEDIA_GMII_MODE;
  363.       break;
  364.     case kIOMediumEthernet100BaseTX  | kIOMediumOptionFullDuplex:
  365.       mediumStatus |= AXE_MEDIA_FULL_DUPLEX;
  366.       mediumStatus |= AXE_MEDIA_100_MODE;
  367.       mediumStatus &= ~AXE_MEDIA_GMII_MODE;
  368.       break;
  369.     case kIOMediumEthernet1000BaseTX  | kIOMediumOptionHalfDuplex:
  370.       mediumStatus &= ~AXE_MEDIA_FULL_DUPLEX;
  371.       mediumStatus &= ~AXE_MEDIA_100_MODE;
  372.       mediumStatus |= AXE_MEDIA_GMII_MODE;
  373.       break;
  374.     case kIOMediumEthernet1000BaseTX  | kIOMediumOptionFullDuplex:
  375.       mediumStatus |= AXE_MEDIA_FULL_DUPLEX;
  376.       mediumStatus &= ~AXE_MEDIA_100_MODE;
  377.       mediumStatus |= AXE_MEDIA_GMII_MODE;
  378.       break;
  379.     default:
  380.       mediumStatus &= ~AXE_MEDIA_FULL_DUPLEX;
  381.       mediumStatus &= ~AXE_MEDIA_100_MODE;
  382.       mediumStatus &= ~AXE_MEDIA_GMII_MODE;
  383.       break;
  384.   }
  385. }
  386.