IPStack - Reworking of network device API
authorJohn Hodge <[email protected]>
Sat, 12 May 2012 10:52:37 +0000 (18:52 +0800)
committerJohn Hodge <[email protected]>
Sat, 12 May 2012 10:52:37 +0000 (18:52 +0800)
- Replaced the VFS API with passing tIPStackBuffer objects about
- Reduced code size in network drivers, and made interface management easier
- FIX: Routing bugs due to older refactoring
- FIX: Ne2000 driver not removing the IO bit from BAR value

20 files changed:
KernelLand/Modules/IPStack/Makefile
KernelLand/Modules/IPStack/adapters.c [new file with mode: 0644]
KernelLand/Modules/IPStack/arp.c
KernelLand/Modules/IPStack/buffer.c
KernelLand/Modules/IPStack/include/adapters.h [new file with mode: 0644]
KernelLand/Modules/IPStack/include/adapters_api.h [new file with mode: 0644]
KernelLand/Modules/IPStack/include/adapters_int.h [new file with mode: 0644]
KernelLand/Modules/IPStack/include/buffer.h
KernelLand/Modules/IPStack/interface.c
KernelLand/Modules/IPStack/ipstack.h
KernelLand/Modules/IPStack/ipv4.c
KernelLand/Modules/IPStack/link.c
KernelLand/Modules/IPStack/link.h
KernelLand/Modules/IPStack/main.c
KernelLand/Modules/IPStack/routing.c
KernelLand/Modules/Network/NE2000/ne2000.c
KernelLand/Modules/Network/RTL8139/rtl8139.c
Usermode/Applications/dhcpclient_src/main.c
Usermode/Applications/ifconfig_src/main.c
Usermode/Applications/ping_src/main.c

index b0ee26b..3ea5f7e 100644 (file)
@@ -1,7 +1,7 @@
 #
 #
 
-OBJ := main.o interface.o
+OBJ := main.o interface.o adapters.o
 OBJ += buffer.o
 OBJ += link.o arp.o
 OBJ += ipv4.o icmp.o
diff --git a/KernelLand/Modules/IPStack/adapters.c b/KernelLand/Modules/IPStack/adapters.c
new file mode 100644 (file)
index 0000000..f4b99be
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * Acess2 Networking Stack
+ * - By John Hodge (thePowersGang)
+ *
+ * adapters.c
+ * - Network Adapter Management
+ */
+#define DEBUG  0
+#define VERSION        VER2(0,1)
+#include "ipstack.h"
+#include "include/buffer.h"
+#include "include/adapters.h"
+#include "include/adapters_int.h"
+#include "link.h"
+#include <api_drv_common.h>    // For the VFS hack
+#include <api_drv_network.h>
+
+// === PROTOTYPES ===
+// --- "External" (NIC) API ---
+void   *IPStack_Adapter_Add(const tIPStack_AdapterType *Type, void *Ptr, const void *HWAddr);
+void   IPStack_Adapter_Del(void *Handle);
+// --- VFS API ---
+char   *Adapter_ReadDir(tVFS_Node *Node, int Pos);
+tVFS_Node      *Adapter_FindDir(tVFS_Node *Node, const char *Name);
+ int   Adapter_DirIOCtl(tVFS_Node *Node, int Num, void *Data);
+ int   Adapter_IOCtl(tVFS_Node *Node, int Num, void *Data);
+// --- "Internal" (IPStack) API ---
+tAdapter       *Adapter_GetByName(const char *Name);
+void   Adapter_SendPacket(tAdapter *Handle, tIPStackBuffer *Buffer);
+// --- Helpers ---
+void   Adapter_int_WatchThread(void *Ptr);
+tIPStackBuffer *Adapter_int_LoopbackWaitPacket(void *Unused);
+ int   Adapter_int_LoopbackSendPacket(void *Unused, tIPStackBuffer *Buffer);
+
+// === GLOBALS ===
+// --- VFS Magic ---
+tVFS_NodeType  gIP_AdaptersDirType = {
+       .ReadDir = Adapter_ReadDir,
+       .FindDir = Adapter_FindDir,
+       .IOCtl = Adapter_DirIOCtl
+};
+tVFS_NodeType  gIP_AdapterType = {
+       // TODO: Should direct IO be allowed?
+       .IOCtl = Adapter_IOCtl
+};
+tVFS_Node      gIP_AdaptersNode = {
+       .Type = &gIP_AdaptersDirType,
+       .Flags = VFS_FFLAG_DIRECTORY,
+       .Size = -1
+};
+// --- Loopback Adapter ---
+tIPStack_AdapterType   gIP_LoopAdapterType = {
+       .Name = "Loopback",
+       .WaitForPacket = Adapter_int_LoopbackWaitPacket,
+       .SendPacket = Adapter_int_LoopbackSendPacket
+       };
+tAdapter       gIP_LoopAdapter;
+// --- Main adapter list ---
+tMutex glIP_Adapters;
+tAdapter       *gpIP_AdapterList;
+tAdapter       *gpIP_AdapterList_Last = (void*)&gpIP_AdapterList;      // HACK!
+ int   giIP_NextAdapterIndex;
+
+// === CODE ===
+// --- "External" (NIC) API ---
+void *IPStack_Adapter_Add(const tIPStack_AdapterType *Type, void *Ptr, const void *HWAddr)
+{
+       tAdapter        *ret;
+       
+       ret = malloc(sizeof(tAdapter) + 6);     // TODO: Don't assume 6-byte MAC addresses
+       ret->Next = NULL;
+       ret->Type = Type;
+       ret->CardHandle = Ptr;
+       ret->RefCount = 0;
+       ret->Index = giIP_NextAdapterIndex++;
+       memcpy(ret->HWAddr, HWAddr, 6);
+
+       memset(&ret->Node, 0, sizeof(ret->Node));
+       ret->Node.Type = &gIP_AdapterType;
+       ret->Node.ImplPtr = ret;
+
+       // TODO: Locking
+       gpIP_AdapterList_Last->Next = ret;
+       gpIP_AdapterList_Last = ret;
+       
+       // Watch the adapter for incoming packets
+       tTID tid = Proc_SpawnWorker(Adapter_int_WatchThread, ret);
+       if(tid < 0) {
+               Log_Warning("IPStack", "Unable to create watcher thread for %p", ret);
+       }
+       
+       return ret;
+}
+
+void *IPStack_Adapter_AddVFS(const char *Path)
+{
+        int    fd, tmp;
+       char    mac[6];
+
+       ENTER("sPath", Path);   
+
+       // Open Device
+       fd = VFS_Open( Path, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE );
+       if( fd == -1 ) {
+               LEAVE('n');
+               return NULL;
+       }
+       
+       // Check that it is a network interface
+       tmp = VFS_IOCtl(fd, 0, NULL);
+       LOG("Device type = %i", tmp);
+       if( tmp != DRV_TYPE_NETWORK ) {
+               Log_Warning("IPStack", "IPStack_Adapter_AddVFS: '%s' is not a network interface", Path);
+               VFS_Close( fd );
+               LEAVE('n');
+               return NULL;
+       }
+       
+       // Get MAC Address
+       VFS_IOCtl(fd, NET_IOCTL_GETMAC, mac);
+
+       return IPStack_Adapter_Add(NULL, (void*)fd, mac);
+}
+
+void IPStack_Adapter_Del(void *Handle)
+{
+       Log_Error("IPStack", "TODO: Implement IPStack_Adapter_Del");
+       // TODO: Allow removing adapters during system operation
+}
+
+// --- VFS API ---
+char *Adapter_ReadDir(tVFS_Node *Node, int Pos)
+{
+       if( Pos < 0 )   return NULL;
+
+       // Loopback
+       if( Pos == 0 ) {
+               return strdup("lo");
+       }
+       Pos --;
+       
+       #define CHECK_LIST(list, type) do{ \
+               tAdapter *a;  int i;\
+               for(i=0,a=list; i < Pos && a; i ++, a = a->Next ); \
+               if( a ) { \
+                       char    buf[sizeof(type)+10]; \
+                       sprintf(buf, type"%i", a->Index); \
+                       return strdup(buf); \
+               } \
+               Pos -= i; \
+       } while(0);
+
+       CHECK_LIST(gpIP_AdapterList, "eth");
+       // TODO: Support other types of adapters (wifi, tap, ...)
+
+       return NULL;
+}
+
+tVFS_Node *Adapter_FindDir(tVFS_Node *Node, const char *Name)
+{
+       tAdapter *a = Adapter_GetByName(Name);
+       if(!a)
+               return NULL;
+       else
+               return &a->Node;
+}
+
+static const char *casIOCtls_Root[] = { DRV_IOCTLNAMES, "add_vfs_adapter", NULL };
+int Adapter_DirIOCtl(tVFS_Node *Node, int Num, void *Data)
+{
+       switch(Num)
+       {
+       BASE_IOCTLS(DRV_TYPE_MISC, "IPStack-AdapterList", VERSION, casIOCtls_Root)
+       
+       case 4:
+               if( !CheckString(Data) )
+                       return -1;
+
+               // Return non-zero if add fails
+               return IPStack_Adapter_AddVFS(Data) == NULL;
+       }
+       return -1;
+}
+
+static const char *casIOCtls_Dev[] = { DRV_IOCTLNAMES, "get_hwaddr", NULL };
+int Adapter_IOCtl(tVFS_Node *Node, int Num, void *Data)
+{
+       tAdapter *adapter = Node->ImplPtr;
+       switch(Num)
+       {
+       BASE_IOCTLS(DRV_TYPE_MISC, "IPStack-Adapter", VERSION, casIOCtls_Dev)
+       
+       case 4:
+               if( !CheckMem(Data, 6) )
+                       return -1;
+
+               memcpy(Data, adapter->HWAddr, 6);
+               return 0;
+       }
+       return -1;
+}
+
+// --- "Internal" (IPStack) API ---
+tAdapter *Adapter_GetByName(const char *Name)
+{
+       if( strcmp(Name, "lo") == 0 ) {
+               return &gIP_LoopAdapter;
+       }
+       
+       if( strncmp(Name, "eth", 3) == 0 )
+       {
+               // Possibly an ethX interface
+                int    index, ofs;
+               
+               // Get the index at the end
+               ofs = ParseInt(Name + 3, &index);
+               if( ofs == 0 || Name[3+ofs] != '\0' )
+                       return NULL;
+               
+               // Find the adapter with that index
+               for( tAdapter *a = gpIP_AdapterList; a && a->Index <= index; a = a->Next ) {
+                       if( a->Index == index )
+                               return a;
+               }
+               
+               return NULL;
+       }
+       
+       return NULL;
+}
+
+void Adapter_SendPacket(tAdapter *Handle, tIPStackBuffer *Buffer)
+{
+       if( Handle->Type == NULL )
+       {
+               size_t outlen = 0;
+               void *data = IPStack_Buffer_CompactBuffer(Buffer, &outlen);
+               VFS_Write((tVAddr)Handle->CardHandle, outlen, data);
+               free(data);
+       }
+       else
+       {
+               Handle->Type->SendPacket( Handle->CardHandle, Buffer );
+       }
+}
+
+// --- Helpers ---
+void Adapter_int_WatchThread(void *Ptr)
+{
+       tAdapter        *Adapter = Ptr;
+       const int       MTU = 1520;
+       tIPStackBuffer  *buf = NULL;
+       void    *data = NULL;
+       
+       if( Adapter->Type == NULL )
+       {
+               data = malloc( MTU );
+               buf = IPStack_Buffer_CreateBuffer(1);
+       }
+
+       
+       Threads_SetName("Adapter Watcher");
+       Log_Log("IPStack", "Thread %i watching eth%i '%s'", Threads_GetTID(), Adapter->Index,
+               Adapter->Type?Adapter->Type->Name:"VFS");
+
+       for( ;; )
+       {
+               if( Adapter->Type == NULL )
+               {
+                       int len = VFS_Read((tVAddr)Adapter->CardHandle, MTU, data);
+                       IPStack_Buffer_AppendSubBuffer(buf, len, 0, buf, NULL, NULL);
+               }
+               else
+               {
+                       buf = Adapter->Type->WaitForPacket( Adapter->CardHandle );
+               }
+       
+               Link_HandlePacket(Adapter, buf);
+       
+               if( Adapter->Type == NULL )
+               {
+                       IPStack_Buffer_ClearBuffer(buf);
+               }
+               else
+               {
+                       IPStack_Buffer_DestroyBuffer(buf);
+               }
+       }
+}
+
+tIPStackBuffer *Adapter_int_LoopbackWaitPacket(void *Unused)
+{
+       Threads_Sleep();
+       return NULL;
+}
+
+int Adapter_int_LoopbackSendPacket(void *Unused, tIPStackBuffer *Buffer)
+{
+       // This is a little hacky :)
+       Link_HandlePacket(&gIP_LoopAdapter, Buffer);
+       return 0;
+}
+
index 607f201..e152e33 100644 (file)
@@ -8,6 +8,7 @@
 #include "arp.h"
 #include "link.h"
 #include "ipv4.h"      // For IPv4_Netmask
