#include <IOKit/network/IOEthernetController.h>
#include <IOKit/network/IOEthernetInterface.h>
#include <IOKit/network/IOGatedOutputQueue.h>
#include <IOKit/IOInterruptEventSource.h>
#include <IOKit/IOTimerEventSource.h>
#include <IOKit/network/IOMbufMemoryCursor.h>
#include <IOKit/IODeviceMemory.h>
#include <IOKit/pci/IOPCIDevice.h>
#include <IOKit/IOLib.h>
extern "C"
{
#include <sys/param.h>
#include <sys/mbuf.h>
}
#define KERNEL_DEBUG( x, a, b, c, d, e )
#include "UniNEnetRegisters.h"
#define USE_ELG 0 // for debugging
#define kEvLogSize (4096*16) // 16 pages = 64K = 4096 events 0x10000
#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
#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
typedef struct elg
{
UInt32 evLogFlag; 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
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
#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"
#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:
elg *fpELG; volatile GMAC_Registers *fpRegs;
GMAC_Registers *fpRegsPhys; 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; bool ready;
bool fWOL; bool enetClockOff;
bool netifEnabled;
bool debugEnabled;
bool debugTxPoll;
IOEthernetAddress myAddress;
bool fIsPromiscuous;
bool multicastEnabled;
bool isFullDuplex;
UInt32 phyType; UInt8 phyId;
UInt32 linkStatusPrev;
UInt16 phyStatusPrev;
UInt16 fPHYControl; UInt32 fPHYType;
OSDictionary * mediumDict;
MediumTable *fpgMediumTable;
UInt32 fMediumTableCount;
UInt32 fTxQueueSize; UInt32 fTxRingElements; UInt32 fRxRingElements;
mbuf **fTxMbuf; mbuf **fRxMbuf; mbuf *txDebuggerPkt;
mbuf *rxMbufBucket;
UInt32 *fRxBucketPhysAddr;
void * debuggerPkt;
u_int32_t debuggerPktSize;
UInt32 txCommandHead; UInt32 txCommandTail;
UInt32 rxCommandHead; UInt32 rxCommandTail;
TxDescriptor *fTxDescriptorRing; UInt32 fTxDescriptorRingPhys;
UInt32 fTxElementsAvail;
UInt32 fTxRingLengthFactor;
RxDescriptor *fRxDescriptorRing; 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;
UInt32 fXIFConfiguration;
UInt32 fRxMACConfiguration;
UInt32 fMACControlConfiguration;
private:
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 ); 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();
const OSSymbol *keyLargo_resetUniNEthernetPhy;
IOService *keyLargo;
public:
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 );
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 );
};