From 9cae7d64750db729b6bee582a8e7203ec3de36b4 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Mon, 6 Jun 2011 22:11:02 +0800 Subject: [PATCH] RTL8136 - Implementing - Implemented (untested) a RTL8139 driver - Debugging in IPv4/NE2000, trying to trace lack of ARP replies --- Makefile.cfg | 2 +- Modules/IPStack/ipstack.h | 1 + Modules/IPStack/ipv4.c | 6 +- Modules/Network/NE2000/ne2000.c | 2 +- Modules/Network/RTL8139/rtl8139.c | 247 +++++++++++++++++++++++++----- 5 files changed, 215 insertions(+), 43 deletions(-) diff --git a/Makefile.cfg b/Makefile.cfg index b0de6628..dab99eca 100644 --- a/Makefile.cfg +++ b/Makefile.cfg @@ -46,7 +46,7 @@ MODULES += Filesystems/NTFS ifeq ($(ARCHDIR),x86) MODULES += Storage/ATA Storage/FDD -MODULES += Network/NE2000 +MODULES += Network/NE2000 Network/RTL8139 MODULES += Display/VESA MODULES += Display/BochsGA MODULES += Interfaces/UDI diff --git a/Modules/IPStack/ipstack.h b/Modules/IPStack/ipstack.h index 2076d5a7..e51fded9 100644 --- a/Modules/IPStack/ipstack.h +++ b/Modules/IPStack/ipstack.h @@ -97,6 +97,7 @@ struct sSocketFile }; static const tMacAddr cMAC_BROADCAST = {{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}; +static const tMacAddr cMAC_ZERO = {{0x00,0x00,0x00,0x00,0x00,0x00}}; #define MAC_SET(t,v) memcpy(&(t),&(v),sizeof(tMacAddr)) #define IP4_SET(t,v) (t).L = (v).L; diff --git a/Modules/IPStack/ipv4.c b/Modules/IPStack/ipv4.c index 69f029c7..eb7e51df 100644 --- a/Modules/IPStack/ipv4.c +++ b/Modules/IPStack/ipv4.c @@ -64,13 +64,13 @@ int IPv4_RegisterCallback(int ID, tIPCallback Callback) int IPv4_SendPacket(tInterface *Iface, tIPv4 Address, int Protocol, int ID, int Length, const void *Data) { tMacAddr to = ARP_Resolve4(Iface, Address); - const tMacAddr zero = {{0,0,0,0,0,0}}; int bufSize = sizeof(tIPv4Header) + Length; char buf[bufSize]; tIPv4Header *hdr = (void*)buf; int ret; - if( MAC_EQU(to, zero) ) { + if( MAC_EQU(to, cMAC_ZERO) ) { + // No route to host return 0; } @@ -222,6 +222,8 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff rt = IPStack_FindRoute(4, NULL, &hdr->Destination); // Get the route (gets the interface) to = ARP_Resolve4(rt->Interface, hdr->Destination); // Resolve address + if( MAC_EQU(to, cMAC_ZERO) ) + return ; // Send packet Log_Log("IPv4", "Forwarding packet to %i.%i.%i.%i (via %i.%i.%i.%i)", diff --git a/Modules/Network/NE2000/ne2000.c b/Modules/Network/NE2000/ne2000.c index 3924ba82..53602e7b 100644 --- a/Modules/Network/NE2000/ne2000.c +++ b/Modules/Network/NE2000/ne2000.c @@ -3,7 +3,7 @@ * * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc */ -#define DEBUG 0 +#define DEBUG 1 #define VERSION ((0<<8)|50) #include #include diff --git a/Modules/Network/RTL8139/rtl8139.c b/Modules/Network/RTL8139/rtl8139.c index 254ad110..32aa7d45 100644 --- a/Modules/Network/RTL8139/rtl8139.c +++ b/Modules/Network/RTL8139/rtl8139.c @@ -9,29 +9,57 @@ #include #include #include +#include // === CONSTANTS === enum eRTL8139_Regs { + // MAC Address MAC0, MAC1, MAC2, MAC3, MAC4, MAC5, - MAR0 = 0x08, - MAR1, MAR2, MAR3, + + // Multicast Registers + MAR0 = 0x08, MAR1, MAR2, MAR3, MAR4, MAR5, MAR6, MAR7, + // Transmit status of descriptors 0 - 3 + TSD0 = 0x10, TSD1 = 0x14, + TSD2 = 0x18, TSD3 = 0x1C, + // Transmit start addresses + TSAD0 = 0x20, TSAD1 = 0x24, + TSAD2 = 0x28, TSAD3 = 0x2C, + RBSTART = 0x30, //!< Recieve Buffer Start (DWord) - // 0x31, 0x32, 0x33 + // Early Recieve Byte Count + ERBCR = 0x34, // 16-bits + // Early RX Status Register + ERSR = 0x36, // ??, ??, ??, RST, RE, TE, ??, ?? CMD = 0x37, - IMR = 0x3C, - ISR = 0x3E, - RCR = 0x44, + CAPR = 0x38, // Current address of packet read + CBA = 0x3A, // Current Buffer Address - Total byte count in RX buffer + + IMR = 0x3C, // Interrupt mask register + ISR = 0x3E, // Interrupt status register + + TCR = 0x40, // Transmit Configuration Register + RCR = 0x44, // Recieve Configuration Register + TCTR = 0x48, // 32-bit timer (count) + MPC = 0x4C, // Missed packet count (due to RX overflow) + + CR_9346 = 0x50, + CONFIG0 = 0x51, + CONFIG1 = 0x52, + // 0x53 resvd + TIMERINT = 0x54, // Fires a timeout when TCTR equals this value - CONFIG1 = 0x52 }; +#define FLAG_ISR_TOK 0x04 +#define FLAG_ISR_ROK 0x01 + // === TYPES === typedef struct sCard { @@ -40,8 +68,16 @@ typedef struct sCard int NumWaitingPackets; - void *ReceiveBuffer; + char *ReceiveBuffer; tPAddr PhysReceiveBuffer; + int ReceiveBufferLength; + int SeenOfs; //!< End of the most recently seen packet (by IRQ) + tMutex ReadMutex; + tSemaphore ReadSemaphore; + + char *TransmitBuffers[4]; + tPAddr PhysTransmitBuffers[4]; + BOOL TransmitInUse; // Flags for each transmit descriptor char Name[2]; tVFS_Node Node; @@ -55,6 +91,7 @@ tVFS_Node *RTL8139_FindDir(tVFS_Node *Node, const char *Filename); int RTL8139_RootIOCtl(tVFS_Node *Node, int ID, void *Arg); Uint64 RTL8139_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); Uint64 RTL8139_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); + int RTL8139_IOCtl(tVFS_Node *Node, int ID, void *Arg); void RTL8139_IRQHandler(int Num); // === GLOBALS === @@ -71,7 +108,7 @@ tDevFS_Driver gRTL8139_DriverInfo = { } }; int giRTL8139_CardCount; -tCard *gpRTL8139_Cards; +tCard *gaRTL8139_Cards; // === CODE === /** @@ -82,20 +119,22 @@ int RTL8139_Install(char **Options) int id = -1; int i = 0; Uint16 base; + tCard *card; giRTL8139_CardCount = PCI_CountDevices( 0x10EC, 0x8139, 0 ); - gpRTL8139_Cards = calloc( giRTL8139_CardCount, sizeof(tCard) ); + gaRTL8139_Cards = calloc( giRTL8139_CardCount, sizeof(tCard) ); while( (id = PCI_GetDevice(0x10EC, 0x8139, 0, id)) != -1 ) { base = PCI_AssignPort( id, 0, 0x100 ); - gpRTL8139_Cards[i].IOBase = base; - gpRTL8139_Cards[i].IRQ = PCI_GetIRQ( id ); + card = &gaRTL8139_Cards[i]; + card->IOBase = base; + card->IRQ = PCI_GetIRQ( id ); // Install IRQ Handler - IRQ_AddHandler(gpRTL8139_Cards[ k ].IRQ, RTL8136_IRQHandler); + IRQ_AddHandler(card->IRQ, RTL8139_IRQHandler); // Power on outb( base + CONFIG1, 0x00 ); @@ -106,43 +145,57 @@ int RTL8139_Install(char **Options) // Set up recieve buffer // - Allocate 3 pages below 4GiB for the recieve buffer (Allows 8k+16+1500) - gpRTL8139_Cards[i].ReceiveBuffer = MM_AllocDMA( 3, 32, &gpRTL8139_Cards[i].PhysReceiveBuffer ); - outl(base + RBSTART, (Uint32)gpRTL8139_Cards[i].PhysReceiveBuffer); + card->ReceiveBuffer = (void*)MM_AllocDMA( 3, 32, &card->PhysReceiveBuffer ); + outd(base + RBSTART, (Uint32)card->PhysReceiveBuffer); // Set IMR to Transmit OK and Receive OK outw(base + IMR, 0x5); + // Set up transmit buffers + // - 2 non-contiguous pages (each page can fit 2 1500 byte packets) + card->TransmitBuffers[0] = (void*)MM_AllocDMA( 1, 32, &card->PhysTransmitBuffers[0] ); + card->TransmitBuffers[1] = card->TransmitBuffers[0] + 0x800; + card->PhysTransmitBuffers[1] = card->PhysTransmitBuffers[0] + 0x800; + + card->TransmitBuffers[2] = (void*)MM_AllocDMA( 1, 32, &card->PhysTransmitBuffers[1] ); + card->TransmitBuffers[3] = card->TransmitBuffers[2] + 0x800; + card->PhysTransmitBuffers[3] = card->PhysTransmitBuffers[2] + 0x800; + + outd(base + TSAD0, card->PhysTransmitBuffers[0]); + outd(base + TSAD1, card->PhysTransmitBuffers[1]); + outd(base + TSAD2, card->PhysTransmitBuffers[2]); + outd(base + TSAD3, card->PhysTransmitBuffers[3]); + // Set recieve buffer size and recieve mask // - Bit 7 being unset tells the card to overflow the recieve buffer if needed // (i.e. when the packet starts at the end of the bufffer, it overflows up // to 1500 bytes) - outl(base + RCR, 0x0F); + outd(base + RCR, 0x0F); // Recive Enable and Transmit Enable outb(base + CMD, 0x0C); // Get the card's MAC address - gpRTL8139_Cards[ i ].MacAddr[0] = inb(base+MAC0); - gpRTL8139_Cards[ i ].MacAddr[1] = inb(base+MAC1); - gpRTL8139_Cards[ i ].MacAddr[2] = inb(base+MAC2); - gpRTL8139_Cards[ i ].MacAddr[3] = inb(base+MAC3); - gpRTL8139_Cards[ i ].MacAddr[4] = inb(base+MAC4); - gpRTL8139_Cards[ i ].MacAddr[5] = inb(base+MAC5); + card->MacAddr[0] = inb(base+MAC0); + card->MacAddr[1] = inb(base+MAC1); + card->MacAddr[2] = inb(base+MAC2); + card->MacAddr[3] = inb(base+MAC3); + card->MacAddr[4] = inb(base+MAC4); + card->MacAddr[5] = inb(base+MAC5); // Set VFS Node - gpRTL8139_Cards[ i ].Name[0] = '0'+i; - gpRTL8139_Cards[ i ].Name[1] = '\0'; - gpRTL8139_Cards[ i ].Node.ImplPtr = &gpRTL8139_Cards[ i ]; - gpRTL8139_Cards[ i ].Node.NumACLs = 0; - gpRTL8139_Cards[ i ].Node.CTime = now(); - gpRTL8139_Cards[ i ].Node.Write = RTL8139_Write; - gpRTL8139_Cards[ i ].Node.Read = RTL8139_Read; - gpRTL8139_Cards[ i ].Node.IOCtl = RTL8139_IOCtl; + card->Name[0] = '0'+i; + card->Name[1] = '\0'; + card->Node.ImplPtr = card; + card->Node.NumACLs = 0; + card->Node.CTime = now(); + card->Node.Write = RTL8139_Write; + card->Node.Read = RTL8139_Read; + card->Node.IOCtl = RTL8139_IOCtl; Log_Log("RTL8139", "Card %i 0x%04x %02x:%02x:%02x:%02x:%02x:%02x", i, base, - gpRTL8139_Cards[ i ].MacAddr[0], gpRTL8139_Cards[ i ].MacAddr[1], - gpRTL8139_Cards[ i ].MacAddr[2], gpRTL8139_Cards[ i ].MacAddr[3], - gpRTL8139_Cards[ i ].MacAddr[4], gpRTL8139_Cards[ i ].MacAddr[5] + card->MacAddr[0], card->MacAddr[1], card->MacAddr[2], + card->MacAddr[3], card->MacAddr[4], card->MacAddr[5] ); i ++; @@ -153,9 +206,9 @@ int RTL8139_Install(char **Options) // --- Root Functions --- char *RTL8139_ReadDir(tVFS_Node *Node, int Pos) { - if( Pos < 0 || Pos > giRTL8139_CardCount ) return NULL; + if( Pos < 0 || Pos >= giRTL8139_CardCount ) return NULL; - return strdup( gpRTL8139_Cards[Pos].Name ); + return strdup( gaRTL8139_Cards[Pos].Name ); } tVFS_Node *RTL8139_FindDir(tVFS_Node *Node, const char *Filename) @@ -163,11 +216,11 @@ tVFS_Node *RTL8139_FindDir(tVFS_Node *Node, const char *Filename) //TODO: It might be an idea to supprt >10 cards if(Filename[0] == '\0' || Filename[0] != '\0') return NULL; if(Filename[0] < '0' || Filename[0] > '9') return NULL; - return &gpRTL8139_Cards[ Filename[0]-'0' ].Node; + return &gaRTL8139_Cards[ Filename[0]-'0' ].Node; } const char *csaRTL8139_RootIOCtls[] = {DRV_IOCTLNAMES, NULL}; -int RTL8139_RootIOCtl(tVFS_Node *Node, int ID, void *Arg) +int RTL8139_RootIOCtl(tVFS_Node *Node, int ID, void *Data) { switch(ID) { @@ -179,16 +232,73 @@ int RTL8139_RootIOCtl(tVFS_Node *Node, int ID, void *Arg) // --- File Functions --- Uint64 RTL8139_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) { - return 0; + tCard *card = Node->ImplPtr; + int read_ofs, pkt_length; + +retry: + Semaphore_Wait( &card->ReadSemaphore, 1 ); + + Mutex_Acquire( &card->ReadMutex ); + + read_ofs = ind( card->IOBase + CAPR ) - card->PhysReceiveBuffer; + + // Check for errors + if( *(Uint16*)&card->ReceiveBuffer[read_ofs] & 0x1E ) { + Mutex_Release( &card->ReadMutex ); + goto retry; // I feel evil + } + + pkt_length = *(Uint16*)&card->ReceiveBuffer[read_ofs+2]; + + // Get packet + if( Length > pkt_length ) Length = pkt_length; + memcpy(Buffer, &card->ReceiveBuffer[read_ofs+4], Length); + + // Update read offset + read_ofs += pkt_length + 4; + read_ofs = (read_ofs + 3) & ~3; // Align + if(read_ofs > card->ReceiveBufferLength) read_ofs = 0; + outd(card->IOBase + CAPR, read_ofs + card->PhysReceiveBuffer); + + Mutex_Release( &card->ReadMutex ); + + return Length; } Uint64 RTL8139_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) { + int td; + Uint32 status; + tCard *card = Node->ImplPtr; + + if( Length > 1500 ) return 0; // MTU exceeded + + // TODO: Implement a semaphore for avaliable tranmit buffers + + // Find an avaliable descriptor + do { + for( td = 0; td < 4; td ++ ) { + if( !(card->TransmitInUse & (1 << td)) ) + break; + } + } while(td == 4 && (Threads_Yield(),1)); + + // Transmit using descriptor `td` + card->TransmitInUse |= (1 << td); + // Copy to buffer + memcpy(card->TransmitBuffers[td], Buffer, Length); + // Start + status = 0; + status |= Length & 0x1FFF; // 0-12: Length + status |= 0 << 13; // 13: OWN bit + status |= (0 & 0x3F) << 16; // 16-21: Early TX threshold (zero atm, TODO: check) + outd(card->IOBase + TSD0 + td, status); + return 0; } const char *csaRTL8139_NodeIOCtls[] = {DRV_IOCTLNAMES, NULL}; -int RTL8139_IOCtl(tVFS_Node *Node, int ID, void *Arg) +int RTL8139_IOCtl(tVFS_Node *Node, int ID, void *Data) { switch(ID) { @@ -196,3 +306,62 @@ int RTL8139_IOCtl(tVFS_Node *Node, int ID, void *Arg) } return 0; } + +void RTL8139_IRQHandler(int Num) +{ + int i, j; + tCard *card; + Uint8 status; + for( i = 0; i < giRTL8139_CardCount; i ++ ) + { + card = &gaRTL8139_Cards[i]; + if( Num != card->IRQ ) break; + + status = inb(card->IOBase + ISR); + + // Transmit OK, a transmit descriptor is now free + if( status & FLAG_ISR_TOK ) + { + outb(card->IOBase + ISR, FLAG_ISR_TOK); + for( j = 0; j < 4; j ++ ) + { + if( ind(card->IOBase + TSD0 + j) & 0x8000 ) { // TSD TOK + card->TransmitInUse &= ~(1 << j); + // TODO: Update semaphore once implemented + } + } + } + + // Recieve OK, inform read + if( status & FLAG_ISR_ROK ) + { + int read_ofs, end_ofs; + int packet_count = 0; + + // Scan recieve buffer for packets + end_ofs = ind(card->IOBase + CBA) - card->PhysReceiveBuffer; + read_ofs = card->SeenOfs; + if( read_ofs > end_ofs ) + { + while( read_ofs < card->ReceiveBufferLength ) + { + packet_count ++; + read_ofs += *(Uint16*)&card->ReceiveBuffer[read_ofs+1] + 2; + } + read_ofs = 0; + } + while( read_ofs < end_ofs ) + { + packet_count ++; + read_ofs += *(Uint16*)&card->ReceiveBuffer[read_ofs+1] + 2; + } + card->SeenOfs = read_ofs; + + Semaphore_Signal( &card->ReadSemaphore, packet_count ); + if( packet_count ) + VFS_MarkAvaliable( &card->Node, 1 ); + + outb(card->IOBase + ISR, FLAG_ISR_ROK); + } + } +} -- 2.20.1