+#include "include/adapters_int.h"      // for MAC addr
 
 #define ARPv6  0
 #define        ARP_CACHE_SIZE  64
@@ -145,7 +146,7 @@ tMacAddr ARP_Resolve4(tInterface *Interface, tIPv4 Address)
        req.HWSize = 6;
        req.SWSize = 4;
        req.Request = htons(1);
-       req.SourceMac = Interface->Adapter->MacAddr;
+       memcpy(&req.SourceMac, Interface->Adapter->HWAddr, 6);  // TODO: Remove hard size
        req.SourceIP = *(tIPv4*)Interface->Address;
        req.DestMac = cMAC_BROADCAST;
        req.DestIP = Address;
@@ -332,7 +333,7 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe
                                req4->DestIP = req4->SourceIP;
                                req4->DestMac = req4->SourceMac;
                                req4->SourceIP = *(tIPv4*)iface->Address;;
-                               req4->SourceMac = Adapter->MacAddr;
+                               memcpy(&req4->SourceMac, Adapter->HWAddr, 6);   // TODO: Remove hard size
                                req4->Request = htons(2);
                                Log_Debug("ARP", "Sending back us (%02x:%02x:%02x:%02x:%02x:%02x)",
                                        req4->SourceMac.B[0], req4->SourceMac.B[1],
@@ -341,7 +342,7 @@ void ARP_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buffe
                                
                                // Assumes only a header and footer at link layer
                                tIPStackBuffer  *buffer = IPStack_Buffer_CreateBuffer(3);
-                               IPStack_Buffer_AppendSubBuffer(buffer, sizeof(struct sArpRequest4), 0, &req4, NULL, NULL);
+                               IPStack_Buffer_AppendSubBuffer(buffer, sizeof(struct sArpRequest4), 0, req4, NULL, NULL);
                                Link_SendPacket(Adapter, 0x0806, req4->DestMac, buffer);
                                IPStack_Buffer_DestroyBuffer(buffer);
                        }
index 9151c1c..b8462e6 100644 (file)
@@ -19,6 +19,8 @@ struct sIPStackBuffer
                const void      *Data;
                size_t  PreLength;
                size_t  PostLength;
+               tIPStackBufferCb        Cb;
+               void    *CbArg;
                // TODO: Callbacks?
        } SubBuffers[];
 };
@@ -36,11 +38,27 @@ tIPStackBuffer *IPStack_Buffer_CreateBuffer(int MaxBuffers)
        return ret;
 }
 
-void IPStack_Buffer_DestroyBuffer(tIPStackBuffer *Buffer)
+void IPStack_Buffer_ClearBuffer(tIPStackBuffer *Buffer)
 {
+       for( int i = 0; i < Buffer->nSubBuffers; i ++ )
+       {
+               if( Buffer->SubBuffers[i].Cb == NULL )
+                       continue ;
+               Buffer->SubBuffers[i].Cb(
+                       Buffer->SubBuffers[i].CbArg,
+                       Buffer->SubBuffers[i].PreLength,
+                       Buffer->SubBuffers[i].PostLength,
+                       Buffer->SubBuffers[i].Data
+                       );
+       }
        // TODO: Fire callbacks?
-       Buffer->MaxSubBufffers = 0;
        Buffer->nSubBuffers = 0;
+}
+
+void IPStack_Buffer_DestroyBuffer(tIPStackBuffer *Buffer)
+{
+       IPStack_Buffer_ClearBuffer(Buffer);
+       Buffer->MaxSubBufffers = 0;
        free(Buffer);
 }
 
@@ -62,6 +80,8 @@ void IPStack_Buffer_AppendSubBuffer(tIPStackBuffer *Buffer,
        Buffer->SubBuffers[index].Data = Data;
        Buffer->SubBuffers[index].PreLength = HeaderLen;
        Buffer->SubBuffers[index].PostLength = FooterLen;
+       Buffer->SubBuffers[index].Cb = Cb;
+       Buffer->SubBuffers[index].CbArg = Arg;
 }
 
 size_t IPStack_Buffer_GetLength(tIPStackBuffer *Buffer)
@@ -69,9 +89,43 @@ size_t IPStack_Buffer_GetLength(tIPStackBuffer *Buffer)
        return Buffer->TotalLength;
 }
 
+size_t IPStack_Buffer_GetData(tIPStackBuffer *Buffer, void *Dest, size_t MaxBytes)
+{
+       Uint8   *dest = Dest;
+       size_t  rem_space = MaxBytes;
+       size_t  len;
+       
+       for( int i = Buffer->nSubBuffers; i -- && rem_space != 0; )
+       {
+               len = MIN(Buffer->SubBuffers[i].PreLength, rem_space);
+               memcpy(dest,
+                       Buffer->SubBuffers[i].Data,
+                       len
+                       );
+               dest += len;
+               rem_space -= len;
+       }
+       for( int i = 0; i < Buffer->nSubBuffers && rem_space; i ++ )
+       {
+               if( Buffer->SubBuffers[i].PostLength == 0  )
+                       continue ;
+               
+               len = MIN(Buffer->SubBuffers[i].PostLength, rem_space);
+               memcpy(dest,
+                       (Uint8*)Buffer->SubBuffers[i].Data + Buffer->SubBuffers[i].PreLength,
+                       len
+                       );
+               dest += len;
+               rem_space -= len;
+       }
+       
+       return MaxBytes - rem_space;
+}
+
 void *IPStack_Buffer_CompactBuffer(tIPStackBuffer *Buffer, size_t *Length)
 {
        void    *ret;
+       
        ret = malloc(Buffer->TotalLength);
        if(!ret) {
                *Length = 0;
@@ -79,27 +133,9 @@ void *IPStack_Buffer_CompactBuffer(tIPStackBuffer *Buffer, size_t *Length)
        }
        
        *Length = Buffer->TotalLength;
-       
-       Uint8   *dest = ret;
-       for( int i = Buffer->nSubBuffers; i --; )
-       {
-               memcpy(dest,
-                       Buffer->SubBuffers[i].Data,
-                       Buffer->SubBuffers[i].PreLength
-                       );
-               dest += Buffer->SubBuffers[i].PreLength;
-       }
-       for( int i = 0; i < Buffer->nSubBuffers; i ++ )
-       {
-               if( Buffer->SubBuffers[i].PostLength )
-               {
-                       memcpy(dest,
-                               (Uint8*)Buffer->SubBuffers[i].Data + Buffer->SubBuffers[i].PreLength,
-                               Buffer->SubBuffers[i].PostLength
-                               );
-                       dest += Buffer->SubBuffers[i].PreLength;
-               }
-       }
+
+       IPStack_Buffer_GetData(Buffer, ret, Buffer->TotalLength);
+
        return ret;
 }
 
