More work on IPStack (Also fixed Proc_SpawnWorker)
authorJohn Hodge <[email protected]>
Mon, 23 Nov 2009 09:18:49 +0000 (17:18 +0800)
committerJohn Hodge <[email protected]>
Mon, 23 Nov 2009 09:18:49 +0000 (17:18 +0800)
- Fixed structures in IPStack not being packed
- Fixed instances when byte orders were not handled
- Added stub UDP support
- Added copious ammounts of debug code to IPStack
- Added packet reception to NE2000 driver
- Changed autoconf in ifconfig to set the IP to 10.0.0.55

16 files changed:
Kernel/Makefile.BuildNum
Kernel/arch/x86/mm_virt.c
Kernel/arch/x86/proc.c
Modules/IPStack/Makefile
Modules/IPStack/arp.c
Modules/IPStack/arp.h
Modules/IPStack/icmp.c
Modules/IPStack/ipstack.h
Modules/IPStack/ipv4.c
Modules/IPStack/ipv4.h
Modules/IPStack/link.c
Modules/IPStack/main.c
Modules/IPStack/udp.c [new file with mode: 0644]
Modules/IPStack/udp.h [new file with mode: 0644]
Modules/NE2000/ne2000.c
Usermode/Applications/ifconfig_src/main.c

index 92b8fa6..a8d4311 100644 (file)
@@ -1 +1 @@
-BUILD_NUM = 1020
+BUILD_NUM = 1039
index 9892998..c29db50 100644 (file)
@@ -15,7 +15,7 @@
 #include <proc.h>
 
 #define KERNEL_STACKS          0xF0000000
-#define        KERNEL_STACK_SIZE       0x00002000
+#define        KERNEL_STACK_SIZE       0x00008000
 #define KERNEL_STACKS_END      0xFD000000
 #define WORKER_STACKS          0x00100000      // Thread0 Only!
 #define        WORKER_STACK_SIZE       KERNEL_STACK_SIZE
@@ -628,19 +628,23 @@ tVAddr MM_NewWorkerStack()
        giLastUsedWorker = base;
        // We have one
        base = WORKER_STACKS + base * WORKER_STACK_SIZE;
+       //Log(" MM_NewWorkerStack: base = 0x%x", base);
        
        // Acquire the lock for the temp fractal mappings
        LOCK(&gilTempFractal);
        
        // Set the temp fractals to TID0's address space
-       *gTmpCR3 = (Uint)gaInitPageDir | 3;
+       *gTmpCR3 = ((Uint)gaInitPageDir - KERNEL_BASE) | 3;
+       //Log(" MM_NewWorkerStack: *gTmpCR3 = 0x%x", *gTmpCR3);
        INVLPG( gaTmpDir );
        
+       
        // Check if the directory is mapped (we are assuming that the stacks
-       // will fit neatly in a directory
+       // will fit neatly in a directory)
+       //Log(" MM_NewWorkerStack: gaTmpDir[ 0x%x ] = 0x%x", base>>22, gaTmpDir[ base >> 22 ]);
        if(gaTmpDir[ base >> 22 ] == 0) {
                gaTmpDir[ base >> 22 ] = MM_AllocPhys() | 3;
-               INVLPG( &gaTmpTable[ (base>>22) & ~0x3FF ] );
+               INVLPG( &gaTmpTable[ (base>>12) & ~0x3FF ] );
        }
        
        // Mapping Time!
@@ -649,6 +653,7 @@ tVAddr MM_NewWorkerStack()
                pages[ addr >> 12 ] = MM_AllocPhys();
                gaTmpTable[ (base + addr) >> 12 ] = pages[addr>>12] | 3;
        }
+       *gTmpCR3 = 0;
        // Release the temp mapping lock
        RELEASE(&gilTempFractal);
        
@@ -656,6 +661,9 @@ tVAddr MM_NewWorkerStack()
        oldstack = (esp + KERNEL_STACK_SIZE-1) & ~(KERNEL_STACK_SIZE-1);
        esp = oldstack - esp;   // ESP as an offset in the stack
        
+       // Make `base` be the top of the stack
+       base += WORKER_STACK_SIZE;
+       
        i = (WORKER_STACK_SIZE>>12) - 1;
        // Copy the contents of the old stack to the new one, altering the addresses
        // `addr` is refering to bytes from the stack base (mem downwards)
@@ -672,10 +680,11 @@ tVAddr MM_NewWorkerStack()
                        else    // Seems not, best leave it alone
                                tmpPage[j] = stack[j];
                }
-               MM_FreeTemp((Uint)tmpPage);
+               MM_FreeTemp((tVAddr)tmpPage);
                i --;
        }
        
+       //Log("MM_NewWorkerStack: RETURN 0x%x", base);
        return base;
 }
 
index f9c5ba1..60f015b 100644 (file)
@@ -337,13 +337,14 @@ int Proc_SpawnWorker()
        memcpy(new, &gThreadZero, sizeof(tThread));
        // Set Thread ID
        new->TID = giNextTID++;
