From: John Hodge Date: Sat, 12 May 2012 10:52:37 +0000 (+0800) Subject: IPStack - Reworking of network device API X-Git-Tag: rel0.15~707^2~6 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=33495f1efd207f0af4f804858f247db0983fcb8f;hp=da7b3d59eac9f14919af6b10298972163493a09a;p=tpg%2Facess2.git IPStack - Reworking of network device API - 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 --- diff --git a/KernelLand/Modules/IPStack/Makefile b/KernelLand/Modules/IPStack/Makefile index b0ee26b8..3ea5f7e7 100644 --- a/KernelLand/Modules/IPStack/Makefile +++ b/KernelLand/Modules/IPStack/Makefile @@ -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 index 00000000..f4b99beb --- /dev/null +++ b/KernelLand/Modules/IPStack/adapters.c @@ -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 // For the VFS hack +#include + +// === 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; +} + diff --git a/KernelLand/Modules/IPStack/arp.c b/KernelLand/Modules/IPStack/arp.c index 607f201e..e152e33d 100644 --- a/KernelLand/Modules/IPStack/arp.c +++ b/KernelLand/Modules/IPStack/arp.c @@ -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); } diff --git a/KernelLand/Modules/IPStack/buffer.c b/KernelLand/Modules/IPStack/buffer.c index 9151c1c1..b8462e60 100644 --- a/KernelLand/Modules/IPStack/buffer.c +++ b/KernelLand/Modules/IPStack/buffer.c @@ -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 index 00000000..768fd9e2 --- /dev/null +++ b/KernelLand/Modules/IPStack/include/adapters.h @@ -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 index 00000000..0ecd8473 --- /dev/null +++ b/KernelLand/Modules/IPStack/include/adapters_api.h @@ -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 index 00000000..c474818a --- /dev/null +++ b/KernelLand/Modules/IPStack/include/adapters_int.h @@ -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 + diff --git a/KernelLand/Modules/IPStack/include/buffer.h b/KernelLand/Modules/IPStack/include/buffer.h index 62c1308c..ad0516ab 100644 --- a/KernelLand/Modules/IPStack/include/buffer.h +++ b/KernelLand/Modules/IPStack/include/buffer.h @@ -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 diff --git a/KernelLand/Modules/IPStack/interface.c b/KernelLand/Modules/IPStack/interface.c index b0b63b9a..9ff3f17d 100644 --- a/KernelLand/Modules/IPStack/interface.c +++ b/KernelLand/Modules/IPStack/interface.c @@ -7,7 +7,7 @@ #include "ipstack.h" #include "link.h" #include -#include +#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; -} diff --git a/KernelLand/Modules/IPStack/ipstack.h b/KernelLand/Modules/IPStack/ipstack.h index e51fded9..5ea5dc97 100644 --- a/KernelLand/Modules/IPStack/ipstack.h +++ b/KernelLand/Modules/IPStack/ipstack.h @@ -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 diff --git a/KernelLand/Modules/IPStack/ipv4.c b/KernelLand/Modules/IPStack/ipv4.c index d5c2f965..3162301c 100644 --- a/KernelLand/Modules/IPStack/ipv4.c +++ b/KernelLand/Modules/IPStack/ipv4.c @@ -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); diff --git a/KernelLand/Modules/IPStack/link.c b/KernelLand/Modules/IPStack/link.c index 37b72608..3dcd2949 100644 --- a/KernelLand/Modules/IPStack/link.c +++ b/KernelLand/Modules/IPStack/link.c @@ -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 diff --git a/KernelLand/Modules/IPStack/link.h b/KernelLand/Modules/IPStack/link.h index bdea0e2c..ac073429 100644 --- a/KernelLand/Modules/IPStack/link.h +++ b/KernelLand/Modules/IPStack/link.h @@ -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 === diff --git a/KernelLand/Modules/IPStack/main.c b/KernelLand/Modules/IPStack/main.c index d5d1ebc2..3aecfb30 100644 --- a/KernelLand/Modules/IPStack/main.c +++ b/KernelLand/Modules/IPStack/main.c @@ -8,6 +8,7 @@ #include "link.h" #include #include +#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 ); diff --git a/KernelLand/Modules/IPStack/routing.c b/KernelLand/Modules/IPStack/routing.c index 7173d1f3..c4b53926 100644 --- a/KernelLand/Modules/IPStack/routing.c +++ b/KernelLand/Modules/IPStack/routing.c @@ -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); } } diff --git a/KernelLand/Modules/Network/NE2000/ne2000.c b/KernelLand/Modules/Network/NE2000/ne2000.c index 01f5f1fe..c8ea019e 100644 --- a/KernelLand/Modules/Network/NE2000/ne2000.c +++ b/KernelLand/Modules/Network/NE2000/ne2000.c @@ -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 #include -#include #include -#include #include +#include // === 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) diff --git a/KernelLand/Modules/Network/RTL8139/rtl8139.c b/KernelLand/Modules/Network/RTL8139/rtl8139.c index 8492fe8f..84f141ff 100644 --- a/KernelLand/Modules/Network/RTL8139/rtl8139.c +++ b/KernelLand/Modules/Network/RTL8139/rtl8139.c @@ -6,10 +6,9 @@ #define VERSION ((0<<8)|20) #include #include -#include #include -#include #include +#include // === 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); diff --git a/Usermode/Applications/dhcpclient_src/main.c b/Usermode/Applications/dhcpclient_src/main.c index 643624a2..149bd0a1 100644 --- a/Usermode/Applications/dhcpclient_src/main.c +++ b/Usermode/Applications/dhcpclient_src/main.c @@ -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? diff --git a/Usermode/Applications/ifconfig_src/main.c b/Usermode/Applications/ifconfig_src/main.c index 334ea137..bbb8666e 100644 --- a/Usermode/Applications/ifconfig_src/main.c +++ b/Usermode/Applications/ifconfig_src/main.c @@ -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] ); diff --git a/Usermode/Applications/ping_src/main.c b/Usermode/Applications/ping_src/main.c index 33113c8d..7686e5cc 100644 --- a/Usermode/Applications/ping_src/main.c +++ b/Usermode/Applications/ping_src/main.c @@ -1,5 +1,5 @@ /* - * Acess2 IFCONFIG command + * Acess2 ping command */ #include #include