1
0
mirror of https://github.com/Halofreak1990/XFXFramework synced 2024-12-26 13:49:34 +01:00

Added AFL packet driver

Implemented SocketAddress class
Fixed Array class
This commit is contained in:
Tom Lint 2014-07-15 17:22:43 +02:00
parent da0bfcaa6f
commit e234c493b4
11 changed files with 1550 additions and 32 deletions

View File

@ -20,10 +20,10 @@ using namespace System::Collections::Generic;
namespace System
{
/**
*
* Represents a single-dimension array.
*/
template <typename T>
class Array : public ICollection<T>, public IEnumerable<T>
class Array : public IEnumerable<T>
{
private:
T* _array;
@ -39,7 +39,8 @@ namespace System
public:
const int Length;
Array(const int size) : _array(new T[size]), _version(0), Length(size)
Array(const int size)
: _array(new T[size]), _version(0), Length(size)
{
memset(_array, 0, sizeof(T) * size);
}
@ -72,13 +73,10 @@ namespace System
{
sassert(array != null, String::Format("array; %s", FrameworkResources::ArgumentNull_Generic));
for(int i = 0, j = index; i < Length; i++)
{
array[j] = _array[i];
}
memcpy(&array[index], &_array[0], sizeof(T) * Length);
}
inline IEnumerator<T>* GetEnumerator() const
inline IEnumerator<T>* GetEnumerator()
{
return new ArrayEnumerator(this);
}
@ -118,8 +116,17 @@ namespace System
_version++;
}
inline const T& operator[](const int index) const
{
sassert(index > 0 && index < Length, "");
return _array[index];
}
inline T& operator[](const int index)
{
sassert(index > 0 && index < Length, "");
return _array[index];
}
@ -177,7 +184,8 @@ namespace System
public:
const int Length;
Array(const int size) : _array(new T*[size]), _version(0), Length(size)
Array(const int size)
: _array(new T*[size]), _version(0), Length(size)
{
memset(_array, 0, sizeof(T *) * size);
}
@ -185,10 +193,7 @@ namespace System
Array(const Array<T *> &obj)
: _array(new T*[obj.Length]), _version(obj._version), Length(obj.Length)
{
for (int i = 0; i < Length; i++)
{
_array[i] = obj._array[i];
}
memcpy(_array, obj._array, sizeof(T *) * Length);
}
~Array() { delete _array; }
@ -207,10 +212,7 @@ namespace System
{
sassert(array != null, String::Format("array; %s", FrameworkResources::ArgumentNull_Generic));
for(int i = 0, j = index; i < Length; i++)
{
array[j] = _array[i];
}
memcpy(array[index], _array[0], sizeof(T *) * Length);
}
inline IEnumerator<T *>* GetEnumerator() const
@ -242,6 +244,7 @@ namespace System
int num = startIndex;
int num2 = (startIndex + count) - 1;
while (num < num2)
{
swap(_array[num], _array[num2]);
@ -252,8 +255,17 @@ namespace System
_version++;
}
inline T* operator[](const int index)
inline const T*& operator[](const int index) const
{
sassert(index > 0 && index < Length, "");
return _array[index];
}
inline T*& operator[](const int index)
{
sassert(index > 0 && index < Length, "");
return _array[index];
}

View File

@ -36,7 +36,7 @@ namespace System
IPEndPoint(const long long address, const int port);
IPEndPoint(IPAddress * const address, const int port);
EndPoint * Create(SocketAddress socketAddress);
EndPoint * Create(SocketAddress * const socketAddress);
bool Equals(Object const * const obj) const;
int GetHashCode() const;
SocketAddress * Serialize();

View File

@ -7,6 +7,7 @@
#ifndef _SYSTEM_NET_SOCKETADDRESS_
#define _SYSTEM_NET_SOCKETADDRESS_
#include <System/Array.h>
#include <System/Object.h>
#include <System/Types.h>
#include <System/Net/Sockets/Enums.h>
@ -23,13 +24,11 @@ namespace System
class SocketAddress : public Object
{
private:
AddressFamily_t addressFamily;
int bufferSize;
Array<byte> data;
public:
AddressFamily_t getFamily();
int getSize();
byte operator[](int offset);
SocketAddress(AddressFamily_t family);
SocketAddress(AddressFamily_t family, int size);
@ -38,6 +37,9 @@ namespace System
int GetHashCode() const;
static const Type& GetType();
const String ToString();
const byte& operator[](const int index) const;
byte& operator[](const int index);
};
}
}

View File

@ -25,10 +25,13 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <System/Int32.h>
#include <System/Net/SocketAddress.h>
#include <System/String.h>
#include <System/Type.h>
#include <sassert.h>
namespace System
{
namespace Net
@ -37,24 +40,60 @@ namespace System
AddressFamily_t SocketAddress::getFamily()
{
return addressFamily;
return (AddressFamily_t)(data[0] + (data[1] << 8));
}
int SocketAddress::getSize()
{
return bufferSize;
return data.Length;
}
SocketAddress::SocketAddress(AddressFamily_t family)
: addressFamily(family)
: data(32)
{
// TODO: implement remainder
data[0] = (byte)family;
data[1] = (byte)((int)family >> 8);
}
SocketAddress::SocketAddress(AddressFamily_t family, int size)
: addressFamily(family), bufferSize(size)
: data(size)
{
// TODO: implement remainder
sassert(size >= 2, "size is too small");
data[0] = (byte)family;
data[1] = (byte)((int)family >> 8);
}
bool SocketAddress::Equals(Object const * const obj) const
{
SocketAddress* sa = as<SocketAddress *>(obj);
if (sa != NULL && sa->data.Length == data.Length)
{
for (int i = 0; i < data.Length; i++)
{
if (data[i] != sa->data[i])
{
return false;
}
}
return true;
}
return false;
}
int SocketAddress::GetHashCode() const
{
int code = 0;
for (int i = 0; i < data.Length; i++)
{
code += data[i] + i;
}
return code;
}
const Type& SocketAddress::GetType()
@ -64,12 +103,51 @@ namespace System
const String SocketAddress::ToString()
{
// TODO: implement
String af;
switch ((AddressFamily_t)data[0])
{
case AddressFamily::InterNetwork:
af = "InterNetwork";
break;
case AddressFamily::InterNetworkV6:
af = "InterNetworkV6";
break;
case AddressFamily::Unknown:
af = "Unknown";
break;
case AddressFamily::Unspecified:
af = "Unspecified";
break;
}
int size = data.Length;
String ret = af + ":" + Int32::ToString(size) + ":{";
for (int i = 2; i < size; i++)
{
int val = (int)data[i];
ret = ret + val;
if (i < size - 1)
{
ret = ret + ",";
}
}
ret = ret + "}";
return(ret);
}
byte SocketAddress::operator[](int offset)
const byte& SocketAddress::operator[](const int index) const
{
// TODO: implement
return data[index];
}
byte& SocketAddress::operator[](const int index)
{
return data[index];
}
}
}

269
src/libSystem/detect_ping.c Normal file
View File