-       // Set kernel stack
+       // Create a new worker stack (in PID0's address space)
+       // The stack is relocated by this code
        new->KernelStack = MM_NewWorkerStack();
 
        // Get ESP and EBP based in the new stack
        __asm__ __volatile__ ("mov %%esp, %0": "=r"(esp));
        __asm__ __volatile__ ("mov %%ebp, %0": "=r"(ebp));
-       esp = cur->KernelStack - (new->KernelStack - esp);
+       esp = new->KernelStack - (cur->KernelStack - esp);
        ebp = new->KernelStack - (cur->KernelStack - ebp);      
        
        // Save core machine state
@@ -357,6 +358,9 @@ int Proc_SpawnWorker()
        
        // Set EIP as parent
        new->SavedState.EIP = eip;
+       // Mark as active
+       new->Status = THREAD_STAT_ACTIVE;
+       Threads_AddActive( new );
        
        return new->TID;
 }
@@ -557,7 +561,8 @@ void Proc_Scheduler(int CPU)
        gTSSs[CPU].ESP0 = thread->KernelStack;
        
        // Set address space
-       __asm__ __volatile__ ("mov %0, %%cr3"::"a"(gCurrentThread->MemState.CR3));
+       if( gCurrentThread->MemState.CR3 != 0 )
+               __asm__ __volatile__ ("mov %0, %%cr3"::"a"(gCurrentThread->MemState.CR3));
        // Switch threads
        __asm__ __volatile__ (
                "mov %1, %%esp\n\t"     // Restore ESP
index 6226f4f..6c26f2d 100644 (file)
@@ -1,7 +1,10 @@
 #
 #
 
-OBJ = main.o link.o arp.o ipv4.o ipv6.o
+OBJ  = main.o link.o arp.o
+OBJ += ipv4.o icmp.o
+OBJ += ipv6.o
+OBJ += udp.o
 NAME = IPStack
 
 -include ../Makefile.tpl
index cc194e9..2ee4fac 100644 (file)
@@ -95,21 +95,43 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe
                return;
        }
        
-       switch( req4->Request )
+       Log("[ARP  ] Request ID %i", ntohs(req4->Request));
+       
+       switch( ntohs(req4->Request) )
        {
        case 1: // You want my IP?
+               Log("[ARP  ] ARP Request Address class %i", req4->SWSize);
                // Check what type of IP it is
                switch( req4->SWSize )
                {
                case 4:
+                       Log("[ARP  ] From MAC %02x:%02x:%02x:%02x:%02x:%02x",
+                               req4->SourceMac.B[0], req4->SourceMac.B[1],
+                               req4->SourceMac.B[2], req4->SourceMac.B[3],
+                               req4->SourceMac.B[4], req4->SourceMac.B[5]);
+                       Log("[ARP  ] to MAC %02x:%02x:%02x:%02x:%02x:%02x",
+                               req4->DestMac.B[0], req4->DestMac.B[1],
+                               req4->DestMac.B[2], req4->DestMac.B[3],
+                               req4->DestMac.B[4], req4->DestMac.B[5]);
+                       Log("[ARP  ] ARP Request IPv4 Address %i.%i.%i.%i",
+                               req4->DestIP.B[0], req4->DestIP.B[1], req4->DestIP.B[2],
+                               req4->DestIP.B[3]);
+                       Log("[ARP  ] from %i.%i.%i.%i",
+                               req4->SourceIP.B[0], req4->SourceIP.B[1],
+                               req4->SourceIP.B[2], req4->SourceIP.B[3]);
                        iface = IPv4_GetInterface(Adapter, req4->DestIP, 0);
                        if( iface )
                        {
-                               IP4_SET(req4->DestIP, req4->SourceIP);
+                               req4->DestIP = req4->SourceIP;
                                req4->DestMac = req4->SourceMac;
                                req4->SourceIP = iface->IP4.Address;
                                req4->SourceMac = Adapter->MacAddr;
                                req4->Request = htons(2);
+                               Log("[ARP  ] Hey, That's us!");
+                               Log("[ARP  ] Sending back %02x:%02x:%02x:%02x:%02x:%02x",
+                                       req4->SourceMac.B[0], req4->SourceMac.B[1],
+                                       req4->SourceMac.B[2], req4->SourceMac.B[3],
+                                       req4->SourceMac.B[4], req4->SourceMac.B[5]);
                                Link_SendPacket(Adapter, 0x0806, req4->DestMac, sizeof(tArpRequest4), req4);
                        }
                        break;
index 64f07c3..07cdb64 100644 (file)
@@ -19,7 +19,7 @@ struct sArpRequest4 {
        tIPv4   SourceIP;
        tMacAddr        DestMac;
        tIPv4   DestIP;
-};
+} __attribute__((packed));
 
 struct sArpRequest6 {
        Uint16  HWType;
@@ -30,6 +30,6 @@ struct sArpRequest6 {
        tIPv6   SourceIP;
        tMacAddr        DestMac;
        tIPv6   DestIP;
-};
+} __attribute__((packed));
 
 #endif
index 4eb4fa4..5d53cc6 100644 (file)
@@ -3,11 +3,12 @@
  * - ICMP Handling
  */
 #include "ipstack.h"
+#include "ipv4.h"
 #include "icmp.h"
 
 // === PROTOTYPES ===
 void   ICMP_Initialise();
-void   ICMP_GetPacket(tInterface *Interface, int Length, void *Buffer);
+void   ICMP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer);
 
 // === GLOBALS ===
 
