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