diff --git a/KernelLand/Modules/IPStack/include/adapters.h b/KernelLand/Modules/IPStack/include/adapters.h
new file mode 100644 (file)
index 0000000..768fd9e
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Acess2 Networking Stack
+ * - By John Hodge (thePowersGang)
+ *
+ * adapters.h
+ * - Network Adapter Management (IPStack Internal)
+ */
+#ifndef _IPSTACK__ADAPTERS_H_
+#define _IPSTACK__ADAPTERS_H_
+
+#include "adapters_api.h"
+
+extern tAdapter        *Adapter_GetByName(const char *Name);
+extern void    Adapter_SendPacket(tAdapter *Handle, tIPStackBuffer *Buffer);
+
+
+#endif
+
diff --git a/KernelLand/Modules/IPStack/include/adapters_api.h b/KernelLand/Modules/IPStack/include/adapters_api.h
new file mode 100644 (file)
index 0000000..0ecd847
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Acess2 Networking Stack
+ * - By John Hodge (thePowersGang)
+ *
+ * adapters_api.h
+ * - Network Adapter Management (API Header)
+ */
+#ifndef _IPSTACK__ADAPTERS_API_H_
+#define _IPSTACK__ADAPTERS_API_H_
+
+#include "buffer.h"
+
+typedef struct sIPStack_AdapterType tIPStack_AdapterType;
+
+struct sIPStack_AdapterType
+{
+        int    Type;
+       Uint    Flags;
+       const char      *Name;
+       
+        int    (*SendPacket)(void *Card, tIPStackBuffer *Buffer);
+       tIPStackBuffer  *(*WaitForPacket)(void *Card);
+};
+
+extern void    *IPStack_Adapter_Add(const tIPStack_AdapterType *Type, void *Ptr, const void *HWAddr);
+extern void    IPStack_Adapter_Del(void *Handle);
+
+#endif
+
diff --git a/KernelLand/Modules/IPStack/include/adapters_int.h b/KernelLand/Modules/IPStack/include/adapters_int.h
new file mode 100644 (file)
index 0000000..c474818
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Acess2 Networking Stack
+ * - By John Hodge (thePowersGang)
+ *
+ * adapters_int.h
+ * - Network Adapter Management (API Header)
+ */
+#ifndef _IPSTACK__ADAPTERS_INT_H_
+#define _IPSTACK__ADAPTERS_INT_H_
+
+#include "adapters.h"
+#include "adapters_api.h"
+
+struct sAdapter
+{
+       struct sAdapter *Next;
+
+        int    RefCount;
+        int    Index;
+       
+       const tIPStack_AdapterType      *Type;
+       void    *CardHandle;    
+
+       tVFS_Node       Node;
+
+       char    HWAddr[];
+};
+
+extern void    Adapter_SendPacket(tAdapter *Handle, tIPStackBuffer *Buffer);
+extern void    Adapter_Watch(tAdapter *Handle);
+
+#endif
+
index 62c1308..ad0516a 100644 (file)
@@ -15,6 +15,10 @@ typedef void (*tIPStackBufferCb)(void *Arg, size_t HeadLen, size_t FootLen, cons
  * \brief Create a buffer object, with space for \a MaxSubBuffers calls to IPStack_Buffer_AppendSubBuffer
  */
 extern tIPStackBuffer  *IPStack_Buffer_CreateBuffer(int MaxSubBuffers);
+/**
+ * \brief Clear a buffer object without deallocating it
+ */
+extern void    IPStack_Buffer_ClearBuffer(tIPStackBuffer *Buffer);
 /**
  * \brief Destory a created buffer object
  */
@@ -38,6 +42,15 @@ extern void  IPStack_Buffer_AppendSubBuffer(tIPStackBuffer *Buffer,
  * \brief Get the total length of a buffer
  */
 extern size_t  IPStack_Buffer_GetLength(tIPStackBuffer *Buffer);
+
+/**
+ * \brief Copy data from a buffer to a preallocated flat buffer
+ * \param Dest Destination flat buffer
+ * \param MaxBytes     Maximum number of bytes to copy (size of \a Dest)
+ * \return Number of bytes copied
+ */
+extern size_t  IPStack_Buffer_GetData(tIPStackBuffer *Buffer, void *Dest, size_t MaxBytes);
+
 /**
  * \brief Get a sub-buffer from the buffer object
  * \param PrevID       Previous return value, or -1 to start
index b0b63b9..9ff3f17 100644 (file)
@@ -7,7 +7,7 @@
 #include "ipstack.h"
 #include "link.h"
 #include <api_drv_common.h>
-#include <api_drv_network.h>
+#include "include/adapters.h"
 
 // === CONSTANTS ===
 //! Default timeout value, 30 seconds
@@ -17,6 +17,7 @@
 extern int     IPv4_Ping(tInterface *Iface, tIPv4 Addr);
 //extern int   IPv6_Ping(tInterface *Iface, tIPv6 Addr);
 extern tVFS_Node       gIP_RouteNode;
+extern tVFS_Node       gIP_AdaptersNode;
 
 // === PROTOTYPES ===
 char   *IPStack_Root_ReadDir(tVFS_Node *Node, int Pos);
@@ -25,7 +26,6 @@ tVFS_Node     *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name);
 
  int   IPStack_AddFile(tSocketFile *File);
 tInterface     *IPStack_AddInterface(const char *Device, const char *Name);
-tAdapter       *IPStack_GetAdapter(const char *Path);
 
 char   *IPStack_Iface_ReadDir(tVFS_Node *Node, int Pos);
 tVFS_Node      *IPStack_Iface_FindDir(tVFS_Node *Node, const char *Name);
@@ -53,17 +53,10 @@ tInterface  gIP_LoopInterface = {
 tShortSpinlock glIP_Interfaces;
 tInterface     *gIP_Interfaces = NULL;
 tInterface     *gIP_Interfaces_Last = NULL;
+ int   giIP_NextIfaceId = 1;
 
 tSocketFile    *gIP_FileTemplates;
 
-tAdapter       gIP_LoopAdapter = {
-       .DeviceLen = 8,
-       .Device = "LOOPBACK"
-       };
-tMutex glIP_Adapters;
-tAdapter       *gIP_Adapters = NULL;
- int   giIP_NextIfaceId = 1;
-
 // === CODE ===
 
 /**
@@ -81,12 +74,17 @@ char *IPStack_Root_ReadDir(tVFS_Node *Node, int Pos)
                LEAVE('s', "routes");
                return strdup("routes");
        }
-       // Pseudo Interfaces
+       // Adapters
        if( Pos == 1 ) {
+               LEAVE('s', "adapters");
+               return strdup("adapters");
+       }
+       // Pseudo Interfaces
+       if( Pos == 2 ) {
                LEAVE('s', "lo");
                return strdup("lo");
        }
-       Pos -= 2;
+       Pos -= 3;
        
        // Traverse the list
        for( iface = gIP_Interfaces; iface && Pos--; iface = iface->Next ) ;
@@ -145,6 +143,12 @@ tVFS_Node *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name)
                return &gIP_RouteNode;
        }
        
+       // Adapters subdir
+       if( strcmp(Name, "adapters") == 0 ) {
+               LEAVE('p', &gIP_AdaptersNode);
+               return &gIP_AdaptersNode;
+       }
+       
        // Loopback
        if( strcmp(Name, "lo") == 0 ) {
                LEAVE('p', &gIP_LoopInterface.Node);
@@ -210,7 +214,7 @@ tInterface *IPStack_AddInterface(const char *Device, const char *Name)
        
        ENTER("sDevice", Device);
        
-       card = IPStack_GetAdapter(Device);
+       card = Adapter_GetByName(Device);
        if( !card ) {
                Log_Debug("IPStack", "Unable to open card '%s'", Device);
                LEAVE('n');
@@ -436,14 +440,15 @@ int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data)
         * - Gets the name of the attached device
         */
        case 8:
-               if( iface->Adapter == NULL )
+               Log_Error("IPStack", "TODO: Reimplement interface.ioctl(get_device)");
+//             if( iface->Adapter == NULL )
                        LEAVE_RET('i', 0);
-               if( Data == NULL )
-                       LEAVE_RET('i', iface->Adapter->DeviceLen);
-               if( !CheckMem( Data, iface->Adapter->DeviceLen+1 ) )
-                       LEAVE_RET('i', -1);
-               strcpy( Data, iface->Adapter->Device );
-               LEAVE_RET('i', iface->Adapter->DeviceLen);
+//             if( Data == NULL )
+//                     LEAVE_RET('i', iface->Adapter->DeviceLen);
+//             if( !CheckMem( Data, iface->Adapter->DeviceLen+1 ) )
+//                     LEAVE_RET('i', -1);
+//             strcpy( Data, iface->Adapter->Device );
+//             LEAVE_RET('i', iface->Adapter->DeviceLen);
        
        /*
         * ping
@@ -471,109 +476,3 @@ int IPStack_Iface_IOCtl(tVFS_Node *Node, int ID, void *Data)
        return 0;
 }
 
-// --- Internal ---
-/**
- * \fn tAdapter *IPStack_GetAdapter(const char *Path)
- * \brief Gets/opens an adapter given the path
- */
-tAdapter *IPStack_GetAdapter(const char *Path)
-{
-       tAdapter        *dev;
-        int    tmp;
-       
-       ENTER("sPath", Path);
-       
-       // Check for loopback
-       if( strcmp(Path, "LOOPBACK") == 0 )
-       {
-               // Initialise if required
-               if( gIP_LoopAdapter.DeviceFD == 0 )
-               {
-                       dev = &gIP_LoopAdapter;
-                       
-                       dev->NRef = 1;
-                       dev->DeviceLen = 8;
-                       
-                       dev->DeviceFD = VFS_Open( "/Devices/fifo/anon", VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE );
-                       if( dev->DeviceFD == -1 ) {
-                               Log_Warning("IPStack", "Unable to open FIFO '/Devices/fifo/anon' for loopback");
-                               return NULL;
-                       }
-                       
-                       dev->MacAddr.B[0] = 'A';
-                       dev->MacAddr.B[1] = 'c';
-                       dev->MacAddr.B[2] = 'e';
-                       dev->MacAddr.B[3] = 's';
-                       dev->MacAddr.B[4] = 's';
-                       dev->MacAddr.B[5] = '2';
-                       
-                       // Start watcher
-                       Link_WatchDevice( dev );
-               }
-               LEAVE('p', &gIP_LoopAdapter);
-               return &gIP_LoopAdapter;
-       }
-       
-       Mutex_Acquire( &glIP_Adapters );
-       
-       // Check if this adapter is already open
-       for( dev = gIP_Adapters; dev; dev = dev->Next )
-       {
-               if( strcmp(dev->Device, Path) == 0 ) {
-                       dev->NRef ++;
-                       Mutex_Release( &glIP_Adapters );
-                       LEAVE('p', dev);
-                       return dev;
-               }
-       }
-       
-       // Ok, so let's open it
-       dev = malloc( sizeof(tAdapter) + strlen(Path) + 1 );
-       if(!dev) {
-               Log_Warning("IPStack", "GetAdapter - malloc() failed");
-               Mutex_Release( &glIP_Adapters );
-               LEAVE('n');
-               return NULL;
-       }
-       
-       // Fill Structure
-       strcpy( dev->Device, Path );
-       dev->NRef = 1;
-       dev->DeviceLen = strlen(Path);
-       
-       // Open Device
-       dev->DeviceFD = VFS_Open( dev->Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE );
-       if( dev->DeviceFD == -1 ) {
-               free( dev );
-               Mutex_Release( &glIP_Adapters );
-               LEAVE('n');
-               return NULL;
-       }
-       
-       // Check that it is a network interface
-       tmp = VFS_IOCtl(dev->DeviceFD, 0, NULL);
-       LOG("Device type = %i", tmp);
-       if( tmp != DRV_TYPE_NETWORK ) {
-               Log_Warning("IPStack", "IPStack_GetAdapter: '%s' is not a network interface", dev->Device);
-               VFS_Close( dev->DeviceFD );
-               free( dev );
-               Mutex_Release( &glIP_Adapters );
-               LEAVE('n');
-               return NULL;
-       }
-       
-       // Get MAC Address
-       VFS_IOCtl(dev->DeviceFD, NET_IOCTL_GETMAC, &dev->MacAddr);
-       
-       // Add to list
-       dev->Next = gIP_Adapters;
-       gIP_Adapters = dev;
-       
-       Mutex_Release( &glIP_Adapters );
-       
-       // Start watcher
-       Link_WatchDevice( dev );
-       
-       LEAVE('p', dev);
-       return dev;
-}
index e51fded..5ea5dc9 100644 (file)
@@ -71,6 +71,7 @@ struct sInterface {
        char    Name[];
 };
 
+#if 0
 /**
  * \brief Represents a network adapter
  */
@@ -84,6 +85,7 @@ struct sAdapter {
         int    DeviceLen;      //!< Device name length
        char    Device[];       //!< Device name
 };
+#endif
 
 /**
  * \brief Describes a socket file definition
index d5c2f96..3162301 100644 (file)
@@ -15,6 +15,7 @@ extern tInterface     *gIP_Interfaces;
 extern void    ICMP_Initialise();
 extern  int    ICMP_Ping(tInterface *Interface, tIPv4 Addr);
 extern tMacAddr        ARP_Resolve4(tInterface *Interface, tIPv4 Address);
+extern void    ARP_UpdateCache4(tIPv4 SWAddr, tMacAddr HWAddr);
 
 // === PROTOTYPES ===
  int   IPv4_Initialise();
@@ -185,6 +186,9 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff
                hdr->Source.B[0], hdr->Source.B[1], hdr->Source.B[2], hdr->Source.B[3],
                hdr->Destination.B[0], hdr->Destination.B[1], hdr->Destination.B[2], hdr->Destination.B[3]
                );
+
+       // TODO: Tell ARP?
+       ARP_UpdateCache4(hdr->Source, From);
        
        // Get Data and Data Length
        dataLength = ntohs(hdr->TotalLength) - sizeof(tIPv4Header);
index 37b7260..3dcd294 100644 (file)
@@ -1,10 +1,15 @@
 /*
- * Acess2 IP Stack
- * - Link/Media Layer Interface
+ * Acess2 Networking Stack
+ * - By John Hodge (thePowersGang)
+ *
+ * link.c
+ * - Ethernet/802.3 Handling code
+ * TODO: Rename file
  */
 #include "ipstack.h"
 #include "link.h"
 #include "include/buffer.h"
+#include "include/adapters_int.h"
 
 // === CONSTANTS ===
 #define        MAX_PACKET_SIZE 2048
@@ -12,7 +17,7 @@
 // === PROTOTYPES ===
 void   Link_RegisterType(Uint16 Type, tPacketCallback Callback);
 void   Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, tIPStackBuffer *Buffer);
-void   Link_WatchDevice(tAdapter *Adapter);
+ int   Link_HandlePacket(tAdapter *Adapter, tIPStackBuffer *Buffer);
 // --- CRC ---
 void   Link_InitCRC(void);
 Uint32 Link_CalculateCRC(tIPStackBuffer *Buffer);
@@ -87,7 +92,7 @@ void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, tIPStackBuffer
                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;
+       memcpy(&hdr->Src, Adapter->HWAddr, 6);  // TODO: Remove hard coded 6
        hdr->Type = htons(Type);
        *(Uint32*)(buf + sizeof(tEthernetHeader) + ofs) = 0;
 
@@ -95,95 +100,67 @@ void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, tIPStackBuffer
        
        *(Uint32*)(buf + sizeof(tEthernetHeader) + ofs) = htonl( Link_CalculateCRC(Buffer) );
 
-       size_t outlen = 0;
-       void *data = IPStack_Buffer_CompactBuffer(Buffer, &outlen);
-       VFS_Write(Adapter->DeviceFD, outlen, data);
-       free(data);
+       Log_Log("Net Link", " 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]
+               );
+
+       Adapter_SendPacket(Adapter, Buffer);
 }
 
