#ifndef _RTL8139_H
#define _RTL8139_H
#include <IOKit/assert.h>
#include <IOKit/IOTimerEventSource.h>
#include <IOKit/IODeviceMemory.h>
#include <IOKit/IOInterruptEventSource.h>
#include <IOKit/IOBufferMemoryDescriptor.h>
#include <IOKit/pci/IOPCIDevice.h>
#include <IOKit/network/IOEthernetController.h>
#include <IOKit/network/IOEthernetInterface.h>
#include <IOKit/network/IOGatedOutputQueue.h>
#include <IOKit/network/IOMbufMemoryCursor.h>
#include <IOKit/IOUserClient.h>
#include <libkern/OSByteOrder.h>
extern "C" {
#include <sys/kpi_mbuf.h>
}
#include "RTL8139HW.h"
#define RTL8139 com_apple_driver_RTL8139
#ifdef DEBUG
#warning ***************************************************
#warning ** DEBUG defined - turn off for deployment build **
#warning ***************************************************
#define DEBUG_LOG(args...) kprintf(args)
#else
#define DEBUG_LOG(args...)
#endif
#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 )
#define UC_ELG(A,B,ASCI,STRING) fProvider->EvLog( (UInt32)(A), (UInt32)(B), (UInt32)(ASCI), STRING )
void EvLog( UInt32 a, UInt32 b, UInt32 ascii, char* str );
UInt32 Alrt( UInt32 a, UInt32 b, UInt32 ascii, char* str );
#warning *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
#warning The USE_ELG debugging facility is enabled. *** *** *** *** *** *** *** *** *** *** ***
#warning *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
#else
#define ELG(A,B,ASCI,S)
#define ALRT(A,B,ASCI,STRING) IOLog( "{ %8x %8x} " STRING "\n", (unsigned int)(A), (unsigned int)(B) )
#define UC_ELG(A,B,ASCI,STRING)
#endif
typedef struct elg
{
UInt32 evLogFlag; UInt8 *evLogBuf;
UInt8 *evLogBufe;
UInt8 *evLogBufp;
UInt32 startTimeSecs; UInt32 lostEvents; UInt32 wrapCount; UInt32 alertCount;
addr64_t physAddr; UInt32 reserved0x38; UInt32 lastAlrt; };
#ifdef CRAP
#if USE_ELG
#define READ_REGISTER( REG ) (UInt32)(fCellClockEnabled ? OSReadLittleInt32( (void*)fpRegs, offsetof( Rltk_Registers, REG ) ) : Alrt( 0, offsetof( Rltk_Registers, REG ), 'REG-', "RTL8139: regs unavail" ) )
#define WRITE_REGISTER( REG, VAL ) writeRegister( &fpRegs->REG, VAL )
#else
#define READ_REGISTER( REG ) OSReadLittleInt32( (void*)fpRegs, offsetof( Rltk_Registers, REG ) )
#define WRITE_REGISTER( REG, VAL ) OSWriteLittleInt32( (void*)fpRegs, offsetof( Rltk_Registers, REG ), VAL )
#endif // USE_ELG
#endif // CRAP
#define BUMP_NET_COUNTER(x) do { netStats->x += 1; } while(0)
#define BUMP_ETHER_COUNTER(x) do { etherStats->dot3StatsEntry.x += 1; } while(0)
#define BUMP_ETHER_RX_COUNTER(x) do { etherStats->dot3RxExtraEntry.x += 1; } while(0)
#define BUMP_ETHER_TX_COUNTER(x) do { etherStats->dot3TxExtraEntry.x += 1; } while(0)
#define kWatchdogTimerPeriod 1000 // milliseconds
#define kTxBufferCount 4 // 4 TX buffers/descriptors
#define kTransmitQueueCapacity 256
#define MINPACK 64 // minimum output packet length with 4 FCS bytes
#define MAXPACK 1518 // maximum output packet length with 4 FCS bytes
#define RX_BUF_SIZE (1024 * 64) // max out the Rx buffer size
#define TX_BUF_SIZE (1024 * 2)
struct rbuf_hdr_t
{
#if defined( __BIG_ENDIAN__ ) // FIXME
UInt16 rb_count; UInt16 rb_status; #elif defined( __LITTLE_ENDIAN__ )
UInt16 rb_status; UInt16 rb_count; #else
#error Unknown machine endianess
#endif
};
enum
{
kSelectLoopbackMAC = 0x20,
kSelectLoopbackPHY = 0x21,
kRltkUserCmd_GetLog = 0x30, kRltkUserCmd_GetRegs = 0x31, kRltkUserCmd_GetOneReg = 0x32, kRltkUserCmd_WriteOneReg = 0x35, };
struct UCRequest
{
UInt32 reqID;
UInt8* pLogBuffer;
UInt32 bufSize;
};
class RTL8139;
class RTL8139UserClient : public IOUserClient
{
OSDeclareDefaultStructors( RTL8139UserClient ) ;
private:
RTL8139 *fProvider;
IOExternalMethod fMethods[1]; task_t fTask;
IOMemoryMap *fMap;
public:
static RTL8139UserClient* withTask( task_t owningTask );
virtual IOReturn clientClose();
virtual IOReturn clientDied();
virtual IOReturn registerNotificationPort( mach_port_t port, UInt32 type ); virtual IOReturn connectClient( IOUserClient *client );
virtual IOExternalMethod* getExternalMethodForIndex( UInt32 index );
virtual bool start( IOService *provider );
private:
IOReturn doRequest( void *pIn, void *pOut, IOByteCount inputSize, IOByteCount *outPutSize );
IOReturn getRltkLog( void *pIn, void *pOut, IOByteCount inputSize, IOByteCount *outPutSize );
IOReturn getRltkRegs( void *pIn, void *pOut, IOByteCount inputSize, IOByteCount *outPutSize );
IOReturn writeOneRltkReg( void *pIn, void *pOut, IOByteCount inputSize, IOByteCount *outPutSize );
};
class RTL8139 : public IOEthernetController
{
OSDeclareDefaultStructors( RTL8139 ) ;
public:
elg *fpELG; IOBufferMemoryDescriptor *fpELGMemDesc;
IOEthernetInterface * netif;
IOPCIDevice * pciNub;
IOWorkLoop * workLoop;
IOInterruptEventSource * interruptSrc;
IOOutputQueue * fTransmitQueue;
IOTimerEventSource * timerSrc;
IOKernelDebugger * debugger;
IONetworkStats * netStats;
IOEthernetStats * etherStats;
IOMemoryMap * csrMap;
volatile void * csrBase;
OSDictionary * mediumDict;
const IONetworkMedium * mediumTable[ MEDIUM_INDEX_COUNT ];
IOBufferMemoryDescriptor *fpTxRxMD;
IOPhysicalAddress fTxRxPhysical;
UInt8 *fpTxRxBuffers;
UInt8 fTxBufOwnership[ kTxBufferCount ];
volatile bool fTxBufReclaimed;
UInt8 fTxSendIndex, fTxAckIndex;
UInt8 fTxSendCount;
UInt32 fTSD_ERTXTH;
IOPhysicalAddress fRxBufferPhys;
UInt8 *fpRxBuffer;
UInt16 fRxOffset;
enum
{
kOwnedByChip = 0,
kOwnedByHost = 1
};
UInt8 reg_config1;
UInt32 reg_rcr;
UInt32 currentLevel;
bool enabledByBSD;
bool enabledByKDP;
bool interruptEnabled;
bool forceLinkChange;
bool fSpeed100;
bool fPauseSupported;
MediumIndex currentMediumIndex;
UInt16 phyStatusLast;
UInt16 reg_bms;
UInt32 reg_mar0;
UInt32 reg_mar4;
void restartReceiver();
void transmitterInterrupt( bool* reclaimed );
void receiverInterrupt( bool* queued );
void interruptOccurred( IOInterruptEventSource* src, int count );
bool initEventSources( IOService* provider );
bool initPCIConfigSpace( IOPCIDevice* provider );
bool enableAdapter( UInt32 level );
bool disableAdapter( UInt32 level );
enum
{
kActivationLevel0 = 0,
kActivationLevel1,
kActivationLevel2
};
bool setActivationLevel( UInt32 newLevel );
void timeoutOccurred( IOTimerEventSource * timer );
bool allocateDescriptorMemory();
enum
{
kFullInitialization = 0,
kResetChip = 1
};
bool initAdapter( IOOptionBits options );
void disableHardwareInterrupts();
void enableHardwareInterrupts();
void reclaimTransmitBuffer();
bool phyAddMediumType( IOMediumType type, UInt32 bps, MediumIndex index );
void phyProbeMediaCapability();
bool phyReset();
bool phyWaitForAutoNegotiation();
bool phySetMedium( MediumIndex mediumIndex );
bool phySetMedium( const IONetworkMedium * medium );
void phyReportLinkStatus();
const IONetworkMedium * phyGetMediumWithIndex( MediumIndex index ) const;
inline void csrWrite32( UInt16 offset, UInt32 value )
{
ELG( value, offset, 'Wr32', "csrWrite32" );
OSWriteLittleInt32( csrBase, offset, value );
}
inline void csrWrite16( UInt16 offset, UInt16 value )
{
ELG( value, offset, 'Wr16', "csrWrite16" );
OSWriteLittleInt16( csrBase, offset, value );
}
inline void csrWrite8( UInt16 offset, UInt8 value )
{
ELG( value, offset, 'Wr08', "csrWrite8" );
*((UInt8*)csrBase + offset) = value;
}
inline UInt32 csrRead32( UInt16 offset )
{ return OSReadLittleInt32( csrBase, offset ); }
inline UInt16 csrRead16( UInt16 offset )
{ return OSReadLittleInt16( csrBase, offset ); }
inline UInt8 csrRead8( UInt16 offset )
{ return *((UInt8*)csrBase + offset); }
public:
UInt32 fLoopback; UInt32 fLoopbackMode;
#ifdef USE_ELG
void AllocateEventLog( UInt32 size );
void EvLog( UInt32 a, UInt32 b, UInt32 ascii, char* str );
UInt32 Alrt( UInt32 a, UInt32 b, UInt32 ascii, char* str );
#endif // USE_ELG
virtual bool init( OSDictionary *properties );
virtual bool start( IOService *provider );
virtual void stop( IOService *provider );
virtual void free();
virtual IOReturn enable( IONetworkInterface *netif );
virtual IOReturn disable( IONetworkInterface *netif );
virtual IOReturn enable( IOKernelDebugger *netif );
virtual IOReturn disable( IOKernelDebugger *netif );
virtual bool setLinkStatus( UInt32 status,
const IONetworkMedium *activeMedium = 0,
UInt64 speed = 0,
OSData *data = 0 );
virtual UInt32 outputPacket( mbuf_t m, void *param );
virtual void getPacketBufferConstraints(
IOPacketBufferConstraints *constraints ) const;
virtual IOOutputQueue* createOutputQueue();
virtual const OSString* newVendorString() const;
virtual const OSString* newModelString() const;
virtual IOReturn selectMedium( const IONetworkMedium *medium );
virtual bool configureInterface( IONetworkInterface *interface );
virtual bool createWorkLoop();
virtual IOWorkLoop* getWorkLoop() const;
virtual IOReturn getHardwareAddress( IOEthernetAddress *addr );
virtual IOReturn setPromiscuousMode( bool enabled );
virtual IOReturn setMulticastMode( bool enabled );
virtual IOReturn setMulticastList( IOEthernetAddress *addrs, UInt32 count );
virtual void sendPacket( void *pkt, UInt32 pktLen );
virtual void receivePacket( void * pkt, UInt32 * pktLen, UInt32 timeout );
virtual IOReturn registerWithPolicyMaker( IOService *policyMaker );
virtual IOReturn setPowerState( unsigned long powerStateOrdinal,
IOService *policyMaker );
virtual IOReturn newUserClient( task_t, void*, UInt32, IOUserClient** );
void registerEEPROM();
void outCommand( UInt16 cmd );
int inEEPROM16( int location );
void outBit( UInt16 bit );
int inBit();
void write9346CR( UInt8 value );
};
#endif