@ -0,0 +1,269 @@
//Ping detection (it detects incoming pings, but does not reply to them -only arp-)
//Write here your xbox ip address
//(first 3 numbers should match your PC IP address, last one must be unique on your network)
#define MY_IP_ADDRESS "192.168.0.10"
#include <hal/xbox.h>
#include <hal/input.h>
#include <xboxkrnl/xboxkrnl.h>
#include <openxdk/debug.h>
#include <ctype.h>
#include "string.h"
#include "stdio.h"
#include <stdlib.h>
#include "memory.h"
#include "pktdrv.h"
struct _arp
{
//ethernet header (14 bytes)
unsigned char EthDst[6]; //0xFFFFFFFFFFFF=any (broadcast)
unsigned char EthSrc[6];
unsigned short ProtocolType; //0x0608 (0x08 then 0x06)=IP ARP
//arp header (2+2+1+1+2+6+4+6+4=28 bytes)
unsigned short Hardware; //0x0100 (0x00 then 0x01)=Ethernet (10Mbps)
unsigned short Protocol; //0x0008 (0x08 then 0x00)=IP
unsigned char HardwareAddrLen; //6 (bytes)
unsigned char ProtocolAddrLen; //4 (bytes)
unsigned short Operation; //0x0100 (0x00 then 0x01)=Request 0x0200=Answer
unsigned char SenderHardwareAddr[6];
unsigned char SenderProtocolAddr[4]; //Sender IP address
unsigned char TargetHardwareAddr[6]; //0 if not known yet
unsigned char TargetProtocolAddr[4]; //Target IP address
};
struct _ip
{
//ethernet header (14 bytes)
unsigned char EthDst[6]; //0xFFFFFFFFFFFF=any (broadcast)
unsigned char EthSrc[6];
unsigned short ProtocolType; //0x0008 (0x08 then 0x00)=IP
//ip header (8 bytes)
unsigned char Version:4; //4 bits, value 4
unsigned char HeaderLength:4; //4 bits, value 5 (means 20 bytes)
unsigned char DifferentiatedServices; //0
unsigned short TotalLength; //0x2000 (0x00 then 0x20)=32 bytes
unsigned short Identifier; //Variant
unsigned short FragmentationFlagOffset;//0
unsigned char TimeToLive; //128
unsigned char Protocol; //1 = ICMP (Internet Control Message Protocol)
unsigned short HeaderChecksum; //Variant
unsigned char SrcIPAddr[4]; //Sender IP address
unsigned char DstIPAddr[4]; //Target IP address
//icmp sub-protocol
unsigned char ICMPType; //8 = Echo request
unsigned char ICMPCode; //0
unsigned short Checksum; //Variant
unsigned short ID; //Variant
unsigned short SequenceNumber; //0 then increments with retries
unsigned char ICMPDataArea[18];
};
static unsigned long counter=0;
static unsigned int packetsize=0;
static unsigned char *packetbuffer;
unsigned long myipaddress;
void report(void)
{
int i;
unsigned char *p;
struct _arp *parp;
struct _ip *pip;
debugPrint("Received packets : %ld\n",counter);
debugPrint("Last received packet size : %d bytes\n",packetsize);
if (packetsize<100)
{
p=packetbuffer;
for(i=0;i<packetsize;i++)
{
if ((i==6)||(i==12)||(i==14)) debugPrint(" ");
debugPrint("%02x",*p);
p++;
}
debugPrint("\n");
parp=(struct _arp *)packetbuffer;
if ( (parp->ProtocolType==0x0608)&&
(parp->Operation==0x100) )
debugPrint("It was an ARP request from %d.%d.%d.%d\n",
parp->SenderProtocolAddr[0],
parp->SenderProtocolAddr[1],
parp->SenderProtocolAddr[2],
parp->SenderProtocolAddr[3]);
pip=(struct _ip *)packetbuffer;
if ( (pip->ProtocolType==0x0008)&&
(pip->Protocol==1)&&
(pip->ICMPType==8) )
debugPrint("It was a Ping request from %d.%d.%d.%d!\nPktdrv worked!\n",
pip->SrcIPAddr[0],
pip->SrcIPAddr[1],
pip->SrcIPAddr[2],
pip->SrcIPAddr[3]);
}
}
int Pktdrv_Callback(unsigned char *packetaddr, unsigned int size)
{
//We are either called from a Dpc (if line uncommented in MyPktdrvDpc)
//or from our own code (no need to be reentrant)
counter++;
packetsize=size;
memcpy(packetbuffer,packetaddr,packetsize);
return 1; //we declare we have taken the packet (reply 0 if you want keep it for later)
}
void process_last_packet(void)
{
struct _ip *pip;
struct _arp *parp;
parp = (struct _arp *)packetbuffer;
if ((parp->ProtocolType == 0x608) && (parp->Operation == 0x100))
{
// It's an ARP request
unsigned char tmp[4];
unsigned long ltmp;
memcpy(tmp,parp->TargetProtocolAddr,4);
ltmp = *((unsigned long *)tmp);
// Are we the target?
if (ltmp == myipaddress)
{
// Yes, build up an ARP response (invert src and dst)
memcpy(parp->EthDst,parp->EthSrc,6);
Pktdrv_GetEthernetAddr(parp->EthSrc);
parp->Operation=0x200;
memcpy(parp->TargetHardwareAddr,parp->SenderHardwareAddr,6);
Pktdrv_GetEthernetAddr(parp->SenderHardwareAddr);
memcpy(parp->TargetProtocolAddr,parp->SenderProtocolAddr,4);
memcpy(parp->SenderProtocolAddr,tmp,4);
debugPrint("Answering to ARP request now!\n");
// As a rule, always wait until number of packet not yet sent goes
// below the number of buffers -ring- you are using to send them
while (Pktdrv_GetQueuedTxPkts() >= 1) { /*wait*/ };
// In this sample we only send a reply to a request. It never waits.
Pktdrv_SendPacket(packetbuffer,14+28);
}
}
pip = (struct _ip *)packetbuffer;
if ((pip->ProtocolType == 0x0008) &&
(pip->Protocol == 1) &&
(pip->ICMPType == 8))
{
// It's a Ping request (an IP packet with a ICMP Echo request inside)
unsigned char tmp[4];
unsigned long ltmp;
memcpy(tmp,pip->DstIPAddr,4);
ltmp = *((unsigned long *)tmp);
// Are we the target?
if (ltmp == myipaddress)
{
debugPrint("It's a Ping request from %d.%d.%d.%d!\nPktdrv is working!\n",
pip->SrcIPAddr[0],
pip->SrcIPAddr[1],
pip->SrcIPAddr[2],
pip->SrcIPAddr[3]);
//Here we should build up an answer to the ping request
//Do it yourself as an exercise...
//Caution checksums are tricky to calculate...
}
}
}
void XBoxStartup(void)
{
int i,v,n,done=0;
char *p;
unsigned char *p2;
packetbuffer = (unsigned char *)MmAllocateContiguousMemoryEx(
1520,
0, //lowest acceptable
0xFFFFFFFF, //highest acceptable
0, //no need to align to specific boundaries multiple
4); //non cached, non ordered
if (!packetbuffer) return; //don't waste my time!
// convert IP address string into an unsigned long
p = MY_IP_ADDRESS;
p2 = (unsigned char *)&myipaddress;
for (i = 0, n = 0, v = 0; i < strlen(p) + 1; i++)
{
if (isdigit(p[i]))
v = v * 10 + p[i] - '0';
else
if ((p[i] == '.') || (p[i] == '\0'))
{
*p2 = (unsigned char)(v&255);
v = 0;
p2++;
n++;
if (n == 4) break;
}
}
XInput_Init();
if (Pktdrv_Init())
{
debugPrint("Try to ping your XBOX!\n");
debugPrint("Press A to show statistics\n");
debugPrint("Press B to stop program\n");
while(!done)
{
//When a ping will come, we will receive an ARP then an IP
//-ARP will ask who has the requested ip address on network
//-We will reply and that will give sender our MAC Address
//-The ping itself (an IP packet) will then come
if (Pktdrv_ReceivePackets())
{
//We received at least 1 packet. Process last received packet.
process_last_packet();
}
XInput_GetEvents();
for (i = 0; i < 4; i++)
{
if(g_Pads[i].PressedButtons.ucAnalogButtons[XPAD_A]) report();
if(g_Pads[i].PressedButtons.ucAnalogButtons[XPAD_B]) done = 1;
}
};
Pktdrv_Quit();
}
else
debugPrint("Couldn't initialize network packet driver\n");
XInput_Quit();
MmFreeContiguousMemory(packetbuffer);
debugPrint("Quitting...\n");
XSleep(5000);
XReboot();
}

View File