-void Link_WorkerThread(void *Ptr)
+int Link_HandlePacket(tAdapter *Adapter, tIPStackBuffer *Buffer)
 {
-       tAdapter        *Adapter = Ptr;
+       size_t  len = 0;
+       void    *data = IPStack_Buffer_CompactBuffer(Buffer, &len);
        
-       Threads_SetName(Adapter->Device);
-       Log_Log("Net Link", "Thread %i watching '%s'", Threads_GetTID(), Adapter->Device);
+       tEthernetHeader *hdr = (void*)data;
+        int    i;
+       Uint32  checksum;
 
-       // 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)
-               //Log_Debug("NET", "Waiting on adapter FD#0x%x", Adapter->DeviceFD);
-               ret = VFS_Read(Adapter->DeviceFD, MAX_PACKET_SIZE, buf);
-               if(ret == -1)   break;
-               
-               if(ret < sizeof(tEthernetHeader)) {
-                       Log_Log("Net Link", "Recieved an undersized packet (%i < %i)",
-                               ret, sizeof(tEthernetHeader));
-                       continue;
-               }
-               
-               Log_Log("Net Link",
-                       "Packet from %02x:%02x:%02x:%02x:%02x:%02x"
-                       " to %02x:%02x:%02x:%02x:%02x:%02x (Type=%04x)",
-                       hdr->Src.B[0], hdr->Src.B[1], hdr->Src.B[2],
-                       hdr->Src.B[3], hdr->Src.B[4], hdr->Src.B[5],
-                       hdr->Dest.B[0], hdr->Dest.B[1], hdr->Dest.B[2],
-                       hdr->Dest.B[3], hdr->Dest.B[4], hdr->Dest.B[5],
-                       ntohs(hdr->Type)
-                       );
-               checksum = *(Uint32*)&hdr->Data[ret-sizeof(tEthernetHeader)-4];
-               //Log_Log("NET", "Checksum 0x%08x", checksum);
-               // TODO: Check checksum
+       if(len < sizeof(tEthernetHeader)) {
+               Log_Log("Net Link", "Recieved an undersized packet (%i < %i)",
+                       len, sizeof(tEthernetHeader));
+               free(data);
+               return 1;
+       }
                
-               // Check if there is a registered callback for this packet type
-               for( i = giRegisteredTypes; i--; )
-               {
-                       if(gaRegisteredTypes[i].Type == ntohs(hdr->Type))       break;
-               }
-               // No? Ignore it
-               if( i == -1 ) {
-                       Log_Log("Net Link", "Unregistered type 0x%x", ntohs(hdr->Type));
-                       continue;
-               }
+       Log_Log("Net Link",
+               "Packet from %02x:%02x:%02x:%02x:%02x:%02x"
+               " to %02x:%02x:%02x:%02x:%02x:%02x (Type=%04x)",
+               hdr->Src.B[0], hdr->Src.B[1], hdr->Src.B[2],
+               hdr->Src.B[3], hdr->Src.B[4], hdr->Src.B[5],
+               hdr->Dest.B[0], hdr->Dest.B[1], hdr->Dest.B[2],
+               hdr->Dest.B[3], hdr->Dest.B[4], hdr->Dest.B[5],
+               ntohs(hdr->Type)
+               );
+       checksum = *(Uint32*)&hdr->Data[len-sizeof(tEthernetHeader)-4];
+       //Log_Log("NET", "Checksum 0x%08x", checksum);
+       // TODO: Check checksum
+       
+       // Check if there is a registered callback for this packet type
+       for( i = giRegisteredTypes; i--; )
+       {
+               if(gaRegisteredTypes[i].Type == ntohs(hdr->Type))       break;
+       }
+       // No? Ignore it
+       if( i == -1 ) {
+               Log_Log("Net Link", "Unregistered type 0x%x", ntohs(hdr->Type));
                
-               // Call the callback
-               gaRegisteredTypes[i].Callback(
-                       Adapter,
-                       hdr->Src,
-                       ret - sizeof(tEthernetHeader),
-                       hdr->Data
-                       );
+               free(data);     
+               return 1;
        }
        
-       Log_Log("Net Link", "Watcher terminated (file closed)");
-       
-       Threads_Exit(0, 0);
-}
-
-/**
- * \fn void Link_WatchDevice(tAdapter *Adapter)
- * \brief Spawns a worker thread to watch the specified adapter
- */
-void Link_WatchDevice(tAdapter *Adapter)
-{
-        int    tid;
-
-       if( !gbLink_CRCTableGenerated )
-               Link_InitCRC();
-       
-       tid = Proc_SpawnWorker(Link_WorkerThread, Adapter);     // Create a new worker thread
+       // Call the callback
+       gaRegisteredTypes[i].Callback(
+               Adapter,
+               hdr->Src,
+               len - sizeof(tEthernetHeader),
+               hdr->Data
+               );
        
-       if(tid < 0) {
-               Log_Warning("Net Link", "Unable to create watcher thread for '%s'", Adapter->Device);
-               return ;
-       }
+       free(data);
        
-       Log_Log("Net Link", "Watching '%s' using tid %i", Adapter->Device, tid);
+       return 0;
 }
 
 // From http://www.cl.cam.ac.uk/research/srg/bluebook/21/crc/node6.html
index bdea0e2..ac07342 100644 (file)
@@ -12,6 +12,7 @@ typedef void (*tPacketCallback)(tAdapter *Interface, tMacAddr From, int Length,
 
 extern void    Link_RegisterType(Uint16 Type, tPacketCallback Callback);
 extern void    Link_SendPacket(tAdapter *Interface, Uint16 Type, tMacAddr To, tIPStackBuffer *Buffer);
+extern int     Link_HandlePacket(tAdapter *Adapter, tIPStackBuffer *Buffer);
 extern void    Link_WatchDevice(tAdapter *Adapter);
 
 // === INTERNAL ===
index d5d1ebc..3aecfb3 100644 (file)
@@ -8,6 +8,7 @@
 #include "link.h"
 #include <modules.h>
 #include <fs_devfs.h>
+#include "include/adapters.h"
 
 // === IMPORTS ===
 extern int     ARP_Initialise();
@@ -16,7 +17,6 @@ extern void   TCP_Initialise();
 extern int     IPv4_Initialise();
 extern int     IPv6_Initialise();
 
-extern tAdapter        *IPStack_GetAdapter(const char *Path);
 extern char    *IPStack_Root_ReadDir(tVFS_Node *Node, int Pos);
 extern tVFS_Node       *IPStack_Root_FindDir(tVFS_Node *Node, const char *Name);
 extern int     IPStack_Root_IOCtl(tVFS_Node *Node, int ID, void *Data);
@@ -192,7 +192,7 @@ int IPStack_Install(char **Arguments)
        }
        
        // Initialise loopback interface
-       gIP_LoopInterface.Adapter = IPStack_GetAdapter("LOOPBACK");
+       gIP_LoopInterface.Adapter = Adapter_GetByName("lo");
        
        DevFS_AddDevice( &gIP_DriverInfo );
        
index 7173d1f..c4b5392 100644 (file)
@@ -27,6 +27,7 @@ tRoute        *_Route_FindExactRoute(int Type, void *Network, int Subnet, int Metric);
 // - Route Management
 tRoute *IPStack_Route_Create(int AddrType, void *Network, int SubnetBits, int Metric);
 tRoute *IPStack_AddRoute(const char *Interface, void *Network, int SubnetBits, void *NextHop, int Metric);
+tRoute *_Route_FindInterfaceRoute(int AddressType, void *Address);
 tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address);
 // - Individual Routes
  int   IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data);
@@ -112,17 +113,25 @@ tVFS_Node *IPStack_RouteDir_FindDir(tVFS_Node *Node, const char *Name)
                rt = IPStack_FindRoute(type, NULL, addrData);
                if(!rt) return NULL;
        