@@ -18,7 +19,7 @@ void  ICMP_GetPacket(tInterface *Interface, int Length, void *Buffer);
  */
 void ICMP_Initialise()
 {
-       
+       IPv4_RegisterCallback(IP4PROT_ICMP, ICMP_GetPacket);
 }
 
 /**
@@ -27,6 +28,11 @@ void ICMP_Initialise()
  */
 void ICMP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
 {
-       //tICMPHeader   *hdr = Buffer;
+       tICMPHeader     *hdr = Buffer;
        
+       Log("[ICMP ] hdr->Type = %i", hdr->Type);
+       Log("[ICMP ] hdr->Code = %i", hdr->Code);
+       Log("[ICMP ] hdr->Checksum = 0x%x", ntohs(hdr->Checksum));
+       Log("[ICMP ] hdr->ID = 0x%x", ntohs(hdr->ID));
+       Log("[ICMP ] hdr->Sequence = 0x%x", ntohs(hdr->Sequence));
 }
index 8c88dac..9315f40 100644 (file)
@@ -19,16 +19,16 @@ typedef void        (*tIPCallback)(tInterface *Interface, void *Address, int Length, vo
 union uIPv4 {
        Uint32  L;
        Uint8   B[4];
-};
+} __attribute__((packed));
 
 union uIPv6 {
        Uint32  L[4];
        Uint8   B[16];
-};
+} __attribute__((packed));
 
 struct sMacAddr {
        Uint8   B[6];
-};
+} __attribute__((packed));
 
 struct sInterface {
        struct sInterface       *Next;
@@ -78,6 +78,6 @@ static const tMacAddr cMAC_BROADCAST = {{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};
 #define htonl(in)      BigEndian32(in)
 #define ntonb(v)       (v)
 #define ntohs(in)      BigEndian16(in)
-#define ntohl(in)      BigEndian16(in)
+#define ntohl(in)      BigEndian32(in)
 
 #endif
index 9723d8d..7e7c585 100644 (file)
@@ -8,9 +8,12 @@
 
 // === IMPORTS ===
 extern tInterface      *gIP_Interfaces;
+extern void    ICMP_Initialise();
+extern void    UDP_Initialise();
 
 // === PROTOTYPES ===
  int   IPv4_Initialise();
+ int   IPv4_RegisterCallback(int ID, tIPCallback Callback);
 void   IPv4_int_GetPacket(tAdapter *Interface, tMacAddr From, int Length, void *Buffer);
 tInterface     *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast);
 Uint32 IPv4_Netmask(int FixedBits);
@@ -24,10 +27,24 @@ tIPCallback gaIPv4_Callbacks[256];
  */
 int IPv4_Initialise()
 {
+       ICMP_Initialise();
+       UDP_Initialise();
        Link_RegisterType(IPV4_ETHERNET_ID, IPv4_int_GetPacket);
        return 1;
 }
 
+/**
+ * \fn int IPv4_RegisterCallback( int ID, tIPCallback Callback )
+ * \brief Registers a callback
+ */
+int IPv4_RegisterCallback(int ID, tIPCallback Callback)
+{
+       if( ID < 0 || ID > 255 )        return 0;
+       if( gaIPv4_Callbacks[ID] )      return 0;
+       gaIPv4_Callbacks[ID] = Callback;
+       return 1;
+}
+
 /**
  * \fn void IPv4_int_GetPacket(tInterface *Adapter, tMacAddr From, int Length, void *Buffer)
  * \brief Process an IPv4 Packet
@@ -40,18 +57,41 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff
         int    dataLength;
        if(Length < sizeof(tIPv4Header))        return;
        
+       //Log("[IPv4 ] Version = %i", hdr->Version);
+       Log("[IPv4 ] HeaderLength = %i", hdr->HeaderLength);
+       Log("[IPv4 ] DiffServices = %i", hdr->DiffServices);
+       //Log("[IPv4 ] TotalLength = %i", ntohs(hdr->TotalLength) );
+       //Log("[IPv4 ] Identifcation = %i", ntohs(hdr->Identifcation) );
+       //Log("[IPv4 ] TTL = %i", hdr->TTL );
+       Log("[IPv4 ] Protocol = %i", hdr->Protocol );
+       //Log("[IPv4 ] HeaderChecksum = 0x%x", ntohs(hdr->HeaderChecksum) );
+       Log("[IPv4 ] Source = %i.%i.%i.%i",
+               hdr->Source.B[0], hdr->Source.B[1], hdr->Source.B[2], hdr->Source.B[3] );
+       Log("[IPv4 ] Destination = %i.%i.%i.%i",
+               hdr->Destination.B[0], hdr->Destination.B[1],
+               hdr->Destination.B[2], hdr->Destination.B[3] );
+       
        // Check that the version IS IPv4
-       if(hdr->Version != 4)   return;
+       if(hdr->Version != 4) {
+               Log("[IPv4 ] hdr->Version(%i) != 4", hdr->Version);
+               return;
+       }
        
        // Check Header checksum
        //TODO
        
        // Check Packet length
-       if(hdr->TotalLength > Length)   return;
+       if( ntohs(hdr->TotalLength) > Length) {
+               Log("[IPv4 ] hdr->TotalLength(%i) > Length(%i)", hdr->TotalLength, Length);
+               return;
+       }
        
        // Get Interface (allowing broadcasts)
-       iface = IPv4_GetInterface(Adapter, hdr->Source, 1);
-       if(!iface)      return; // Not for us? Well, let's ignore it
+       iface = IPv4_GetInterface(Adapter, hdr->Destination, 1);
+       if(!iface) {
+               Log("[IPv4 ] Ignoring Packet (Not for us)");
+               return; // Not for us? Well, let's ignore it
+       }
        
        // Defragment
        //TODO
@@ -71,6 +111,9 @@ tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast)
 {
        tInterface      *iface = NULL;
        Uint32  netmask;
+       Uint32  addr, this;
+       
+       addr = ntohl( Address.L );
        
        for( iface = gIP_Interfaces; iface; iface = iface->Next)
        {
@@ -81,10 +124,20 @@ tInterface *IPv4_GetInterface(tAdapter *Adapter, tIPv4 Address, int Broadcast)
                
                if( !Broadcast )        continue;
                
+               this = ntohl( iface->IP4.Address.L );
+               
                // Check for broadcast
                netmask = IPv4_Netmask(iface->IP4.SubnetBits);
-               if( (Address.L & netmask) == (iface->IP4.Address.L & netmask)
-                && (Address.L & ~netmask) == (0xFFFFFFFF & ~netmask) )
+               
+               //Log("netmask = 0x%08x", netmask);
+               //Log("addr = 0x%08x", addr);
+               //Log("this = 0x%08x", this);
+               //Log("%08x == %08x && %08x == %08x",
+               //      (addr & netmask), (this & netmask),
+               //      (addr & ~netmask), (0xFFFFFFFF & ~netmask)
+               //      );
+               if( (addr & netmask) == (this & netmask)
+                && (addr & ~netmask) == (0xFFFFFFFF & ~netmask) )
                        return iface;
        }
        return NULL;
@@ -100,5 +153,6 @@ Uint32 IPv4_Netmask(int FixedBits)
        Uint32  ret = 0xFFFFFFFF;
        ret >>= (32-FixedBits);
        ret <<= (32-FixedBits);
+       // Returs a little endian netmask
        return ret;
 }
index 67b3dc8..b092bec 100644 (file)
@@ -12,9 +12,10 @@ typedef struct sIPv4Header   tIPv4Header;
 struct sIPv4Header
 {
        struct {
-               unsigned Version:       4;      // = 4
+               // Spec says Version is first, but stupid bit ordering
                unsigned HeaderLength:  4;      // in 4-byte chunks
-       };
+               unsigned Version:       4;      // = 4
+       } __attribute__((packed));
        Uint8   DiffServices;   // Differentiated Services
        Uint16  TotalLength;
        Uint16  Identifcation;
@@ -24,7 +25,7 @@ struct sIPv4Header
                unsigned DontFragment:  1;
                unsigned MoreFragments: 1;
                unsigned FragOffLow:    5;
-       };
+       } __attribute__((packed));
        Uint8   FragOffHi;      // Number of 8-byte blocks from the original start
        
        Uint8   TTL;    // Max number of hops effectively
@@ -35,7 +36,7 @@ struct sIPv4Header
        tIPv4   Destination;
        
        Uint8   Options[];
-};
+} __attribute__((packed));
 
 #define IP4PROT_ICMP   1
 #define IP4PROT_TCP    6
@@ -43,4 +44,7 @@ struct sIPv4Header
 
 #define IPV4_ETHERNET_ID       0x0800
 
+// === FUNCTIONS ===
+extern int     IPv4_RegisterCallback(int ID, tIPCallback Callback);
+
 #endif
index 4489b52..cb59f0f 100644 (file)
@@ -8,12 +8,21 @@
 // === CONSTANTS ===
 #define        MAX_PACKET_SIZE 2048
 
+// === PROTOTYPES ===
+void   Link_RegisterType(Uint16 Type, tPacketCallback Callback);
+void   Link_InitCRC();
+Uint32 Link_CalculateCRC(void *Data, int Length);
+void   Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, int Length, void *Buffer);
+void   Link_WatchDevice(tAdapter *Adapter);
+
 // === GLOBALS ===
  int   giRegisteredTypes = 0;
 struct {
        Uint16  Type;
        tPacketCallback Callback;
 }      *gaRegisteredTypes;
+ int   gbLink_CRCTableGenerated = 0;
+Uint32 gaiLink_CRCTable[256];
 
 // === CODE ===
 /**
@@ -26,6 +35,9 @@ void Link_RegisterType(Uint16 Type, tPacketCallback Callback)
 {
         int    i;
        void    *tmp;
+       
+       Type = htons(Type);     // Set to network order
+       
        for( i = giRegisteredTypes; i -- ; )
        {
                if(gaRegisteredTypes[i].Type == Type) {
@@ -58,16 +70,23 @@ void Link_RegisterType(Uint16 Type, tPacketCallback Callback)
  */
 void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, int Length, void *Buffer)
 {
-        int    bufSize = sizeof(tEthernetHeader) + Length;
-       Uint8   buf[bufSize];
+        int    bufSize = sizeof(tEthernetHeader) + Length + 4;
+       Uint8   buf[bufSize];   // dynamic stack arrays ftw!
        tEthernetHeader *hdr = (void*)buf;
        
+       Log("[NET  ] Sending %i bytes to %02x:%02x:%02x:%02x:%02x:%02x (Type 0x%x)",
+               Length, To.B[0], To.B[1], To.B[2], To.B[3], To.B[4], To.B[5], Type);
+       
        hdr->Dest = To;
        hdr->Src = Adapter->MacAddr;
        hdr->Type = htons(Type);
        
        memcpy(hdr->Data, Buffer, Length);
        
+       *(Uint32*) &hdr->Data[Length] = 0;
+       *(Uint32*) &hdr->Data[Length] = htonl( Link_CalculateCRC(buf, bufSize) );
+       
+       
        VFS_Write(Adapter->DeviceFD, bufSize, buf);
 }
 