@ -73,12 +73,14 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Debug.cpp" />
<ClCompile Include="detect_ping.c" />
<ClCompile Include="DnsEndPoint.cpp" />
<ClCompile Include="EndPoint.cpp" />
<ClCompile Include="IPAddress.cpp" />
<ClCompile Include="IPEndPoint.cpp" />
<ClCompile Include="NetworkChange.cpp" />
<ClCompile Include="NetworkInterface.cpp" />
<ClCompile Include="pktdrv.c" />
<ClCompile Include="SocketAddress.cpp" />
<ClCompile Include="Socket.cpp" />
<ClCompile Include="SocketAsyncEventArgs.cpp" />
@ -99,6 +101,7 @@
<ClInclude Include="..\..\include\System\Net\Sockets\Enums.h" />
<ClInclude Include="..\..\include\System\Net\Sockets\Socket.h" />
<ClInclude Include="..\..\include\System\Net\Sockets\SocketAsyncEventArgs.h" />
<ClInclude Include="pktdrv.h" />
</ItemGroup>
<ItemGroup>
<None Include="makefile" />

View File

@ -81,6 +81,12 @@
<ClCompile Include="EndPoint.cpp">
<Filter>Source Files\Net</Filter>
</ClCompile>
<ClCompile Include="detect_ping.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pktdrv.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\System\ComponentModel\CancelEventArgs.h">
@ -122,6 +128,9 @@
<ClInclude Include="..\..\include\System\Net\DnsEndPoint.h">
<Filter>Header Files\Net</Filter>
</ClInclude>
<ClInclude Include="pktdrv.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="makefile" />

166
src/libSystem/license.txt Normal file
View File

@ -0,0 +1,166 @@
The Academic Free License
v. 2.0
This Academic Free License (the "License") applies to any original work
of authorship (the "Original Work") whose owner (the "Licensor") has
placed the following notice immediately following the copyright notice
for the Original Work:
*Licensed under the Academic Free License version 2.0*
1) *Grant of Copyright License.* Licensor hereby grants You a
world-wide, royalty-free, non-exclusive, perpetual, sublicenseable
license to do the following:
a) to reproduce the Original Work in copies;
b) to prepare derivative works ("Derivative Works") based upon the
Original Work;
c) to distribute copies of the Original Work and Derivative Works to
the public;
d) to perform the Original Work publicly; and
e) to display the Original Work publicly.
2) *Grant of Patent License.* Licensor hereby grants You a world-wide,
royalty-free, non-exclusive, perpetual, sublicenseable license, under
patent claims owned or controlled by the Licensor that are embodied in
the Original Work as furnished by the Licensor, to make, use, sell and
offer for sale the Original Work and Derivative Works.
3) *Grant of Source Code License.* The term "Source Code" means the
preferred form of the Original Work for making modifications to it and
all available documentation describing how to modify the Original Work.
Licensor hereby agrees to provide a machine-readable copy of the Source
Code of the Original Work along with each copy of the Original Work that
Licensor distributes. Licensor reserves the right to satisfy this
obligation by placing a machine-readable copy of the Source Code in an
information repository reasonably calculated to permit inexpensive and
convenient access by You for as long as Licensor continues to distribute
the Original Work, and by publishing the address of that information
repository in a notice immediately following the copyright notice that
applies to the Original Work.
4) *Exclusions From License Grant. *Neither the names of Licensor, nor
the names of any contributors to the Original Work, nor any of their
trademarks or service marks, may be used to endorse or promote products
derived from this Original Work without express prior written permission
of the Licensor. Nothing in this License shall be deemed to grant any
rights to trademarks, copyrights, patents, trade secrets or any other
intellectual property of Licensor except as expressly stated herein. No
patent license is granted to make, use, sell or offer to sell
embodiments of any patent claims other than the licensed claims defined
in Section 2. No right is granted to the trademarks of Licensor even if
such marks are included in the Original Work. Nothing in this License
shall be interpreted to prohibit Licensor from licensing under different
terms from this License any Original Work that Licensor otherwise would
have a right to license.
5) This section intentionally omitted.
6) *Attribution Rights.* You must retain, in the Source Code of any
Derivative Works that You create, all copyright, patent or trademark
notices from the Source Code of the Original Work, as well as any
notices of licensing and any descriptive text identified therein as an
"Attribution Notice." You must cause the Source Code for any Derivative
Works that You create to carry a prominent Attribution Notice reasonably
calculated to inform recipients that You have modified the Original Work.
7) *Warranty of Provenance and Disclaimer of Warranty.* Licensor
warrants that the copyright in and to the Original Work and the patent
rights granted herein by Licensor are owned by the Licensor or are
sublicensed to You under the terms of this License with the permission
of the contributor(s) of those copyrights and patent rights. Except as
expressly stated in the immediately proceeding sentence, the Original
Work is provided under this License on an "AS IS" BASIS and WITHOUT
WARRANTY, either express or implied, including, without limitation, the
warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL
WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential
part of this License. No license to Original Work is granted hereunder
except under this disclaimer.
8) *Limitation of Liability.* Under no circumstances and under no legal
theory, whether in tort (including negligence), contract, or otherwise,
shall the Licensor be liable to any person for any direct, indirect,
special, incidental, or consequential damages of any character arising
as a result of this License or the use of the Original Work including,
without limitation, damages for loss of goodwill, work stoppage,
computer failure or malfunction, or any and all other commercial damages
or losses. This limitation of liability shall not apply to liability for
death or personal injury resulting from Licensor's negligence to the
extent applicable law prohibits such limitation. Some jurisdictions do
not allow the exclusion or limitation of incidental or consequential
damages, so this exclusion and limitation may not apply to You.
9) *Acceptance and Termination.* If You distribute copies of the
Original Work or a Derivative Work, You must make a reasonable effort
under the circumstances to obtain the express assent of recipients to
the terms of this License. Nothing else but this License (or another
written agreement between Licensor and You) grants You permission to
create Derivative Works based upon the Original Work or to exercise any
of the rights granted in Section 1 herein, and any attempt to do so
except under the terms of this License (or another written agreement
between Licensor and You) is expressly prohibited by U.S. copyright law,
the equivalent laws of other countries, and by international treaty.
Therefore, by exercising any of the rights granted to You in Section 1
herein, You indicate Your acceptance of this License and all of its
terms and conditions.
10) *Termination for Patent Action.* This License shall terminate
automatically and You may no longer exercise any of the rights granted
to You by this License as of the date You commence an action, including
a cross-claim or counterclaim, for patent infringement (i) against
Licensor with respect to a patent applicable to software or (ii) against
any entity with respect to a patent applicable to the Original Work (but
excluding combinations of the Original Work with other software or
hardware).
11) *Jurisdiction, Venue and Governing Law.* Any action or suit relating
to this License may be brought only in the courts of a jurisdiction
wherein the Licensor resides or in which Licensor conducts its primary
business, and under the laws of that jurisdiction excluding its
conflict-of-law provisions. The application of the United Nations
Convention on Contracts for the International Sale of Goods is expressly
excluded. Any use of the Original Work outside the scope of this License
or after its termination shall be subject to the requirements and
penalties of the U.S. Copyright Act, 17 U.S.C. - 101 et seq., the
equivalent laws of other countries, and international treaty. This
section shall survive the termination of this License.
12) *Attorneys Fees.* In any action to enforce the terms of this License
or seeking damages relating thereto, the prevailing party shall be
entitled to recover its costs and expenses, including, without
limitation, reasonable attorneys' fees and costs incurred in connection
with such action, including any appeal of such action. This section
shall survive the termination of this License.
13) *Miscellaneous.* This License represents the complete agreement
concerning the subject matter hereof. If any provision of this License
is held to be unenforceable, such provision shall be reformed only to
the extent necessary to make it enforceable.
14) *Definition of "You" in This License.* "You" throughout this
License, whether in upper or lower case, means an individual or a legal
entity exercising rights under, and complying with all of the terms of,
this License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with you. For
purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether
by contract or otherwise, or (ii) ownership of fifty percent (50%) or
more of the outstanding shares, or (iii) beneficial ownership of such
entity.
15) *Right to Use.* You may use the Original Work in all ways not
otherwise restricted or conditioned by this License or by law, and
Licensor promises not to interfere with or be responsible for such uses
by You.
This license is Copyright (C) 2003 Lawrence E. Rosen. All rights
reserved. Permission is hereby granted to copy and distribute this
license without modification. This license may not be modified without
the express written permission of its copyright owner.