-               if( rt->Interface )
+               if( !rt->Interface )
                {       
-                       // Return the interface node
-                       // - Sure it's hijacking it from inteface.c's area, but it's
-                       //   simpler this way
-                       return &rt->Interface->Node;
+                       LOG("Why does this route not have a node? trying to find an iface for the next hop");
+
+                       rt = _Route_FindInterfaceRoute(type, rt->NextHop);
+                       if(!rt) {
+                               Log_Notice("Cannot find route to next hop '%s'",
+                                       IPStack_PrintAddress(type, rt->NextHop));
+                               return NULL;
+                       }
                }
-               else
-               {
+               if( !rt->Interface ) {
+                       Log_Notice("Routes", "No interface for route %p, what the?", rt);
                        return NULL;
                }
+               // Return the interface node
+               // - Sure it's hijacking it from inteface.c's area, but it's
+               //   simpler this way
+               return &rt->Interface->Node;
        }
        else if( Name[0] == '#' )
        {
@@ -435,13 +444,56 @@ tRoute *IPStack_AddRoute(const char *Interface, void *Network, int SubnetBits, v
        return rt;
 }
 
+/**
+ * \brief Locates what interface should be used to get directly to an address
+ */
+tRoute *_Route_FindInterfaceRoute(int AddressType, void *Address)
+{
+       tRoute  *best = NULL, *rt;
+        int addrSize = IPStack_GetAddressSize(AddressType);
+       for( tInterface *iface = gIP_Interfaces; iface; iface = iface->Next )
+       {
+               if( iface->Type != AddressType )        continue;
+               
+               // Check if the address matches
+               if( !IPStack_CompareAddress(AddressType, iface->Address, Address, iface->SubnetBits) )
+                       continue;
+               
+               rt = &iface->Route;
+               if( !rt->Interface )
+               {
+                       memcpy(rt->Network, iface->Address, addrSize);
+                       memset(rt->NextHop, 0, addrSize);
+                       rt->Metric = DEFAUTL_METRIC;
+                       rt->SubnetBits = iface->SubnetBits;
+                       rt->Interface = iface;
+               }
+               
+               if( best ) {
+                       // More direct routes are preferred
+                       if( best->SubnetBits > rt->SubnetBits ) {
+                               LOG("Skipped - less direct (%i < %i)", rt->SubnetBits, best->SubnetBits);
+                               continue;
+                       }
+                       // If equally direct, choose the best metric
+                       if( best->SubnetBits == rt->SubnetBits && best->Metric < rt->Metric ) {
+                               LOG("Skipped - higher metric (%i > %i)", rt->Metric, best->Metric);
+                               continue;
+                       }
+               }
+               
+               best = rt;
+       }
+
+       return best;
+}
+
 /**
  */
 tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address)
 {
        tRoute  *rt;
        tRoute  *best = NULL;
-       tInterface      *iface;
         int    addrSize;
        
        ENTER("iAddressType pInterface sAddress",
@@ -460,7 +512,7 @@ tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address)
        for( rt = gIP_Routes; rt; rt = rt->Next )
        {
                // Check interface
-               if( Interface && rt->Interface != Interface )   continue;
+               if( Interface && rt->Interface && rt->Interface != Interface )  continue;
                // Check address type
                if( rt->AddressType != AddressType )    continue;
                
@@ -489,37 +541,7 @@ tRoute *IPStack_FindRoute(int AddressType, tInterface *Interface, void *Address)
        // Check against implicit routes
        if( !best && !Interface )
        {
-               for( iface = gIP_Interfaces; iface; iface = iface->Next )
-               {
-                       if( Interface && iface != Interface )   continue;
-                       if( iface->Type != AddressType )        continue;
-                       
-                       
-                       // Check if the address matches
-                       if( !IPStack_CompareAddress(AddressType, iface->Address, Address, iface->SubnetBits) )
-                               continue;
-                       
-                       if( best ) {
-                               // More direct routes are preferred
-                               if( best->SubnetBits > rt->SubnetBits ) {
-                                       LOG("Skipped - less direct (%i < %i)", rt->SubnetBits, best->SubnetBits);
-                                       continue;
-                               }
-                               // If equally direct, choose the best metric
-                               if( best->SubnetBits == rt->SubnetBits && best->Metric < rt->Metric ) {
-                                       LOG("Skipped - higher metric (%i > %i)", rt->Metric, best->Metric);
-                                       continue;
-                               }
-                       }
-                       
-                       rt = &iface->Route;
-                       memcpy(rt->Network, iface->Address, addrSize);
-                       memset(rt->NextHop, 0, addrSize);
-                       rt->Metric = DEFAUTL_METRIC;
-                       rt->SubnetBits = iface->SubnetBits;
-                       
-                       best = rt;
-               }
+               best = _Route_FindInterfaceRoute(AddressType, Address);
        }
        if( !best && Interface )
        {
@@ -559,6 +581,8 @@ int IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data)
 {
        tRoute  *rt = Node->ImplPtr;
         int    addrSize = IPStack_GetAddressSize(rt->AddressType);
+
+       ENTER("pNode iID pData", Node, ID, Data);
        
        switch(ID)
        {
@@ -567,57 +591,57 @@ int IPStack_Route_IOCtl(tVFS_Node *Node, int ID, void *Data)
        
        // Get Next Hop
        case 4:
-               if( !CheckMem(Data, addrSize) ) return -1;
+               if( !CheckMem(Data, addrSize) ) LEAVE_RET('i', -1);
                memcpy(Data, rt->NextHop, addrSize);
-               return 1;
+               LEAVE_RET('i', 1);
        // Set Next Hop
        case 5:
-               if( Threads_GetUID() != 0 )     return -1;
-               if( !CheckMem(Data, addrSize) ) return -1;
+               if( Threads_GetUID() != 0 )     LEAVE_RET('i', -1);
+               if( !CheckMem(Data, addrSize) ) LEAVE_RET('i', -1);
                memcpy(rt->NextHop, Data, addrSize);
-               return 1;
+               LEAVE_RET('i', 1);
 
        // Get interface name
        case 6:
                if( !rt->Interface ) {
                        if(Data && !CheckMem(Data, 1) )
-                               return -1;
+                               LEAVE_RET('i', -1);
                        if(Data)
                                *(char*)Data = 0;
-                       return 0;
+                       LEAVE_RET('i', 0);
                }
                if( Data ) {
                        if( !CheckMem(Data, strlen(rt->Interface->Name) + 1) )
-                               return -1;
+                               LEAVE_RET('i', -1);
                        strcpy(Data, rt->Interface->Name);
                }
-               return strlen(rt->Interface->Name);
+               LEAVE_RET('i', strlen(rt->Interface->Name));
        // Set interface name
        case 7:
                if( Threads_GetUID() != 0 )
-                       return -1;
+                       LEAVE_RET('i', -1);
                if( !CheckString(Data) )
-                       return -1;
+                       LEAVE_RET('i', -1);
                else
                {
                        tInterface      *iface;
                        tVFS_Node       *tmp;
                        tmp = IPStack_Root_FindDir(NULL, Data);
                        if(!tmp)
-                               return -1;
+                               LEAVE_RET('i', -1);
                        iface = tmp->ImplPtr;
                        if(tmp->Type->Close)    tmp->Type->Close(tmp);
                        
                        if( iface->Type != rt->AddressType )
-                               return -1;
+                               LEAVE_RET('i', -1);
 
                        // TODO: Other checks?          
        
                        rt->Interface = iface;
                }
-               return 0;
+               LEAVE_RET('i', 0);
 
        default:
-               return -1;
+               LEAVE_RET('i', -1);
        }
 }
index 01f5f1f..c8ea019 100644 (file)
@@ -1,16 +1,16 @@
-/* Acess2
- * NE2000 Driver
+/*
+ * Acess2 NE2000 Driver
+ * - By John Hodge (thePowersGang)
  * 
  * See: ~/Sources/bochs/bochs.../iodev/ne2k.cc
  */
 #define        DEBUG   1
-#define VERSION        ((0<<8)|50)
+#define VERSION        VER2(0,6)
 #include <acess.h>
 #include <modules.h>
-#include <fs_devfs.h>
 #include <drv_pci.h>
-#include <api_drv_network.h>
 #include <semaphore.h>
+#include <IPStack/include/adapters_api.h>
 
 // === CONSTANTS ===
 #define        MEM_START       0x40
@@ -76,18 +76,15 @@ typedef struct sNe2k_Card {
        
         int    NextMemPage;    //!< Next Card Memory page to use
                
-       char    Name[2];        // "0"
-       tVFS_Node       Node;   //!< VFS Node
+       void    *IPStackHandle;
        Uint8   MacAddr[6];     //!< Cached MAC address
 } tCard;
 
 // === PROTOTYPES ===
  int   Ne2k_Install(char **Arguments);
-char   *Ne2k_ReadDir(tVFS_Node *Node, int Pos);
-tVFS_Node      *Ne2k_FindDir(tVFS_Node *Node, const char *Name);
- int   Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data);
-size_t Ne2k_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
-size_t Ne2k_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
+
+ int   Ne2k_SendPacket(void *Ptr, tIPStackBuffer *Buffer);
+tIPStackBuffer *Ne2k_WaitForPacket(void *Ptr);
 
  int   Ne2k_int_ReadDMA(tCard *Card, int FirstPage, int NumPages, void *Buffer);
 Uint8  Ne2k_int_GetWritePage(tCard *Card, Uint16 Length);
@@ -95,26 +92,13 @@ void        Ne2k_IRQHandler(int IntNum, void *Ptr);
 
 // === GLOBALS ===
 MODULE_DEFINE(0, VERSION, Ne2k, Ne2k_Install, NULL, NULL);
-tVFS_NodeType  gNe2K_RootNodeType = {
-       .ReadDir = Ne2k_ReadDir,
-       .FindDir = Ne2k_FindDir,
-       .IOCtl = Ne2k_IOCtl
-       };
-tVFS_NodeType  gNe2K_DevNodeType = {
-       .Write = Ne2k_Write,
-       .Read = Ne2k_Read,
-       .IOCtl = Ne2k_IOCtl     
-       };
-tDevFS_Driver  gNe2k_DriverInfo = {
-       NULL, "ne2k",
-       {
-       .NumACLs = 1,
-       .ACLs = &gVFS_ACL_EveryoneRX,
-       .Flags = VFS_FFLAG_DIRECTORY,
-       .Type = &gNe2K_RootNodeType
-       }
+tIPStack_AdapterType   gNe2k_AdapterType = {
+       .Name = "Ne2k",
+       .Type = 0,      // TODO: Differentiate differnet wire protos and speeds
+       .Flags = 0,     // TODO: IP checksum offloading, MAC checksum offloading etc
+       .SendPacket = Ne2k_SendPacket,
+       .WaitForPacket = Ne2k_WaitForPacket
 };
-Uint16 gNe2k_BaseAddress;
  int   giNe2k_CardCount = 0;
 tCard  *gpNe2k_Cards = NULL;
 
@@ -136,8 +120,9 @@ int Ne2k_Install(char **Options)
        {
                giNe2k_CardCount += PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device );
        }
-       
        if( giNe2k_CardCount == 0 )     return MODULE_ERR_NOTNEEDED;
+
+       LOG("%i NE2K cards found", giNe2k_CardCount);
        
        // Enumerate Cards
        k = 0;
@@ -146,24 +131,35 @@ int Ne2k_Install(char **Options)
        for( i = 0; i < NUM_COMPAT_DEVICES; i ++ )
        {
                count = PCI_CountDevices( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device );
-               for( j = 0; j < count; j ++,k ++ )
+               for( j = 0; j < count; j ++, k ++ )
                {
+                       tCard   *card = &gpNe2k_Cards[k];
+                       
                        id = PCI_GetDevice( csaCOMPAT_DEVICES[i].Vendor, csaCOMPAT_DEVICES[i].Device, j );
                        // Create Structure
                        base = PCI_GetBAR( id, 0 );
-                       gpNe2k_Cards[ k ].IOBase = base;
-                       gpNe2k_Cards[ k ].IRQ = PCI_GetIRQ( id );
-                       gpNe2k_Cards[ k ].NextMemPage = 64;
-                       gpNe2k_Cards[ k ].NextRXPage = RX_FIRST;
+                       LOG("%i: %i/%i id = %i, base = 0x%x", k, i, j, id, base);
+                       if( !(base & 1) ) {
+                               Log_Warning("Ne2k", "PCI %i's BARs are incorrect (BAR0 is not IO)", id);
+                               continue ;
+                       }
+                       base &= ~1;
+                       card->IOBase = base;
+                       card->IRQ = PCI_GetIRQ( id );
+                       card->NextMemPage = 64;
+                       card->NextRXPage = RX_FIRST;
                        
                        // Install IRQ Handler
-                       IRQ_AddHandler(gpNe2k_Cards[ k ].IRQ, Ne2k_IRQHandler, &gpNe2k_Cards[k]);
+                       IRQ_AddHandler(card->IRQ, Ne2k_IRQHandler, &gpNe2k_Cards[k]);
+                       LOG("%i: IRQ %i mapped, IOBase = 0x%x", k, card->IRQ, card->IOBase);
                        
                        // Reset Card
                        outb( base + 0x1F, inb(base + 0x1F) );
-                       while( (inb( base+ISR ) & 0x80) == 0 );
+                       while( (inb( base + ISR ) & 0x80) == 0 );
                        outb( base + ISR, 0x80 );
-                       
+               
+                       LOG("Reset done");
+       
                        // Initialise Card
                        outb( base + CMD, 0x40|0x21 );  // Page 1, No DMA, Stop
                        outb( base + CURR, RX_FIRST );  // Current RX page
@@ -180,12 +176,12 @@ int Ne2k_Install(char **Options)
                        outb( base + RSAR0, 0 );        // Clear Source Address
                        outb( base + RSAR1, 0 );
                        outb( base + CMD, 0x0A );       // Remote Read, Start
-                       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);
+                       card->MacAddr[0] = inb(base+0x10);//    inb(base+0x10);
+                       card->MacAddr[1] = inb(base+0x10);//    inb(base+0x10);
+                       card->MacAddr[2] = inb(base+0x10);//    inb(base+0x10);
+                       card->MacAddr[3] = inb(base+0x10);//    inb(base+0x10);
+                       card->MacAddr[4] = inb(base+0x10);//    inb(base+0x10);
+                       card->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
@@ -198,111 +194,49 @@ int Ne2k_Install(char **Options)
                        outb( base+TPSR, 0x40); // Set Transmit Start
                        
                        Log_Log("Ne2k", "Card %i 0x%04x IRQ%i %02x:%02x:%02x:%02x:%02x:%02x",
-                               k, base, gpNe2k_Cards[ k ].IRQ,
-                               gpNe2k_Cards[k].MacAddr[0], gpNe2k_Cards[k].MacAddr[1],
-                               gpNe2k_Cards[k].MacAddr[2], gpNe2k_Cards[k].MacAddr[3],
-                               gpNe2k_Cards[k].MacAddr[4], gpNe2k_Cards[k].MacAddr[5]
+                               k, base, card->IRQ,
+                               card->MacAddr[0], card->MacAddr[1],
+                               card->MacAddr[2], card->MacAddr[3],
+                               card->MacAddr[4], card->MacAddr[5]
                                );
                        
-                       // Set VFS Node
-                       gpNe2k_Cards[ k ].Name[0] = '0'+k;
-                       gpNe2k_Cards[ k ].Name[1] = '\0';
-                       gpNe2k_Cards[ k ].Node.ImplPtr = &gpNe2k_Cards[ k ];
-                       gpNe2k_Cards[ k ].Node.NumACLs = 0;     // Root Only
-                       gpNe2k_Cards[ k ].Node.CTime = now();
-                       gpNe2k_Cards[ k ].Node.Type = &gNe2K_DevNodeType;
+                       card->IPStackHandle = IPStack_Adapter_Add(&gNe2k_AdapterType, card, card->MacAddr);
                        
                        // Initialise packet semaphore
                        // - Start at zero, no max
-                       Semaphore_Init( &gpNe2k_Cards[k].Semaphore, 0, 0, "NE2000", gpNe2k_Cards[ k ].Name );
+                       char    name[10];
+                       sprintf(name, "%i", k-1);
+                       Semaphore_Init( &card->Semaphore, 0, 0, "NE2000", name );
                }
        }
        