@@ -89,12 +108,16 @@ void Link_WatchDevice(tAdapter *Adapter)
                return ;
        }
        
+       if( !gbLink_CRCTableGenerated )
+               Link_InitCRC();
+       
        // Child Thread
        while(Adapter->DeviceFD != -1)
        {
                Uint8   buf[MAX_PACKET_SIZE];
                tEthernetHeader *hdr = (void*)buf;
                 int    ret, i;
+               Uint32  checksum;
                
                // Wait for a packet (Read on a network device is blocking)
                ret = VFS_Read(Adapter->DeviceFD, MAX_PACKET_SIZE, buf);
@@ -105,13 +128,27 @@ void Link_WatchDevice(tAdapter *Adapter)
                        continue;
                }
                
+               Log("[NET  ] Packet from %02x:%02x:%02x:%02x:%02x:%02x",
+                       hdr->Src.B[0], hdr->Src.B[1], hdr->Src.B[2],
+                       hdr->Src.B[3], hdr->Src.B[4], hdr->Src.B[5]
+                       );
+               Log("[NET  ] to %02x:%02x:%02x:%02x:%02x:%02x",
+                       hdr->Dest.B[0], hdr->Dest.B[1], hdr->Dest.B[2],
+                       hdr->Dest.B[3], hdr->Dest.B[4], hdr->Dest.B[5]
+                       );
+               checksum = *(Uint32*)&hdr->Data[ret-sizeof(tEthernetHeader)-4];
+               Log("[NET  ] Checksum 0x%08x", checksum);
+               
                // Check if there is a registered callback for this packet type
                for( i = giRegisteredTypes; i--; )
                {
-                       if(gaRegisteredTypes[i].Type == hdr->Type)      continue;
+                       if(gaRegisteredTypes[i].Type == hdr->Type)      break;
                }
                // No? Ignore it
