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:
parent
da0bfcaa6f
commit
e234c493b4
@ -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];
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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
269
src/libSystem/detect_ping.c
Normal 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();
|
||||
}
|
@ -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" />
|
||||
|
@ -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
166
src/libSystem/license.txt
Normal 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.
|
||||
|
@ -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
968
src/libSystem/pktdrv.c
Normal 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
11
src/libSystem/pktdrv.h
Normal 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
|
Loading…
x
Reference in New Issue
Block a user