-       gNe2k_DriverInfo.RootNode.Size = giNe2k_CardCount;
-       DevFS_AddDevice( &gNe2k_DriverInfo );
        return MODULE_ERR_OK;
 }
 
-/**
- * \fn char *Ne2k_ReadDir(tVFS_Node *Node, int Pos)
- */
-char *Ne2k_ReadDir(tVFS_Node *Node, int Pos)
-{
-       char    ret[2];
-       if(Pos < 0 || Pos >= giNe2k_CardCount)  return NULL;
-       ret[0] = '0'+Pos;
-       ret[1] = '\0';
-       return strdup(ret);
-}
-
-/**
- * \fn tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, const char *Name)
- */
-tVFS_Node *Ne2k_FindDir(tVFS_Node *Node, const char *Name)
-{
-       if(Name[0] == '\0' || Name[1] != '\0')  return NULL;
-       
-       return &gpNe2k_Cards[ Name[0]-'0' ].Node;
-}
-
-static const char *casIOCtls[] = { DRV_IOCTLNAMES, DRV_NETWORK_IOCTLNAMES, NULL };
-/**
- * \fn int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data)
- * \brief IOCtl calls for a network device
- */
-int Ne2k_IOCtl(tVFS_Node *Node, int ID, void *Data)
-{
-       ENTER("pNode iID pData", Node, ID, Data);
-       switch( ID )
-       {
-       BASE_IOCTLS(DRV_TYPE_NETWORK, "NE2000", VERSION, casIOCtls);
-       }
-       
-       // If this is the root, return
-       if( Node == &gNe2k_DriverInfo.RootNode ) {
-               LEAVE('i', 0);
-               return 0;
-       }
-       
-       // Device specific settings
-       switch( ID )
-       {
-       case NET_IOCTL_GETMAC:
-               if( !CheckMem(Data, 6) ) {
-                       LEAVE('i', -1);
-                       return -1;
-               }
-               memcpy( Data, ((tCard*)Node->ImplPtr)->MacAddr, 6 );
-               LEAVE('i', 1);
-               return 1;
-       }
-       LEAVE('i', 0);
-       return 0;
-}
-
 /**
  * \brief Send a packet from the network card
  */