View File

@ -26,7 +26,7 @@ LD_FLAGS = $(CLINK) $(ALIGN) $(SHARED) $(ENTRYPOINT) $(STRIP)
LD_DIRS = -L$(PREFIX)/i386-pc-xbox/lib -L$(PREFIX)/lib
LD_LIBS = $(LD_DIRS) -lmscorlib -lm -lopenxdk -lhal -lc -lusb -lc -lxboxkrnl -lc -lhal -lxboxkrnl -lhal -lopenxdk -lc -lgcc -lstdc++
OBJS = CancelEventArgs.o Debug.o DnsEndPoint.o EndPoint.o IPAddress.o IPEndPoint.o NetworkChange.o NetworkInterface.o Socket.o SocketAddress.o SocketAsyncEventArgs.o Stopwatch.o
OBJS = CancelEventArgs.o Debug.o DnsEndPoint.o EndPoint.o IPAddress.o IPEndPoint.o NetworkChange.o NetworkInterface.o pktdrv.o Socket.o SocketAddress.o SocketAsyncEventArgs.o Stopwatch.o
all: libSystem.a

968
src/libSystem/pktdrv.c Normal file
View File

@ -0,0 +1,968 @@
// XBOX low level network interface driver (packet driver)
// =======================================================
// Minimum capabilites : send and receive ethernet packets
// Based on forcedeth Linux nForce driver
// Ring of buffers for received packets is handled by driver.
// Ring of buffers for sent packets must be handled by yourself.
// Driver will only handle the ring of descriptors for them.
// i.e Call Pktdrv_SendPacket with a buffer address taken among
// your ring of n buffers in a circular way and always verify
// that Pktdrv_GetQueuedTxPkts()<n before calling Pktdrv_SendPacket
// In most case, people will just handle n=1 buffer for sending.
// Buffers must be contiguous memory buffers (use Mm fonction).
// int Pktdrv_Callback(unsigned char *packetaddr, unsigned int packetsize)
// has to be defined in your code. Check frequently the number of pkts
// your callback accepted with Pktdrv_ReceivePackets() to trigger calls.
// (NBBUFF pkts will be safely stored until you decide to check for them)
// return 0 if you couldn't receive packet (will be kept for next time).
// In MyPktdrvDpc you can uncomment a line in order to have your callback
// called as soon as a packet arrives (your callback will be called by
// a DPC which means you don't need to be reentrant but you shouldn't
// mess with fpu unless you save and restore fpu processor state)
#include <hal/xbox.h>
#include <openxdk/debug.h>
#include <xboxkrnl/xboxkrnl.h>
#include "string.h"
#include "stdio.h"
#include <stdlib.h>
#include <memory.h>
#include "pktdrv.h"
//#define DISPLAYMSG
// Defines number of Rx & Tx descriptors, and number of buffers -ring- for received pkts
#define NBBUFF 32
extern unsigned long times(void *);
// temporary dirty interface
extern int something_to_send;
extern unsigned char *packet_to_send;
extern unsigned int size_of_packet_to_send;
extern int Pktdrv_Callback(unsigned char *packetaddr, unsigned int packetsize);
#define MIN(a,b) (((a) < (b))? (a) : (b))
struct s_MyStructures
{
char MyContext[1];
unsigned char NbrRxBuffersWithoutCheck;
unsigned char Ethaddr[6];
unsigned char Ethaddr2[6];
unsigned char Ethaddr_reversed[6];
KDPC MyPktdrvDpcObject;
ULONG PktdrvIsrCounter;
KIRQL IrqLevel;
ULONG Vector;
ULONG Speed;
ULONG OldPhyState;
ULONG PhysicalMinusVirtual; // = buffers_physaddr - buffers_addrs;
ULONG NbrRxBuffers;
ULONG RxBufferDesc; //= buffers_addr + 2048;
ULONG RxBufferTail; //= buffers_addr + 2048 + g_s->NbrRxBuffers * 8 - 8;
ULONG RxBufferNext; //= buffers_addr + 2048; //Point to next incoming packet entry
ULONG NbrTxBuffers;
ULONG TxBufferDesc; //= buffers_addr;
ULONG TxBufferLast; //= buffers_addr; //Points to last sent packet(s) to check
ULONG TxBufferNext; //= buffers_addr; //Points to next packet to send entry
ULONG TxBufferTail; //= buffers_addr + 8 * g_s->NbrTxBuffers - 8;
ULONG QueuedTxPkts;
};
static int g_running=0;
static struct s_MyStructures *g_s;
static KINTERRUPT s_MyInterruptObject;
// Types and descriptions coming from
// - ntddk.h (WinXP SP1 DDK)
// - winddk.h (Reactos source)
// - forcedeth.c (Linux NVidia nForce driver)
/*
* Hardware registers:
*/
enum
{
NvRegIrqStatus = 0x000,
#define NVREG_IRQSTAT_BIT0EVENT 0x002
#define NVREG_IRQSTAT_BIT1EVENT 0x004
#define NVREG_IRQSTAT_BIT2EVENT 0x008
#define NVREG_IRQSTAT_MIIEVENT 0x040
#define NVREG_IRQSTAT_UNKEVENT 0x080
#define NVREG_IRQSTAT_MASK 0x1FF
NvRegIrqMask = 0x004,
#define NVREG_IRQ_RX_ERROR 0x0001
#define NVREG_IRQ_RX 0x0002
#define NVREG_IRQ_RX_NOBUF 0x0004
#define NVREG_IRQ_TX_ERROR 0x0008
#define NVREG_IRQ_TX_OK 0x0010
#define NVREG_IRQ_TIMER 0x0020
#define NVREG_IRQ_LINK 0x0040
#define NVREG_IRQ_RX_FORCED 0x0080
#define NVREG_IRQ_TX_FORCED 0x0100
#define NVREG_IRQMASK_THROUGHPUT 0x00DF
#define NVREG_IRQMASK_CPU 0x0040
#define NVREG_IRQ_TX_ALL 0x0118
//=(NVREG_IRQ_TX_ERROR|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_FORCED)
#define NVREG_IRQ_RX_ALL 0x0087
//=(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_RX_FORCED)
#define NVREG_IRQ_OTHER 0x0060
//=(NVREG_IRQ_TIMER|NVREG_IRQ_LINK)
#define NVREG_IRQ_UNKNOWN 0x01FF
//=(~
// (
// NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|
// NVREG_IRQ_TX_ERROR|NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|
// NVREG_IRQ_LINK|NVREG_IRQ_RX_FORCED|NVREG_IRQ_TX_FORCED
// )
// )
NvRegUnknownSetupReg6 = 0x008,
#define NVREG_UNKSETUP6_VAL 3
/*
* NVREG_POLL_DEFAULT is the interval length of the timer source on the Pktdrv
* NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms
*/
NvRegPollingInterval = 0x00c,
#define NVREG_POLL_DEFAULT_THROUGHPUT 970
#define NVREG_POLL_DEFAULT_CPU 013
NvRegMSIMap0 = 0x020,
NvRegMSIMap1 = 0x024,
NvRegMSIIrqMask = 0x030,
#define NVREG_MSI_VECTOR_0_ENABLED 0x001
NvRegMacReset = 0x03c,
#define NVREG_MAC_RESET_ASSERT 0x0F3
NvRegDuplexMode = 0x080,
#define NVREG_DUPLEX_MODE_HDFLAG 0x00000002
#define NVREG_DUPLEX_MODE_FORCEF 0x003B0F3C
#define NVREG_DUPLEX_MODE_FORCEH 0x003B0F3E
#define NVREG_DUPLEX_MODE_FDMASK 0xFFFFFFFD
NvRegTransmitterControl = 0x084,
#define NVREG_SendCTL_START 0x01
NvRegTransmitterStatus = 0x088,
#define NVREG_SendSTAT_BUSY 0x01
NvRegPacketFilterFlags = 0x08c,
#define NVREG_PFF_ALWAYS 0x7F0008
#define NVREG_PFF_PROMISC 0x000080
#define NVREG_PFF_MYADDR 0x000020
#define NVREG_PFF_ALWAYS_MYADDR 0x7F0020
NvRegOffloadConfig = 0x090,
#define NVREG_OFFLOAD_HOMEPHY 0x601
#define NVREG_OFFLOAD_NORMAL 0x5EE
NvRegReceiverControl = 0x094,
#define NVREG_RCVCTL_START 0x01
NvRegReceiverStatus = 0x098,
#define NVREG_RCVSTAT_BUSY 0x01
NvRegRandomSeed = 0x09c,
#define NVREG_RNDSEED_MASK 0x00FF
#define NVREG_RNDSEED_FORCE 0x7F00
#define NVREG_RNDSEED_FORCE2 0x2D00
#define NVREG_RNDSEED_FORCE3 0x7400
NvRegUnknownSetupReg1 = 0x0A0,
#define NVREG_UNKSETUP1_VAL 0x16070F
NvRegUnknownSetupReg2 = 0x0A4,
#define NVREG_UNKSETUP2_VAL 0x16
NvRegMacAddrA = 0x0A8,
NvRegMacAddrB = 0x0AC,
NvRegMulticastAddrA = 0x0B0,
#define NVREG_MCASTADDRA_FORCE 0x01
NvRegMulticastAddrB = 0x0B4,
NvRegMulticastMaskA = 0x0B8,
NvRegMulticastMaskB = 0x0BC,
NvRegPhyInterface = 0x0C0,
#define PHY_RGMII 0x10000000
NvRegTxRingPhysAddr = 0x100,
NvRegRxRingPhysAddr = 0x104,
NvRegRingSizes = 0x108,
#define NVREG_RINGSZ_TXSHIFT 0
#define NVREG_RINGSZ_RXSHIFT 16
NvRegUnkTransmitterReg = 0x10c,
NvRegLinkSpeed = 0x110,
#define NVREG_LINKSPEED_FORCE 0x10000
#define NVREG_LINKSPEED_10MBPS 1000
#define NVREG_LINKSPEED_100MBPS 100
#define NVREG_LINKSPEED_1000MBPS 50
#define NVREG_LINKSPEED_MASK 0xFFF
NvRegUnknownSetupReg5 = 0x130,
#define NVREG_UNKSETUP5_BIT31 (1<<31)
NvRegUnknownSetupReg3 = 0x13C,
#define NVREG_UNKSETUP3_VAL1 0x200010
NvRegUnknownSetupReg7 = 0x140,
#define NVREG_UNKSETUP7_VAL1 0x300010
NvRegTxRxControl = 0x144,
#define NVREG_TXRXCTL_KICK 0x0001
#define NVREG_TXRXCTL_BIT1 0x0002
#define NVREG_TXRXCTL_BIT2 0x0004
#define NVREG_TXRXCTL_IDLE 0x0008
#define NVREG_TXRXCTL_RESET 0x0010
#define NVREG_TXRXCTL_RXCHECK 0x0400
#define NVREG_TXRXCTL_DESC_1 0x0000
#define NVREG_TXRXCTL_DESC_2 0x2100
#define NVREG_TXRXCTL_DESC_3 0x2200
#define NVREG_TXRXCTL_VLANSTRIP 0x0040
#define NVREG_TXRXCTL_VLANINS 0x0080
NvRegTxRingPhysAddrHigh = 0x148,
NvRegRxRingPhysAddrHigh = 0x14C,
NvRegMIIStatus = 0x180,
#define NVREG_MIISTAT_ERROR 0x0001
#define NVREG_MIISTAT_LINKCHANGE 0x0008
#define NVREG_MIISTAT_MASK 0x000F
#define NVREG_MIISTAT_MASK2 0x000F
NvRegUnknownSetupReg4 = 0x184,
#define NVREG_UNKSETUP4_VAL 8
NvRegAdapterControl = 0x188,
#define NVREG_ADAPTCTL_START 0x02
#define NVREG_ADAPTCTL_LINKUP 0x04
#define NVREG_ADAPTCTL_PHYVALID 0x40000
#define NVREG_ADAPTCTL_RUNNING 0x100000
#define NVREG_ADAPTCTL_PHYSHIFT 24
NvRegMIISpeed = 0x18c,
#define NVREG_MIISPEED_BIT8 (1<<8)
#define NVREG_MIIDELAY 5
NvRegMIIControl = 0x190,
#define NVREG_MIICTL_INUSE 0x08000
#define NVREG_MIICTL_WRITE 0x00400
#define NVREG_MIICTL_ADDRSHIFT 5
NvRegMIIData = 0x194,
NvRegWakeUpFlags = 0x200,
#define NVREG_WAKEUPFLAGS_VAL 0x7770
#define NVREG_WAKEUPFLAGS_BUSYSHIFT 24
#define NVREG_WAKEUPFLAGS_ENABLESHIFT 16
#define NVREG_WAKEUPFLAGS_D3SHIFT 12
#define NVREG_WAKEUPFLAGS_D2SHIFT 8
#define NVREG_WAKEUPFLAGS_D1SHIFT 4
#define NVREG_WAKEUPFLAGS_D0SHIFT 0
#define NVREG_WAKEUPFLAGS_ACCEPT_MAGPAT 0x01
#define NVREG_WAKEUPFLAGS_ACCEPT_WAKEUPPAT 0x02
#define NVREG_WAKEUPFLAGS_ACCEPT_LINKCHANGE 0x04
#define NVREG_WAKEUPFLAGS_ENABLE 0x1111
NvRegPatternCRC = 0x204,
NvRegPatternMask = 0x208,
NvRegPowerCap = 0x268,
#define NVREG_POWERCAP_D3SUPP (1<<30)
#define NVREG_POWERCAP_D2SUPP (1<<26)
#define NVREG_POWERCAP_D1SUPP (1<<25)
NvRegPowerState = 0x26c,
#define NVREG_POWERSTATE_POWEREDUP 0x8000
#define NVREG_POWERSTATE_VALID 0x0100
#define NVREG_POWERSTATE_MASK 0x0003
#define NVREG_POWERSTATE_D0 0x0000
#define NVREG_POWERSTATE_D1 0x0001
#define NVREG_POWERSTATE_D2 0x0002
#define NVREG_POWERSTATE_D3 0x0003
NvRegVlanControl = 0x300,
#define NVREG_VLANCONTROL_ENABLE 0x2000
NvRegMSIXMap0 = 0x3E0,
NvRegMSIXMap1 = 0x3E4,
NvRegMSIXIrqStatus = 0x3F0,
NvRegPowerState2 = 0x600,
#define NVREG_POWERSTATE2_POWERUP_MASK 0x0F11
#define NVREG_POWERSTATE2_POWERUP_REV_A3 0x0001
};
#define EEPROM_INDEX_MACADDR 0x101
#define FLAG_MASK_V1 0xffff0000
#define LEN_MASK_V1 (0xffffffff ^ FLAG_MASK_V1)
#define NV_TX_LASTPACKET (1<<16)
#define NV_TX_RETRYERROR (1<<19)
#define NV_TX_FORCED_INTERRUPT (1<<24)
#define NV_TX_DEFERRED (1<<26)
#define NV_TX_CARRIERLOST (1<<27)
#define NV_TX_LATECOLLISION (1<<28)
#define NV_TX_UNDERFLOW (1<<29)
#define NV_TX_ERROR (1<<30)
#define NV_TX_VALID (1<<31)
#define NV_RX_DESCRIPTORVALID (1<<16)
#define NV_RX_MISSEDFRAME (1<<17)
#define NV_RX_SUBSTRACT1 (1<<18)
#define NV_RX_ERROR1 (1<<23)
#define NV_RX_ERROR2 (1<<24)
#define NV_RX_ERROR3 (1<<25)
#define NV_RX_ERROR4 (1<<26)
#define NV_RX_CRCERR (1<<27)
#define NV_RX_OVERFLOW (1<<28)
#define NV_RX_FRAMINGERR (1<<29)
#define NV_RX_ERROR (1<<30)
#define NV_RX_AVAIL (1<<31)
// PhyGetLinkState
#define PHY_LINK_RUNNING 0x01
#define PHY_LINK_100MBPS 0x02
#define PHY_LINK_10MBPS 0x04
#define PHY_LINK_FULL_DUPLEX 0x08
#define PHY_LINK_HALF_DUPLEX 0x10
// Register access macros for XBOX
#define BASE 0xFEF00000
#define REG(x) (*((DWORD *)(BASE+(x))))
#define REGW(x) (*((WORD *)(BASE+(x))))
#define REGB(x) (*((BYTE *)(BASE+(x))))
typedef enum _MEMORY_CACHING_TYPE_ORIG
{
MmFrameBufferCached = 2
} MEMORY_CACHING_TYPE_ORIG;
typedef enum _MEMORY_CACHING_TYPE
{
MmNonCached = 0,
MmCached = 1,
MmWriteCombined = MmFrameBufferCached,
MmHardwareCoherentCached,
MmNonCachedUnordered, // IA64
MmUSWCCached,
MmMaximumCacheType
} MEMORY_CACHING_TYPE;
/*
MmNonCached : The requested memory should not be cached by the processor.
MmCached : The processor should cache the requested memory.
MmWriteCombined : The requested memory should not be cached by the processor,
but writes to the memory can be combined by the processor.
*/
// Checks for possible received packets
static int PktdrvRecvInterrupt(void)
{
ULONG p;
ULONG flag;
BOOLEAN fatal;
int handled;
int n=0;
// Look for next entry in Rx ring and read its flag
while(1)
{
p = g_s->RxBufferNext;
flag = *((ULONG *)(p + 4));
if (flag & NV_RX_AVAIL) return n; //we received nothing!
if ((flag & NV_RX_DESCRIPTORVALID) == 0)
{
// Not a received packet
}
else
{
fatal = FALSE;
if (flag & NV_RX_ERROR)
{
if (flag & NV_RX_FRAMINGERR) { /* not fatal */ }
if (flag & NV_RX_OVERFLOW) { fatal = TRUE; }
if (flag & NV_RX_CRCERR) { fatal = TRUE; }
if (flag & NV_RX_ERROR4) { fatal = TRUE; }
if (flag & NV_RX_ERROR3) { fatal = TRUE; }
if (flag & NV_RX_ERROR2) { fatal = TRUE; }
if (flag & NV_RX_ERROR1) { fatal = TRUE; }
}
if (!fatal)
{
//Call user callback and warn that a packet has been received
//Phys Addr of packet is *p
//Length of packet is 1 up to 2046 bytes
//Length = ( (*((ULONG *)(p+4))) & 0x7FF ) + 1
handled = Pktdrv_Callback(
(unsigned char *)((*((ULONG *)p)) - g_s->PhysicalMinusVirtual),
(unsigned int)(((*((ULONG *)(p + 4))) & 0x7FF ) + 1 ));
if (!handled)
return n; //We probably lack space up there
else
n++;
}
}
//Empty the entry
*((ULONG *)(p + 4)) = NV_RX_AVAIL | 2045;
//Have RxBufferNext Point to next entry in ring
if (g_s->RxBufferNext == g_s->RxBufferTail) //return to start of ring?
g_s->RxBufferNext = g_s->RxBufferDesc;
else
g_s->RxBufferNext += 8;
};
return n;
}
// Detects if Tx ring is full or not
static BOOLEAN PktdrvSendReady(void)
{
return (g_s->QueuedTxPkts != g_s->NbrTxBuffers);
}
// Checks for a patcket to send
static void PktdrvSendInterrupt(void)
{
ULONG p, flag;
// Before we send any packet, let's check if last packets have been sent
while (g_s->TxBufferLast != g_s->TxBufferNext)
{
p = g_s->TxBufferLast;
flag = *((ULONG *)(p + 4));
if ((flag & NV_TX_VALID) == 0)
{
//Packet is gone, reduce counter and check next one.
//Note that errors and actual number of bytes sent
//can be read from flag right now and right here!
//Actual number is higher because of padding...
g_s->QueuedTxPkts--;
//Let's cleanup
*((ULONG *)p) = 0;
*((ULONG *)(p + 4)) = 0;
//Have TxBufferLast point to next entry
if (g_s->TxBufferLast == g_s->TxBufferTail)
g_s->TxBufferLast = g_s->TxBufferDesc;
else
g_s->TxBufferLast += 8;
}
else
break; //packet not sent already, we will check later
}
}
static void PktdrvSendPacket(unsigned char *buffer, int length)
{
ULONG p;
if (PktdrvSendReady()) // Do we have room in the Tx ring?
{
// p points to next free entry of Tx ring descriptor
p = g_s->TxBufferNext;
MmLockUnlockBufferPages(
(ULONG)buffer,
length,
0);
*((ULONG *)p) = MmGetPhysicalAddress(buffer);
*((ULONG *)(p + 4)) = (length-1) | NV_TX_VALID | NV_TX_LASTPACKET;
g_s->QueuedTxPkts++;
//Have TxBufferNext point to next entry
if (g_s->TxBufferNext == g_s->TxBufferTail) //return to start of ring?
g_s->TxBufferNext = g_s->TxBufferDesc;
else
g_s->TxBufferNext += 8;
REG(NvRegTxRxControl) = NVREG_TXRXCTL_KICK;
}
else
{
//Tx ring is full
//User should do : while(Xnet_GetQueuedPkts()>=n) { /*wait*/ }; then send pkt
//That will prevent the loss of sent packet right here
//Where n is the number of buffers (ring) where pending outcoming packets are
//stored. In most case n=1 (just one buffer is used to send 1 packet at a time)
}
}
// Starts Pktdrv
static void PktdrvStartSendRecv(void)
{
REG(NvRegLinkSpeed) = NVREG_LINKSPEED_FORCE | g_s->Speed;
REG(NvRegTransmitterControl) = NVREG_SendCTL_START;
REG(NvRegReceiverControl) = NVREG_RCVCTL_START;
REG(NvRegTxRxControl) = NVREG_TXRXCTL_KICK | NVREG_TXRXCTL_BIT1;
}
//Stops Pktdrv
static void PktdrvStopSendRecv(void)
{
int i;
REG(NvRegLinkSpeed) = 0;
REG(NvRegReceiverControl) = 0;
REG(NvRegTransmitterControl) = 0;
for (i = 0; i < 500; i++)
{
if (((REGB(NvRegReceiverStatus) & NVREG_RCVSTAT_BUSY) == 0) &&
((REGB(NvRegTransmitterStatus) & NVREG_SendSTAT_BUSY) == 0))
break;
KeStallExecutionProcessor(10); //Wait 10 microseconds
}
REG(NvRegTxRxControl) = NVREG_TXRXCTL_BIT2;
for (i = 0; i < 100000; i++)
{
if (REGB(NvRegTxRxControl) & NVREG_TXRXCTL_IDLE) break;
KeStallExecutionProcessor(10);
}
REG(NvRegTxRxControl) = 0;
}
// Resets Pktdrv
static void PktdrvReset(void)
{
PktdrvStopSendRecv();
REG(NvRegTxRxControl) = NVREG_TXRXCTL_RESET;
KeStallExecutionProcessor(10); // 10 microseconds of busy-wait
REG(NvRegTxRxControl) = 0;
KeStallExecutionProcessor(10);
REG(NvRegUnknownSetupReg4) = 0;
REG(NvRegIrqMask) = 0;
REG(NvRegWakeUpFlags) = 0;
REG(NvRegUnknownSetupReg6) = 0;
REG(NvRegTxRingPhysAddr) = 0;
REG(NvRegRxRingPhysAddr) = 0;
REG(NvRegUnkTransmitterReg) = 0;
REG(NvRegLinkSpeed) = 0;
REG(NvRegTransmitterStatus) = REG(NvRegTransmitterStatus);
REG(NvRegReceiverStatus) = REG(NvRegReceiverStatus);
REG(NvRegMIIStatus) = REG(NvRegMIIStatus);
REG(NvRegIrqStatus) = REG(NvRegIrqStatus);
}
// Checks possible speed or duplex mode change
static void PktdrvMiiInterrupt(int mode)
{
// Verifies if speed or duplex mode changed
// mode=1 -> startup mode (calls PhyGetLinkState(0))
// (used at startup, before Pktdrv driver is started)
// mode=0 -> running mode (calls PhyGetLinkState(1))
// (used in interrupt, while Pktdrv driver is running)
ULONG state,dummy;
mode &= 1; // only 0 or 1 is accepted
dummy = REG(NvRegAdapterControl); // just read it
state = PhyGetLinkState(1 - mode);
if ((mode == 0) && (state == g_s->OldPhyState)) return; // All is ok, remain silent
//We want details (startup) or state changed (both modes)
#ifdef DISPLAYMSG
debugPrint("Transceiver link state :\n");
if (state & PHY_LINK_RUNNING)
debugPrint(" Running at ");
else
debugPrint(" NOT running at ");
if (state & PHY_LINK_100MBPS)
debugPrint("100 Mbps ");
else
if (state & PHY_LINK_10MBPS)
debugPrint("10 Mbps ");
else
debugPrint("unknown speed ");
if (state & PHY_LINK_FULL_DUPLEX)
debugPrint("in full duplex mode\n");
else
if (state & PHY_LINK_HALF_DUPLEX)
debugPrint("in half duplex mode\n");
else
debugPrint("in unknown duplex mode\n");
#endif
if (mode == 0) PktdrvStopSendRecv(); // Pktdrv is running. Stop it.
if (state & PHY_LINK_10MBPS) // update Speed member in structure
g_s->Speed = NVREG_LINKSPEED_10MBPS; // decimal value 1000!!!
else
g_s->Speed = NVREG_LINKSPEED_100MBPS; // decimal value 100
if (state & PHY_LINK_FULL_DUPLEX) // update mode in Pktdrv register
REG(NvRegDuplexMode) &= NVREG_DUPLEX_MODE_FDMASK;
else
REG(NvRegDuplexMode) |= NVREG_DUPLEX_MODE_HDFLAG;
if (mode == 0) PktdrvStartSendRecv(); // Mode changed. Restart Pktdrv.
// This function will read g_s->Speed and program speed link register.
g_s->OldPhyState = state;
}
static BOOLEAN __stdcall MyPktdrvIsr(PKINTERRUPT Interrupt, PVOID ServiceContext)
{
REG(NvRegIrqMask) = 0;
if (g_running)
{
KeInsertQueueDpc(&g_s->MyPktdrvDpcObject,NULL,NULL);
g_s->PktdrvIsrCounter++;
}
return TRUE;
}
static void __stdcall MyPktdrvDpc
(
PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2
)
{
// DPCs allow to use non reentrant procedures (called sequentially, FOR SURE).
// CAUTION : if you use fpu in DPC you have to save & restore yourself fpu state!!!
// (fpu=floating point unit, i.e the coprocessor executing floating point opcodes)
ULONG irq_status;
ULONG mii_status;
if (g_running == 0) return;
mii_status = 0;
irq_status = NVREG_IRQSTAT_BIT0EVENT |
NVREG_IRQSTAT_BIT1EVENT |
NVREG_IRQSTAT_BIT2EVENT |
NVREG_IRQSTAT_UNKEVENT;
while (irq_status)
{
if (irq_status & NVREG_IRQSTAT_MIIEVENT) PktdrvMiiInterrupt(0);
REG(NvRegMIIStatus) = mii_status;
REG(NvRegIrqStatus) = irq_status;
//uncomment this line if you want your callback to be called as soon as packet arrived
// PktdrvRecvInterrupt(); //Check if we received packets // (let them stock up)
PktdrvSendInterrupt(); //Check if we have a packet to send
if (irq_status & NVREG_IRQSTAT_BIT1EVENT)
{
REG(NvRegTxRxControl) = NVREG_TXRXCTL_BIT1;
}
mii_status = REG(NvRegMIIStatus);
irq_status = REG(NvRegIrqStatus);
};
REG(NvRegIrqMask) = NVREG_IRQ_LINK |
NVREG_IRQ_TX_OK |
NVREG_IRQ_TX_ERROR |
NVREG_IRQ_RX_NOBUF |
NVREG_IRQ_RX |
NVREG_IRQ_RX_ERROR;
return;
}
void Pktdrv_Quit(void)
{
if (g_running == 0) return;
g_running = 0;
PktdrvStopSendRecv();
PktdrvReset();
KeDisconnectInterrupt(&s_MyInterruptObject);
MmFreeContiguousMemory((void *)g_s->TxBufferDesc);
free(g_s);
}
// Returns 1 if everything is ok
int Pktdrv_Init(void)
{
int n,len,type;
ULONG buffers_addr;
ULONG buffers_physaddr;
ULONG status;
ULONG buffers_total_size;
ULONG p,p2;
ULONG RandomValue;
if (g_running == 1) return 1;
g_s = (struct s_MyStructures *)malloc(sizeof(struct s_MyStructures));
// g_s holds the various needed structures
if (!g_s)
{
debugPrint("Can't allocate global structure.\n");
return 0;
}
g_s->Vector = HalGetInterruptVector(4,&g_s->IrqLevel);
KeInitializeDpc(&g_s->MyPktdrvDpcObject,&MyPktdrvDpc,&g_s->MyContext);
KeInitializeInterrupt(&s_MyInterruptObject,
&MyPktdrvIsr,
&g_s->MyContext,
g_s->Vector,
g_s->IrqLevel,
LevelSensitive,
TRUE);
PktdrvReset();
g_s->NbrRxBuffersWithoutCheck = NBBUFF; //Total buffers = NBBUFF+2 (Tx&Rx Descriptors)
n = g_s->NbrRxBuffersWithoutCheck;
g_s->NbrRxBuffers = MIN(n,256);
g_s->NbrTxBuffers = MIN(n,256);
//Rx ring will point to the pool of n allocated buffers
//Tx ring is empty at startup may point to any contiguous buffer physical address
buffers_total_size = ((n + 1 + 1) << 11);
//allocates n+1+1 DMA buffers 2048 bytes each
buffers_addr = (ULONG)MmAllocateContiguousMemoryEx(
buffers_total_size,
0, //lowest acceptable
0x10000, //highest acceptable
0, //no need to align to specific boundaries multiple
MmNonCachedUnordered); //4
if (!buffers_addr)
buffers_addr=(ULONG)MmAllocateContiguousMemoryEx(
buffers_total_size,
0, //lowest acceptable
0xFFFFFFFF, //highest acceptable
0, //no need to align to specific boundaries multiple
MmNonCachedUnordered); //4
if (!buffers_addr)
{
debugPrint("Can't allocate DMA reception buffers\n");
free(g_s);
return 0;
}
//Write zeroes in first buffer and second buffer (descriptors)
memset((void *)buffers_addr, 0, 4096);
buffers_physaddr = MmGetPhysicalAddress((void *)buffers_addr);
g_s->PhysicalMinusVirtual = buffers_physaddr - buffers_addr;
g_s->RxBufferDesc = buffers_addr + 2048;
g_s->RxBufferNext = buffers_addr + 2048;
g_s->RxBufferTail = buffers_addr + 2048 + g_s->NbrRxBuffers * 8 - 8;
g_s->TxBufferDesc = buffers_addr;
g_s->TxBufferLast = buffers_addr;
g_s->TxBufferNext = buffers_addr;
g_s->TxBufferTail = buffers_addr + 8 * g_s->NbrTxBuffers - 8;
p = buffers_addr + 4096 + 2 + g_s->PhysicalMinusVirtual; //Points 1st buffer at offset 2
p2 = buffers_addr + 2048;
while(p2 <= g_s->RxBufferTail)
{
*((DWORD *)p2) = p; //Physical address of offset 2 of buffer
*((DWORD *)(p2 + 4)) = NV_RX_AVAIL | 2045; //Makes all Rx buffers available
//2046 bytes available for incoming packet at offset 2
p2 += 8;
p += 2048;
};
//Buffers description :
//1st buffer is a list of n pointers+flags (every 8 bytes) and is Tx ring descriptor
//2nd buffer is a list of n pointers+flags (every 8 bytes) and is Rx ring descriptor
//3rd buffer and following ones are pointed by the Rx ring pointers (at offset 2)
//(n buffers used for packet receiving at startup while Tx ring is all zeroed)
//Total : 1+1+n buffers
//Descriptor is a list of 8 bytes values (a 32 bits physical address + a 32 bits flag)
//The flag has the length (minus one) of available room/received packet/to send packet
//in the lower 11 bits of the 32 bits flag
len = 0;
ExQueryNonVolatileSetting(EEPROM_INDEX_MACADDR, &type, g_s->Ethaddr, 6, &len);
if (len != 6)
debugPrint("Can't read ethernet address from EEPROM\n");
#ifdef DISPLAYMSG
else
debugPrint("EEPROM MacAddress = %02x %02x %02x %02x %02x %02x\n",
g_s->Ethaddr[0],
g_s->Ethaddr[1],
g_s->Ethaddr[2],
g_s->Ethaddr[3],
g_s->Ethaddr[4],
g_s->Ethaddr[5]);
#endif
g_s->Speed = NVREG_LINKSPEED_100MBPS;
g_s->Ethaddr_reversed[0] = g_s->Ethaddr[5];
g_s->Ethaddr_reversed[1] = g_s->Ethaddr[4];
g_s->Ethaddr_reversed[2] = g_s->Ethaddr[3];
g_s->Ethaddr_reversed[3] = g_s->Ethaddr[2];
g_s->Ethaddr_reversed[4] = g_s->Ethaddr[1];
g_s->Ethaddr_reversed[5] = g_s->Ethaddr[0];
//Writing the MAC address (6 bytes ethernet address)
REG(NvRegMacAddrA) = *((DWORD *)&g_s->Ethaddr_reversed[0]);
REG(NvRegMacAddrB) = (ULONG)(*((WORD *)&g_s->Ethaddr_reversed[4]));
REG(NvRegMulticastMaskA) = 0xFFFFFFFF;
REG(NvRegMulticastMaskB) = 0x0000FFFF;
REG(NvRegMulticastAddrA) = *((DWORD *)&g_s->Ethaddr[0]); //Yes, not reversed!
REG(NvRegMulticastAddrB) = (ULONG)(*((WORD *)&g_s->Ethaddr[4]));
RandomValue = times(0) + 0x1234 + *((DWORD *)g_s->Ethaddr) + *((WORD *)&g_s->Ethaddr[4]);
//In case of ethernet colision, random duration pauses are used before retry
REG(NvRegRandomSeed) = (RandomValue & NVREG_RNDSEED_MASK) | NVREG_RNDSEED_FORCE;
REG(NvRegOffloadConfig) = NVREG_OFFLOAD_NORMAL; //1518 bytes
REG(NvRegPacketFilterFlags) = NVREG_PFF_ALWAYS_MYADDR;
REG(NvRegDuplexMode) = NVREG_DUPLEX_MODE_FORCEH;
REG(NvRegUnknownSetupReg1) = NVREG_UNKSETUP1_VAL;
REG(NvRegUnknownSetupReg2) = NVREG_UNKSETUP2_VAL;
//Writing the DMA buffers addresses and sizes
REG(NvRegTxRingPhysAddr) = g_s->TxBufferDesc + g_s->PhysicalMinusVirtual; // 1st buf phys
REG(NvRegRxRingPhysAddr) = g_s->RxBufferDesc + g_s->PhysicalMinusVirtual; // 2nd buf phys
REG(NvRegRingSizes) = ((g_s->NbrRxBuffers - 1) << 16) | (g_s->NbrTxBuffers - 1);
REG(NvRegUnknownSetupReg7) = NVREG_UNKSETUP7_VAL1;
REG(NvRegUnknownSetupReg3) = NVREG_UNKSETUP7_VAL1; //Yes, Val7 into Reg3!
REG(NvRegAdapterControl) = (1 << NVREG_ADAPTCTL_PHYSHIFT) | NVREG_ADAPTCTL_PHYVALID;
REG(NvRegMIISpeed) = NVREG_MIISPEED_BIT8 | NVREG_MIIDELAY;
KeStallExecutionProcessor(50); //50 micro seconds of busy-wait
g_running=1;
// XBOX specific (nForce specific)
if (PhyInitialize(0, 0) < 0) // Initialize transceiver
{
debugPrint("PhyInitialize error\n");
Pktdrv_Quit();
return 0;
}
REG(NvRegAdapterControl) = NVREG_ADAPTCTL_RUNNING;
KeStallExecutionProcessor(50);
PktdrvMiiInterrupt(1); //force display/update of current speed and duplex mode
PktdrvStartSendRecv();
REG(NvRegMIIStatus) = REG(NvRegMIIStatus);
REG(NvRegIrqStatus) = REG(NvRegIrqStatus);
REG(NvRegUnknownSetupReg4) = NVREG_UNKSETUP4_VAL;
REG(NvRegIrqMask)= NVREG_IRQ_LINK |
NVREG_IRQ_TX_OK |
NVREG_IRQ_TX_ERROR |
NVREG_IRQ_RX_NOBUF |
NVREG_IRQ_RX |
NVREG_IRQ_RX_ERROR;
status = KeConnectInterrupt(&s_MyInterruptObject);
if (status == 0)
{
debugPrint("KeConnectInterrupt error\n");
Pktdrv_Quit();
return 0;
}
#ifdef DISPLAYMSG
else
debugPrint("Network interruption initialized successfully\n");
#endif
return 1;
}
int Pktdrv_ReceivePackets(void)
{
if (g_running) return PktdrvRecvInterrupt(); //returns nbr of packets accepted by callback
return 0;
}
void Pktdrv_SendPacket(unsigned char *buffer,int length)
{
if (g_running)
{
PktdrvSendInterrupt();
// if QueuedTxPkts>=n (n=number of outgoing buffers -ring- in calling app)
// then packet will not be sent (app has to wait until QueuedTxPkts<n)
PktdrvSendPacket(buffer,length);
}
}
void Pktdrv_GetEthernetAddr(unsigned char *address)
{
if ((address) && (g_running))
{
memcpy(address, g_s->Ethaddr, 6);
}
}
int Pktdrv_GetQueuedTxPkts(void)
{
if (g_running)
{
PktdrvSendInterrupt(); // detects any sent packet and updates QueuedTxPkts
return g_s->QueuedTxPkts;
}
else
return 0;
}

11
src/libSystem/pktdrv.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef _Pktdrv_
#define _Pktdrv_
int Pktdrv_Init(void);
void Pktdrv_Quit(void);
int Pktdrv_ReceivePackets(void);
void Pktdrv_SendPacket(unsigned char *buffer,int length);
void Pktdrv_GetEthernetAddr(unsigned char *address);
int Pktdrv_GetQueuedTxPkts(void);
#endif