-               if( i == -1 )   continue;
+               if( i == -1 ) {
+                       Log("[NET  ] Unregistered type 0x%x", ntohs(hdr->Type));
+                       continue;
+               }
                
                // Call the callback
                gaRegisteredTypes[i].Callback(
@@ -124,3 +161,50 @@ void Link_WatchDevice(tAdapter *Adapter)
        
        Log("[NET  ] Watcher terminated (file closed)");
 }
+
+// From http://www.cl.cam.ac.uk/research/srg/bluebook/21/crc/node6.html
+#define        QUOTIENT        0x04c11db7
+void Link_InitCRC(void)
+{
+     int       i, j;
+    Uint32     crc;
+
+    for (i = 0; i < 256; i++)
+    {
+        crc = i << 24;
+        for (j = 0; j < 8; j++)
+        {
+            if (crc & 0x80000000)
+                crc = (crc << 1) ^ QUOTIENT;
+            else
+                crc = crc << 1;
+        }
+        gaiLink_CRCTable[i] = crc;
+    }
+       
+       gbLink_CRCTableGenerated = 1;
+}
+
+Uint32 Link_CalculateCRC(void *Data, int Length)
+{
+       // x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
+       Uint32  result;
+     int       i;
+       Uint32  *data = Data;
+    
+    if(Length < 4)     return 0;
+
+    result = *data++ << 24;
+    result |= *data++ << 16;
+    result |= *data++ << 8;
+    result |= *data++;
+    result = ~ result;
+    Length -= 4;
+    
+    for( i = 0; i < Length; i++ )
+    {
+        result = (result << 8 | *data++) ^ gaiLink_CRCTable[result >> 24];
+    }
+    
+    return ~result;
+}
index 05e2897..7f1e02f 100644 (file)
@@ -12,7 +12,8 @@
 #include <tpl_drv_network.h>
 
 // === IMPORTS ===