-size_t Ne2k_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
+int Ne2k_SendPacket(void *Ptr, tIPStackBuffer *Buffer)
 {
-       tCard   *Card = (tCard*)Node->ImplPtr;
-       const Uint16    *buf = Buffer;
-        int    rem = Length;
+       tCard   *Card = Ptr;
+        int    length;
         int    page;
        
-       ENTER("pNode XOffset xLength pBuffer", Node, Offset, Length, Buffer);
+       ENTER("pPtr pBuffer", Ptr, Buffer);
        
+       length = IPStack_Buffer_GetLength(Buffer);
+
        // TODO: Lock
        
        // Sanity Check Length
-       if(Length > TX_BUF_SIZE*256) {
+       if(length > TX_BUF_SIZE*256) {
                Log_Warning(
                        "Ne2k",
                        "Ne2k_Write - Attempting to send over TX_BUF_SIZE*256 (%i) bytes (%i)",
-                       TX_BUF_SIZE*256, Length
+                       TX_BUF_SIZE*256, length
                        );
-               LEAVE('i', 0);
-               return 0;
+               LEAVE('i', -1);
+               return -1;
        }
        
        // Make sure that the card is in page 0
@@ -312,23 +246,31 @@ size_t Ne2k_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buff
        outb(Card->IOBase + ISR, 0x40); // Bit 6
        
        // Send Size - Transfer Byte Count Register
-       outb(Card->IOBase + TBCR0, Length & 0xFF);
-       outb(Card->IOBase + TBCR1, Length >> 8);
+       outb(Card->IOBase + TBCR0, length & 0xFF);
+       outb(Card->IOBase + TBCR1, length >> 8);
        
        // Send Size - Remote Byte Count Register
-       outb(Card->IOBase + RBCR0, Length & 0xFF);
-       outb(Card->IOBase + RBCR1, Length >> 8);
+       outb(Card->IOBase + RBCR0, length & 0xFF);
+       outb(Card->IOBase + RBCR1, length >> 8);
        
        // Set up transfer
        outb(Card->IOBase + RSAR0, 0x00);       // Page Offset
-       page = Ne2k_int_GetWritePage(Card, Length);
+       page = Ne2k_int_GetWritePage(Card, length);
        outb(Card->IOBase + RSAR1, page);       // Page Offset
        // Start
        outb(Card->IOBase + CMD, 0|0x10|0x2);   // Page 0, Remote Write, Start
        
        // Send Data
-       for(rem = Length; rem > 0; rem -= 2) {
-               outw(Card->IOBase + 0x10, *buf++);
+       size_t  buflen;
+       const void      *bufptr;
+       for(int id = -1; (id = IPStack_Buffer_GetBuffer(Buffer, -1, &buflen, &bufptr)) != -1; )
+       {
+               const Uint16    *buf = bufptr;
+               if( buflen & 1 )
+                       Log_Notice("NE2000", "Alignment issue in TX buffer");
+               buflen = (buflen + 1) / 2;
+               while(buflen --)
+                       outw(Card->IOBase + 0x10, *buf++);
        }
        
        while( !(inb(Card->IOBase + ISR) & 0x40) )      // Wait for Remote DMA Complete
@@ -343,31 +285,39 @@ size_t Ne2k_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buff
        // Complete DMA
        //outb(Card->IOBase + CMD, 0|0x20);
        
-       LEAVE('i', Length);
-       return Length;
+       LEAVE('i', 0);
+       return 0;
+}
+
+void _FreeHeapSubBuf(void *Arg, size_t Pre, size_t Post, const void *DataBuf)
+{
+       free(Arg);
 }
 
 /**
  * \brief Wait for and read a packet from the network card
  */
-size_t Ne2k_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+tIPStackBuffer *Ne2k_WaitForPacket(void *Ptr)
 {
-       tCard   *Card = Node->ImplPtr;
+       tCard   *Card = Ptr;
        Uint8   page;
        Uint8   data[256];
+       void    *buf;
+       tIPStackBuffer  *ret;
        struct {
                Uint8   Status;
                Uint8   NextPacketPage;
                Uint16  Length; // Little Endian
        }       *pktHdr;
        
-       ENTER("pNode XOffset xLength pBuffer", Node, Offset, Length, Buffer);
+       ENTER("pPtr", Ptr);
        
        // Wait for packets
        if( Semaphore_Wait( &Card->Semaphore, 1 ) != 1 )
        {
                // Error or interrupted
-               LEAVE_RET('i', 0);
+               LEAVE('n');
+               return NULL;
        }
        
        outb(Card->IOBase, 0x22 | (1 << 6));    // Page 6
@@ -384,52 +334,60 @@ size_t Ne2k_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
        LOG("pktHdr->Status = 0x%x", pktHdr->Status);
        LOG("pktHdr->NextPacketPage = %i", pktHdr->NextPacketPage);
        LOG("pktHdr->Length = 0x%03x", pktHdr->Length);
-       
+
+       ret = IPStack_Buffer_CreateBuffer(1);
+       if(!ret)        LEAVE_RET('n', NULL);
+       buf = malloc( pktHdr->Length );
+       if(!buf)        LEAVE_RET('n', NULL);
+       IPStack_Buffer_AppendSubBuffer(ret, pktHdr->Length, 0, buf, _FreeHeapSubBuf, buf);
+
        // 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);
+               memcpy(buf, &data[4], pktHdr->Length);
        }
        // No? oh damn, now we need to allocate a buffer
        else
        {
                 int    pages = pktHdr->NextPacketPage - page;
-               char    *buf = malloc( pages*256 );
+               Uint8   *writepos = buf;
+                int    rem_bytes = pktHdr->Length;
                
                LOG("pktHdr->Length (%i) > 256 - 4, allocated buffer %p", pktHdr->Length, buf);
                
-               if(!buf)        LEAVE_RET('i', -1);
                
                // Copy the already read data
-               memcpy(buf, data, 256);
+               memcpy(writepos, data+4, 256-4);
+               writepos += 256-4;
+               rem_bytes -= 256-4;
                
                // Read all the needed pages
                page ++;
                if(page == RX_LAST+1)   page = RX_FIRST;
-               
-               if( page + pages > RX_LAST )
+
+               // - Body Pages
+               if( pages > 2 )
                {
-                        int    first_count = RX_LAST+1 - page;
-                        int    tmp = 0;
-                       tmp += Ne2k_int_ReadDMA(Card, page, first_count, buf+256);
-                       tmp += Ne2k_int_ReadDMA(Card, RX_FIRST, pages-1-first_count, buf+(first_count+1)*256);
-                       LOG("composite return count = %i", tmp);
+                       if( page + pages - 2 > RX_LAST )
+                       {
+                                int    first_count = RX_LAST - page + 1;
+                               Ne2k_int_ReadDMA(Card, page, first_count, writepos);
+                               Ne2k_int_ReadDMA(Card, RX_FIRST, pages-2-first_count, writepos + first_count*256);
+                               writepos += (pages-2-first_count) * 256;
+                       }
+                       else
+                               Ne2k_int_ReadDMA(Card, page, pages - 2, writepos);
+                       page += pages - 2;
+                       if(page > RX_LAST)      page -= (RX_LAST-RX_FIRST)+1;
+                       writepos += (pages-2) * 256;
+                       rem_bytes -= (pages-2) * 256;
                }
-               else
-                       Ne2k_int_ReadDMA(Card, page, pages-1, buf+256);
-               
-               // Wrap length to the packet length
-               if(Length > pktHdr->Length)
-                       Length = pktHdr->Length;
-               else if( Length < pktHdr->Length ) {
-                       Log_Warning("NE2000", "Packet truncated! (%i bytes truncated to %i)",
-                               pktHdr->Length, Length);
-               }
-               memcpy(Buffer, &buf[4], Length);
-               
-               free(buf);
+
+               ASSERT(rem_bytes > 0 && rem_bytes <= 0x100);
+
+               // Final page
+               Ne2k_int_ReadDMA(Card, page, 1, data);
+               memcpy(writepos, data, rem_bytes);
        }
        
        // Write BNRY (maximum page for incoming packets)
@@ -440,8 +398,8 @@ size_t Ne2k_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
        // Set next RX Page and decrement the waiting list
        Card->NextRXPage = pktHdr->NextPacketPage;
        
-       LEAVE('i', Length);
-       return Length;
+       LEAVE('p', ret);
+       return ret;
 }
 
 int Ne2k_int_ReadDMA(tCard *Card, int FirstPage, int NumPages, void *Buffer)
index 8492fe8..84f141f 100644 (file)
@@ -6,10 +6,9 @@
 #define VERSION        ((0<<8)|20)
 #include <acess.h>
 #include <modules.h>
-#include <fs_devfs.h>
 #include <drv_pci.h>
-#include <api_drv_network.h>
 #include <semaphore.h>
+#include <IPStack/include/adapters_api.h>
 
 // === CONSTANTS ===
 #define VENDOR_ID      0x10EC
@@ -38,7 +37,7 @@ enum eRTL8139_Regs
        // Early RX Status Register
        ERSR = 0x36,
        
-       // ??, ??, ??, RST, RE, TE, ??, ??
+       // -, -, -, RST, RE, TE, -, BUFE
        CMD     = 0x37,
        
        CAPR    = 0x38, // Current address of packet read
@@ -92,42 +91,26 @@ typedef struct sCard
        tMutex  CurTXProtector; //!< Protects \a .CurTXDescriptor
         int    CurTXDescriptor;
        
-       char    Name[2];
-       tVFS_Node       Node;
+       void    *IPStackHandle;
        Uint8   MacAddr[6];
 }      tCard;
 
 // === PROTOTYPES ===
  int   RTL8139_Install(char **Options);
-char   *RTL8139_ReadDir(tVFS_Node *Node, int Pos);
-tVFS_Node      *RTL8139_FindDir(tVFS_Node *Node, const char *Filename);
- int   RTL8139_RootIOCtl(tVFS_Node *Node, int ID, void *Arg);
-size_t RTL8139_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer);
-size_t RTL8139_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
- int   RTL8139_IOCtl(tVFS_Node *Node, int ID, void *Arg);
+tIPStackBuffer *RTL8139_WaitForPacket(void *Ptr);
+void   RTL8139_int_UpdateCAPR(void *Ptr, size_t pkt_length, size_t Unused, const void *DataPtr);
+ int   RTL8139_SendPacket(void *Ptr, tIPStackBuffer *Buffer);
 void   RTL8139_IRQHandler(int Num, void *Ptr);
 
 // === GLOBALS ===
 MODULE_DEFINE(0, VERSION, RTL8139, RTL8139_Install, NULL, NULL);
-tVFS_NodeType  gRTL8139_RootNodeType = {
-       .ReadDir = RTL8139_ReadDir,
-       .FindDir = RTL8139_FindDir,
-       .IOCtl = RTL8139_IOCtl
+tIPStack_AdapterType   gRTL8139_AdapterType = {
+       .Name = "RTL8139",
+       .Type = 0,      // TODO: Differentiate differnet wire protos and speeds
+       .Flags = 0,     // TODO: IP checksum offloading, MAC checksum offloading etc
+       .SendPacket = RTL8139_SendPacket,
+       .WaitForPacket = RTL8139_WaitForPacket
        };
-tVFS_NodeType  gRTL8139_DevNodeType = {
-       .Write = RTL8139_Write,
-       .Read = RTL8139_Read,
-       .IOCtl = RTL8139_IOCtl  
-       };
-tDevFS_Driver  gRTL8139_DriverInfo = {
-       NULL, "RTL8139",
-       {
-       .NumACLs = 1,
-       .ACLs = &gVFS_ACL_EveryoneRX,
-       .Flags = VFS_FFLAG_DIRECTORY,
-       .Type = &gRTL8139_RootNodeType
-       }
-};
  int   giRTL8139_CardCount;
 tCard  *gaRTL8139_Cards;
 
@@ -220,14 +203,9 @@ int RTL8139_Install(char **Options)
                card->MacAddr[4] = inb(base+MAC4);
                card->MacAddr[5] = inb(base+MAC5);
                
-               // Set VFS Node
-               card->Name[0] = '0'+i;
-               card->Name[1] = '\0';
-               card->Node.ImplPtr = card;
-               card->Node.NumACLs = 0;
-               card->Node.CTime = now();
-               card->Node.Type = &gRTL8139_DevNodeType;
-               
+               // Interface with IPStack
+               card->IPStackHandle = IPStack_Adapter_Add(&gRTL8139_AdapterType, card, card->MacAddr);
+
                Log_Log("RTL8139", "Card %i 0x%04x, IRQ %i %02x:%02x:%02x:%02x:%02x:%02x",
                        i, card->IOBase, card->IRQ,
                        card->MacAddr[0], card->MacAddr[1], card->MacAddr[2],
@@ -235,53 +213,24 @@ int RTL8139_Install(char **Options)
                        );
        }
        
-       gRTL8139_DriverInfo.RootNode.Size = giRTL8139_CardCount;
-       DevFS_AddDevice( &gRTL8139_DriverInfo );
-       
        return MODULE_ERR_OK;
 }
 
-// --- Root Functions ---
-char *RTL8139_ReadDir(tVFS_Node *Node, int Pos)
-{
-       if( Pos < 0 || Pos >= giRTL8139_CardCount )     return NULL;
-       
-       return strdup( gaRTL8139_Cards[Pos].Name );
-}
-
-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[1] != '\0')  return NULL;
-       if(Filename[0] < '0' || Filename[0] > '9')      return NULL;
-       return &gaRTL8139_Cards[ Filename[0]-'0' ].Node;
-}
-
-const char *csaRTL8139_RootIOCtls[] = {DRV_IOCTLNAMES, NULL};
-int RTL8139_RootIOCtl(tVFS_Node *Node, int ID, void *Data)
-{
-       ENTER("pNode iID pData", Node, ID, Data);
-       switch(ID)
-       {
-       BASE_IOCTLS(DRV_TYPE_NETWORK, "RTL8139", VERSION, csaRTL8139_RootIOCtls);
-       }
-       LEAVE('i', 0);
-       return 0;
-}
-
 // --- File Functions ---
