Disable XOnline patches and partially implement NVNet emulation. (#703)
Network connection does not work yet but it satisfies titles enough to stop them crashing. Tetris Worlds gets to (very broken) gameplay with this All titles that use Xbox Live, or even System Link are likely to see some improvements.
This commit is contained in:
parent
7bd59bb5b3
commit
b4c45cfccb
|
@ -40,8 +40,16 @@
|
|||
#define _CXBXKRNL_INTERNAL
|
||||
#define _XBOXKRNL_DEFEXTRN_
|
||||
|
||||
// prevent name collisions
|
||||
|
||||
namespace xboxkrnl
|
||||
{
|
||||
#include <xboxkrnl/xboxkrnl.h> // For PKINTERRUPT, etc.
|
||||
};
|
||||
|
||||
#include "CxbxKrnl.h"
|
||||
#include "Emu.h"
|
||||
#include "EmuKrnl.h"
|
||||
#include "EmuNVNet.h"
|
||||
|
||||
// NVNET Register Definitions
|
||||
|
@ -178,6 +186,116 @@ enum {
|
|||
# define NVREG_POWERSTATE_D3 0x0003
|
||||
};
|
||||
|
||||
#define IOPORT_SIZE 0x8
|
||||
#define MMIO_SIZE 0x400
|
||||
|
||||
#define NV_TX_LASTPACKET (1<<0)
|
||||
#define NV_TX_RETRYERROR (1<<3)
|
||||
#define NV_TX_LASTPACKET1 (1<<8)
|
||||
#define NV_TX_DEFERRED (1<<10)
|
||||
#define NV_TX_CARRIERLOST (1<<11)
|
||||
#define NV_TX_LATECOLLISION (1<<12)
|
||||
#define NV_TX_UNDERFLOW (1<<13)
|
||||
#define NV_TX_ERROR (1<<14)
|
||||
#define NV_TX_VALID (1<<15)
|
||||
#define NV_RX_DESCRIPTORVALID (1<<0)
|
||||
#define NV_RX_MISSEDFRAME (1<<1)
|
||||
#define NV_RX_SUBSTRACT1 (1<<3)
|
||||
#define NV_RX_BIT4 (1<<4)
|
||||
#define NV_RX_ERROR1 (1<<7)
|
||||
#define NV_RX_ERROR2 (1<<8)
|
||||
#define NV_RX_ERROR3 (1<<9)
|
||||
#define NV_RX_ERROR4 (1<<10)
|
||||
#define NV_RX_CRCERR (1<<11)
|
||||
#define NV_RX_OVERFLOW (1<<12)
|
||||
#define NV_RX_FRAMINGERR (1<<13)
|
||||
#define NV_RX_ERROR (1<<14)
|
||||
#define NV_RX_AVAIL (1<<15)
|
||||
|
||||
/* Miscelaneous hardware related defines: */
|
||||
#define NV_PCI_REGSZ 0x270
|
||||
|
||||
/* various timeout delays: all in usec */
|
||||
#define NV_TXRX_RESET_DELAY 4
|
||||
#define NV_TXSTOP_DELAY1 10
|
||||
#define NV_TXSTOP_DELAY1MAX 500000
|
||||
#define NV_TXSTOP_DELAY2 100
|
||||
#define NV_RXSTOP_DELAY1 10
|
||||
#define NV_RXSTOP_DELAY1MAX 500000
|
||||
#define NV_RXSTOP_DELAY2 100
|
||||
#define NV_SETUP5_DELAY 5
|
||||
#define NV_SETUP5_DELAYMAX 50000
|
||||
#define NV_POWERUP_DELAY 5
|
||||
#define NV_POWERUP_DELAYMAX 5000
|
||||
#define NV_MIIBUSY_DELAY 50
|
||||
#define NV_MIIPHY_DELAY 10
|
||||
#define NV_MIIPHY_DELAYMAX 10000
|
||||
#define NV_WAKEUPPATTERNS 5
|
||||
#define NV_WAKEUPMASKENTRIES 4
|
||||
|
||||
/* General driver defaults */
|
||||
#define NV_WATCHDOG_TIMEO (2*HZ)
|
||||
#define DEFAULT_MTU 1500
|
||||
|
||||
#define RX_RING 4
|
||||
#define TX_RING 2
|
||||
/* limited to 1 packet until we understand NV_TX_LASTPACKET */
|
||||
#define TX_LIMIT_STOP 10
|
||||
#define TX_LIMIT_START 5
|
||||
|
||||
/* rx/tx mac addr + type + vlan + align + slack*/
|
||||
#define RX_NIC_BUFSIZE (DEFAULT_MTU + 64)
|
||||
/* even more slack */
|
||||
#define RX_ALLOC_BUFSIZE (DEFAULT_MTU + 128)
|
||||
|
||||
#define OOM_REFILL (1+HZ/20)
|
||||
#define POLL_WAIT (1+HZ/100)
|
||||
|
||||
#define MII_READ (-1)
|
||||
#define MII_PHYSID1 0x02 /* PHYS ID 1 */
|
||||
#define MII_PHYSID2 0x03 /* PHYS ID 2 */
|
||||
#define MII_BMCR 0x00 /* Basic mode control register */
|
||||
#define MII_BMSR 0x01 /* Basic mode status register */
|
||||
#define MII_ADVERTISE 0x04 /* Advertisement control reg */
|
||||
#define MII_LPA 0x05 /* Link partner ability reg */
|
||||
|
||||
#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
|
||||
#define BMSR_BIT2 0x0004 /* Unknown... */
|
||||
|
||||
/* Link partner ability register. */
|
||||
#define LPA_SLCT 0x001f /* Same as advertise selector */
|
||||
#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
|
||||
#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
|
||||
#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
|
||||
#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
|
||||
#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */
|
||||
#define LPA_RESV 0x1c00 /* Unused... */
|
||||
#define LPA_RFAULT 0x2000 /* Link partner faulted */
|
||||
#define LPA_LPACK 0x4000 /* Link partner acked us */
|
||||
#define LPA_NPAGE 0x8000 /* Next page bit */
|
||||
|
||||
/*******************************************************************************
|
||||
* Primary State Structure
|
||||
******************************************************************************/
|
||||
|
||||
struct NvNetState {
|
||||
uint8_t regs[MMIO_SIZE / 4];
|
||||
uint32_t phy_regs[6];
|
||||
uint8_t tx_ring_index;
|
||||
uint8_t tx_ring_size;
|
||||
uint8_t rx_ring_index;
|
||||
uint8_t rx_ring_size;
|
||||
uint8_t txrx_dma_buf[RX_ALLOC_BUFSIZE];
|
||||
FILE *packet_dump_file;
|
||||
char *packet_dump_path;
|
||||
} NvNetState;
|
||||
|
||||
struct RingDesc {
|
||||
uint32_t packet_buffer;
|
||||
uint16_t length;
|
||||
uint16_t flags;
|
||||
};
|
||||
|
||||
char* EmuNVNet_GetRegisterName(xbaddr addr)
|
||||
{
|
||||
switch (addr) {
|
||||
|
@ -226,17 +344,28 @@ char* EmuNVNet_GetRegisterName(xbaddr addr)
|
|||
}
|
||||
}
|
||||
|
||||
uint8_t NVNetRegs[NVNET_SIZE];
|
||||
char* EmuNVNet_GetMiiRegisterName(uint8_t reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case MII_PHYSID1: return "MII_PHYSID1";
|
||||
case MII_PHYSID2: return "MII_PHYSID2";
|
||||
case MII_BMCR: return "MII_BMCR";
|
||||
case MII_BMSR: return "MII_BMSR";
|
||||
case MII_ADVERTISE: return "MII_ADVERTISE";
|
||||
case MII_LPA: return "MII_LPA";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t EmuNVNet_GetRegister(xbaddr addr, unsigned int size)
|
||||
{
|
||||
switch (size) {
|
||||
case sizeof(uint32_t) :
|
||||
return ((uint32_t *)NVNetRegs)[addr >> 2];
|
||||
case sizeof(uint16_t) :
|
||||
return ((uint16_t *)NVNetRegs)[addr >> 1];
|
||||
case sizeof(uint8_t) :
|
||||
return NVNetRegs[addr];
|
||||
case sizeof(uint32_t) :
|
||||
return ((uint32_t *)NvNetState.regs)[addr >> 2];
|
||||
case sizeof(uint16_t) :
|
||||
return ((uint16_t *)NvNetState.regs)[addr >> 1];
|
||||
case sizeof(uint8_t) :
|
||||
return NvNetState.regs[addr];
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -245,25 +374,135 @@ uint32_t EmuNVNet_GetRegister(xbaddr addr, unsigned int size)
|
|||
void EmuNVNet_SetRegister(xbaddr addr, uint32_t value, unsigned int size)
|
||||
{
|
||||
switch (size) {
|
||||
case sizeof(uint32_t) :
|
||||
((uint32_t *)NVNetRegs)[addr >> 2] = value;
|
||||
break;
|
||||
case sizeof(uint16_t) :
|
||||
((uint16_t *)NVNetRegs)[addr >> 1] = (uint16_t)value;
|
||||
break;
|
||||
case sizeof(uint8_t) :
|
||||
NVNetRegs[addr] = (uint8_t)value;
|
||||
break;
|
||||
case sizeof(uint32_t):
|
||||
((uint32_t *)NvNetState.regs)[addr >> 2] = value;
|
||||
break;
|
||||
case sizeof(uint16_t):
|
||||
((uint16_t *)NvNetState.regs)[addr >> 1] = (uint16_t)value;
|
||||
break;
|
||||
case sizeof(uint8_t):
|
||||
NvNetState.regs[addr] = (uint8_t)value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void EmuNVNet_UpdateIRQ()
|
||||
{
|
||||
if (EmuNVNet_GetRegister(NvRegIrqMask, 4) &&
|
||||
EmuNVNet_GetRegister(NvRegIrqStatus, 4)) {
|
||||
DbgPrintf("EmuNVNet: Asserting IRQ\n");
|
||||
HalSystemInterrupts[4].Assert(true);
|
||||
} else {
|
||||
HalSystemInterrupts[4].Assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
int EmuNVNet_MiiReadWrite(uint64_t val)
|
||||
{
|
||||
uint32_t mii_ctl;
|
||||
int write, retval, phy_addr, reg;
|
||||
|
||||
retval = 0;
|
||||
mii_ctl = EmuNVNet_GetRegister(NvRegMIIControl, 4);
|
||||
|
||||
phy_addr = (mii_ctl >> NVREG_MIICTL_ADDRSHIFT) & 0x1f;
|
||||
reg = mii_ctl & ((1 << NVREG_MIICTL_ADDRSHIFT) - 1);
|
||||
write = mii_ctl & NVREG_MIICTL_WRITE;
|
||||
|
||||
DbgPrintf("nvnet mii %s: phy 0x%x %s [0x%x]\n", write ? "write" : "read", phy_addr, EmuNVNet_GetMiiRegisterName(reg), reg);
|
||||
|
||||
if (phy_addr != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (write) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
switch (reg) {
|
||||
case MII_BMSR:
|
||||
/* Phy initialization code waits for BIT2 to be set.. If not set,
|
||||
* software may report controller as not running */
|
||||
retval = BMSR_ANEGCOMPLETE | BMSR_BIT2;
|
||||
break;
|
||||
case MII_ADVERTISE:
|
||||
/* Fall through... */
|
||||
case MII_LPA:
|
||||
retval = LPA_10HALF | LPA_10FULL;
|
||||
retval |= LPA_100HALF | LPA_100FULL | LPA_100BASE4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
uint32_t EmuNVNet_Read(xbaddr addr, int size)
|
||||
{
|
||||
DbgPrintf("EmuNVNet_Read%d: %s (0x%08X)\n", size, EmuNVNet_GetRegisterName(addr), addr);
|
||||
|
||||
switch (addr) {
|
||||
case NvRegMIIData:
|
||||
return EmuNVNet_MiiReadWrite(MII_READ);
|
||||
case NvRegMIIControl:
|
||||
return EmuNVNet_GetRegister(addr, size) & ~NVREG_MIICTL_INUSE;
|
||||
case NvRegMIIStatus:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return EmuNVNet_GetRegister(addr,size);
|
||||
}
|
||||
|
||||
void EmuNVNet_Write(xbaddr addr, uint32_t value, int size)
|
||||
{
|
||||
switch (addr) {
|
||||
case NvRegRingSizes:
|
||||
EmuNVNet_SetRegister(addr, value, size);
|
||||
NvNetState.rx_ring_size = ((value >> NVREG_RINGSZ_RXSHIFT) & 0xffff) + 1;
|
||||
NvNetState.tx_ring_size = ((value >> NVREG_RINGSZ_TXSHIFT) & 0xffff) + 1;
|
||||
break;
|
||||
case NvRegMIIData:
|
||||
EmuNVNet_MiiReadWrite(value);
|
||||
break;
|
||||
case NvRegTxRxControl:
|
||||
if (value == NVREG_TXRXCTL_KICK) {
|
||||
DbgPrintf("NvRegTxRxControl = NVREG_TXRXCTL_KICK!\n");
|
||||
EmuWarning("TODO: nvnet_dma_packet_from_guest");
|
||||
// nvnet_dma_packet_from_guest(s);
|
||||
}
|
||||
|
||||
if (value & NVREG_TXRXCTL_BIT2) {
|
||||
EmuNVNet_SetRegister(NvRegTxRxControl, NVREG_TXRXCTL_IDLE, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
if (value & NVREG_TXRXCTL_BIT1) {
|
||||
EmuNVNet_SetRegister(NvRegIrqStatus, 0, 4);
|
||||
break;
|
||||
} else if (value == 0) {
|
||||
uint32_t temp = EmuNVNet_GetRegister(NvRegUnknownSetupReg3, 4);
|
||||
if (temp == NVREG_UNKSETUP3_VAL1) {
|
||||
/* forcedeth waits for this bit to be set... */
|
||||
EmuNVNet_SetRegister(NvRegUnknownSetupReg5,
|
||||
NVREG_UNKSETUP5_BIT31, 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
EmuNVNet_SetRegister(NvRegTxRxControl, value, size);
|
||||
break;
|
||||
case NvRegIrqMask:
|
||||
EmuNVNet_SetRegister(addr, value, size);
|
||||
EmuNVNet_UpdateIRQ();
|
||||
break;
|
||||
case NvRegIrqStatus:
|
||||
EmuNVNet_SetRegister(addr, EmuNVNet_GetRegister(addr, size) & ~value, size);
|
||||
EmuNVNet_UpdateIRQ();
|
||||
break;
|
||||
default:
|
||||
EmuNVNet_SetRegister(addr, value, size);
|
||||
break;
|
||||
}
|
||||
|
||||
DbgPrintf("EmuNVNet_Write%d: %s (0x%08X) = 0x%08X\n", size, EmuNVNet_GetRegisterName(addr), addr, value);
|
||||
return EmuNVNet_SetRegister(addr, value, size);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ namespace NtDll
|
|||
|
||||
#include "EmuXTL.h"
|
||||
|
||||
/*
|
||||
// ******************************************************************
|
||||
// * patch: WSAStartup
|
||||
// ******************************************************************
|
||||
|
@ -69,11 +70,12 @@ int WINAPI XTL::EMUPATCH(WSAStartup)
|
|||
// Prevent this function from failing by requesting a version of Winsock that
|
||||
// we know for sure is actually supported on Windows. This also fixes one error
|
||||
// in the 4920 dashboard.
|
||||
int ret = WSAStartup(MAKEWORD(2,2) /*wVersionRequested*/, lpWSAData);
|
||||
int ret = WSAStartup(MAKEWORD(2,2) /*wVersionRequested, lpWSAData);
|
||||
|
||||
RETURN(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
// ******************************************************************
|
||||
// * patch: XNetStartup
|
||||
// ******************************************************************
|
||||
|
@ -92,6 +94,7 @@ INT WINAPI XTL::EMUPATCH(XNetStartup)
|
|||
RETURN(ret);
|
||||
}
|
||||
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: This::Emusocket
|
||||
// ******************************************************************
|
||||
|
@ -258,6 +261,7 @@ int WINAPI XTL::EMUPATCH(ioctlsocket)
|
|||
|
||||
RETURN(ret);
|
||||
}
|
||||
*/
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: XOnlineLaunchNewImage
|
||||
|
@ -280,6 +284,7 @@ HRESULT WINAPI XOnlineLaunchNewImage
|
|||
RETURN(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
// ******************************************************************
|
||||
// * patch: XOnlineLogon
|
||||
// ******************************************************************
|
||||
|
@ -307,4 +312,5 @@ HRESULT WINAPI XTL::EMUPATCH(XOnlineLogon)
|
|||
HRESULT ret = HRESULT(0x80151000L); // XONLINE_E_LOGON_NO_NETWORK_CONNECTION
|
||||
|
||||
RETURN(ret);
|
||||
}
|
||||
}
|
||||
*/
|
Loading…
Reference in New Issue