- int   ARP_Initialise();
+extern int     ARP_Initialise();
+extern int     IPv4_Initialise();
 
 // === PROTOTYPES ===
  int   IPStack_Install(char **Arguments);
@@ -54,6 +55,7 @@ int IPStack_Install(char **Arguments)
        
        // Install Handlers
        ARP_Initialise();
+       IPv4_Initialise();
        
        if(Arguments)
        {
diff --git a/Modules/IPStack/udp.c b/Modules/IPStack/udp.c
new file mode 100644 (file)
index 0000000..c57f284
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Acess2 IP Stack
+ * - UDP Handling
+ */
+#include "ipstack.h"
+#include "udp.h"
+
+// === PROTOTYPES ===
+void   UDP_Initialise();
+void   UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer);
+
+// === GLOBALS ===
+
+// === CODE ===
+/**
+ * \fn void TCP_Initialise()
+ * \brief Initialise the TCP Layer
+ */
+void UDP_Initialise()
+{
+       IPv4_RegisterCallback(IP4PROT_UDP, UDP_GetPacket);
+}
+
+/**
+ * \fn void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
+ * \brief Handles a packet from the IP Layer
+ */
+void UDP_GetPacket(tInterface *Interface, void *Address, int Length, void *Buffer)
+{
+       tUDPHeader      *hdr = Buffer;
+       
+       Log("[UDP  ] hdr->SourcePort = %i", ntohs(hdr->SourcePort));
+       Log("[UDP  ] hdr->DestPort = %i", ntohs(hdr->DestPort));
+       Log("[UDP  ] hdr->Length = %i", ntohs(hdr->Length));
+       Log("[UDP  ] hdr->Checksum = 0x%x", ntohs(hdr->Checksum));
+}
diff --git a/Modules/IPStack/udp.h b/Modules/IPStack/udp.h
new file mode 100644 (file)
index 0000000..be2ff64
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Acess2 IP Stack
+ * - UDP Definitions
+ */
+#ifndef _UDP_H_
+#define _UDP_H_
+
+#include "ipstack.h"
+#include "ipv4.h"
+
+typedef struct sUDPHeader      tUDPHeader;
+
+struct sUDPHeader
+{
+       Uint16  SourcePort;
+       Uint16  DestPort;
+       Uint16  Length;
+       Uint16  Checksum;
+       Uint8   Data[];
+};
+
+#endif
index 3717a99..7f95154 100644 (file)
@@ -3,7 +3,7 @@
  * 
  * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc
  */
-#define        DEBUG   1
+#define        DEBUG   0
 #define VERSION        ((0<<8)|50)
 #include <common.h>
 #include <modules.h>
@@ -20,6 +20,7 @@
 #define TX_FIRST       (MEM_START+RX_BUF_SIZE)
 #define TX_LAST                (MEM_END)
 #define        TX_BUF_SIZE     0x40