-size_t RTL8139_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer)
+tIPStackBuffer *RTL8139_WaitForPacket(void *Ptr)
 {
-       tCard   *card = Node->ImplPtr;
+       tCard   *card = Ptr;
        Uint16  read_ofs, pkt_length;
-        int    new_read_ofs;
+       tIPStackBuffer  *ret;
 
-       ENTER("pNode XOffset xLength pBuffer", Node, Offset, Length, Buffer);
+       ENTER("pPtr", Ptr);
 
 retry:
+       LOG("IMR = %x, ISR = %x", inw(card->IOBase + IMR), inw(card->IOBase + ISR));
        if( Semaphore_Wait( &card->ReadSemaphore, 1 ) != 1 )
        {
-               LEAVE_RET('i', 0);
+               LEAVE('n');
+               return NULL;
        }
        
        Mutex_Acquire( &card->ReadMutex );
@@ -293,6 +242,37 @@ retry:
        
        pkt_length = *(Uint16*)&card->ReceiveBuffer[read_ofs+2];
        
+       // Check for errors
+       if( *(Uint16*)&card->ReceiveBuffer[read_ofs] & 0x1E )
+       {
+               // Update CAPR
+               RTL8139_int_UpdateCAPR( card, pkt_length, 0, &card->ReceiveBuffer[read_ofs+4] );
+               Mutex_Release( &card->ReadMutex );
+               goto retry;     // I feel evil
+       }
+       
+       ret = IPStack_Buffer_CreateBuffer(1);
+       IPStack_Buffer_AppendSubBuffer(ret,
+               pkt_length, 0, &card->ReceiveBuffer[read_ofs+4],
+               RTL8139_int_UpdateCAPR, card
+               );
+       
+       Mutex_Release( &card->ReadMutex );
+       
+       LEAVE('p', ret);
+       return ret;
+}
+
+/**
+ * \brief Updates CAPR after a packet has been read
+ * \note Assumes that buffers are freed in the order we allocate them
+ */
+void RTL8139_int_UpdateCAPR(void *Ptr, size_t pkt_length, size_t Unused, const void *DataPtr)
+{
+       tCard   *card = Ptr;
+        int    read_ofs = DataPtr - (const void *)card->ReceiveBuffer - 4;
+        int    new_read_ofs;
+
        // Calculate new read offset
        new_read_ofs = read_ofs + pkt_length + 4;
        new_read_ofs = (new_read_ofs + 3) & ~3; // Align
@@ -302,38 +282,24 @@ retry:
        }
        new_read_ofs -= 0x10;   // I dunno
        LOG("new_read_ofs = %i", new_read_ofs);
-       
-       // Check for errors
-       if( *(Uint16*)&card->ReceiveBuffer[read_ofs] & 0x1E ) {
-               // Update CAPR
-               outw(card->IOBase + CAPR, new_read_ofs);
-               Mutex_Release( &card->ReadMutex );
-               goto retry;     // I feel evil
-       }
-       
-       // Get packet
-       if( Length > pkt_length )       Length = pkt_length;
-       memcpy(Buffer, &card->ReceiveBuffer[read_ofs+4], Length);
-       
+
        // Update CAPR
        outw(card->IOBase + CAPR, new_read_ofs);
-       
-       Mutex_Release( &card->ReadMutex );
-       
-       LEAVE('i', Length);
-       
-       return Length;
 }
 
-size_t RTL8139_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
+int RTL8139_SendPacket(void *Ptr, tIPStackBuffer *Buffer)
 {
-        int    td;
+        int    td, length;
        Uint32  status;
-       tCard   *card = Node->ImplPtr;
-       
-       if( Length > 1500 )     return 0;       // MTU exceeded
+       tCard   *card = Ptr;
        
-       ENTER("pNode XLength pBuffer", Node, Length, Buffer);
+       ENTER("pPtr pBuffer", Ptr, Buffer);
+
+       length = IPStack_Buffer_GetLength(Buffer);
+       if( length > 1500 ) {
+               LEAVE('i', -1);
+               return -1;      // MTU exceeded
+       }
        
        // TODO: Implement a semaphore for avaliable transmit buffers
 
@@ -351,40 +317,20 @@ size_t RTL8139_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *B
        // Transmit using descriptor `td`
        LOG("card->PhysTransmitBuffers[td] = %P", card->PhysTransmitBuffers[td]);
        outd(card->IOBase + TSAD0 + td*4, card->PhysTransmitBuffers[td]);
-       LOG("card->TransmitBuffers[td] = %p", card->TransmitBuffers[td]);
+       
        // Copy to buffer
-       memcpy(card->TransmitBuffers[td], Buffer, Length);
+       LOG("card->TransmitBuffers[td] = %p", card->TransmitBuffers[td]);
+       IPStack_Buffer_GetData(Buffer, card->TransmitBuffers[td], length);
+       
        // Start
        status = 0;
-       status |= Length & 0x1FFF;      // 0-12: Length
+       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)
        LOG("status = 0x%08x", status);
        outd(card->IOBase + TSD0 + td*4, status);
        
-       LEAVE('i', (int)Length);
-       
-       return Length;
-}
-
-const char *csaRTL8139_NodeIOCtls[] = {DRV_IOCTLNAMES, NULL};
-int RTL8139_IOCtl(tVFS_Node *Node, int ID, void *Data)
-{
-       tCard   *card = Node->ImplPtr;
-       ENTER("pNode iID pData", Node, ID, Data);
-       switch(ID)
-       {
-       BASE_IOCTLS(DRV_TYPE_NETWORK, "RTL8139", VERSION, csaRTL8139_NodeIOCtls);
-       case NET_IOCTL_GETMAC:
-               if( !CheckMem(Data, 6) ) {
-                       LEAVE('i', -1);
-                       return -1;
-               }
-               memcpy( Data, card->MacAddr, 6 );
-               LEAVE('i', 1);
-               return 1;
-       }
-       LEAVE('i', 0);
+       LEAVE('i', 0);  
        return 0;
 }
 
@@ -394,11 +340,10 @@ void RTL8139_IRQHandler(int Num, void *Ptr)
        tCard   *card = Ptr;
        Uint16  status;
 
-       LOG("Num = %i", Num);
-       
        if( Num != card->IRQ )  return;
                
        status = inw(card->IOBase + ISR);
+       if( !status )   return ;
        LOG("status = 0x%02x", status);
                
        // Transmit OK, a transmit descriptor is now free
@@ -476,8 +421,8 @@ void RTL8139_IRQHandler(int Num, void *Ptr)
                {
                        if( Semaphore_Signal( &card->ReadSemaphore, packet_count ) != packet_count ) {
                                // Oops?
+                               Log_Warning("RTL8139", "IRQ: signalling read semaphore failed, Oops?");
                        }
-                       VFS_MarkAvaliable( &card->Node, 1 );
                }
                
                outw(card->IOBase + ISR, FLAG_ISR_ROK);
index 643624a..149bd0a 100644 (file)
@@ -91,7 +91,7 @@ int main(int argc, char *argv[])
                ifaces->Adapter = argv[1];
        }
        else {
-               Scan_Dir( &ifaces, "/Devices" );
+               Scan_Dir( &ifaces, "/Devices/ip/adapters" );
        }
 
        for( i = ifaces; i; i = i->Next )
@@ -150,34 +150,14 @@ void Scan_Dir(tInterface **IfaceList, const char *Directory)
 
        while( readdir(dp, filename) )
        {
-                int    pathlen = strlen(Directory) + 1 + strlen(filename) + 1;
-               char    path[pathlen];
-                int    fd;
-               t_sysFInfo      info;
-
-               sprintf(path, "%s/%s", Directory, filename);
-               fd = open(path, 0);
-
-               // Check if the device type is 9 (Network)
-               if( ioctl(fd, 0, NULL) != 9 )
-                       continue ;
-
-               // Check if it's a directory
-               finfo(fd, &info, 0);
-               if( info.flags & FILEFLAG_DIRECTORY )
-               {
-                       // If so, recurse
-                       Scan_Dir(IfaceList, path);
-               }
-               else
-               {
-                       // Otherwise, add it to the list
-                       tInterface      *new = malloc(sizeof(tInterface) + pathlen);
-                       new->Adapter = (void*)(new + 1);
-                       strcpy(new->Adapter, path);
-                       new->Next = *IfaceList;
-                       *IfaceList = new;
-               }
+               if( filename[0] == '.' )        continue ;              
+               if( strcmp(filename, "lo") == 0 )       continue ;
+
+               tInterface *new = malloc(sizeof(tInterface) + strlen(filename)+1);
+               new->Adapter = (void*)(new + 1);
+               strcpy(new->Adapter, filename);
+               new->Next = *IfaceList;
+               *IfaceList = new;
        }
        close(dp);
 }
@@ -253,11 +233,17 @@ void Send_DHCPDISCOVER(tInterface *Iface)
        msg->giaddr = htonl(0); // giaddr - Zero?
        // Request MAC address from network adapter
        {
-               int fd = open(Iface->Adapter, 0);
-               // TODO: Check if open() failed
-               ioctl(fd, 4, msg->chaddr);
-               // TODO: Check if ioctl() failed
-               close(fd);
+               char    path[] = "/Devices/ip/adapters/ethXXXX";
+               sprintf(path, "/Devices/ip/adapters/%s", Iface->Adapter);
+               int fd = open(path, 0);
+               if(fd == -1) {
+                       _SysDebug("Unable to open adapter %s", path);
+               }
+               else {
+                       ioctl(fd, 4, msg->chaddr);
+                       // TODO: Check if ioctl() failed
+                       close(fd);
+               }
        }
        memset(msg->sname, 0, sizeof(msg->sname));      // Nuke the rest
        memset(msg->file, 0, sizeof(msg->file));        // Nuke the rest
@@ -356,7 +342,10 @@ int Handle_Packet(tInterface *Iface)
                break;
        case 2: // DHCPOFFER
                // Send out request for this address
-               if( Iface->State != STATE_DISCOVER_SENT )       return 0;
+               if( Iface->State != STATE_DISCOVER_SENT ) {
+                       _SysDebug("Ignoring DHCPOFFER when not in STATE_DISCOVER_SENT");
+                       return 0;
+               }
                Send_DHCPREQUEST(Iface, data, dhcp_msg_type_ofs);
                break;
        case 3: // DHCPREQUEST - wut?
index 334ea13..bbb8666 100644 (file)
@@ -134,7 +134,6 @@ int main(int argc, char *argv[])
                        PrintUsage(argv[0]);
                        return -1;
                }
-               // TODO: Also set the IP address as the usage says it does
                ret = AddInterface( argv[2] );
                if(ret < 0)     return ret;
                ret = SetAddress( ret, argv[3] );
index 33113c8..7686e5c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Acess2 IFCONFIG command
+ * Acess2 ping command
  */
 #include <stdlib.h>
 #include <stdint.h>

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