/* * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * Copyright (c) 1998-1999 Apple Software, Inc. * * Interface definition for the UniN Ethernet Controller * * HISTORY * */ #include #include #include #include #include #include #include #include #include /* bcopy */ extern "C" { #include #include } // No kernel tracing support at this time. #define KERNEL_DEBUG( x, a, b, c, d, e ) #include "UniNEnetRegisters.h" /***** For fans of kprintf, IOLog and debugging infrastructure of the *****/ /***** string ilk, please modify the ELG and ALRT macros or their *****/ /***** associated EvLog and Alrt functions to suit your taste. These *****/ /***** macros currently are set up to log events to a wraparound *****/ /***** buffer with minimal performance impact. They take 2 UInt32 *****/ /***** parameters so that when the buffer is dumped 16 bytes per line, *****/ /***** time stamps (~1 microsecond) run down the left side while *****/ /***** unique 4-byte ASCII codes can be read down the right side. *****/ /***** Preserving this convention facilitates different maintainers *****/ /***** using different debugging styles with minimal code clutter. *****/ #define USE_ELG 0 // for debugging #define kEvLogSize (4096*16) // 16 pages = 64K = 4096 events 0x10000 ///#define kEvLogSize (4096*1) // 1 page = 4K = 256 events #if USE_ELG /* (( */ #define ELG(A,B,ASCI,STRING) EvLog( (UInt32)(A), (UInt32)(B), (UInt32)(ASCI), STRING ) #define ALRT(A,B,ASCI,STRING) Alrt( (UInt32)(A), (UInt32)(B), (UInt32)(ASCI), STRING ) void EvLog( UInt32 a, UInt32 b, UInt32 ascii, char* str ); void Alrt( UInt32 a, UInt32 b, UInt32 ascii, char* str ); #else /* ) not USE_ELG: ( */ #define ELG(A,B,ASCI,S) #define ALRT(A,B,ASCI,STRING) IOLog( "UniNEnet: %8x %8x " STRING "\n", (unsigned int)(A), (unsigned int)(B) ) #endif /* USE_ELG )) */ typedef struct elg /* Event Log flag and pointers */ { UInt32 evLogFlag; // debugging only UInt8 *evLogBuf; UInt8 *evLogBufe; UInt8 *evLogBufp; }; #define NETWORK_STAT_ADD( x ) (fpNetStats->x++) #define ETHERNET_STAT_ADD( x ) (fpEtherStats->x++) #if USE_ELG #define READ_REGISTER( REG ) (UInt32)(enetClockOff ? Alrt( 0, 0, 'REG-', "regs unavail" ) : \ OSReadLittleInt32( (void*)&fpRegs->REG, 0 ) ) #define WRITE_REGISTER( REG, VAL ) writeRegister( &fpRegs->REG, VAL ) #else #define READ_REGISTER( REG ) OSReadLittleInt32( (void*)&fpRegs->REG, 0 ) #define WRITE_REGISTER( REG, VAL ) OSWriteLittleInt32( (void*)&fpRegs->REG, 0, VAL ) #endif // USE_ELG /*#if USE_ELG #define WRITE_REGISTER( REG, VAL ) writeRegister( &fpRegs->REG, VAL ) #else #define WRITE_REGISTER( REG, VAL ) OSWriteLittleInt32( (void*)&fpRegs->REG, 0, VAL ) #endif // USE_ELG */ typedef void *IOPPCAddress; enum LinkStatus { kLinkStatusUnknown, kLinkStatusDown, kLinkStatusUp, }; struct MediumTable { UInt32 type; UInt32 speed; }; #define kNumOfPowerStates 2 #define kUniNsettle_time 500 // guess 500 microseconds for settling /* Items in the IORegistry: */ #define kTxQueueSize "TxPacketQueueSize" #define kTxRingElements "TxRingElements: 32,64,128,256,512,1024,2048,4096,8192" #define kRxRingElements "RxRingElements: 32,64,128,256,512,1024,2048,4096,8192" /* Performance tracepoints * * DBG_UniN_RXIRQ - Receive ISR run time * DBG_UniN_TXIRQ - Transmit ISR run time * DBG_UniN_TXQUEUE - Transmit packet passed from network stack * DBG_UniN_TXCOMPLETE - Transmit packet sent * DBG_UniN_RXCOMPLETE - Receive packet passed to network stack */ #define DBG_UniN_ENET 0x0900 #define DBG_UniN_RXIRQ DRVDBG_CODE( DBG_DRVNETWORK, (DBG_UniN_ENET+1) ) #define DBG_UniN_TXIRQ DRVDBG_CODE( DBG_DRVNETWORK, (DBG_UniN_ENET+2) ) #define DBG_UniN_TXQUEUE DRVDBG_CODE( DBG_DRVNETWORK, (DBG_UniN_ENET+3) ) #define DBG_UniN_TXCOMPLETE DRVDBG_CODE( DBG_DRVNETWORK, (DBG_UniN_ENET+4) ) #define DBG_UniN_RXCOMPLETE DRVDBG_CODE( DBG_DRVNETWORK, (DBG_UniN_ENET+5) ) class UniNEnet: public IOEthernetController { OSDeclareDefaultStructors( UniNEnet ) private: // Instance variables: elg *fpELG; // pointer to ELG structure & buffer volatile GMAC_Registers *fpRegs; GMAC_Registers *fpRegsPhys; // for ml_probe_read IOPCIDevice * nub; IOMemoryMap * ioMapEnet; volatile IOPPCAddress ioBaseEnet; IOEthernetInterface * networkInterface; IOBasicOutputQueue * transmitQueue; IOPacketQueue * debugQueue; IOKernelDebugger * debugger; IOWorkLoop * workLoop; IOInterruptEventSource * interruptSource; IONetworkStats * fpNetStats; IOEthernetStats * fpEtherStats; IOTimerEventSource * timerSource; IOMbufBigMemoryCursor * mbufCursor; bool fBuiltin; // UniN builtin = 1; PCI card = 0 bool ready; bool fWOL; // WakeOnLAN desired. bool enetClockOff; bool netifEnabled; bool debugEnabled; bool debugTxPoll; IOEthernetAddress myAddress; bool isPromiscuous; bool multicastEnabled; bool isFullDuplex; UInt32 phyType; // both PHY ID registers UInt8 phyId; UInt32 linkStatusPrev; UInt16 phyStatusPrev; UInt16 fPHYControl; // 16 bit PHY Control register. UInt32 fPHYType; // 5400, 5401 or 5201 for PM OSDictionary * mediumDict; MediumTable *fpgMediumTable; UInt32 fMediumTableCount; UInt32 fTxQueueSize; // size of the Tx queue UInt32 fTxRingElements; // number of Tx ring elements UInt32 fRxRingElements; // number of Rx ring elements mbuf **fTxMbuf; // array of Tx mBuf pointers; index of last segment of pkt -> mbuf mbuf **fRxMbuf; // array of Rx mBuf pointers mbuf *txDebuggerPkt; mbuf *rxMbufBucket; UInt32 *fRxBucketPhysAddr; // Physical addr of bit bucket void * debuggerPkt; u_int32_t debuggerPktSize; UInt32 txCommandHead; // TX ring descriptor index UInt32 txCommandTail; UInt32 rxCommandHead; // RX ring descriptor index UInt32 rxCommandTail; TxDescriptor *fTxDescriptorRing; // TX descriptor ring ptr UInt32 fTxDescriptorRingPhys; UInt32 fTxElementsAvail; UInt32 fTxRingLengthFactor; RxDescriptor *fRxDescriptorRing; // RX descriptor ring ptr UInt32 fRxDescriptorRingPhys; UInt32 fRxRingLengthFactor; UInt32 txIntCnt; UInt32 txRingIndexLast; UInt32 txWDInterrupts; UInt32 txWDCount; UInt32 rxWDInterrupts; UInt32 rxWDCount; UInt16 hashTableUseCount[256]; UInt16 hashTableMask[16]; unsigned long currentPowerState; /* must be 0 or 1 */ /* Local copies of certain key registers: */ UInt32 fXIFConfiguration; UInt32 fRxMACConfiguration; UInt32 fMACControlConfiguration; private: // Instance methods: void AllocateEventLog( UInt32 size ); void EvLog( UInt32 a, UInt32 b, UInt32 ascii, char* str ); UInt32 Alrt( UInt32 a, UInt32 b, UInt32 ascii, char* str ); bool allocateMemory(); bool initTxRing(); bool initRxRing(); void flushRings( bool, bool ); // Flush Tx and Rx rings bool initChip(); void setDuplexMode(bool duplexMode); void startChip(); void stopChip(); bool genRxDescriptor( UInt32 index ); void monitorLinkStatus( bool firstPoll = false ); bool transmitPacket(struct mbuf * packet); bool transmitInterruptOccurred(); void debugTransmitInterruptOccurred(); void debugTransmitCleanup(); bool receiveInterruptOccurred(); bool receivePackets(bool fDebugger); void packetToDebugger(struct mbuf * packet, u_int size); void restartReceiver(); void putToSleep(bool pangeaClockOnly); bool wakeUp(bool pangeaClockOnly); void sendDummyPacket(); void resetHashTableMask(); void addToHashTableMask(u_int8_t *addr); void removeFromHashTableMask(u_int8_t *addr); void updateHashTableMask(); #ifdef DEBUG void dumpRegisters(); #endif DEBUG void sendPacket(void * pkt, UInt32 pkt_len); void receivePacket(void * pkt, UInt32 * pkt_len, UInt32 timeout); bool miiReadWord(unsigned short * dataPtr, unsigned short reg, UInt8 phy); bool miiWriteWord(unsigned short data, unsigned short reg, UInt8 phy); void miiWrite(UInt32 miiData, UInt32 dataSize); bool miiResetPHY(UInt8 phy); bool miiWaitForLink(UInt8 phy); bool miiWaitForAutoNegotiation(UInt8 phy); void miiRestartAutoNegotiation(UInt8 phy); bool miiFindPHY(UInt8 * phy_num); bool miiInitializePHY(UInt8 phy); UInt32 outputPacket(struct mbuf * m, void * param); void interruptOccurred(IOInterruptEventSource * src, int count); void timeoutOccurred(IOTimerEventSource * timer); bool createMediumTables(); void writeRegister( volatile UInt32 *pReg, UInt32 data ); void getPhyType(); void stopPHY(); void startPHY(); bool hardwareResetPHY(); // callPlatformFunction symbols const OSSymbol *keyLargo_resetUniNEthernetPhy; IOService *keyLargo; public: // Override methods: virtual bool init(OSDictionary * properties = 0); virtual bool start(IOService * provider); virtual void free(); virtual bool createWorkLoop(); virtual IOWorkLoop * getWorkLoop() const; virtual IOReturn enable(IONetworkInterface * netif); virtual IOReturn disable(IONetworkInterface * netif); virtual IOReturn setWakeOnMagicPacket( bool active ); virtual IOReturn getPacketFilters( const OSSymbol *group, UInt32 *filters ) const; virtual IOReturn getHardwareAddress(IOEthernetAddress *addr); virtual IOReturn setMulticastMode(IOEnetMulticastMode mode); virtual IOReturn setMulticastList(IOEthernetAddress *addrs, UInt32 count); virtual IOReturn setPromiscuousMode(IOEnetPromiscuousMode mode); virtual IOOutputQueue * createOutputQueue(); virtual const OSString * newVendorString() const; virtual const OSString * newModelString() const; virtual const OSString * newRevisionString() const; virtual IOReturn enable(IOKernelDebugger * debugger); virtual IOReturn disable(IOKernelDebugger * debugger); virtual bool configureInterface( IONetworkInterface *netif ); virtual IOReturn getChecksumSupport( UInt32 *checksumMask, UInt32 checksumFamily, bool isOutput ); // Power management methods: virtual IOReturn registerWithPolicyMaker( IOService *policyMaker ); virtual UInt32 maxCapabilityForDomainState( IOPMPowerFlags state); virtual UInt32 initialPowerStateForDomainState( IOPMPowerFlags state ); virtual UInt32 powerStateForDomainState( IOPMPowerFlags state ); virtual IOReturn setPowerState( UInt32 powerStateOrdinal, IOService *whatDevice ); };/* end class UniNEnet */