+#define        MAX_PACKET_QUEUE        10
 
 static const struct {
        Uint16  Vendor;
@@ -60,11 +61,18 @@ enum eNe2k_Page0Write {
        IMR             //!< interrupt mask register (init)
 };
 
+enum eNe2k_Page1Read {
+       CURR = 7        //!< current page
+};
+
 // === TYPES ===
 typedef struct sNe2k_Card {
        Uint16  IOBase; //!< IO Port Address from PCI
        Uint8   IRQ;    //!< IRQ Assigned from PCI
        
+        int    NumWaitingPackets;
+        int    NextRXPage;
+       
         int    NextMemPage;    //!< Next Card Memory page to use
        
        Uint8   Buffer[RX_BUF_SIZE];
@@ -80,6 +88,7 @@ char  *Ne2k_ReadDir(tVFS_Node *Node, int Pos);
 tVFS_Node      *Ne2k_FindDir(tVFS_Node *Node, char *Name);
  int   Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data);
 Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
+Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
 Uint8  Ne2k_int_GetWritePage(tCard *Card, Uint16 Length);
 void   Ne2k_IRQHandler(int IntNum);
 
@@ -120,8 +129,8 @@ int Ne2k_Install(char **Options)
        
        // Enumerate Cards
        k = 0;
-       gpNe2k_Cards = malloc( giNe2k_CardCount * sizeof(tCard) );
-       memsetd(gpNe2k_Cards, 0, giNe2k_CardCount * sizeof(tCard) / 4);
+       gpNe2k_Cards = calloc( giNe2k_CardCount, sizeof(tCard) );
+       
        for( i = 0; i < NUM_COMPAT_DEVICES; i ++ )
        {
                count = PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, 0 );
@@ -133,6 +142,7 @@ int Ne2k_Install(char **Options)
                        gpNe2k_Cards[ k ].IOBase = base;
                        gpNe2k_Cards[ k ].IRQ = PCI_GetIRQ( id );
                        gpNe2k_Cards[ k ].NextMemPage = 64;
+                       gpNe2k_Cards[ k ].NextRXPage = RX_FIRST;
                        
                        // Install IRQ Handler
                        IRQ_AddHandler(gpNe2k_Cards[ k ].IRQ, Ne2k_IRQHandler);
@@ -143,6 +153,8 @@ int Ne2k_Install(char **Options)
                        outb( base + ISR, 0x80 );
                        
                        // Initialise Card
+                       outb( base + CMD, 0x40|0x21 );  // Page 1, No DMA, Stop
+                       outb( base + CURR, RX_FIRST );  // Current RX page
                        outb( base + CMD, 0x21 );       // No DMA and Stop
                        outb( base + DCR, 0x49 );       // Set WORD mode
                        outb( base + IMR, 0x00 );
@@ -156,12 +168,12 @@ int Ne2k_Install(char **Options)
                        outb( base + CMD, 0x0A );       // Remote Read, Start
                        
                        // Read MAC Address
-                       gpNe2k_Cards[ k ].MacAddr[0] = inb(base+0x10);  inb(base+0x10);
-                       gpNe2k_Cards[ k ].MacAddr[1] = inb(base+0x10);  inb(base+0x10);
-                       gpNe2k_Cards[ k ].MacAddr[2] = inb(base+0x10);  inb(base+0x10);
-                       gpNe2k_Cards[ k ].MacAddr[3] = inb(base+0x10);  inb(base+0x10);
-                       gpNe2k_Cards[ k ].MacAddr[4] = inb(base+0x10);  inb(base+0x10);
-                       gpNe2k_Cards[ k ].MacAddr[5] = inb(base+0x10);  inb(base+0x10);
+                       gpNe2k_Cards[ k ].MacAddr[0] = inb(base+0x10);//        inb(base+0x10);
+                       gpNe2k_Cards[ k ].MacAddr[1] = inb(base+0x10);//        inb(base+0x10);
+                       gpNe2k_Cards[ k ].MacAddr[2] = inb(base+0x10);//        inb(base+0x10);
+                       gpNe2k_Cards[ k ].MacAddr[3] = inb(base+0x10);//        inb(base+0x10);
+                       gpNe2k_Cards[ k ].MacAddr[4] = inb(base+0x10);//        inb(base+0x10);
+                       gpNe2k_Cards[ k ].MacAddr[5] = inb(base+0x10);//        inb(base+0x10);
                        
                        outb( base+PSTART, RX_FIRST);   // Set Receive Start
                        outb( base+BNRY, RX_LAST-1);    // Set Boundary Page
@@ -197,6 +209,7 @@ int Ne2k_Install(char **Options)
                        gpNe2k_Cards[ k ].Node.NumACLs = 0;     // Root Only
                        gpNe2k_Cards[ k ].Node.CTime = now();
                        gpNe2k_Cards[ k ].Node.Write = Ne2k_Write;
+                       gpNe2k_Cards[ k ].Node.Read = Ne2k_Read;
                        gpNe2k_Cards[ k ].Node.IOCtl = Ne2k_IOCtl;
                }
        }
@@ -331,7 +344,7 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        for(rem = Length; rem; rem -= 2)
                outw(Card->IOBase + 0x10, *buf++);
        
-       while( inb(Card->IOBase + ISR) == 0   // Wait for Remote DMA Complete
+       while( inb(Card->IOBase + ISR) == 0 )   // Wait for Remote DMA Complete
                ;       //Proc_Yield();
        
        outb( Card->IOBase + ISR, 0x40 );       // ACK Interrupt
@@ -346,6 +359,106 @@ Uint64 Ne2k_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
        return Length;
 }
 
