From fdcaf5a6653e5782893ea00a970e276edc941b21 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Mon, 5 Mar 2012 08:41:02 +0800 Subject: [PATCH] Modules/RTL8169 - Incomplete --- KernelLand/Modules/Network/RTL8169/Makefile | 8 + KernelLand/Modules/Network/RTL8169/rtl8169.c | 174 +++++++++++++++++++ KernelLand/Modules/Network/RTL8169/rtl8169.h | 33 ++++ 3 files changed, 215 insertions(+) create mode 100644 KernelLand/Modules/Network/RTL8169/Makefile create mode 100644 KernelLand/Modules/Network/RTL8169/rtl8169.c create mode 100644 KernelLand/Modules/Network/RTL8169/rtl8169.h diff --git a/KernelLand/Modules/Network/RTL8169/Makefile b/KernelLand/Modules/Network/RTL8169/Makefile new file mode 100644 index 00000000..10a214f2 --- /dev/null +++ b/KernelLand/Modules/Network/RTL8169/Makefile @@ -0,0 +1,8 @@ +# +# + +OBJ = rtl8169.o +NAME = RTL8169 + +-include ../Makefile.tpl + diff --git a/KernelLand/Modules/Network/RTL8169/rtl8169.c b/KernelLand/Modules/Network/RTL8169/rtl8169.c new file mode 100644 index 00000000..23abdb17 --- /dev/null +++ b/KernelLand/Modules/Network/RTL8169/rtl8169.c @@ -0,0 +1,174 @@ +/* + * Acess2 RealTek 8169 Gigabit Network Controller Driver + * - By John Hodge (thePowersGang) + * + * rtl8169.c + * - Driver source + */ +#define DEBUG 0 +#define VERSION 0x001 +#include +#include +#include +#include +#include "rtl8169.h" + +#define N_RX_DESCS 128 +#define N_TX_DESCS (256-N_RX_DESCS) // 256 * 16 = 4096 (1 page) +#define RX_BUF_SIZE 1024 // Most packets will fit in one buffer + +#define INT_SYSERR (1 << 15) // System Error +#define INT_TIMEOUT (1 << 14) // Timer fire (TCTR reg) +#define INT_LINKCHANGE (1 << 5) +#define INT_TXERR (1 << 3) +#define INT_TXOK (1 << 2) +#define INT_RXERR (1 << 1) +#define INT_RXOK (1 << 0) + +enum eRegisters +{ + REG_TXC = 0x40, + REG_RXC = 0x44, +} + +// === PROTOTYPES === + int RTL8169_Initialise(char **Arguments); +void RTL8169_Cleanup(void); +void RTL8169_InterruptHandler(int IRQ, void *CardPtr); + +// === GLOBALS === +MODULE_DEFINE(0, RTL8169, RTL8169_Initialise, RTL8169_Cleanup, NULL); + int giRTL8169_CardCount; +tCard *gaRTL8169_Cards; + +// === CODE === +int RTL8169_Initialise(char **Arguments) +{ + const Uint16 vendor_id = 0x10EC; + const Uint16 device_id = 0x8129; // 8169 = 0x8129 PCI? + giRTL8169_CardCount = PCI_CountDevices(vendor_id, device_id); + if( !giRTL8169_CardCount ) return MODULE_ERR_NOTNEEDED; + + // Allocate card structures + gaRTL8169_Cards = malloc( sizeof(tCard) * giRTL8169_CardCount ); + + // Initialise devices + for( int id = -1, int i = 0 ; (id = PCI_GetDevice(vendor_id, device_id, id)) != -1; i ++ ) + { + tCard *card = &gaRTL8169_Cards[i]; + card->PCIId = id; + + card->IOAddr = PCI_GetBAR(id, 0); + if( !(card->IOAddr & 1) ) { + // Invalid IO address + Log_Warning("RTL8169", "Card %i doesn't have BAR0 as an IO space", i); + continue; + } + + if(card->IOAddr == 1 ) + { + // Try MMIO + card->PMemAddr = PCI_GetBAR(id, 1); + if( card->PMemAddr == 0 ) { + Log_Warning("RTL8169", "TODO: Allocate MMIO space"); + continue ; + } + card->MemAddr = MM_MapHWPages(card->PMemAddr, 1); + } + + card->IRQNum = PCI_GetIRQ(card); + IRQ_AddHandler( card->IRQNum, RTL8169_InterruptHandler, card ); + + RTL8169_int_SetupCard(card); + } +} + +void RTL8169_int_SetupCard(tCard *Card) +{ + // Initialise RX/TX Descs + // TODO: Handle non-64-bit PCI + Card->RXDescs = MM_AllocDMA(1, -1, &Card->RXDescsPhys); + Card->TXDescs = Card->RXDescs + N_RX_DESCS; + + // - RX Descs - Max of 4096 bytes per packet (1 page) + tPAddr paddr; + for( int i = 0; i < N_RX_DESCS; i += 2 ) + { + t8169_Desc *desc; + + desc = &Card->RXDescs[i]; + if( i % (PAGE_SIZE/RX_BUF_SIZE) == 0 ) + Card->RXBufs[i] = MM_AllocDMA(1, 64, &paddr); + else + Card->RXBufs[i] = Card->RXBufs[i-1] + RX_BUF_SIZE; + desc->FrameLength = RX_BUF_SIZE; + desc->Flags = TXD_FLAG_OWN; + desc->VLANTag = 0; + desc->VLANFlags = 0; + desc->AddressLow = paddr & 0xFFFFFFFF; + desc->AddressHigh = paddr >> 32; + paddr += RX_BUF_SIZE; + } + Card->RXDescs[N_RX_DESCS-1].Flags |= TXD_FLAG_EOR; + // - TX Descs - Just clear + memset(Card->TXDescs, 0, sizeof(t8169_Desc)*N_TX_DESCS); + Card->TXDescs[N_TX_DESCS-1].Flags |= TXD_FLAG_EOR; + + // Reset + _WriteB(Card, 0x37, 0x10); + while( _ReadB(Card, 0x37) & 0x10 ) + ; // TODO: Timeout + + // Read MAC address + for( int i = 0; i < 6; i ++ ) + Card->MacAddr[i] = _ReadB(Card, i); + + // Initialise +// _WriteB(Card, 0x50, 0xC0); + _WriteD(Card, 0x40, 0x03000700); // TX Config + _WriteD(Card, 0x44, 0x0000E70F); // RX Config + _WriteW(Card, 0xDA, RX_BUF_SIZE-1); // Max RX Size + _WriteW(Card, 0xEC, 2048/32); // Max TX size (in units of 32/128 bytes) + + _WriteQ(Card, 0x20, MM_GetPhysAddr( (tVAddr)Card->TXDescs )); +// _WriteQ(Card, 0x28, MM_GetPhysAddr( (tVAddr)Card->TXHighDescs )); + _WriteQ(Card, 0xE4, MM_GetPhysAddr( (tVAddr)Card->RXDescs )); + + _WriteW(Card, 0x3C, INT_LINKCHANGE|INT_TXOK|INT_RXOK); // Set interrupt mask + + _WriteB(card, 0x37, 0x0C); // Enable +} + +void RTL8169_InterruptHandler(int IRQ, void *CardPtr) +{ + +} + +// --- IO --- +void _WriteW(tCard *Card, int Offset, Uint16 Value) +{ + if( Card->MemAddr ) + ((Uint16*)Card->MemAddr)[Offset/2] = Value; + else + outw(Card->IOAddr & ~1, Offset, Value); +} + +void _WriteD(tCard *Card, int Offset, Uint32 Value) +{ + if( Card->MemAddr ) + ((Uint32*)Card->MemAddr)[Offset/4] = Value; + else + outl(Card->IOAddr & ~1, Offset, Value); +} + +void _WriteQ(tCard *Card, int Offset, Uint64 Value) +{ + if( Card->MemAddr ) { + ((Uint32*)Card->MemAddr)[Offset/4+0] = Value; + ((Uint32*)Card->MemAddr)[Offset/4+1] = Value>>32; + } + else { + outd(Card->IOAddr & ~1, Offset, Value); + outd(Card->IOAddr & ~1, Offset+4, Value>>32); + } +} diff --git a/KernelLand/Modules/Network/RTL8169/rtl8169.h b/KernelLand/Modules/Network/RTL8169/rtl8169.h new file mode 100644 index 00000000..6f310807 --- /dev/null +++ b/KernelLand/Modules/Network/RTL8169/rtl8169.h @@ -0,0 +1,33 @@ +/* + * Acess2 RealTek 8169 Gigabit Network Controller Driver + * - By John Hodge (thePowersGang) + * + * rtl8169.h + * - Driver header + */ +#ifndef _RTL8169_H_ +#define _RTL8169_H_ + +#define TXD_FLAG_OWN 0x8000 // Driver/Controller flag +#define TXD_FLAG_EOR 0x4000 // End of ring +#define TXD_FLAG_FS 0x2000 // First segment of a packet +#define TXD_FLAG_LS 0x1000 // Last segment of a packet +#define TXD_FLAG_LGSEN 0x0800 // Larget send +#define TXD_FLAG_IPCS 0x0004 // Offload IP checksum (only if LGSEN=0) +#define TXD_FLAG_UDPCS 0x0002 // Offload UDP checksum (only if LGSEN=0) +#define TXD_FLAG_TCPCS 0x0001 // Offload TCP checksum (only if LGSEN=0) + +typedef struct s8169_Desc t8169_Desc; + +struct s8169_Desc +{ + Uint16 FrameLength; + Uint16 Flags; + Uint16 VLANTag; // Encoded VIDL(8):PRIO(3):CFI:VIDH(4) + Uint16 VLANFlags; + Uint32 AddressLow; + Uint32 AddressHigh; +} PACKED; // sizeof() = 16 bytes + +#endif + -- 2.20.1