+/**
+ * \fn Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+ * \brief Wait for and read a packet from the network card
+ */
+Uint64 Ne2k_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+{
+       tCard   *Card = (tCard*)Node->ImplPtr;
+       Uint8   page;
+       Uint8   data[256];
+        int    i;
+       struct {
+               Uint8   Status;
+               Uint8   NextPacketPage;
+               Uint16  Length; // Little Endian
+       }       *pktHdr;
+       
+       ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
+       
+       while(Card->NumWaitingPackets == 0)     Threads_Yield();
+       
+       // Make sure that the card is in page 0
+       outb(Card->IOBase + CMD, 0|0x22);       // Page 0, Start, NoDMA
+       
+       // Get BOUNDARY
+       page = Card->NextRXPage;
+       
+       // Set up transfer
+       outb(Card->IOBase + RBCR0, 0);
+       outb(Card->IOBase + RBCR1, 1);  // 256-bytes
+       outb(Card->IOBase + RSAR0, 0x00);       // Page Offset
+       outb(Card->IOBase + RSAR1, page);       // Page Number
+       
+       outb(Card->IOBase + CMD, 0|0x08|0x2);   // Page 0, Remote Read, Start
+       
+       // Clear Remote DMA Flag
+       outb(Card->IOBase + ISR, 0x40); // Bit 6
+       
+       // Read data
+       for(i = 0; i < 128; i ++)
+               ((Uint16*)data)[i] = inw(Card->IOBase + 0x10);
+       
+       pktHdr = (void*)data;
+       //Log("Ne2k_Read: Recieved packet (%i bytes)", pktHdr->Length);
+       
+       // Have we read all the required bytes yet?
+       if(pktHdr->Length < 256 - 4)
+       {
+               if(Length > pktHdr->Length)
+                       Length = pktHdr->Length;
+               memcpy(Buffer, &data[4], Length);
+               page ++;
+               if(page == RX_LAST+1)   page = RX_FIRST;
+       }
+       // No? oh damn, now we need to allocate a buffer
+       else {
+                int    j = 256/2;
+               char    *buf = malloc( (pktHdr->Length + 4 + 255) & ~255 );
+               
+               if(!buf) {
+                       LEAVE('i', -1);
+                       return -1;
+               }
+               
+               memcpy(buf, data, 256);
+               
+               page ++;
+               while(page != pktHdr->NextPacketPage)
+               {
+                       if(page == RX_LAST+1)   page = RX_FIRST;
+                       
+                       outb(Card->IOBase + RBCR0, 0);
+                       outb(Card->IOBase + RBCR1, 1);  // 256-bytes
+                       outb(Card->IOBase + RSAR0, 0x00);       // Page Offset
+                       outb(Card->IOBase + RSAR1, page);       // Page Number
+                       outb(Card->IOBase + CMD, 0|0x08|0x2);   // Page 0, Remote Read, Start
+                       
+                       for(i = 0; i < 128; i ++)
+                               ((Uint16*)buf)[j+i] = inw(Card->IOBase + 0x10);
+                       j += 128;
+                       page ++;
+               }
+               
+               if(Length > pktHdr->Length)
+                       Length = pktHdr->Length;
+               memcpy(Buffer, &buf[4], Length);
+       }
+       
+       // Write BNRY
+       if(page == RX_FIRST)
+               outb( Card->IOBase + BNRY, RX_LAST );
+       else
+               outb( Card->IOBase + BNRY, page-1 );
+       // Set next RX Page and decrement the waiting list
+       Card->NextRXPage = page;
+       Card->NumWaitingPackets --;
+       
+       LEAVE('i', Length);
+       return Length;
+}
+
 /**
  * \fn Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length)
  */
@@ -367,10 +480,28 @@ Uint8 Ne2k_int_GetWritePage(tCard *Card, Uint16 Length)
 void Ne2k_IRQHandler(int IntNum)
 {
         int    i;
+       Uint8   byte;
        for( i = 0; i < giNe2k_CardCount; i++ )
        {
-               if(gpNe2k_Cards[i].IRQ == IntNum) {
-                       LOG("Clearing interrupts on card %i (0x%x)\n", i, inb( gpNe2k_Cards[i].IOBase + ISR ));
+               if(gpNe2k_Cards[i].IRQ == IntNum)
+               {
+                       byte = inb( gpNe2k_Cards[i].IOBase + ISR );
+                       
+                       // 0: Packet recieved (no error)
+                       if( byte & 1 )
+                       {
+                               gpNe2k_Cards[i].NumWaitingPackets ++;
+                               if( gpNe2k_Cards[i].NumWaitingPackets > MAX_PACKET_QUEUE )
+                                       gpNe2k_Cards[i].NumWaitingPackets = MAX_PACKET_QUEUE;
+                       }
+                       // 1: Packet sent (no error)
+                       // 2: Recieved with error
+                       // 3: Transmission Halted (Excessive Collisions)
+                       // 4: Recieve Buffer Exhausted
+                       // 5: 
+                       // 6: Remote DMA Complete
+                       // 7: Reset
+                       //LOG("Clearing interrupts on card %i (was 0x%x)\n", i, byte);
                        outb( gpNe2k_Cards[i].IOBase + ISR, 0xFF );     // Reset All
                        return ;
                }
index 47798a8..ea8dcb8 100644 (file)
@@ -135,8 +135,9 @@ int DoAutoConfig( char *Device )
 {
         int    tmp, fd;
        char    path[sizeof(IPSTACK_ROOT)+5+1]; // ip000
-       uint8_t addr[4] = {192,168,1,39};
-       uint8_t gw[4] = {192,168,1,1};
+       uint8_t addr[4] = {10,0,0,55};
+       uint8_t gw[4] = {10,0,0,1};
+        int    subnet = 8;
        
        tmp = AddInterface(Device);
        if( tmp < 0 )   return tmp;
@@ -158,14 +159,16 @@ int DoAutoConfig( char *Device )
        // Set Address
        ioctl(fd, ioctl(fd, 3, "set_address"), addr);
        // Set Subnet
-       tmp = 24;
-       ioctl(fd, ioctl(fd, 3, "getset_subnet"), &tmp);
+       ioctl(fd, ioctl(fd, 3, "getset_subnet"), &subnet);
        // Set Gateway
        ioctl(fd, ioctl(fd, 3, "set_gateway"), gw);
        
        close(fd);
        
-       printf("Set address to 192.168.1.39/24 (GW: 192.168.1.1)\n");
+       printf("Set address to %i.%i.%i.%i/%i (GW: %i.%i.%i.%i)\n",
+               addr[0], addr[1], addr[2], addr[3],
+               subnet,
+               gw[0], gw[1], gw[2], gw[3]);
        
        return 0;
 }

UCC git Repository :: git.ucc.asn.au