From b8ebe973b9142a495cbbb3e053558c89e7371213 Mon Sep 17 00:00:00 2001 From: rogerman Date: Wed, 12 Sep 2018 16:54:33 -0700 Subject: [PATCH] WiFi: Huge code cleanup and refactor, mostly reworking register handling. - Note that functionality should remain practically the same as before. Any actual functional changes are completely unintentional. --- desmume/src/saves.cpp | 134 +- desmume/src/wifi.cpp | 3267 +++++++++++++++++++++++++++++++---------- desmume/src/wifi.h | 2885 +++++++++++++++++++++++++++++++----- 3 files changed, 5079 insertions(+), 1207 deletions(-) diff --git a/desmume/src/saves.cpp b/desmume/src/saves.cpp index b5d385819..5d4b6bc4d 100644 --- a/desmume/src/saves.cpp +++ b/desmume/src/saves.cpp @@ -301,79 +301,78 @@ SFORMAT SF_MOVIE[]={ { 0 } }; -// TODO: integrate the new wifi state variables once everything is settled SFORMAT SF_WIFI[]={ - { "W000", 4, 1, &wifiMac.powerOn}, - { "W010", 4, 1, &wifiMac.powerOnPending}, + { "W000", 4, 1, &legacyWifiSF.powerOn}, + { "W010", 4, 1, &legacyWifiSF.powerOnPending}, - { "W020", 2, 1, &wifiMac.rfStatus}, - { "W030", 2, 1, &wifiMac.rfPins}, + { "W020", 2, 1, &legacyWifiSF.rfStatus}, + { "W030", 2, 1, &legacyWifiSF.rfPins}, - { "W040", 2, 1, &wifiMac.IE}, - { "W050", 2, 1, &wifiMac.IF}, + { "W040", 2, 1, &legacyWifiSF.IE}, + { "W050", 2, 1, &legacyWifiSF.IF}, - { "W060", 2, 1, &wifiMac.macMode}, - { "W070", 2, 1, &wifiMac.wepMode}, - { "W080", 4, 1, &wifiMac.WEP_enable}, + { "W060", 2, 1, &legacyWifiSF.macMode}, + { "W070", 2, 1, &legacyWifiSF.wepMode}, + { "W080", 4, 1, &legacyWifiSF.WEP_enable}, - { "W100", 2, 1, &wifiMac.TXCnt}, - { "W120", 2, 1, &wifiMac.TXStat}, + { "W100", 2, 1, &legacyWifiSF.TXCnt}, + { "W120", 2, 1, &legacyWifiSF.TXStat}, - { "W200", 2, 1, &wifiMac.RXCnt}, - { "W210", 2, 1, &wifiMac.RXCheckCounter}, + { "W200", 2, 1, &legacyWifiSF.RXCnt}, + { "W210", 2, 1, &legacyWifiSF.RXCheckCounter}, - { "W220", 1, 6, &wifiMac.mac.bytes}, - { "W230", 1, 6, &wifiMac.bss.bytes}, + { "W220", 1, 6, &legacyWifiSF.macAddr[0]}, + { "W230", 1, 6, &legacyWifiSF.bssid[0]}, - { "W240", 2, 1, &wifiMac.aid}, - { "W250", 2, 1, &wifiMac.pid}, - { "W260", 2, 1, &wifiMac.retryLimit}, + { "W240", 2, 1, &legacyWifiSF.aid}, + { "W250", 2, 1, &legacyWifiSF.pid}, + { "W260", 2, 1, &legacyWifiSF.retryLimit}, - { "W270", 4, 1, &wifiMac.crystalEnabled}, - { "W280", 8, 1, &wifiMac.usec}, - { "W290", 4, 1, &wifiMac.usecEnable}, - { "W300", 8, 1, &wifiMac.ucmp}, - { "W310", 4, 1, &wifiMac.ucmpEnable}, - { "W320", 2, 1, &wifiMac.eCount}, - { "W330", 4, 1, &wifiMac.eCountEnable}, + { "W270", 4, 1, &legacyWifiSF.crystalEnabled}, + { "W280", 8, 1, &legacyWifiSF.usec}, + { "W290", 4, 1, &legacyWifiSF.usecEnable}, + { "W300", 8, 1, &legacyWifiSF.ucmp}, + { "W310", 4, 1, &legacyWifiSF.ucmpEnable}, + { "W320", 2, 1, &legacyWifiSF.eCount}, + { "W330", 4, 1, &legacyWifiSF.eCountEnable}, - { "WR00", 4, 1, &wifiMac.RF.CFG1.val}, - { "WR01", 4, 1, &wifiMac.RF.IFPLL1.val}, - { "WR02", 4, 1, &wifiMac.RF.IFPLL2.val}, - { "WR03", 4, 1, &wifiMac.RF.IFPLL3.val}, - { "WR04", 4, 1, &wifiMac.RF.RFPLL1.val}, - { "WR05", 4, 1, &wifiMac.RF.RFPLL2.val}, - { "WR06", 4, 1, &wifiMac.RF.RFPLL3.val}, - { "WR07", 4, 1, &wifiMac.RF.RFPLL4.val}, - { "WR08", 4, 1, &wifiMac.RF.CAL1.val}, - { "WR09", 4, 1, &wifiMac.RF.TXRX1.val}, - { "WR10", 4, 1, &wifiMac.RF.PCNT1.val}, - { "WR11", 4, 1, &wifiMac.RF.PCNT2.val}, - { "WR12", 4, 1, &wifiMac.RF.VCOT1.val}, + { "WR00", 4, 1, &legacyWifiSF.rf_cfg1}, + { "WR01", 4, 1, &legacyWifiSF.rf_ifpll1}, + { "WR02", 4, 1, &legacyWifiSF.rf_ifpll2}, + { "WR03", 4, 1, &legacyWifiSF.rf_ifpll3}, + { "WR04", 4, 1, &legacyWifiSF.rf_rfpll1}, + { "WR05", 4, 1, &legacyWifiSF.rf_rfpll2}, + { "WR06", 4, 1, &legacyWifiSF.rf_rfpll3}, + { "WR07", 4, 1, &legacyWifiSF.rf_rfpll4}, + { "WR08", 4, 1, &legacyWifiSF.rf_cal1}, + { "WR09", 4, 1, &legacyWifiSF.rf_txrx1}, + { "WR10", 4, 1, &legacyWifiSF.rf_pcnt1}, + { "WR11", 4, 1, &legacyWifiSF.rf_pcnt2}, + { "WR12", 4, 1, &legacyWifiSF.rf_vcot1}, - { "W340", 1, 105, &wifiMac.BB.data[0]}, + { "W340", 1, 105, &legacyWifiSF.bb_data[0]}, - { "W350", 2, 1, &wifiMac.rfIOCnt.val}, - { "W360", 2, 1, &wifiMac.rfIOStatus.val}, - { "W370", 4, 1, &wifiMac.rfIOData.val}, - { "W380", 2, 1, &wifiMac.bbIOCnt.val}, + { "W350", 2, 1, &legacyWifiSF.rfIOCnt}, + { "W360", 2, 1, &legacyWifiSF.rfIOStatus}, + { "W370", 4, 1, &legacyWifiSF.rfIOData}, + { "W380", 2, 1, &legacyWifiSF.bbIOCnt}, - { "W400", 2, 0x1000, &wifiMac.RAM[0]}, - { "W410", 2, 1, &wifiMac.RXRangeBegin}, - { "W420", 2, 1, &wifiMac.RXRangeEnd}, - { "W430", 2, 1, &wifiMac.RXWriteCursor}, - { "W460", 2, 1, &wifiMac.RXReadCursor}, - { "W470", 2, 1, &wifiMac.RXUnits}, - { "W480", 2, 1, &wifiMac.RXBufCount}, - { "W490", 2, 1, &wifiMac.CircBufReadAddress}, - { "W500", 2, 1, &wifiMac.CircBufWriteAddress}, - { "W510", 2, 1, &wifiMac.CircBufRdEnd}, - { "W520", 2, 1, &wifiMac.CircBufRdSkip}, - { "W530", 2, 1, &wifiMac.CircBufWrEnd}, - { "W540", 2, 1, &wifiMac.CircBufWrSkip}, + { "W400", 2, 0x1000, &legacyWifiSF.wifiRAM[0]}, + { "W410", 2, 1, &legacyWifiSF.rxRangeBegin}, + { "W420", 2, 1, &legacyWifiSF.rxRangeEnd}, + { "W430", 2, 1, &legacyWifiSF.rxWriteCursor}, + { "W460", 2, 1, &legacyWifiSF.rxReadCursor}, + { "W470", 2, 1, &legacyWifiSF.rxUnits}, + { "W480", 2, 1, &legacyWifiSF.rxBufCount}, + { "W490", 2, 1, &legacyWifiSF.circBufReadAddress}, + { "W500", 2, 1, &legacyWifiSF.circBufWriteAddress}, + { "W510", 2, 1, &legacyWifiSF.circBufReadEnd}, + { "W520", 2, 1, &legacyWifiSF.circBufReadSkip}, + { "W530", 2, 1, &legacyWifiSF.circBufWriteEnd}, + { "W540", 2, 1, &legacyWifiSF.circBufWriteSkip}, - { "W580", 2, 0x800, &wifiMac.IOPorts[0]}, - { "W590", 2, 1, &wifiMac.randomSeed}, + { "W580", 2, 0x800, &legacyWifiSF.wifiIOPorts[0]}, + { "W590", 2, 1, &legacyWifiSF.randomSeed}, { 0 } }; @@ -1065,6 +1064,8 @@ static void writechunks(EMUFILE &os) svn_rev = 0; save_time = tm.get_Ticks(); + + wifiHandler->PrepareSaveStateWrite(); savestate_WriteChunk(os,1,SF_ARM9); savestate_WriteChunk(os,2,SF_ARM7); @@ -1143,7 +1144,20 @@ static bool ReadStateChunks(EMUFILE &is, s32 totalsize) case 91: if(!gfx3d_loadstate(is,size)) ret=false; break; case 100: if(!ReadStateChunk(is,SF_MOVIE, size)) ret=false; break; case 101: if(!mov_loadstate(is, size)) ret=false; break; - case 110: if(!ReadStateChunk(is,SF_WIFI,size)) ret=false; break; + + case 110: + { + if (ReadStateChunk(is,SF_WIFI,size)) + { + wifiHandler->ParseSaveStateRead(); + } + else + { + ret = false; + } + break; + } + case 120: if(!ReadStateChunk(is,SF_RTC,size)) ret=false; break; case 130: if(!ReadStateChunk(is,SF_INFO,size)) ret=false; else haveInfo=true; break; case 140: if(!s_slot1_loadstate(is, size)) ret=false; break; diff --git a/desmume/src/wifi.cpp b/desmume/src/wifi.cpp index cee889b1e..efee5643f 100755 --- a/desmume/src/wifi.cpp +++ b/desmume/src/wifi.cpp @@ -77,7 +77,7 @@ typedef struct pcap pcap_t; #define PCAP_ERRBUF_SIZE 256 #endif -wifimac_t wifiMac; +LegacyWifiSFormat legacyWifiSF; /******************************************************************************* @@ -353,174 +353,79 @@ static void WIFI_initCRC32Table() *******************************************************************************/ -static void WIFI_resetRF(rffilter_t *rf) +static void WIFI_resetRF(RF2958_IOREG_MAP &rf) { /* reinitialize RF chip with the default values refer RF2958 docs */ /* CFG1 */ - rf->CFG1.bits.IF_VGA_REG_EN = 1; - rf->CFG1.bits.IF_VCO_REG_EN = 1; - rf->CFG1.bits.RF_VCO_REG_EN = 1; - rf->CFG1.bits.HYBERNATE = 0; - rf->CFG1.bits.REF_SEL = 0; + rf.CFG1.IF_VGA_REG_EN = 1; + rf.CFG1.IF_VCO_REG_EN = 1; + rf.CFG1.RF_VCO_REG_EN = 1; + rf.CFG1.HYBERNATE = 0; + rf.CFG1.REF_SEL = 0; /* IFPLL1 */ - rf->IFPLL1.bits.DAC = 3; - rf->IFPLL1.bits.P1 = 0; - rf->IFPLL1.bits.LD_EN1 = 0; - rf->IFPLL1.bits.AUTOCAL_EN1 = 0; - rf->IFPLL1.bits.PDP1 = 1; - rf->IFPLL1.bits.CPL1 = 0; - rf->IFPLL1.bits.LPF1 = 0; - rf->IFPLL1.bits.VTC_EN1 = 1; - rf->IFPLL1.bits.KV_EN1 = 0; - rf->IFPLL1.bits.PLL_EN1 = 0; + rf.IFPLL1.DAC = 3; + rf.IFPLL1.P1 = 0; + rf.IFPLL1.LD_EN1 = 0; + rf.IFPLL1.AUTOCAL_EN1 = 0; + rf.IFPLL1.PDP1 = 1; + rf.IFPLL1.CPL1 = 0; + rf.IFPLL1.LPF1 = 0; + rf.IFPLL1.VTC_EN1 = 1; + rf.IFPLL1.KV_EN1 = 0; + rf.IFPLL1.PLL_EN1 = 0; /* IFPLL2 */ - rf->IFPLL2.bits.IF_N = 0x22; + rf.IFPLL2.IF_N = 0x22; /* IFPLL3 */ - rf->IFPLL3.bits.KV_DEF1 = 8; - rf->IFPLL3.bits.CT_DEF1 = 7; - rf->IFPLL3.bits.DN1 = 0x1FF; + rf.IFPLL3.KV_DEF1 = 8; + rf.IFPLL3.CT_DEF1 = 7; + rf.IFPLL3.DN1 = 0x1FF; /* RFPLL1 */ - rf->RFPLL1.bits.DAC = 3; - rf->RFPLL1.bits.P = 0; - rf->RFPLL1.bits.LD_EN = 0; - rf->RFPLL1.bits.AUTOCAL_EN = 0; - rf->RFPLL1.bits.PDP = 1; - rf->RFPLL1.bits.CPL = 0; - rf->RFPLL1.bits.LPF = 0; - rf->RFPLL1.bits.VTC_EN = 0; - rf->RFPLL1.bits.KV_EN = 0; - rf->RFPLL1.bits.PLL_EN = 0; + rf.RFPLL1.DAC = 3; + rf.RFPLL1.P = 0; + rf.RFPLL1.LD_EN = 0; + rf.RFPLL1.AUTOCAL_EN = 0; + rf.RFPLL1.PDP = 1; + rf.RFPLL1.CPL = 0; + rf.RFPLL1.LPF = 0; + rf.RFPLL1.VTC_EN = 1; + rf.RFPLL1.KV_EN = 0; + rf.RFPLL1.PLL_EN = 0; /* RFPLL2 */ - rf->RFPLL2.bits.NUM2 = 0; - rf->RFPLL2.bits.N2 = 0x5E; + rf.RFPLL2.NUM2 = 0; + rf.RFPLL2.N2 = 0x5E; /* RFPLL3 */ - rf->RFPLL3.bits.NUM2 = 0; + rf.RFPLL3.NUM2 = 0; /* RFPLL4 */ - rf->RFPLL4.bits.KV_DEF = 8; - rf->RFPLL4.bits.CT_DEF = 7; - rf->RFPLL4.bits.DN = 0x145; + rf.RFPLL4.KV_DEF = 8; + rf.RFPLL4.CT_DEF = 7; + rf.RFPLL4.DN = 0x145; /* CAL1 */ - rf->CAL1.bits.LD_WINDOW = 2; - rf->CAL1.bits.M_CT_VALUE = 8; - rf->CAL1.bits.TLOCK = 7; - rf->CAL1.bits.TVCO = 0x0F; + rf.CAL1.LD_WINDOW = 2; + rf.CAL1.M_CT_VALUE = 8; + rf.CAL1.TLOCK = 7; + rf.CAL1.TVCO = 0x0F; /* TXRX1 */ - rf->TXRX1.bits.TXBYPASS = 0; - rf->TXRX1.bits.INTBIASEN = 0; - rf->TXRX1.bits.TXENMODE = 0; - rf->TXRX1.bits.TXDIFFMODE = 0; - rf->TXRX1.bits.TXLPFBW = 2; - rf->TXRX1.bits.RXLPFBW = 2; - rf->TXRX1.bits.TXVGC = 0; - rf->TXRX1.bits.PCONTROL = 0; - rf->TXRX1.bits.RXDCFBBYPS = 0; + rf.TXRX1.TXBYPASS = 0; + rf.TXRX1.INTBIASEN = 0; + rf.TXRX1.TXENMODE = 0; + rf.TXRX1.TXDIFFMODE = 0; + rf.TXRX1.TXLPFBW = 2; + rf.TXRX1.RXLPFBW = 2; + rf.TXRX1.TXVGC = 0; + rf.TXRX1.PCONTROL = 0; + rf.TXRX1.RXDCFBBYPS = 0; /* PCNT1 */ - rf->PCNT1.bits.TX_DELAY = 0; - rf->PCNT1.bits.PC_OFFSET = 0; - rf->PCNT1.bits.P_DESIRED = 0; - rf->PCNT1.bits.MID_BIAS = 0; + rf.PCNT1.TX_DELAY = 0; + rf.PCNT1.PC_OFFSET = 0; + rf.PCNT1.P_DESIRED = 0; + rf.PCNT1.MID_BIAS = 0; /* PCNT2 */ - rf->PCNT2.bits.MIN_POWER = 0; - rf->PCNT2.bits.MID_POWER = 0; - rf->PCNT2.bits.MAX_POWER = 0; + rf.PCNT2.MIN_POWER = 0; + rf.PCNT2.MID_POWER = 0; + rf.PCNT2.MAX_POWER = 0; /* VCOT1 */ - rf->VCOT1.bits.AUX1 = 0; - rf->VCOT1.bits.AUX = 0; -} - - -void WIFI_setRF_CNT(u16 val) -{ - if (!wifiMac.rfIOStatus.bits.busy) - wifiMac.rfIOCnt.val = val; -} - -void WIFI_setRF_DATA(u16 val, u8 part) -{ - if (!wifiMac.rfIOStatus.bits.busy) - { - rfIOData_t *rfreg = (rfIOData_t *)&wifiMac.RF; - switch (wifiMac.rfIOCnt.bits.readOperation) - { - case 1: /* read from RF chip */ - /* low part of data is ignored on reads */ - /* on high part, the address is read, and the data at this is written back */ - if (part==1) - { - wifiMac.rfIOData.array16[part] = val; - if (wifiMac.rfIOData.bits.address > (sizeof(wifiMac.RF) / 4)) return; /* out of bound */ - /* get content of the addressed register */ - wifiMac.rfIOData.bits.content = rfreg[wifiMac.rfIOData.bits.address].bits.content; - } - break; - case 0: /* write to RF chip */ - wifiMac.rfIOData.array16[part] = val; - if (wifiMac.rfIOData.bits.address > (sizeof(wifiMac.RF) / 4)) return; /* out of bound */ - /* the actual transfer is done on high part write */ - if (part==1) - { - switch (wifiMac.rfIOData.bits.address) - { - case 5: /* write to upper part of the frequency filter */ - case 6: /* write to lower part of the frequency filter */ - { - u32 channelFreqN; - rfreg[wifiMac.rfIOData.bits.address].bits.content = wifiMac.rfIOData.bits.content; - /* get the complete rfpll.n */ - channelFreqN = (u32)wifiMac.RF.RFPLL3.bits.NUM2 + ((u32)wifiMac.RF.RFPLL2.bits.NUM2 << 18) + ((u32)wifiMac.RF.RFPLL2.bits.N2 << 24); - /* frequency setting is out of range */ - if (channelFreqN<0x00A2E8BA) return; - /* substract base frequency (channel 1) */ - channelFreqN -= 0x00A2E8BA; - } - return; - case 13: - /* special purpose register: TEST1, on write, the RF chip resets */ - WIFI_resetRF(&wifiMac.RF); - return; - } - /* set content of the addressed register */ - rfreg[wifiMac.rfIOData.bits.address].bits.content = wifiMac.rfIOData.bits.content; - } - break; - } - } -} - -u16 WIFI_getRF_DATA(u8 part) -{ - if (!wifiMac.rfIOStatus.bits.busy) - return wifiMac.rfIOData.array16[part]; - else - /* data is not (yet) available */ - return 0; - } - -u16 WIFI_getRF_STATUS() -{ - return wifiMac.rfIOStatus.val; -} - -/******************************************************************************* - - BB-Chip - - *******************************************************************************/ - -void WIFI_setBB_CNT(u16 val) -{ - wifiMac.bbIOCnt.val = val; - - if(wifiMac.bbIOCnt.bits.mode == 1) - wifiMac.BB.data[wifiMac.bbIOCnt.bits.address] = WIFI_IOREG(REG_WIFI_BBWRITE); -} - -u8 WIFI_getBB_DATA() -{ - if((!wifiMac.bbIOCnt.bits.enable) || (wifiMac.bbIOCnt.bits.mode != 2)) - return 0; - - return wifiMac.BB.data[wifiMac.bbIOCnt.bits.address]; + rf.VCOT1.AUX1 = 0; + rf.VCOT1.AUX = 0; } /******************************************************************************* @@ -533,60 +438,98 @@ u8 WIFI_getBB_DATA() *******************************************************************************/ -static void WIFI_BeaconTXStart(); +static void WIFI_TXStart(const WifiTXLocIndex txSlotIndex, IOREG_W_TXBUF_LOCATION &txLocation); static void WIFI_triggerIRQMask(u16 mask) { - u16 oResult,nResult; - oResult = wifiMac.IE & wifiMac.IF; - wifiMac.IF = wifiMac.IF | (mask & ~0x0400); - nResult = wifiMac.IE & wifiMac.IF; - - if (!oResult && nResult) + WIFI_IOREG_MAP &io = wifiHandler->GetWifiData().io; + + u16 oldFlags = io.IF.value & io.IE.value; + + io.IF.value |= (mask & 0xFBFF); + u16 newFlags = io.IF.value & io.IE.value; + + if (!oldFlags && newFlags) { - NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_ARM7_WIFI); /* cascade it via arm7 wifi irq */ + NDS_makeIrq(ARMCPU_ARM7, IRQ_BIT_ARM7_WIFI); // cascade it via arm7 wifi irq } } static void WIFI_triggerIRQ(u8 irq) { + WIFI_IOREG_MAP &io = wifiHandler->GetWifiData().io; + switch (irq) { - case WIFI_IRQ_TXSTART: - wifiMac.TXSeqNo++; - break; - case WIFI_IRQ_TIMEPREBEACON: - if (wifiMac.TXPower & 0x0001) + case WIFI_IRQ_TXSTART: // IRQ 7 + io.TX_SEQNO.Number++; + break; + + case WIFI_IRQ_TIMEPREBEACON: // IRQ 15 { - wifiMac.rfStatus = 1; - wifiMac.rfPins = 0x0084; + if (io.POWER_TX.AutoWakeup != 0) + { + io.RF_STATUS.Status = 0x1; + io.RF_PINS.CarrierSense = 0; + io.RF_PINS.TXMain = 0; + io.RF_PINS.UNKNOWN1 = 1; + io.RF_PINS.TX_On = 0; + io.RF_PINS.RX_On = 1; + } + break; } - break; - case WIFI_IRQ_TIMEBEACON: - wifiMac.BeaconCount1 = wifiMac.BeaconInterval; - - if (wifiMac.ucmpEnable) + + case WIFI_IRQ_TIMEBEACON: // IRQ 14 { - wifiMac.BeaconCount2 = 0xFFFF; - wifiMac.TXCnt &= 0xFFF2; - - WIFI_BeaconTXStart(); - - if (wifiMac.ListenCount == 0) wifiMac.ListenCount = wifiMac.ListenInterval; - wifiMac.ListenCount--; + io.BEACONCOUNT1 = io.BEACONINT.Interval; + + if (io.US_COMPARECNT.EnableCompare != 0) + { + io.BEACONCOUNT2 = 0xFFFF; + io.TXREQ_READ.Loc1 = 0; + io.TXREQ_READ.Loc2 = 0; + io.TXREQ_READ.Loc3 = 0; + + WIFI_TXStart(WifiTXLocIndex_BEACON, io.TXBUF_BEACON); + + if (io.TXBUF_BEACON.TransferRequest != 0) + { + io.TXBUSY.Beacon = 1; + } + + if (io.LISTENCOUNT.Count == 0) + { + io.LISTENCOUNT.Count = io.LISTENINT.Interval; + } + + io.LISTENCOUNT.Count--; + } + break; } - break; - case WIFI_IRQ_TIMEPOSTBEACON: - if (wifiMac.TXPower & 0x0002) + + case WIFI_IRQ_TIMEPOSTBEACON: // IRQ 13 { - wifiMac.rfStatus = 9; - wifiMac.rfPins = 0x0004; + if (io.POWER_TX.AutoSleep != 0) + { + io.RF_STATUS.Status = 0x9; + io.RF_PINS.CarrierSense = 0; + io.RF_PINS.TXMain = 1; + io.RF_PINS.UNKNOWN1 = 1; + io.RF_PINS.TX_On = 1; + io.RF_PINS.RX_On = 0; + + io.INTERNAL_034 = 0x0002; + io.TXREQ_READ.value &= 0x0010; + io.POWERSTATE.WillPowerOn = 0; + io.POWERSTATE.IsPowerOff = 1; + } + break; } - break; - case WIFI_IRQ_UNK: - WIFI_LOG(2, "IRQ 12 triggered.\n"); - wifiMac.TXSeqNo++; - break; + + case WIFI_IRQ_UNK: // IRQ 12 + WIFI_LOG(2, "IRQ 12 triggered.\n"); + io.TX_SEQNO.Number++; + break; } WIFI_triggerIRQMask(1<GetWifiData().io; u16 ret = 0x0010; u16 frameCtl = *(u16*)&packet[0]; @@ -619,7 +563,7 @@ INLINE u16 WIFI_GetRXFlags(u8* packet) if (frameCtl & 0x0400) ret |= 0x0100; - if (!memcmp(&packet[10], &wifiMac.bss.bytes[0], 6)) + if (!memcmp(&packet[10], io.BSSID, 6)) ret |= 0x8000; //printf("----- Computing RX flags for received frame: FrameCtl = %04X, Flags = %04X -----\n", frameCtl, ret); @@ -649,8 +593,11 @@ INLINE void WIFI_MakeRXHeader(u8* buf, u16 flags, u16 xferRate, u16 len, u8 maxR static void WIFI_RXPutWord(u16 val) { + WifiData &wifi = wifiHandler->GetWifiData(); + WIFI_IOREG_MAP &io = wifi.io; + /* abort when RX data queuing is not enabled */ - if (!(wifiMac.RXCnt & 0x8000)) return; + if (io.RXCNT.EnableRXFIFOQueuing == 0) return; /* abort when ringbuffer is full */ //if (wifiMac.RXReadCursor == wifiMac.RXWriteCursor) return; /*if(wifiMac.RXWriteCursor >= wifiMac.RXReadCursor) @@ -660,34 +607,37 @@ static void WIFI_RXPutWord(u16 val) return; }*/ /* write the data to cursor position */ - wifiMac.RAM[wifiMac.RXWriteCursor & 0xFFF] = val; + wifi.RAM[io.RXBUF_WRCSR.HalfwordAddress] = val; // printf("wifi: written word %04X to circbuf addr %04X\n", val, (wifiMac.RXWriteCursor << 1)); /* move cursor by one */ //printf("written one word to %04X (start %04X, end %04X), ", wifiMac.RXWriteCursor, wifiMac.RXRangeBegin, wifiMac.RXRangeEnd); - wifiMac.RXWriteCursor++; + io.RXBUF_WRCSR.HalfwordAddress++; /* wrap around */ // wifiMac.RXWriteCursor %= (wifiMac.RXRangeEnd - wifiMac.RXRangeBegin) >> 1; // printf("new addr=%04X\n", wifiMac.RXWriteCursor); - if (wifiMac.RXWriteCursor >= ((wifiMac.RXRangeEnd & 0x1FFE) >> 1)) - wifiMac.RXWriteCursor = ((wifiMac.RXRangeBegin & 0x1FFE) >> 1); + if (io.RXBUF_WRCSR.HalfwordAddress >= ((io.RXBUF_END & 0x1FFE) >> 1)) + io.RXBUF_WRCSR.HalfwordAddress = ((io.RXBUF_BEGIN & 0x1FFE) >> 1); } -static void WIFI_TXStart(u8 slot) +static void WIFI_TXStart(const WifiTXLocIndex txSlotIndex, IOREG_W_TXBUF_LOCATION &txLocation) { + WifiData &wifi = wifiHandler->GetWifiData(); + WIFI_IOREG_MAP &io = wifi.io; + WIFI_LOG(3, "TX slot %i trying to send a packet: TXCnt = %04X, TXBufLoc = %04X\n", - slot, wifiMac.TXCnt, wifiMac.TXSlot[slot]); + (int)txSlotIndex, io.TXREQ_READ.value, txLocation.value); - if (BIT15(wifiMac.TXSlot[slot])) /* is slot enabled? */ + if (txLocation.TransferRequest != 0) /* is slot enabled? */ { //printf("send packet at %08X, lr=%08X\n", NDS_ARM7.instruct_adr, NDS_ARM7.R[14]); u16 txLen; - // the address has to be somewhere in the circular buffer, so drop the other bits - u16 address = (wifiMac.TXSlot[slot] & 0x0FFF); + u16 address = txLocation.HalfwordAddress; + // is there even enough space for the header (6 hwords) in the tx buffer? if (address > 0x1000-6) { WIFI_LOG(1, "TX slot %i trying to send a packet overflowing from the TX buffer (address %04X). Attempt ignored.\n", - slot, (address << 1)); + (int)txSlotIndex, (address << 1)); return; } @@ -695,12 +645,12 @@ static void WIFI_TXStart(u8 slot) // slot, wifiMac.RAM[address+6]); // 12 byte header TX Header: http://www.akkit.org/info/dswifi.htm#FmtTx - txLen = wifiMac.RAM[address+5]; + txLen = wifi.RAM[address+5]; // zero length if (txLen == 0) { WIFI_LOG(1, "TX slot %i trying to send a packet with length field set to zero. Attempt ignored.\n", - slot); + (int)txSlotIndex); return; } @@ -708,181 +658,112 @@ static void WIFI_TXStart(u8 slot) txLen = WIFI_alignedLen(txLen); // unsupported txRate - switch (wifiMac.RAM[address+4] & 0xFF) + switch (wifi.RAM[address+4] & 0xFF) { case 10: // 1 mbit case 20: // 2 mbit break; default: // other rates WIFI_LOG(1, "TX slot %i trying to send a packet with transfer rate field set to an invalid value of %i. Attempt ignored.\n", - slot, wifiMac.RAM[address+4] & 0xFF); + (int)txSlotIndex, wifi.RAM[address+4] & 0xFF); return; } // Set sequence number if required - if (!BIT13(wifiMac.TXSlot[slot])) + if ( (txSlotIndex == WifiTXLocIndex_BEACON) || (txLocation.IEEESeqCtrl == 0) ) { // u16 seqctl = wifiMac.RAM[address + 6 + 22]; // wifiMac.RAM[address + 6 + 11] = (seqctl & 0x000F) | (wifiMac.TXSeqNo << 4); - wifiMac.RAM[address + 6 + 11] = wifiMac.TXSeqNo << 4; + wifi.RAM[address + 6 + 11] = io.TX_SEQNO.Number << 4; } // Calculate and set FCS - u32 crc32 = WIFI_calcCRC32((u8*)&wifiMac.RAM[address + 6], txLen - 4); - *(u32*)&wifiMac.RAM[address + 6 + ((txLen-4) >> 1)] = crc32; + u32 crc32 = WIFI_calcCRC32((u8*)&wifi.RAM[address + 6], txLen - 4); + *(u32*)&wifi.RAM[address + 6 + ((txLen-4) >> 1)] = crc32; WIFI_triggerIRQ(WIFI_IRQ_TXSTART); - - if(slot > wifiMac.txCurSlot) - wifiMac.txCurSlot = slot; - - wifiMac.txSlotBusy[slot] = 1; - wifiMac.txSlotAddr[slot] = address; - wifiMac.txSlotLen[slot] = txLen; - wifiMac.txSlotRemainingBytes[slot] = (txLen + 12); - - wifiMac.RXTXAddr = address; - - wifiMac.rfStatus = 0x0003; - wifiMac.rfPins = 0x0046; - -#if 0 - WIFI_SoftAP_RecvPacketFromDS((u8*)&wifiMac.RAM[address+6], txLen); - WIFI_triggerIRQ(WIFI_IRQ_TXEND); - - wifiMac.RAM[address] = 0x0001; - wifiMac.RAM[address+4] &= 0x00FF; -#endif - } -} - -static void WIFI_ExtraTXStart() -{ - if (BIT15(wifiMac.TXSlotExtra)) - { - u16 txLen; - u16 address = wifiMac.TXSlotExtra & 0x0FFF; - // is there even enough space for the header (6 hwords) in the tx buffer? - if (address > 0x1000-6) - { - return; - } - - //printf("---------- SENDING A PACKET ON EXTRA SLOT, FrameCtl = %04X ----------\n", - // wifiMac.RAM[address+6]); - - // 12 byte header TX Header: http://www.akkit.org/info/dswifi.htm#FmtTx - txLen = wifiMac.RAM[address+5]; - // zero length - if (txLen == 0) - { - return; - } - - // Align packet length - txLen = WIFI_alignedLen(txLen); - - // unsupported txRate - switch (wifiMac.RAM[address+4] & 0xFF) - { - case 10: // 1 mbit - case 20: // 2 mbit - break; - default: // other rates - return; - } - - // Set sequence number if required - if (!BIT13(wifiMac.TXSlotExtra)) - { - //u16 seqctl = wifiMac.RAM[address + 6 + 22]; - //wifiMac.RAM[address + 6 + 11] = (seqctl & 0x000F) | (wifiMac.TXSeqNo << 4); - wifiMac.RAM[address + 6 + 11] = wifiMac.TXSeqNo << 4; - } - - // Calculate and set FCS - u32 crc32 = WIFI_calcCRC32((u8*)&wifiMac.RAM[address + 6], txLen - 4); - *(u32*)&wifiMac.RAM[address + 6 + ((txLen-4) >> 1)] = crc32; - - // Note: Extra transfers trigger two TX start interrupts according to GBATek - WIFI_triggerIRQ(WIFI_IRQ_TXSTART); - wifiHandler->CommSendPacket((u8 *)&wifiMac.RAM[address+6], txLen); - WIFI_triggerIRQ(WIFI_IRQ_UNK); - - if (BIT13(wifiMac.TXStatCnt)) - { - WIFI_triggerIRQ(WIFI_IRQ_TXEND); - wifiMac.TXStat = 0x0B01; - } - else if (BIT14(wifiMac.TXStatCnt)) - { - WIFI_triggerIRQ(WIFI_IRQ_TXEND); - wifiMac.TXStat = 0x0801; - } - - wifiMac.TXSlotExtra &= 0x7FFF; - - wifiMac.RAM[address] = 0x0001; - wifiMac.RAM[address+4] &= 0x00FF; - } -} - -static void WIFI_BeaconTXStart() -{ - if (wifiMac.BeaconEnable) - { - u16 txLen; - u16 address = wifiMac.BeaconAddr; - // is there even enough space for the header (6 hwords) in the tx buffer? - if (address > 0x1000-6) - { - return; - } - - // 12 byte header TX Header: http://www.akkit.org/info/dswifi.htm#FmtTx - txLen = wifiMac.RAM[address+5]; - // zero length - if (txLen == 0) - { - return; - } - - // Align packet length - txLen = WIFI_alignedLen(txLen); - - // unsupported txRate - switch (wifiMac.RAM[address+4] & 0xFF) - { - case 10: // 1 mbit - case 20: // 2 mbit - break; - default: // other rates - return; - } - - // Set sequence number - //u16 seqctl = wifiMac.RAM[address + 6 + 22]; - //wifiMac.RAM[address + 6 + 11] = (seqctl & 0x000F) | (wifiMac.TXSeqNo << 4); - wifiMac.RAM[address + 6 + 11] = wifiMac.TXSeqNo << 4; - - // Set timestamp - *(u64*)&wifiMac.RAM[address + 6 + 12] = wifiMac.usec; - - // Calculate and set FCS - u32 crc32 = WIFI_calcCRC32((u8*)&wifiMac.RAM[address + 6], txLen - 4); - *(u32*)&wifiMac.RAM[address + 6 + ((txLen-4) >> 1)] = crc32; - - WIFI_triggerIRQ(WIFI_IRQ_TXSTART); - wifiHandler->CommSendPacket((u8 *)&wifiMac.RAM[address+6], txLen); - if (BIT15(wifiMac.TXStatCnt)) + if ( (txSlotIndex == WifiTXLocIndex_LOC1) || (txSlotIndex == WifiTXLocIndex_LOC2) || (txSlotIndex == WifiTXLocIndex_LOC3) ) { + TXPacketInfo &txPacketInfo = wifiHandler->GetPacketInfoAtSlot(txSlotIndex); + txPacketInfo.bodyLen = txLen; + txPacketInfo.remainingBytes = txPacketInfo.bodyLen + 12; + + switch (txSlotIndex) + { + case WifiTXLocIndex_LOC1: io.TXBUSY.Loc1 = 1; break; + //case WifiTXLocIndex_CMD: io.TXBUSY.Cmd = 1; break; + case WifiTXLocIndex_LOC2: io.TXBUSY.Loc2 = 1; break; + case WifiTXLocIndex_LOC3: io.TXBUSY.Loc3 = 1; break; + //case WifiTXLocIndex_BEACON: io.TXBUSY.Beacon = 1; break; + + default: + break; + } + + if (txSlotIndex == WifiTXLocIndex_LOC3) + { + wifi.txCurrentSlot = WifiTXLocIndex_LOC3; + } + else if ( (txSlotIndex == WifiTXLocIndex_LOC2) && (wifi.txCurrentSlot == WifiTXLocIndex_LOC1) ) + { + wifi.txCurrentSlot = WifiTXLocIndex_LOC2; + } + + io.RXTX_ADDR.HalfwordAddress = address; + + io.RF_STATUS.Status = 0x03; + io.RF_PINS.CarrierSense = 0; + io.RF_PINS.TXMain = 1; + io.RF_PINS.UNKNOWN1 = 1; + io.RF_PINS.TX_On = 1; + io.RF_PINS.RX_On = 0; +#if 0 + WIFI_SoftAP_RecvPacketFromDS((u8*)&wifi.RAM[address+6], txLen); WIFI_triggerIRQ(WIFI_IRQ_TXEND); - wifiMac.TXStat = 0x0301; + + wifi.RAM[address] = 0x0001; + wifi.RAM[address+4] &= 0x00FF; +#endif + } + else if (txSlotIndex == WifiTXLocIndex_CMD) + { + wifiHandler->CommSendPacket((u8 *)&wifi.RAM[address+6], txLen); + WIFI_triggerIRQ(WIFI_IRQ_UNK); + + // If bit 13 is set, then it has priority over bit 14 + if (io.TXSTATCNT.UpdateTXStat_0B01 != 0) + { + WIFI_triggerIRQ(WIFI_IRQ_TXEND); + io.TXSTAT.value = 0x0B01; + } + else if (io.TXSTATCNT.UpdateTXStat_0800 != 0) + { + WIFI_triggerIRQ(WIFI_IRQ_TXEND); + io.TXSTAT.value = 0x0800; + } + + txLocation.TransferRequest = 0; + + wifi.RAM[address] = 0x0001; + wifi.RAM[address+4] &= 0x00FF; + } + else if (txSlotIndex == WifiTXLocIndex_BEACON) + { + // Set timestamp + *(u64*)&wifi.RAM[address + 6 + 12] = io.US_COUNT; + + wifiHandler->CommSendPacket((u8 *)&wifi.RAM[address+6], txLen); + + if (io.TXSTATCNT.UpdateTXStatBeacon != 0) + { + WIFI_triggerIRQ(WIFI_IRQ_TXEND); + io.TXSTAT.value = 0x0301; + } + + wifi.RAM[address] = 0x0001; + wifi.RAM[address+4] &= 0x00FF; } - - wifiMac.RAM[address] = 0x0001; - wifiMac.RAM[address+4] &= 0x00FF; } } @@ -890,6 +771,9 @@ void WIFI_write16(u32 address, u16 val) { bool action = false; if (!nds.power2.wifi) return; + + WifiData &wifi = wifiHandler->GetWifiData(); + WIFI_IOREG_MAP &io = wifi.io; u32 page = address & 0x7000; @@ -905,7 +789,7 @@ void WIFI_write16(u32 address, u16 val) { /* access to the circular buffer */ address &= 0x1FFF; - wifiMac.RAM[address >> 1] = val; + wifi.RAM[address >> 1] = val; return; } @@ -916,329 +800,1351 @@ void WIFI_write16(u32 address, u16 val) address &= 0x0FFF; switch (address) { - case REG_WIFI_ID: - break; - case REG_WIFI_MODE: + case REG_WIFI_MODE: // 0x004 + { + IOREG_W_MODE_RST MODE_RST; + MODE_RST.value = val; + + io.MODE_RST.UNKNOWN1 = MODE_RST.UNKNOWN1; + io.MODE_RST.UNKNOWN2 = MODE_RST.UNKNOWN2; + io.MODE_RST.UNKNOWN3 = MODE_RST.UNKNOWN3; + + if ( (io.MODE_RST.TXMasterEnable == 0) && (MODE_RST.TXMasterEnable != 0) ) { - u16 oldval = wifiMac.macMode; - - if (!BIT0(oldval) && BIT0(val)) - { - WIFI_IOREG(0x034) = 0x0002; - wifiMac.rfPins = 0x0046; - wifiMac.rfStatus = 0x0009; - WIFI_IOREG(0x27C) = 0x0005; - } - - if (BIT0(oldval) && !BIT0(val)) - { - WIFI_IOREG(0x27C) = 0x000A; - } - - if (BIT13(val)) - { - WIFI_IOREG(REG_WIFI_WRITECSRLATCH) = 0x0000; - WIFI_IOREG(0x0C0) = 0x0000; - WIFI_IOREG(0x0C4) = 0x0000; - WIFI_IOREG(REG_WIFI_MAYBE_RATE) = 0x0000; - WIFI_IOREG(0x278) = 0x000F; - } - - if (BIT14(val)) - { - wifiMac.wepMode = 0x0000; - wifiMac.TXStatCnt = 0x0000; - WIFI_IOREG(REG_WIFI_0A) = 0x0000; - wifiMac.mac.words[0] = 0x0000; - wifiMac.mac.words[1] = 0x0000; - wifiMac.mac.words[2] = 0x0000; - wifiMac.bss.words[0] = 0x0000; - wifiMac.bss.words[1] = 0x0000; - wifiMac.bss.words[2] = 0x0000; - wifiMac.pid = 0x0000; - wifiMac.aid = 0x0000; - WIFI_IOREG(REG_WIFI_RETRYLIMIT) = 0x0707; - WIFI_IOREG(0x02E) = 0x0000; - wifiMac.RXRangeBegin = 0x4000; - wifiMac.RXRangeEnd = 0x4800; - WIFI_IOREG(0x084) = 0x0000; - WIFI_IOREG(REG_WIFI_PREAMBLE) = 0x0001; - WIFI_IOREG(REG_WIFI_RXFILTER) = 0x0401; - WIFI_IOREG(0x0D4) = 0x0001; - WIFI_IOREG(REG_WIFI_RXFILTER2) = 0x0008; - WIFI_IOREG(0x0EC) = 0x3F03; - WIFI_IOREG(0x194) = 0x0000; - WIFI_IOREG(0x198) = 0x0000; - WIFI_IOREG(0x1A2) = 0x0001; - WIFI_IOREG(0x224) = 0x0003; - WIFI_IOREG(0x230) = 0x0047; - } - - wifiMac.macMode = val & 0xAFFF; + io.INTERNAL_034 = 0x0002; + io.RF_STATUS.value = 0x0009; + io.RF_PINS.value = 0x0046; + io.INTERNAL_27C = 0x0005; + + // According to GBATEK, the following registers might be reset to some unknown values. + // io.INTERNAL_2A2 = ???; + } + + if ( (io.MODE_RST.TXMasterEnable != 0) && (MODE_RST.TXMasterEnable == 0) ) + { + io.INTERNAL_27C = 0x000A; + } + + io.MODE_RST.TXMasterEnable = MODE_RST.TXMasterEnable; + + if (MODE_RST.ResetPortSet1 != 0) + { + io.RXBUF_WR_ADDR.value = 0x0000; + io.CMD_TOTALTIME = 0x0000; + io.CMD_REPLYTIME = 0x0000; + io.X_1A4 = 0x0000; + io.INTERNAL_278 = 0x000F; + + // According to GBATEK, the following registers might be reset to some unknown values. + //io.TXREQ_SET.value = ???; + //io.INTERNAL_0BA = ???; + //io.INTERNAL_204 = ???; + //io.INTERNAL_25C = ???; + //io.RXTX_ADDR.value = ???; + //io.INTERNAL_274 = ???; + } + + if (MODE_RST.ResetPortSet2 != 0) + { + io.MODE_WEP.value = 0x0000; + io.TXSTATCNT.value = 0x0000; + io.X_00A = 0x0000; + io.MACADDR[0] = 0x00; + io.MACADDR[1] = 0x00; + io.MACADDR[2] = 0x00; + io.MACADDR[3] = 0x00; + io.MACADDR[4] = 0x00; + io.MACADDR[5] = 0x00; + io.BSSID[0] = 0x00; + io.BSSID[1] = 0x00; + io.BSSID[2] = 0x00; + io.BSSID[3] = 0x00; + io.BSSID[4] = 0x00; + io.BSSID[5] = 0x00; + io.AID_LOW.value = 0x0000; + io.AID_FULL.value = 0x0000; + io.TX_RETRYLIMIT.value = 0x0707; + io.INTERNAL_02E = 0x0000; + io.RXBUF_BEGIN = 0x4000; + io.RXBUF_END = 0x4800; + io.TXBUF_TIM.value = 0x0000; + io.PREAMBLE.value = 0x0001; + io.RXFILTER.value = 0x0401; + io.CONFIG_0D4 = 0x0001; + io.RXFILTER2.value = 0x0008; + io.CONFIG_0EC = 0x3F03; + io.TX_HDR_CNT.value = 0x0000; + io.INTERNAL_198 = 0x0000; + io.X_1A2.value = 0x0001; + io.INTERNAL_224 = 0x0003; + io.INTERNAL_230 = 0x0047; } break; - case REG_WIFI_WEP: - wifiMac.wepMode = val; + } + + case REG_WIFI_WEP: // 0x006 + io.MODE_WEP.value = val; break; - case REG_WIFI_TXSTATCNT: - wifiMac.TXStatCnt = val; - //printf("txstatcnt=%04X\n", val); + + case REG_WIFI_TXSTATCNT: // 0x008 + io.TXSTATCNT.value = val; break; - case REG_WIFI_IE: - wifiMac.IE = val; - //printf("wifi ie write %04X\n", val); + + case REG_WIFI_X_00A: // 0x00A + io.X_00A = val; break; - case REG_WIFI_IF: - wifiMac.IF &= ~val; /* clear flagging bits */ + + case REG_WIFI_IF: // 0x010 + io.IF.value &= ~val; break; - case REG_WIFI_MAC0: - case REG_WIFI_MAC1: - case REG_WIFI_MAC2: - wifiMac.mac.words[(address - REG_WIFI_MAC0) >> 1] = val; + + case REG_WIFI_IE: // 0x012 + io.IE.value = val; break; - case REG_WIFI_BSS0: - case REG_WIFI_BSS1: - case REG_WIFI_BSS2: - wifiMac.bss.words[(address - REG_WIFI_BSS0) >> 1] = val; + + case REG_WIFI_MAC0: // 0x018 + io.MACADDR0.value = val; break; - case REG_WIFI_RETRYLIMIT: - wifiMac.retryLimit = val; + + case REG_WIFI_MAC1: // 0x01A + io.MACADDR1.value = val; break; - case REG_WIFI_WEPCNT: - wifiMac.WEP_enable = (val & 0x8000) != 0; + + case REG_WIFI_MAC2: // 0x01C + io.MACADDR2.value = val; break; - case REG_WIFI_POWERSTATE: - wifiMac.powerOn = ((val & 0x0002) ? true : false); - if (wifiMac.powerOn) WIFI_triggerIRQ(WIFI_IRQ_RFWAKEUP); + + case REG_WIFI_BSS0: // 0x020 + io.BSSID0.value = val; break; - case REG_WIFI_POWERFORCE: - if ((val & 0x8000) && (!wifiMac.powerOnPending)) + + case REG_WIFI_BSS1: // 0x022 + io.BSSID1.value = val; + break; + + case REG_WIFI_BSS2: // 0x024 + io.BSSID2.value = val; + break; + + case REG_WIFI_AID_LOW: // 0x028 + io.AID_LOW.value = val & 0x000F; + break; + + case REG_WIFI_AID_HIGH: // 0x02A + io.AID_FULL.value = val & 0x07FF; + break; + + case REG_WIFI_RETRYLIMIT: // 0x02C + io.TX_RETRYLIMIT.value = val; + break; + + case 0x02E: // 0x02E + io.INTERNAL_02E = val; + break; + + case REG_WIFI_RXCNT: // 0x030 + { + IOREG_W_RXCNT RXCNT; + RXCNT.value = val & 0xFF8F; + + io.RXCNT.EnableRXFIFOQueuing = RXCNT.EnableRXFIFOQueuing; + + if (io.RXCNT.UNKNOWN1 != RXCNT.UNKNOWN1) { - /* bool newPower = ((val & 0x0001) ? false : true); - if (newPower != wifiMac.powerOn) + io.RXCNT.UNKNOWN1 = RXCNT.UNKNOWN1; + WIFI_LOG(2, "Writing value of %04Xh to RXCNT.UNKNOWN1\n", (int)io.RXCNT.UNKNOWN1); + } + + if (io.RXCNT.UNKNOWN2 != RXCNT.UNKNOWN2) + { + io.RXCNT.UNKNOWN2 = RXCNT.UNKNOWN2; + WIFI_LOG(2, "Writing value of %04Xh to RXCNT.UNKNOWN2\n", (int)io.RXCNT.UNKNOWN2); + } + + if (RXCNT.CopyAddrToWRCSR != 0) + { + io.RXBUF_WRCSR.HalfwordAddress = io.RXBUF_WR_ADDR.HalfwordAddress; + } + + if (RXCNT.CopyTXBufReply1To2 != 0) + { + io.TXBUF_REPLY2.HalfwordAddress = io.TXBUF_REPLY1.HalfwordAddress; + io.TXBUF_REPLY1.value = 0x0000; + } + break; + } + + case REG_WIFI_WEPCNT: // 0x032 + io.WEP_CNT.value = val & 0x8000; + break; + + case 0x034: // 0x034 + io.INTERNAL_034 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_034\n", (int)io.INTERNAL_034); + break; + + case REG_WIFI_POWER_US: // 0x036 + { + IOREG_W_POWER_US POWER_US; + POWER_US.value = val & 0x0003; + + io.POWER_US.Disable = POWER_US.Disable; + + if (io.POWER_US.UNKNOWN1 != POWER_US.UNKNOWN1) + { + io.POWER_US.UNKNOWN1 = POWER_US.UNKNOWN1; + WIFI_LOG(2, "Writing value of %d to POWER_US.UNKNOWN1\n", (int)POWER_US.UNKNOWN1); + } + break; + } + + case REG_WIFI_POWER_TX: // 0x038 + { + IOREG_W_POWER_TX POWER_TX; + POWER_TX.value = val & 0x000F; + + io.POWER_TX.AutoWakeup = POWER_TX.AutoWakeup; + io.POWER_TX.AutoSleep = POWER_TX.AutoSleep; + + if (io.POWER_TX.UNKNOWN1 != POWER_TX.UNKNOWN1) + { + io.POWER_TX.UNKNOWN1 = POWER_TX.UNKNOWN1; + WIFI_LOG(2, "Writing value of %d to POWER_TX.UNKNOWN1\n", (int)POWER_TX.UNKNOWN1); + } + + if (POWER_TX.UNKNOWN2 != 0) + { + WIFI_LOG(2, "Performing unknown action of POWER_TX.UNKNOWN2\n"); + } + break; + } + + case REG_WIFI_POWERSTATE: // 0x03C + { + IOREG_W_POWERSTATE newPowerState; + newPowerState.value = val; + + io.POWERSTATE.UNKNOWN1 = newPowerState.UNKNOWN1; + io.POWERSTATE.RequestPowerOn = newPowerState.RequestPowerOn; + + if (io.POWERSTATE.RequestPowerOn != 0) + { + WIFI_triggerIRQ(WIFI_IRQ_RFWAKEUP); + + // This is supposedly the TX beacon transfer flag. + // Since reading TXREQ_READ bit 4 should always return a 1 (unless + // POWERFORCE clears it), we'll simply set this bit to 1 on power up + // so that bit 4 gets its default value. + io.TXREQ_READ.UNKNOWN1 = 1; + + // Most likely, there should be some delay between firing the IRQ and + // setting the register bits. But we're not going to emulate the delay + // right now, so we simply change all of the bits immediately. + io.POWERSTATE.RequestPowerOn = 0; + io.POWERSTATE.WillPowerOn = 0; + io.POWERSTATE.IsPowerOff = 0; + } + break; + } + + case REG_WIFI_POWERFORCE: // 0x040 + { + + io.POWERFORCE.value = val & 0x8001; + + if (io.POWERFORCE.ApplyNewPowerOffState != 0) + { + if ( (io.POWERFORCE.NewPowerOffState != 0) && (io.POWERSTATE.IsPowerOff == 0) ) { - if (!newPower) - wifiMac.powerOn = false; - else - wifiMac.powerOnPending = true; - }*/ - wifiMac.powerOn = ((val & 0x0001) ? false : true); + // Immediate action + io.INTERNAL_034 = 0x0002; + io.TXREQ_READ.value = 0x0000; // Note that even bit 4 gets cleared here + io.RF_STATUS.value = 0x0009; + io.RF_PINS.value = 0x0046; + + io.POWERSTATE.WillPowerOn = 0; + io.POWERSTATE.IsPowerOff = 1; + } + else if ( (io.POWERFORCE.NewPowerOffState == 0) && (io.POWERSTATE.IsPowerOff != 0) ) + { + // Delayed action + io.POWERSTATE.WillPowerOn = 1; + } + + // This probably shouldn't happen right here, but we need to write to + // POWERSTATE.IsPowerOff because we need to keep the power on in order + // to force certain in-game errors to occur. Otherwise, the user might + // get caught up in an infinite loop. + if (io.POWERSTATE.WillPowerOn != 0) + { + io.POWERSTATE.IsPowerOff = io.POWERFORCE.NewPowerOffState; + } } break; - case REG_WIFI_POWERACK: - if ((val == 0x0000) && wifiMac.powerOnPending) + } + + case REG_WIFI_POWER_UNK: // 0x048 + io.POWER_UNKNOWN.value = val; + break; + + case REG_WIFI_RXRANGEBEGIN: // 0x050 + { + io.RXBUF_BEGIN = val; + if (io.RXBUF_WRCSR.HalfwordAddress < ((io.RXBUF_BEGIN & 0x1FFE) >> 1)) { - wifiMac.powerOn = true; - wifiMac.powerOnPending = false; + io.RXBUF_WRCSR.HalfwordAddress = ((io.RXBUF_BEGIN & 0x1FFE) >> 1); } break; - case REG_WIFI_POWER_TX: - wifiMac.TXPower = val & 0x0007; - break; - case REG_WIFI_RXCNT: - wifiMac.RXCnt = val & 0xFF0E; - if (BIT0(val)) + } + + case REG_WIFI_RXRANGEEND: // 0x052 + { + io.RXBUF_END = val; + if (io.RXBUF_WRCSR.HalfwordAddress >= ((io.RXBUF_END & 0x1FFE) >> 1)) { - wifiMac.RXWriteCursor = WIFI_IOREG(REG_WIFI_WRITECSRLATCH); - WIFI_IOREG(REG_WIFI_RXHWWRITECSR) = wifiMac.RXWriteCursor; + io.RXBUF_WRCSR.HalfwordAddress = ((io.RXBUF_BEGIN & 0x1FFE) >> 1); } break; - case REG_WIFI_RXRANGEBEGIN: - wifiMac.RXRangeBegin = val; - if (wifiMac.RXWriteCursor < ((val & 0x1FFE) >> 1)) - wifiMac.RXWriteCursor = ((val & 0x1FFE) >> 1); + } + + case REG_WIFI_WRITECSRLATCH: // 0x056 + io.RXBUF_WR_ADDR.value = val & 0x0FFF; break; - case REG_WIFI_RXRANGEEND: - wifiMac.RXRangeEnd = val; - if (wifiMac.RXWriteCursor >= ((val & 0x1FFE) >> 1)) - wifiMac.RXWriteCursor = ((wifiMac.RXRangeBegin & 0x1FFE) >> 1); + + case REG_WIFI_CIRCBUFRADR: // 0x058 + io.RXBUF_RD_ADDR.value = val & 0x1FFE; break; - - case REG_WIFI_CIRCBUFRADR: - wifiMac.CircBufReadAddress = (val & 0x1FFE); + + case REG_WIFI_RXREADCSR: // 0x05A + io.RXBUF_READCSR.value = val & 0x0FFF; break; - case REG_WIFI_RXREADCSR: - wifiMac.RXReadCursor = val; + + case REG_WIFI_RXBUF_COUNT: // 0x05C + io.RXBUF_COUNT.value = val & 0x0FFF; break; - case REG_WIFI_CIRCBUFWADR: - wifiMac.CircBufWriteAddress = val; + + case REG_WIFI_CIRCBUFRD_END: // 0x062 + io.RXBUF_GAP.value = val & 0x1FFE; break; - case REG_WIFI_CIRCBUFWRITE: + + case REG_WIFI_CIRCBUFRD_SKIP: // 0x064 + io.RXBUF_GAPDISP.value = val & 0x0FFF; + break; + + case REG_WIFI_CIRCBUFWADR: // 0x068 + io.TXBUF_WR_ADDR.value = val & 0x1FFE; + break; + + case REG_WIFI_TXBUFCOUNT: // 0x06C + io.TXBUF_COUNT.value = val & 0x0FFF; + break; + + case REG_WIFI_CIRCBUFWRITE: // 0x070 + { /* set value into the circ buffer, and move cursor to the next hword on action */ //printf("wifi: circbuf fifo write at %04X, %04X (action=%i)\n", (wifiMac.CircBufWriteAddress & 0x1FFF), val, action); - wifiMac.RAM[(wifiMac.CircBufWriteAddress >> 1) & 0xFFF] = val; + wifi.RAM[io.TXBUF_WR_ADDR.HalfwordAddress] = val; if (action) { /* move to next hword */ - wifiMac.CircBufWriteAddress+=2; - if (wifiMac.CircBufWriteAddress == wifiMac.CircBufWrEnd) + io.TXBUF_WR_ADDR.HalfwordAddress++; + if (io.TXBUF_WR_ADDR.HalfwordAddress == io.TXBUF_GAP.HalfwordAddress) { /* on end of buffer, add skip hwords to it */ - wifiMac.CircBufWrEnd += wifiMac.CircBufWrSkip * 2; + io.TXBUF_GAP.HalfwordAddress += io.TXBUF_GAPDISP.HalfwordOffset; } } break; - case REG_WIFI_CIRCBUFWR_SKIP: - wifiMac.CircBufWrSkip = val; + } + + case REG_WIFI_CIRCBUFWR_END: // 0x074 + io.TXBUF_GAP.value = val & 0x1FFF; break; - case REG_WIFI_TXLOCBEACON: - wifiMac.BeaconAddr = val & 0x0FFF; - wifiMac.BeaconEnable = BIT15(val); - if (wifiMac.BeaconEnable) + + case REG_WIFI_CIRCBUFWR_SKIP: // 0x076 + io.TXBUF_GAPDISP.value = val & 0x0FFF; + break; + + case 0x078: // 0x078 + io.INTERNAL_078 = val; + break; + + case REG_WIFI_TXLOCBEACON: // 0x080 + { + IOREG_W_TXBUF_LOCATION TXBUF_BEACON; + TXBUF_BEACON.value = val; + + io.TXBUF_BEACON.HalfwordAddress = TXBUF_BEACON.HalfwordAddress; + io.TXBUF_BEACON.Bit12 = TXBUF_BEACON.Bit12; + io.TXBUF_BEACON.IEEESeqCtrl = TXBUF_BEACON.IEEESeqCtrl; + io.TXBUF_BEACON.TransferRequest = TXBUF_BEACON.TransferRequest; + + if (io.TXBUF_BEACON.UNKNOWN1 != TXBUF_BEACON.UNKNOWN1) + { + io.TXBUF_BEACON.UNKNOWN1 = TXBUF_BEACON.UNKNOWN1; + WIFI_LOG(2, "Writing value of %d to TXBUF_BEACON.UNKNOWN1\n", (int)TXBUF_BEACON.UNKNOWN1); + } + + if (io.TXBUF_BEACON.TransferRequest != 0) + { WIFI_LOG(3, "Beacon transmission enabled to send the packet at %08X every %i milliseconds.\n", - 0x04804000 + (wifiMac.BeaconAddr << 1), wifiMac.BeaconInterval); + 0x04804000 + (io.TXBUF_BEACON.HalfwordAddress << 1), io.BEACONINT.Interval); + } break; - case REG_WIFI_TXLOCEXTRA: - wifiMac.TXSlotExtra = val; - WIFI_LOG(2, "Write to port %03X: %04X\n", address, val); + } + + case REG_WIFI_TXBUF_TIM: // 0x084 + io.TXBUF_TIM.value = val & 0x00FF; break; - case 0x094: - // printf("write to 094 port\n"); + + case REG_WIFI_LISTENCOUNT: // 0x088 + io.LISTENCOUNT.value = val & 0x00FF; break; - case 0x098: - case 0x0C0: - case 0x0C4: - case 0x0C8: - case 0x244: - case 0x228: - case 0x290: - case 0x1A0: - case 0x1A2: - case 0x1A4: - case 0x194: - WIFI_LOG(2, "Write to port %03X: %04X\n", address, val); + + case REG_WIFI_BEACONPERIOD: // 0x08C + io.BEACONINT.value = val & 0x03FF; break; - case REG_WIFI_TXLOC1: - case REG_WIFI_TXLOC2: - case REG_WIFI_TXLOC3: - wifiMac.TXSlot[(address - REG_WIFI_TXLOC1) >> 2] = val; - WIFI_LOG(2, "Write to port %03X: %04X\n", address, val); + + case REG_WIFI_LISTENINT: // 0x08E + io.LISTENINT.value = val & 0x00FF; break; - case REG_WIFI_TXRESET: - WIFI_LOG(3, "Write to TXRESET: %04X\n", val); - //if (val & 0x0001) wifiMac.TXSlot[0] &= 0x7FFF; - //if (val & 0x0004) wifiMac.TXSlot[1] &= 0x7FFF; - //if (val & 0x0008) wifiMac.TXSlot[2] &= 0x7FFF; + + case REG_WIFI_TXLOCEXTRA: // 0x090 + { + IOREG_W_TXBUF_LOCATION TXBUF_CMD; + TXBUF_CMD.value = val; + + io.TXBUF_CMD.HalfwordAddress = TXBUF_CMD.HalfwordAddress; + io.TXBUF_CMD.Bit12 = TXBUF_CMD.Bit12; + io.TXBUF_CMD.IEEESeqCtrl = TXBUF_CMD.IEEESeqCtrl; + + if (wifi.cmdCount_u32 != 0) + { + io.TXBUF_CMD.TransferRequest = TXBUF_CMD.TransferRequest; + } + + if (io.TXBUF_CMD.UNKNOWN1 != TXBUF_CMD.UNKNOWN1) + { + io.TXBUF_CMD.UNKNOWN1 = TXBUF_CMD.UNKNOWN1; + WIFI_LOG(2, "Writing value of %d to TXBUF_CMD.UNKNOWN1\n", (int)TXBUF_CMD.UNKNOWN1); + } break; - case REG_WIFI_TXREQ_RESET: - wifiMac.TXCnt &= ~val; + } + + case REG_WIFI_TXBUF_REPLY1: // 0x094 + io.TXBUF_REPLY1.value = val; break; - case REG_WIFI_TXREQ_SET: - wifiMac.TXCnt |= val; - if (BIT0(val)) WIFI_TXStart(0); - if (BIT1(val)) WIFI_ExtraTXStart(); - if (BIT2(val)) WIFI_TXStart(1); - if (BIT3(val)) WIFI_TXStart(2); - //if (val) printf("TXReq: %04X\n", val); + + case 0x09C: // 0x09C + io.INTERNAL_09C = val; break; - case REG_WIFI_RFCNT: - WIFI_setRF_CNT(val); + + case REG_WIFI_TXLOC1: // 0x0A0 + { + IOREG_W_TXBUF_LOCATION TXBUF_LOCn; + TXBUF_LOCn.value = val; + + io.TXBUF_LOC1.HalfwordAddress = TXBUF_LOCn.HalfwordAddress; + io.TXBUF_LOC1.Bit12 = TXBUF_LOCn.Bit12; + io.TXBUF_LOC1.IEEESeqCtrl = TXBUF_LOCn.IEEESeqCtrl; + io.TXBUF_LOC1.TransferRequest = TXBUF_LOCn.TransferRequest; + + if (io.TXBUF_LOC1.UNKNOWN1 != TXBUF_LOCn.UNKNOWN1) + { + io.TXBUF_LOC1.UNKNOWN1 = TXBUF_LOCn.UNKNOWN1; + WIFI_LOG(2, "Writing value of %d to TXBUF_LOC1.UNKNOWN1\n", (int)TXBUF_LOCn.UNKNOWN1); + } break; - case REG_WIFI_RFBUSY: - /* CHECKME: read only? */ + } + + case REG_WIFI_TXLOC2: // 0x0A4 + { + IOREG_W_TXBUF_LOCATION TXBUF_LOCn; + TXBUF_LOCn.value = val; + + io.TXBUF_LOC2.HalfwordAddress = TXBUF_LOCn.HalfwordAddress; + io.TXBUF_LOC2.Bit12 = TXBUF_LOCn.Bit12; + io.TXBUF_LOC2.IEEESeqCtrl = TXBUF_LOCn.IEEESeqCtrl; + io.TXBUF_LOC2.TransferRequest = TXBUF_LOCn.TransferRequest; + + if (io.TXBUF_LOC2.UNKNOWN1 != TXBUF_LOCn.UNKNOWN1) + { + io.TXBUF_LOC2.UNKNOWN1 = TXBUF_LOCn.UNKNOWN1; + WIFI_LOG(2, "Writing value of %d to TXBUF_LOC2.UNKNOWN1\n", (int)TXBUF_LOCn.UNKNOWN1); + } break; - case REG_WIFI_RFDATA1: - WIFI_setRF_DATA(val,0); + } + + case REG_WIFI_TXLOC3: // 0x0A8 + { + IOREG_W_TXBUF_LOCATION TXBUF_LOCn; + TXBUF_LOCn.value = val; + + io.TXBUF_LOC3.HalfwordAddress = TXBUF_LOCn.HalfwordAddress; + io.TXBUF_LOC3.Bit12 = TXBUF_LOCn.Bit12; + io.TXBUF_LOC3.IEEESeqCtrl = TXBUF_LOCn.IEEESeqCtrl; + io.TXBUF_LOC3.TransferRequest = TXBUF_LOCn.TransferRequest; + + if (io.TXBUF_LOC3.UNKNOWN1 != TXBUF_LOCn.UNKNOWN1) + { + io.TXBUF_LOC3.UNKNOWN1 = TXBUF_LOCn.UNKNOWN1; + WIFI_LOG(2, "Writing value of %d to TXBUF_LOC3.UNKNOWN1\n", (int)TXBUF_LOCn.UNKNOWN1); + } break; - case REG_WIFI_RFDATA2: - WIFI_setRF_DATA(val,1); + } + + case REG_WIFI_TXREQ_RESET: // 0x0AC + { + IOREG_W_TXREQ_RESET TXREQ_RESET; + TXREQ_RESET.value = val; + + if (TXREQ_RESET.Loc1 != 0) + { + io.TXREQ_READ.Loc1 = 0; + } + + if (TXREQ_RESET.Cmd != 0) + { + io.TXREQ_READ.Cmd = 0; + } + + if (TXREQ_RESET.Loc2 != 0) + { + io.TXREQ_READ.Loc2 = 0; + } + + if (TXREQ_RESET.Loc3 != 0) + { + io.TXREQ_READ.Loc3 = 0; + } + + if (TXREQ_RESET.UNKNOWN1 != 0) + { + WIFI_LOG(2, "Prevented clearing of TXREQ_READ.UNKNOWN1, for beacon?\n"); + } break; - case REG_WIFI_USCOUNTERCNT: - wifiMac.usecEnable = BIT0(val); + } + + case REG_WIFI_TXREQ_SET: // 0x0AE + { + IOREG_W_TXREQ_SET TXREQ_SET; + TXREQ_SET.value = val; + + if (TXREQ_SET.Loc1 != 0) + { + io.TXREQ_READ.Loc1 = 1; + WIFI_TXStart(WifiTXLocIndex_LOC1, io.TXBUF_LOC1); + } + + if (TXREQ_SET.Cmd != 0) + { + io.TXREQ_READ.Cmd = 1; + WIFI_TXStart(WifiTXLocIndex_CMD, io.TXBUF_CMD); + } + + if (TXREQ_SET.Loc2 != 0) + { + io.TXREQ_READ.Loc2 = 1; + WIFI_TXStart(WifiTXLocIndex_LOC2, io.TXBUF_LOC2); + } + + if (TXREQ_SET.Loc3 != 0) + { + io.TXREQ_READ.Loc3 = 1; + WIFI_TXStart(WifiTXLocIndex_LOC3, io.TXBUF_LOC3); + } + + if (TXREQ_SET.UNKNOWN1 != 0) + { + io.TXREQ_READ.UNKNOWN1 = 1; + WIFI_LOG(2, "Setting of TXREQ_SET.UNKNOWN1, for beacon?\n"); + } break; - case REG_WIFI_USCOMPARECNT: - wifiMac.ucmpEnable = BIT0(val); + } + + case REG_WIFI_TXRESET: // 0x0B4 + { + IOREG_W_TXBUF_RESET TXBUF_RESET; + TXBUF_RESET.value = val; + + if (TXBUF_RESET.Loc1 != 0) + { + io.TXBUF_LOC1.TransferRequest = 0; + } + + if (TXBUF_RESET.Cmd != 0) + { + io.TXBUF_CMD.TransferRequest = 0; + } + + if (TXBUF_RESET.Loc2 != 0) + { + io.TXBUF_LOC2.TransferRequest = 0; + } + + if (TXBUF_RESET.Loc3 != 0) + { + io.TXBUF_LOC3.TransferRequest = 0; + } + + if (TXBUF_RESET.Reply2 != 0) + { + io.TXBUF_REPLY2.Enable = 0; + } + + if (TXBUF_RESET.Reply1 != 0) + { + io.TXBUF_REPLY1.Enable = 0; + } + + const bool reportUnknownWrite = (val != 0xFFFF); + + if (io.TXBUF_RESET.UNKNOWN1 != TXBUF_RESET.UNKNOWN1) + { + io.TXBUF_RESET.UNKNOWN1 = TXBUF_RESET.UNKNOWN1; + + if (reportUnknownWrite) + { + WIFI_LOG(2, "Writing value of %04Xh to TXBUF_RESET.UNKNOWN1\n", (int)io.TXBUF_RESET.UNKNOWN1); + } + } + + if (io.TXBUF_RESET.UNKNOWN2 != TXBUF_RESET.UNKNOWN2) + { + io.TXBUF_RESET.UNKNOWN2 = TXBUF_RESET.UNKNOWN2; + + if (reportUnknownWrite) + { + WIFI_LOG(2, "Writing value of %04Xh to TXBUF_RESET.UNKNOWN2\n", (int)io.TXBUF_RESET.UNKNOWN2); + } + } break; - case REG_WIFI_USCOUNTER0: - wifiMac.usec = (wifiMac.usec & 0xFFFFFFFFFFFF0000ULL) | (u64)val; + } + + case 0x0BA: // 0x0BA + io.INTERNAL_0BA = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_0BA\n", (int)io.INTERNAL_0BA); break; - case REG_WIFI_USCOUNTER1: - wifiMac.usec = (wifiMac.usec & 0xFFFFFFFF0000FFFFULL) | (u64)val << 16; + + case REG_WIFI_PREAMBLE: // 0x0BC + io.PREAMBLE.value = val; break; - case REG_WIFI_USCOUNTER2: - wifiMac.usec = (wifiMac.usec & 0xFFFF0000FFFFFFFFULL) | (u64)val << 32; + + case REG_WIFI_CMD_TOTALTIME: // 0x0C0 + io.CMD_TOTALTIME = val; break; - case REG_WIFI_USCOUNTER3: - wifiMac.usec = (wifiMac.usec & 0x0000FFFFFFFFFFFFULL) | (u64)val << 48; + + case REG_WIFI_CMD_REPLYTIME: // 0x0C4 + io.CMD_REPLYTIME = val; break; - case REG_WIFI_USCOMPARE0: - wifiMac.ucmp = (wifiMac.ucmp & 0xFFFFFFFFFFFF0000ULL) | (u64)(val & 0xFFFE); - //if (BIT0(val)) - // WIFI_triggerIRQ(14); - // wifiMac.usec = wifiMac.ucmp; + + case 0x0C8: // 0x0C8 + io.INTERNAL_0C8 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_0C8\n", (int)io.INTERNAL_0C8); break; - case REG_WIFI_USCOMPARE1: - wifiMac.ucmp = (wifiMac.ucmp & 0xFFFFFFFF0000FFFFULL) | (u64)val << 16; + + case REG_WIFI_RXFILTER: // 0x0D0 + io.RXFILTER.value = val; break; - case REG_WIFI_USCOMPARE2: - wifiMac.ucmp = (wifiMac.ucmp & 0xFFFF0000FFFFFFFFULL) | (u64)val << 32; + + case REG_WIFI_CONFIG_0D4: // 0x0D4 + io.CONFIG_0D4 = val; break; - case REG_WIFI_USCOMPARE3: - wifiMac.ucmp = (wifiMac.ucmp & 0x0000FFFFFFFFFFFFULL) | (u64)val << 48; + + case REG_WIFI_CONFIG_0D8: // 0x0D8 + io.CONFIG_0D8 = val; break; - case REG_WIFI_BEACONPERIOD: - wifiMac.BeaconInterval = val & 0x03FF; + + case REG_WIFI_RX_LEN_CROP: // 0x0DA + io.RX_LEN_CROP.value = val; break; - case REG_WIFI_BEACONCOUNT1: - wifiMac.BeaconCount1 = val; + + case REG_WIFI_RXFILTER2: // 0x0E0 + io.RXFILTER2.value = val; break; - case REG_WIFI_BEACONCOUNT2: - wifiMac.BeaconCount2 = val; + + case REG_WIFI_USCOUNTERCNT: // 0x0E8 + io.US_COUNTCNT.value = val & 0x0001; break; - case REG_WIFI_BBCNT: - WIFI_setBB_CNT(val); + + case REG_WIFI_USCOMPARECNT: // 0x0EA + { + IOREG_W_US_COMPARECNT US_COMPARECNT; + US_COMPARECNT.value = val & 0x0003; + + io.US_COMPARECNT.EnableCompare = US_COMPARECNT.EnableCompare; + + if (US_COMPARECNT.ForceIRQ14 != 0) + { + WIFI_triggerIRQ(WIFI_IRQ_TIMEBEACON); + } break; - case REG_WIFI_RXBUF_COUNT: - wifiMac.RXBufCount = val & 0x0FFF; + } + + case REG_WIFI_CONFIG_0EC: // 0x0EC + io.CONFIG_0EC = val; break; - case REG_WIFI_EXTRACOUNTCNT: - wifiMac.eCountEnable = BIT0(val); + + case REG_WIFI_EXTRACOUNTCNT: // 0x0EE + io.CMD_COUNTCNT.value = val & 0x0001; break; - case REG_WIFI_EXTRACOUNT: - wifiMac.eCount = (u32)val * 10; + + case REG_WIFI_USCOMPARE0: // 0x0F0 + io.US_COMPARE0 = val; break; - case REG_WIFI_LISTENINT: - wifiMac.ListenInterval = val & 0x00FF; + + case REG_WIFI_USCOMPARE1: // 0x0F2 + io.US_COMPARE1 = val; break; - case REG_WIFI_LISTENCOUNT: - wifiMac.ListenCount = val & 0x00FF; + + case REG_WIFI_USCOMPARE2: // 0x0F4 + io.US_COMPARE2 = val; break; - case REG_WIFI_POWER_US: - wifiMac.crystalEnabled = !BIT0(val); + + case REG_WIFI_USCOMPARE3: // 0x0F6 + io.US_COMPARE3 = val; break; - case REG_WIFI_IF_SET: + + case REG_WIFI_USCOUNTER0: // 0x0F8 + io.US_COUNT0 = val; + break; + + case REG_WIFI_USCOUNTER1: // 0x0FA + io.US_COUNT1 = val; + break; + + case REG_WIFI_USCOUNTER2: // 0x0FC + io.US_COUNT2 = val; + break; + + case REG_WIFI_USCOUNTER3: // 0x0FE + io.US_COUNT3 = val; + break; + + case 0x100: // 0x100 + io.INTERNAL_100 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_100\n", (int)io.INTERNAL_100); + break; + + case 0x102: // 0x102 + io.INTERNAL_102 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_102\n", (int)io.INTERNAL_102); + break; + + case 0x104: // 0x104 + io.INTERNAL_104 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_104\n", (int)io.INTERNAL_104); + break; + + case 0x106: // 0x106 + io.INTERNAL_106 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_106\n", (int)io.INTERNAL_106); + break; + + case REG_WIFI_CONTENTFREE: // 0x10C + io.CONTENTFREE = val; + break; + + case REG_WIFI_PREBEACONCOUNT: // 0x110 + io.PRE_BEACON = val; + break; + + case REG_WIFI_EXTRACOUNT: // 0x118 + io.CMD_COUNT = val; + wifi.cmdCount_u32 = (u32)val * 10; + break; + + case REG_WIFI_BEACONCOUNT1: // 0x11C + io.BEACONCOUNT1 = val; + break; + + case REG_WIFI_CONFIG_120: // 0x120 + io.CONFIG_120 = val; + break; + + case REG_WIFI_CONFIG_122: // 0x122 + io.CONFIG_122 = val; + break; + + case REG_WIFI_CONFIG_124: // 0x124 + io.CONFIG_124 = val; + break; + + case 0x126: // 0x126 + io.INTERNAL_126 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_126\n", (int)io.INTERNAL_126); + break; + + case REG_WIFI_CONFIG_128: // 0x128 + io.CONFIG_128 = val; + break; + + case 0x12A: // 0x12A + io.INTERNAL_12A = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_12A\n", (int)io.INTERNAL_12A); + break; + + case REG_WIFI_CONFIG_130: // 0x130 + io.CONFIG_130 = val; + break; + + case REG_WIFI_CONFIG_132: // 0x132 + io.CONFIG_132 = val; + break; + + case REG_WIFI_BEACONCOUNT2: // 0x134 + io.BEACONCOUNT2 = val; + break; + + case REG_WIFI_CONFIG_140: // 0x140 + io.CONFIG_140 = val; + break; + + case REG_WIFI_CONFIG_142: // 0x142 + io.CONFIG_142 = val; + break; + + case REG_WIFI_CONFIG_144: // 0x144 + io.CONFIG_144 = val; + break; + + case REG_WIFI_CONFIG_146: // 0x146 + io.CONFIG_146 = val; + break; + + case REG_WIFI_CONFIG_148: // 0x148 + io.CONFIG_148 = val; + break; + + case REG_WIFI_CONFIG_14A: // 0x14A + io.CONFIG_14A = val; + break; + + case REG_WIFI_CONFIG_14C: // 0x14C + io.CONFIG_14C = val; + break; + + case REG_WIFI_CONFIG_150: // 0x150 + io.CONFIG_150 = val; + break; + + case REG_WIFI_CONFIG_154: // 0x154 + io.CONFIG_154 = val; + break; + + case REG_WIFI_BBCNT: // 0x158 + { + bb_t &bb = wifiHandler->GetWifiData().bb; + + io.BB_CNT.value = val & 0xF0FF; + + if (io.BB_CNT.Index > 0x68) + { + WIFI_LOG(2, "Writing value of %02Xh to BB_CNT.Index, should be 00h-68h\n", (int)io.BB_CNT.Index); + } + else + { + io.BB_BUSY.Busy = 1; + + if (io.BB_CNT.Direction == 5) // Perform a write + { + bb.data[io.BB_CNT.Index] = io.BB_WRITE.Data; + } + else if (io.BB_CNT.Direction == 6) // Perform a read + { + io.BB_READ.Data = bb.data[io.BB_CNT.Index]; + } + + // Normally, there should be some sort of transfer delay, but we're + // not going to emulate the delay right now. Therefore, assume for + // now that the transfer occurs instantaneously and clear the busy + // flag accordingly. + io.BB_BUSY.Busy = 0; + } + break; + } + + case REG_WIFI_BBWRITE: // 0x15A + io.BB_WRITE.value = val & 0x00FF; + break; + + case REG_WIFI_BBMODE: // 0x160 + io.BB_MODE.value = val & 0x0041; + break; + + case REG_WIFI_BBPOWER: // 0x168 + io.BB_POWER.value = val & 0x800F; + break; + + case 0x16A: // 0x16A + io.INTERNAL_16A = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_16A\n", (int)io.INTERNAL_16A); + break; + + case 0x170: // 0x170 + io.INTERNAL_170 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_170\n", (int)io.INTERNAL_170); + break; + + case 0x172: // 0x172 + io.INTERNAL_172 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_172\n", (int)io.INTERNAL_172); + break; + + case 0x174: // 0x174 + io.INTERNAL_174 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_174\n", (int)io.INTERNAL_174); + break; + + case 0x176: // 0x176 + io.INTERNAL_176 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_176\n", (int)io.INTERNAL_176); + break; + + case 0x178: // 0x178 + io.INTERNAL_178 = val; + break; + + case REG_WIFI_RFDATA2: // 0x17C + { + RF2958_IOREG_MAP &rf = wifiHandler->GetWifiData().rf; + + io.RF_DATA2.value = val & 0x00FF; + io.RF_BUSY.Busy = 1; + + const RegAddrRF2958 index = (RegAddrRF2958)io.RF_DATA2.Type2.Index; + + if (io.RF_DATA2.Type2.ReadCommand == 0) // Perform a write + { + switch (index) + { + case REG_RF2958_CFG1: + case REG_RF2958_IPLL1: + case REG_RF2958_IPLL2: + case REG_RF2958_IPLL3: + case REG_RF2958_RFPLL1: + case REG_RF2958_RFPLL4: + case REG_RF2958_CAL1: + case REG_RF2958_TXRX1: + case REG_RF2958_PCNT1: + case REG_RF2958_PCNT2: + case REG_RF2958_VCOT1: + rf.reg[index].DataLSB = io.RF_DATA1.Type2.DataLSB; + rf.reg[index].DataMSB = io.RF_DATA2.Type2.DataMSB; + break; + + case REG_RF2958_RFPLL2: + case REG_RF2958_RFPLL3: + { + u32 channelFreqN; + + rf.reg[index].DataLSB = io.RF_DATA1.Type2.DataLSB; + rf.reg[index].DataMSB = io.RF_DATA2.Type2.DataMSB; + + // get the complete rfpll.n + channelFreqN = (u32)rf.RFPLL3.NUM2 | ((u32)rf.RFPLL2.NUM2 << 18) | ((u32)rf.RFPLL2.N2 << 24); + + // frequency setting is out of range + if (channelFreqN < 0x00A2E8BA) + { + break; + } + + // substract base frequency (channel 1) + channelFreqN -= 0x00A2E8BA; + break; + } + + case REG_RF2958_TEST: + WIFI_LOG(2, "Writing value of %04Xh to RF test register\n", (int)rf.reg[index].Data); + break; + + case REG_RF2958_RESET: + WIFI_resetRF(rf); + break; + + // Any unlisted register is assumed to be unused padding, + // so just do nothing in this case. + default: + break; + } + } + else // Perform a read + { + io.RF_DATA1.Type2.DataLSB = rf.reg[index].DataLSB; + io.RF_DATA2.Type2.DataMSB = rf.reg[index].DataMSB; + } + + // Normally, there should be some sort of transfer delay, but we're + // not going to emulate the delay right now. Therefore, assume for + // now that the transfer occurs instantaneously and clear the busy + // flag accordingly. + io.RF_BUSY.Busy = 0; + break; + } + + case REG_WIFI_RFDATA1: // 0x17E + io.RF_DATA1.value = val; + break; + + case REG_WIFI_RFCNT: // 0x184 + { + if (io.RF_BUSY.Busy == 0) + { + IOREG_W_RF_CNT RF_CNT; + RF_CNT.value = val; + + io.RF_CNT.TransferLen = RF_CNT.TransferLen; + + if (io.RF_CNT.UNKNOWN1 != RF_CNT.UNKNOWN1) + { + io.RF_CNT.UNKNOWN1 = RF_CNT.UNKNOWN1; + WIFI_LOG(2, "Writing value of %d to RF_CNT.UNKNOWN1\n", (int)RF_CNT.UNKNOWN1); + } + + if (io.RF_CNT.UNKNOWN2 != RF_CNT.UNKNOWN2) + { + io.RF_CNT.UNKNOWN2 = RF_CNT.UNKNOWN2; + WIFI_LOG(2, "Writing value of %d to RF_CNT.UNKNOWN2\n", (int)RF_CNT.UNKNOWN2); + } + } + break; + } + + case 0x190: // 0x190 + io.INTERNAL_190 = val; + break; + + case REG_WIFI_TX_HDR_CNT: // 0x194 + io.TX_HDR_CNT.value = val; + break; + + case REG_WIFI_X_1A0: // 0x1A0 + io.X_1A0.value = val; + WIFI_LOG(2, "Writing value of %04Xh to X_1A0\n", (int)io.X_1A0.value); + break; + + case REG_WIFI_X_1A2: // 0x1A2 + io.X_1A2.value = val; + WIFI_LOG(2, "Writing value of %04Xh to X_1A2\n", (int)io.X_1A2.value); + break; + + case REG_WIFI_X_1A4: // 0x1A4 + io.X_1A4 = val; + WIFI_LOG(2, "Writing value of %04Xh to X_1A4\n", (int)io.X_1A4); + break; + + case REG_WIFI_RXSTAT_INC_IE: // 0x1AA + io.RXSTAT_INC_IE.value = val; + break; + + case REG_WIFI_RXSTAT_OVF_IE: // 0x1AE + io.RXSTAT_OVF_IE.value = val; + break; + + case REG_WIFI_RXSTAT0: // 0x1B0 + io.RXSTAT_COUNT.RXSTAT_1B0 = val; + break; + + case REG_WIFI_RXSTAT1: // 0x1B2 + io.RXSTAT_COUNT.RXSTAT_1B2 = val; + break; + + case REG_WIFI_RXSTAT2: // 0x1B4 + io.RXSTAT_COUNT.RXSTAT_1B4 = val; + break; + + case REG_WIFI_RXSTAT3: // 0x1B6 + io.RXSTAT_COUNT.RXSTAT_1B6 = val; + break; + + case REG_WIFI_RXSTAT4: // 0x1B8 + io.RXSTAT_COUNT.RXSTAT_1B8 = val; + break; + + case REG_WIFI_RXSTAT5: // 0x1BA + io.RXSTAT_COUNT.RXSTAT_1BA = val; + break; + + case REG_WIFI_RXSTAT6: // 0x1BC + io.RXSTAT_COUNT.RXSTAT_1BC = val; + break; + + case REG_WIFI_RXSTAT7: // 0x1BE + io.RXSTAT_COUNT.RXSTAT_1BE = val; + break; + + case REG_WIFI_TXERR_COUNT: // 0x1C0 + io.TX_ERR_COUNT.Count++; + break; + + case REG_WIFI_CMD_STAT0: // 0x1D0 + io.CMD_STAT_COUNT.CMD_STAT_1D0 = val; + break; + + case REG_WIFI_CMD_STAT1: // 0x1D2 + io.CMD_STAT_COUNT.CMD_STAT_1D2 = val; + break; + + case REG_WIFI_CMD_STAT2: // 0x1D4 + io.CMD_STAT_COUNT.CMD_STAT_1D4 = val; + break; + + case REG_WIFI_CMD_STAT3: // 0x1D6 + io.CMD_STAT_COUNT.CMD_STAT_1D6 = val; + break; + + case REG_WIFI_CMD_STAT4: // 0x1D8 + io.CMD_STAT_COUNT.CMD_STAT_1D8 = val; + break; + + case REG_WIFI_CMD_STAT5: // 0x1DA + io.CMD_STAT_COUNT.CMD_STAT_1DA = val; + break; + + case REG_WIFI_CMD_STAT6: // 0x1DC + io.CMD_STAT_COUNT.CMD_STAT_1DC = val; + break; + + case REG_WIFI_CMD_STAT7: // 0x1DE + io.CMD_STAT_COUNT.CMD_STAT_1DE = val; + break; + + case 0x1F0: // 0x1F0 + io.INTERNAL_1F0 = val; + break; + + case 0x204: // 0x204 + io.INTERNAL_204 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_204\n", (int)io.INTERNAL_204); + break; + + case 0x208: // 0x208 + io.INTERNAL_208 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_208\n", (int)io.INTERNAL_208); + break; + + case 0x20C: // 0x20C + io.INTERNAL_20C = val; + break; + + case REG_WIFI_IF_SET: // 0x21C WIFI_triggerIRQMask(val); break; - case REG_WIFI_CIRCBUFRD_END: - wifiMac.CircBufRdEnd = (val & 0x1FFE); + + case 0x220: // 0x220 + io.INTERNAL_220 = val; break; - case REG_WIFI_CIRCBUFRD_SKIP: - wifiMac.CircBufRdSkip = val & 0xFFF; + + case 0x224: // 0x224 + io.INTERNAL_224 = val; break; - case REG_WIFI_AID_LOW: - wifiMac.pid = val & 0x0F; + + case REG_WIFI_X_228: // 0x228 + io.X_228 = val; break; - case REG_WIFI_AID_HIGH: - wifiMac.aid = val & 0x07FF; + + case 0x230: // 0x230 + io.INTERNAL_230 = val; break; - case 0xD0: - // printf("wifi: rxfilter=%04X\n", val); + + case 0x234: // 0x234 + io.INTERNAL_234 = val; break; - case 0x0E0: - // printf("wifi: rxfilter2=%04X\n", val); + + case 0x238: // 0x238 + io.INTERNAL_238 = val; break; - + + case 0x23C: // 0x23C + io.INTERNAL_23C = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_23C\n", (int)io.INTERNAL_23C); + break; + + case REG_WIFI_X_244: // 0x244 + io.X_244 = val; + break; + + case 0x248: // 0x248 + io.INTERNAL_248 = val; + break; + + case REG_WIFI_CONFIG_254: // 0x254 + io.CONFIG_254 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only CONFIG_254\n", (int)io.CONFIG_254); + break; + + case 0x258: // 0x258 + io.INTERNAL_258 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_258\n", (int)io.INTERNAL_258); + break; + + case 0x25C: // 0x25C + io.INTERNAL_25C = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_25C\n", (int)io.INTERNAL_25C); + break; + + case 0x260: // 0x260 + io.INTERNAL_260 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_260\n", (int)io.INTERNAL_260); + break; + + case 0x274: // 0x274 + io.INTERNAL_274 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_274\n", (int)io.INTERNAL_274); + break; + + case 0x278: // 0x278 + io.INTERNAL_278 = val; + break; + + case 0x27C: // 0x27C + io.INTERNAL_27C = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_27C\n", (int)io.INTERNAL_27C); + break; + + case REG_WIFI_X_290: // 0x290 + io.X_290.value = val; + break; + + case 0x298: // 0x298 + io.INTERNAL_298 = val; + break; + + case 0x2A0: // 0x2A0 + io.INTERNAL_2A0 = val; + break; + + case 0x2A8: // 0x2A8 + io.INTERNAL_2A8 = val; + break; + + case 0x2AC: // 0x2AC + io.INTERNAL_2AC = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_2AC\n", (int)io.INTERNAL_2AC); + break; + + case 0x2B0: // 0x2B0 + io.INTERNAL_2B0 = val; + break; + + case 0x2B4: // 0x2B4 + io.INTERNAL_2B4 = val; + break; + + case 0x2B8: // 0x2B8 + io.INTERNAL_2B8 = val; + WIFI_LOG(2, "Writing value of %04Xh to possible read-only INTERNAL_2B8\n", (int)io.INTERNAL_2B8); + break; + + case 0x2C0: // 0x2C0 + io.INTERNAL_2C0 = val; + break; + + case REG_WIFI_POWERACK: // 0x2D0 + { + if (io.POWERSTATE.WillPowerOn != 0) + { + io.POWERACK = val; + + if (io.POWERACK == 0x0000) + { + io.POWERSTATE.WillPowerOn = 0; + io.POWERSTATE.IsPowerOff = io.POWERFORCE.NewPowerOffState; + + if (io.POWERSTATE.IsPowerOff == 0) + { + io.POWERSTATE.RequestPowerOn = 0; + WIFI_triggerIRQ(WIFI_IRQ_RFWAKEUP); + + // This is supposedly the TX beacon transfer flag. + // Since reading TXREQ_READ bit 4 should always return a 1 (unless + // POWERFORCE clears it), we'll simply set this bit to 1 on power up + // so that bit 4 gets its default value. + io.TXREQ_READ.UNKNOWN1 = 1; + } + else + { + io.RF_STATUS.Status = 0x9; + io.RF_PINS.CarrierSense = 0; + io.RF_PINS.TXMain = 1; + io.RF_PINS.UNKNOWN1 = 1; + io.RF_PINS.TX_On = 1; + io.RF_PINS.RX_On = 0; + + io.INTERNAL_034 = 0x0002; + io.TXREQ_READ.value &= 0x0010; + io.POWERSTATE.WillPowerOn = 0; + io.POWERSTATE.IsPowerOff = 1; + } + } + } + break; + } + + case 0x2F0: // 0x2F0 + io.INTERNAL_2F0 = val; + break; + + case 0x2F2: // 0x2F2 + io.INTERNAL_2F2 = val; + break; + + case 0x2F4: // 0x2F4 + io.INTERNAL_2F4 = val; + break; + + case 0x2F6: // 0x2F6 + io.INTERNAL_2F6 = val; + break; + + // Report any writes to read-only registers because this shouldn't happen. + case REG_WIFI_ID: // 0x000 + case REG_WIFI_RANDOM: // 0x044 + case REG_WIFI_RXHWWRITECSR: // 0x054 + case REG_WIFI_CIRCBUFREAD: // 0x060 + case REG_WIFI_TXBUF_REPLY2: // 0x098 + case REG_WIFI_TXREQ_READ: // 0x0B0 + case REG_WIFI_TXBUSY: // 0x0B6 + case REG_WIFI_TXSTAT: // 0x0B8 + case REG_WIFI_BBREAD: // 0x15C + case REG_WIFI_BBBUSY: // 0x15E + case REG_WIFI_RFBUSY: // 0x180 + case REG_WIFI_RFPINS: // 0x19C + case REG_WIFI_RXSTAT_INC_IF: // 0x1A8 + case REG_WIFI_RXSTAT_OVF_IF: // 0x1AC + case REG_WIFI_RX_COUNT: // 0x1C4 + case REG_WIFI_TXSEQNO: // 0x210 + case REG_WIFI_RFSTATUS: // 0x214 + case 0x24C: // 0x24C + case 0x24E: // 0x24E + case 0x250: // 0x250 + case 0x264: // 0x264 + case REG_WIFI_RXTX_ADDR: // 0x268 + case 0x270: // 0x270 + case 0x2A2: // 0x2A2 + case 0x2A4: // 0x2A4 + case 0x2C4: // 0x2C4 + case 0x2C8: // 0x2C8 + case 0x2CC: // 0x2CC + WIFI_LOG(2, "Preventing writing value of %04Xh to read-only port 0x%03X\n", val, address); + break; + + // Assume that any unlisted register is just padding. It's meaningless to + // write to padding, so report that here. default: + WIFI_LOG(2, "Preventing writing value of %04Xh to padding address 0x%03X\n", val, address); break; } - - WIFI_IOREG(address) = val; } u16 WIFI_read16(u32 address) { bool action = false; if (!nds.power2.wifi) return 0; + + WifiData &wifi = wifiHandler->GetWifiData(); + WIFI_IOREG_MAP &io = wifi.io; u32 page = address & 0x7000; @@ -1251,254 +2157,861 @@ u16 WIFI_read16(u32 address) // 0x4000 - 0x5FFF: wifi RAM if ((page >= 0x4000) && (page < 0x6000)) { - return wifiMac.RAM[(address & 0x1FFF) >> 1]; + return wifi.RAM[(address & 0x1FFF) >> 1]; } // anything else: I/O ports // only the first mirror causes a special action if (page == 0x0000) action = true; - + address &= 0x0FFF; switch (address) { - case REG_WIFI_ID: + case REG_WIFI_ID: // 0x000 return WIFI_CHIPID; - case REG_WIFI_MODE: - return wifiMac.macMode; - case REG_WIFI_WEP: - return wifiMac.wepMode; - case REG_WIFI_IE: - return wifiMac.IE; - case REG_WIFI_IF: - return wifiMac.IF; - case REG_WIFI_POWERSTATE: - return ((wifiMac.powerOn ? 0x0000 : 0x0200) | (wifiMac.powerOnPending ? 0x0102 : 0x0000)); - case REG_WIFI_RFDATA1: - return WIFI_getRF_DATA(0); - case REG_WIFI_RFDATA2: - return WIFI_getRF_DATA(1); - case REG_WIFI_RFBUSY: - case REG_WIFI_BBBUSY: - return 0; /* we are never busy :p */ - case REG_WIFI_BBREAD: - return WIFI_getBB_DATA(); - case REG_WIFI_RANDOM: - // probably not right, but it's better than using the unsaved and shared rand(). - // at the very least, rand() shouldn't be used when movieMode is active. + + case REG_WIFI_MODE: // 0x004 + return io.MODE_RST.value; + + case REG_WIFI_WEP: // 0x006 + return io.MODE_WEP.value; + + case REG_WIFI_TXSTATCNT: // 0x008 + return io.TXSTATCNT.value; + + case REG_WIFI_X_00A: // 0x00A + return io.X_00A; + + case REG_WIFI_IF: // 0x010 + return io.IF.value; + + case REG_WIFI_IE: // 0x012 + return io.IE.value; + + case REG_WIFI_MAC0: // 0x018 + return io.MACADDR0.value; + + case REG_WIFI_MAC1: // 0x01A + return io.MACADDR1.value; + + case REG_WIFI_MAC2: // 0x01C + return io.MACADDR2.value; + + case REG_WIFI_BSS0: // 0x020 + return io.BSSID0.value; + + case REG_WIFI_BSS1: // 0x022 + return io.BSSID1.value; + + case REG_WIFI_BSS2: // 0x024 + return io.BSSID2.value; + + case REG_WIFI_AID_LOW: // 0x028 + return io.AID_LOW.value; + + case REG_WIFI_AID_HIGH: // 0x02A + return io.AID_FULL.value; + + case REG_WIFI_RETRYLIMIT: // 0x02C + return io.TX_RETRYLIMIT.value; + + case 0x2E: // 0x02E + return io.INTERNAL_02E; + + case REG_WIFI_RXCNT: // 0x030 + return io.RXCNT.value; + + case REG_WIFI_WEPCNT: // 0x032 + return io.WEP_CNT.value; + + case 0x034: // 0x034 + return io.INTERNAL_034; + + case REG_WIFI_POWER_US: // 0x036 + return io.POWER_US.value; + + case REG_WIFI_POWER_TX: // 0x038 + return io.POWER_TX.value; + + case REG_WIFI_POWERSTATE: // 0x03C + return io.POWERSTATE.value; + + case REG_WIFI_POWERFORCE: // 0x040 + return io.POWERFORCE.value; + + case REG_WIFI_RANDOM: // 0x044 + { + u16 returnValue = io.RANDOM.Random; + io.RANDOM.Random = (io.RANDOM.Random & 1) ^ (((io.RANDOM.Random << 1) & 0x7FE) | ((io.RANDOM.Random >> 10) & 0x1)); + return returnValue; + } + + case REG_WIFI_POWER_UNK: // 0x048 + return io.POWER_UNKNOWN.value; + + case REG_WIFI_RXRANGEBEGIN: // 0x050 + return io.RXBUF_BEGIN; + + case REG_WIFI_RXRANGEEND: // 0x052 + return io.RXBUF_END; + + case REG_WIFI_RXHWWRITECSR: // 0x054 + return io.RXBUF_WRCSR.value; + + case REG_WIFI_WRITECSRLATCH: // 0x056 + return io.RXBUF_WR_ADDR.value; + + case REG_WIFI_CIRCBUFRADR: // 0x058 + return io.RXBUF_RD_ADDR.value; + + case REG_WIFI_RXREADCSR: // 0x05A + return io.RXBUF_READCSR.value; + + case REG_WIFI_RXBUF_COUNT: // 0x05C + return io.RXBUF_COUNT.value; + + case REG_WIFI_CIRCBUFREAD: // 0x060 + case REG_WIFI_CIRCBUFWRITE: // 0x070 - mirrored read of 0x060 + { + u16 val = wifi.RAM[io.RXBUF_RD_ADDR.HalfwordAddress]; + + if (action) { - u16 returnValue = wifiMac.randomSeed; - wifiMac.randomSeed = (wifiMac.randomSeed & 1) ^ (((wifiMac.randomSeed << 1) & 0x7FE) | ((wifiMac.randomSeed >> 10) & 0x1)); - return returnValue; - } - - return 0; - case REG_WIFI_MAC0: - case REG_WIFI_MAC1: - case REG_WIFI_MAC2: - //printf("read mac addr: word %i = %02X\n", (address - REG_WIFI_MAC0) >> 1, wifiMac.mac.words[(address - REG_WIFI_MAC0) >> 1]); - return wifiMac.mac.words[(address - REG_WIFI_MAC0) >> 1]; - case REG_WIFI_BSS0: - case REG_WIFI_BSS1: - case REG_WIFI_BSS2: - //printf("read bssid addr: word %i = %02X\n", (address - REG_WIFI_BSS0) >> 1, wifiMac.bss.words[(address - REG_WIFI_BSS0) >> 1]); - return wifiMac.bss.words[(address - REG_WIFI_BSS0) >> 1]; - case REG_WIFI_RXCNT: - return wifiMac.RXCnt; - case REG_WIFI_RXRANGEBEGIN: - return wifiMac.RXRangeBegin; - case REG_WIFI_CIRCBUFREAD: - { - u16 val = wifiMac.RAM[wifiMac.CircBufReadAddress >> 1]; - if (action) + io.RXBUF_RD_ADDR.HalfwordAddress++; + + if (io.RXBUF_RD_ADDR.ByteAddress >= io.RXBUF_END) { - wifiMac.CircBufReadAddress += 2; - - if (wifiMac.CircBufReadAddress >= wifiMac.RXRangeEnd) - { - wifiMac.CircBufReadAddress = wifiMac.RXRangeBegin; - } - else - { - /* skip does not fire after a reset */ - if (wifiMac.CircBufReadAddress == wifiMac.CircBufRdEnd) - { - wifiMac.CircBufReadAddress += wifiMac.CircBufRdSkip * 2; - wifiMac.CircBufReadAddress &= 0x1FFE; - if (wifiMac.CircBufReadAddress + wifiMac.RXRangeBegin == wifiMac.RXRangeEnd) wifiMac.CircBufReadAddress = 0; - } - } - - if (wifiMac.RXBufCount > 0) - { - if (wifiMac.RXBufCount == 1) - { - WIFI_triggerIRQ(WIFI_IRQ_RXCOUNTEXP); - } - wifiMac.RXBufCount--; - } + io.RXBUF_RD_ADDR.ByteAddress = io.RXBUF_BEGIN; + } + else + { + /* skip does not fire after a reset */ + if (io.RXBUF_RD_ADDR.HalfwordAddress == io.RXBUF_GAP.HalfwordAddress) + { + io.RXBUF_RD_ADDR.HalfwordAddress += io.RXBUF_GAPDISP.HalfwordOffset; + if (io.RXBUF_RD_ADDR.ByteAddress + io.RXBUF_BEGIN == io.RXBUF_END) io.RXBUF_RD_ADDR.ByteAddress = 0; + } + } + + if (io.RXBUF_COUNT.Count > 0) + { + if (io.RXBUF_COUNT.Count == 1) + { + WIFI_triggerIRQ(WIFI_IRQ_RXCOUNTEXP); + } + + io.RXBUF_COUNT.Count--; } - return val; } - case REG_WIFI_CIRCBUFRADR: - return wifiMac.CircBufReadAddress; - case REG_WIFI_RXBUF_COUNT: - return wifiMac.RXBufCount; - case REG_WIFI_TXREQ_READ: - //printf("read TX reg %04X\n", address); - return wifiMac.TXCnt | 0x10; - case REG_WIFI_TXBUSY: - //printf("read TX reg %04X\n", address); - return ((wifiMac.txSlotBusy[0] ? 0x01 : 0x00) | (wifiMac.txSlotBusy[1] ? 0x04 : 0x00) | (wifiMac.txSlotBusy[2] ? 0x08 : 0x00)); - case REG_WIFI_TXSTAT: - //printf("read TX reg %04X\n", address); - return wifiMac.TXStat; - case REG_WIFI_TXLOCEXTRA: - //printf("read TX reg %04X\n", address); - return wifiMac.TXSlotExtra; - case REG_WIFI_TXLOC1: - case REG_WIFI_TXLOC2: - case REG_WIFI_TXLOC3: - //printf("read TX reg %04X\n", address); - return wifiMac.TXSlot[(address - REG_WIFI_TXLOC1) >> 2]; - case REG_WIFI_TXLOCBEACON: - //printf("read TX reg %04X\n", address); - break; - case REG_WIFI_EXTRACOUNTCNT: - return wifiMac.eCountEnable?1:0; - case REG_WIFI_EXTRACOUNT: - return (u16)((wifiMac.eCount + 9) / 10); - case REG_WIFI_USCOUNTER0: - return (u16)wifiMac.usec; - case REG_WIFI_USCOUNTER1: - return (u16)(wifiMac.usec >> 16); - case REG_WIFI_USCOUNTER2: - return (u16)(wifiMac.usec >> 32); - case REG_WIFI_USCOUNTER3: - return (u16)(wifiMac.usec >> 48); - case REG_WIFI_USCOMPARE0: - return (u16)wifiMac.ucmp; - case REG_WIFI_USCOMPARE1: - return (u16)(wifiMac.ucmp >> 16); - case REG_WIFI_USCOMPARE2: - return (u16)(wifiMac.ucmp >> 32); - case REG_WIFI_USCOMPARE3: - return (u16)(wifiMac.ucmp >> 48); - case REG_WIFI_BEACONCOUNT1: - return wifiMac.BeaconCount1; - case REG_WIFI_BEACONCOUNT2: - return wifiMac.BeaconCount2; - case REG_WIFI_LISTENCOUNT: - return wifiMac.ListenCount; - case REG_WIFI_POWER_US: - return wifiMac.crystalEnabled?0:1; - case REG_WIFI_CIRCBUFRD_END: - return wifiMac.CircBufRdEnd; - case REG_WIFI_CIRCBUFRD_SKIP: - return wifiMac.CircBufRdSkip; - case REG_WIFI_AID_LOW: - return wifiMac.pid; - case REG_WIFI_AID_HIGH: - return wifiMac.aid; - - // RFSTATUS, RFPINS - // TODO: figure out how to emulate those correctly - // without breaking Nintendo's games - case REG_WIFI_RFSTATUS: + return val; + } + + case REG_WIFI_CIRCBUFRD_END: // 0x062 + return io.RXBUF_GAP.value; + + case REG_WIFI_CIRCBUFRD_SKIP: // 0x064 + return io.RXBUF_GAPDISP.value; + + case REG_WIFI_CIRCBUFWADR: // 0x068 + return io.TXBUF_WR_ADDR.value; + + case REG_WIFI_TXBUFCOUNT: // 0x06C + return io.TXBUF_COUNT.value; + + case REG_WIFI_CIRCBUFWR_END: // 0x074 + return io.TXBUF_GAP.value; + + case REG_WIFI_CIRCBUFWR_SKIP: // 0x076 + return io.TXBUF_GAPDISP.value; + + case 0x078: // 0x078 - mirrored read of 0x068 + return io.TXBUF_WR_ADDR.value; + + case REG_WIFI_TXLOCBEACON: // 0x080 + return io.TXBUF_BEACON.value; + + case REG_WIFI_TXBUF_TIM: // 0x084 + return io.TXBUF_TIM.value; + + case REG_WIFI_LISTENCOUNT: // 0x088 + return io.LISTENCOUNT.value; + + case REG_WIFI_BEACONPERIOD: // 0x08C + return io.BEACONINT.value; + + case REG_WIFI_LISTENINT: // 0x08E + return io.LISTENINT.value; + + case REG_WIFI_TXLOCEXTRA: // 0x090 + return io.TXBUF_CMD.value; + + case REG_WIFI_TXBUF_REPLY1: // 0x094 + return io.TXBUF_REPLY1.value; + + case REG_WIFI_TXBUF_REPLY2: // 0x098 + return io.TXBUF_REPLY2.value; + + case 0x09C: // 0x09C + return io.INTERNAL_09C; + + case REG_WIFI_TXLOC1: // 0x0A0 + return io.TXBUF_LOC1.value; + + case REG_WIFI_TXLOC2: // 0x0A4 + return io.TXBUF_LOC2.value; + + case REG_WIFI_TXLOC3: // 0x0A8 + return io.TXBUF_LOC3.value; + + case REG_WIFI_TXREQ_RESET: // 0x0AC - mirrored read of 0x09C + case REG_WIFI_TXREQ_SET: // 0x0AE - mirrored read of 0x09C + return io.INTERNAL_09C; + + case REG_WIFI_TXREQ_READ: // 0x0B0 + return io.TXREQ_READ.value; + + case REG_WIFI_TXRESET: // 0x0B4 - mirrored read of 0x0B6 + case REG_WIFI_TXBUSY: // 0x0B6 + return io.TXBUSY.value; + + case REG_WIFI_TXSTAT: // 0x0B8 + return io.TXSTAT.value; + + case 0x0BA: // 0x0BA + return io.INTERNAL_0BA; + + case REG_WIFI_PREAMBLE: // 0x0BC + return io.PREAMBLE.value; + + case REG_WIFI_CMD_TOTALTIME: // 0x0C0 + return io.CMD_TOTALTIME; + + case REG_WIFI_CMD_REPLYTIME: // 0x0C4 + return io.CMD_REPLYTIME; + + case 0x0C8: // 0x0C8 + return io.INTERNAL_0C8; + + case REG_WIFI_RXFILTER: // 0x0D0 + return io.RXFILTER.value; + + case REG_WIFI_CONFIG_0D4: // 0x0D4 + return io.CONFIG_0D4; + + case REG_WIFI_CONFIG_0D8: // 0x0D8 + return io.CONFIG_0D8; + + case REG_WIFI_RX_LEN_CROP: // 0x0DA + return io.RX_LEN_CROP.value; + + case REG_WIFI_RXFILTER2: // 0x0E0 + return io.RXFILTER2.value; + + case REG_WIFI_USCOUNTERCNT: // 0x0E8 + return io.US_COUNTCNT.value; + + case REG_WIFI_USCOMPARECNT: // 0x0EA + return io.US_COMPARECNT.value; + + case REG_WIFI_CONFIG_0EC: // 0x0EC + return io.CONFIG_0EC; + + case REG_WIFI_EXTRACOUNTCNT: // 0x0EE + return io.CMD_COUNTCNT.value; + + case REG_WIFI_USCOMPARE0: // 0x0F0 + return io.US_COMPARE0; + + case REG_WIFI_USCOMPARE1: // 0x0F2 + return io.US_COMPARE1; + + case REG_WIFI_USCOMPARE2: // 0x0F4 + return io.US_COMPARE2; + + case REG_WIFI_USCOMPARE3: // 0x0F6 + return io.US_COMPARE3; + + case REG_WIFI_USCOUNTER0: // 0x0F8 + return io.US_COUNT0; + + case REG_WIFI_USCOUNTER1: // 0x0FA + return io.US_COUNT1; + + case REG_WIFI_USCOUNTER2: // 0x0FC + return io.US_COUNT2; + + case REG_WIFI_USCOUNTER3: // 0x0FE + return io.US_COUNT3; + + case 0x100: // 0x100 + return io.INTERNAL_100; + + case 0x102: // 0x102 + return io.INTERNAL_102; + + case 0x104: // 0x104 + return io.INTERNAL_104; + + case 0x106: // 0x106 + return io.INTERNAL_106; + + case REG_WIFI_CONTENTFREE: // 0x10C + return io.CONTENTFREE; + + case REG_WIFI_PREBEACONCOUNT: // 0x110 + return io.PRE_BEACON; + + case REG_WIFI_EXTRACOUNT: // 0x118 + return (u16)((wifi.cmdCount_u32 + 9) / 10); + + case REG_WIFI_BEACONCOUNT1: // 0x11C + return io.BEACONCOUNT1; + + case REG_WIFI_CONFIG_120: // 0x120 + return io.CONFIG_120; + + case REG_WIFI_CONFIG_122: // 0x122 + return io.CONFIG_122; + + case REG_WIFI_CONFIG_124: // 0x124 + return io.CONFIG_124; + + case 0x126: // 0x126 + return io.INTERNAL_126; + + case REG_WIFI_CONFIG_128: // 0x128 + return io.CONFIG_128; + + case 0x12A: // 0x12A + return io.INTERNAL_12A; + + case REG_WIFI_CONFIG_130: // 0x130 + return io.CONFIG_130; + + case REG_WIFI_CONFIG_132: // 0x132 + return io.CONFIG_132; + + case REG_WIFI_BEACONCOUNT2: // 0x134 + return io.BEACONCOUNT2; + + case REG_WIFI_CONFIG_140: // 0x140 + return io.CONFIG_140; + + case REG_WIFI_CONFIG_142: // 0x142 + return io.CONFIG_142; + + case REG_WIFI_CONFIG_144: // 0x144 + return io.CONFIG_144; + + case REG_WIFI_CONFIG_146: // 0x146 + return io.CONFIG_146; + + case REG_WIFI_CONFIG_148: // 0x148 + return io.CONFIG_148; + + case REG_WIFI_CONFIG_14A: // 0x14A + return io.CONFIG_14A; + + case REG_WIFI_CONFIG_14C: // 0x14C + return io.CONFIG_14C; + + case REG_WIFI_CONFIG_150: // 0x150 + return io.CONFIG_150; + + case REG_WIFI_CONFIG_154: // 0x154 + return io.CONFIG_154; + + case REG_WIFI_BBCNT: // 0x158 - mirrored read of 0x15C + return io.BB_READ.value; + + case REG_WIFI_BBWRITE: // 0x15A + return 0; + + case REG_WIFI_BBREAD: // 0x15C + return io.BB_READ.value; + + case REG_WIFI_BBBUSY: // 0x15E + return io.BB_BUSY.value; + + case REG_WIFI_BBMODE: // 0x160 + return io.BB_MODE.value; + + case REG_WIFI_BBPOWER: // 0x168 + return io.BB_POWER.value; + + case 0x16A: // 0x16A + return io.INTERNAL_16A; + + case 0x170: // 0x170 + return io.INTERNAL_170; + + case 0x172: // 0x172 + return io.INTERNAL_172; + + case 0x174: // 0x174 + return io.INTERNAL_174; + + case 0x176: // 0x176 + return io.INTERNAL_176; + + case 0x178: // 0x178 - mirrored read of 0x17C + case REG_WIFI_RFDATA2: // 0017C + { + if (io.RF_BUSY.Busy == 0) + { + return io.RF_DATA2.value; + } + else + { + return 0; + } + } + + case REG_WIFI_RFDATA1: // 0x17E + { + if (io.RF_BUSY.Busy == 0) + { + return io.RF_DATA1.value; + } + else + { + return 0; + } + } + + case REG_WIFI_RFBUSY: // 0x180 + return io.RF_BUSY.value; + + case REG_WIFI_RFCNT: // 0x184 + return io.RF_CNT.value; + + case 0x190: // 0x190 + return io.INTERNAL_190; + + case REG_WIFI_TX_HDR_CNT: // 0x194 + return io.TX_HDR_CNT.value; + + case 0x198: // 0x198 + return io.INTERNAL_198; + + case REG_WIFI_X_1A0: // 0x1A0 + return io.X_1A0.value; + + case REG_WIFI_X_1A2: // 0x1A2 + return io.X_1A2.value; + + case REG_WIFI_X_1A4: // 0x1A4 + return io.X_1A4; + + case REG_WIFI_RXSTAT_INC_IF: // 0x1A8 + return io.RXSTAT_INC_IF.value; + + case REG_WIFI_RXSTAT_INC_IE: // 0x1AA + return io.RXSTAT_INC_IE.value; + + case REG_WIFI_RXSTAT_OVF_IF: // 0x1AC + return io.RXSTAT_OVF_IF.value; + + case REG_WIFI_RXSTAT_OVF_IE: // 0x1AE + return io.RXSTAT_OVF_IE.value; + + case REG_WIFI_RXSTAT0: // 0x1B0 + return io.RXSTAT_COUNT.RXSTAT_1B0; + + case REG_WIFI_RXSTAT1: // 0x1B2 + return io.RXSTAT_COUNT.RXSTAT_1B2; + + case REG_WIFI_RXSTAT2: // 0x1B4 + return io.RXSTAT_COUNT.RXSTAT_1B4; + + case REG_WIFI_RXSTAT3: // 0x1B6 + return io.RXSTAT_COUNT.RXSTAT_1B6; + + case REG_WIFI_RXSTAT4: // 0x1B8 + return io.RXSTAT_COUNT.RXSTAT_1B8; + + case REG_WIFI_RXSTAT5: // 0x1BA + return io.RXSTAT_COUNT.RXSTAT_1BA; + + case REG_WIFI_RXSTAT6: // 0x1BC + return io.RXSTAT_COUNT.RXSTAT_1BC; + + case REG_WIFI_RXSTAT7: // 0x1BE + return io.RXSTAT_COUNT.RXSTAT_1BE; + + case REG_WIFI_TXERR_COUNT: // 0x1C0 + return io.TX_ERR_COUNT.value; + + case REG_WIFI_RX_COUNT: // 0x1C4 + return io.RX_COUNT.value; + + case REG_WIFI_CMD_STAT0: // 0x1D0 + return io.CMD_STAT_COUNT.CMD_STAT_1D0; + + case REG_WIFI_CMD_STAT1: // 0x1D2 + return io.CMD_STAT_COUNT.CMD_STAT_1D2; + + case REG_WIFI_CMD_STAT2: // 0x1D4 + return io.CMD_STAT_COUNT.CMD_STAT_1D4; + + case REG_WIFI_CMD_STAT3: // 0x1D6 + return io.CMD_STAT_COUNT.CMD_STAT_1D6; + + case REG_WIFI_CMD_STAT4: // 0x1D8 + return io.CMD_STAT_COUNT.CMD_STAT_1D8; + + case REG_WIFI_CMD_STAT5: // 0x1DA + return io.CMD_STAT_COUNT.CMD_STAT_1DA; + + case REG_WIFI_CMD_STAT6: // 0x1DC + return io.CMD_STAT_COUNT.CMD_STAT_1DC; + + case REG_WIFI_CMD_STAT7: // 0x1DE + return io.CMD_STAT_COUNT.CMD_STAT_1DE; + + case 0x1F0: // 0x1F0 + return io.INTERNAL_1F0; + + case 0x204: // 0x204 + return io.INTERNAL_204; + + case 0x208: // 0x208 + return io.INTERNAL_208; + + case 0x20C: // 0x20C - mirrored read of 0x09C + return io.INTERNAL_09C; + + case REG_WIFI_TXSEQNO: // 0x210 + return io.TX_SEQNO.value; + + case REG_WIFI_IF_SET: // 0x21C - mirrored read of 0x010 + return io.IF.value; + + case 0x220: // 0x220 + return io.INTERNAL_220; + + case 0x224: // 0x224 + return io.INTERNAL_224; + + case REG_WIFI_X_228: // 0x228 + return 0; + + case 0x230: // 0x230 + return io.INTERNAL_230; + + case 0x234: // 0x234 + return io.INTERNAL_234; + + case 0x238: // 0x238 + return io.INTERNAL_238; + + case 0x23C: // 0x23C + return io.INTERNAL_23C; + + case REG_WIFI_X_244: // 0x244 + return io.X_244; + + case 0x248: // 0x248 + return io.INTERNAL_248; + + case 0x24C: // 0x24C + return io.INTERNAL_24C; + + case 0x24E: // 0x24E + return io.INTERNAL_24E; + + case 0x250: // 0x250 + return io.INTERNAL_250; + + case REG_WIFI_CONFIG_254: // 0x254 + return io.CONFIG_254; + + case 0x258: // 0x258 + return io.INTERNAL_258; + + case 0x25C: // 0x25C + return io.INTERNAL_25C; + + case 0x260: // 0x260 + return io.INTERNAL_260; + + case 0x264: // 0x264 + return io.INTERNAL_264; + + case REG_WIFI_RXTX_ADDR: // 0x268 + return io.RXTX_ADDR.value; + + case 0x270: // 0x270 + return io.INTERNAL_270; + + case 0x274: // 0x274 + return io.INTERNAL_274; + + case 0x278: // 0x278 + return io.INTERNAL_278; + + case 0x27C: // 0x27C + return io.INTERNAL_27C; + + case REG_WIFI_X_290: // 0x290 + return io.X_290.value; + + case 0x298: // 0x298 - mirrored read of 0x084 + return io.TXBUF_TIM.value; + + case 0x2A0: // 0x2A0 + return io.INTERNAL_2A0; + + case 0x2A2: // 0x2A2 + return io.INTERNAL_2A2; + + case 0x2A4: // 0x2A4 + return io.INTERNAL_2A4; + + case 0x2A8: // 0x2A8 - mirrored read of 0x238 + return io.INTERNAL_238; + + case 0x2AC: // 0x2AC + return io.INTERNAL_2AC; + + case 0x2B0: // 0x2B0 - mirrored read of 0x084 + return io.TXBUF_TIM.value; + + case 0x2B4: // 0x2B4 + return io.INTERNAL_2B4; + + case 0x2B8: // 0x2B8 + return io.INTERNAL_2B8; + + case 0x2C0: // 0x2C0 + return io.INTERNAL_2C0; + + case 0x2C4: // 0x2C4 + return io.INTERNAL_2C4; + + case 0x2C8: // 0x2C8 + return io.INTERNAL_2C8; + + case 0x2CC: // 0x2CC + return io.INTERNAL_2CC; + + case REG_WIFI_POWERACK: // 0x2D0 + { + if (io.POWERSTATE.WillPowerOn != 0) + { + return io.POWERACK; + } + else + { + break; + } + } + + case 0x2F0: // 0x2F0 + return io.INTERNAL_2F0; + + case 0x2F2: // 0x2F2 + return io.INTERNAL_2F2; + + case 0x2F4: // 0x2F4 + return io.INTERNAL_2F4; + + case 0x2F6: // 0x2F6 + return io.INTERNAL_2F6; + + // RFSTATUS, RFPINS + // TODO: figure out how to emulate those correctly + // without breaking Nintendo's games + case REG_WIFI_RFSTATUS: // 0x214 return 0x0009; - case REG_WIFI_RFPINS: + case REG_WIFI_RFPINS: // 0x19C return 0x00C6; - case 0x268: - return wifiMac.RXTXAddr; - default: // printf("wifi: read unhandled reg %03X\n", address); break; } - - return WIFI_IOREG(address); + + // TODO: We return the default value for the original NDS. However, the default value is different for NDS Lite. + WIFI_LOG(2, "Reading value of %04Xh from unlabeled register 0x%03X\n", 0xFFFF, address); + return 0xFFFF; } void WIFI_usTrigger() { - if (wifiMac.crystalEnabled) + WifiData &wifi = wifiHandler->GetWifiData(); + WIFI_IOREG_MAP &io = wifi.io; + + if (io.POWER_US.Disable == 0) { /* a usec has passed */ - if (wifiMac.usecEnable) - wifiMac.usec++; - + if (io.US_COUNTCNT.EnableCounter != 0) + { + io.US_COUNT++; + } + // Note: the extra counter is decremented every 10 microseconds. // To avoid a modulo every microsecond, we multiply the counter // value by 10 and decrement it every microsecond :) - if (wifiMac.eCountEnable) + if (io.CMD_COUNTCNT.EnableCounter != 0) { - if (wifiMac.eCount > 0) + if (wifi.cmdCount_u32 > 0) { - wifiMac.eCount--; - if (wifiMac.eCount == 0) - WIFI_ExtraTXStart(); + wifi.cmdCount_u32--; + + if (wifi.cmdCount_u32 == 0) + { + WIFI_TXStart(WifiTXLocIndex_CMD, io.TXBUF_CMD); + } } } // The beacon counters are in milliseconds // GBATek says they're decremented every 1024 usecs - if (!(wifiMac.usec & 1023)) + if ( !(io.US_COUNT & 1023) ) { - wifiMac.BeaconCount1--; + io.BEACONCOUNT1--; - if (wifiMac.BeaconCount1 == (WIFI_IOREG(REG_WIFI_PREBEACONCOUNT) >> 10)) - WIFI_triggerIRQ(WIFI_IRQ_TIMEPREBEACON); - else if (wifiMac.BeaconCount1 == 0) - WIFI_triggerIRQ(WIFI_IRQ_TIMEBEACON); - - if (wifiMac.BeaconCount2 > 0) + if ( io.BEACONCOUNT1 == (io.PRE_BEACON >> 10) ) { - wifiMac.BeaconCount2--; - if (wifiMac.BeaconCount2 == 0) + WIFI_triggerIRQ(WIFI_IRQ_TIMEPREBEACON); + } + else if (io.BEACONCOUNT1 == 0) + { + WIFI_triggerIRQ(WIFI_IRQ_TIMEBEACON); + } + + if (io.BEACONCOUNT2 > 0) + { + io.BEACONCOUNT2--; + + if (io.BEACONCOUNT2 == 0) + { WIFI_triggerIRQ(WIFI_IRQ_TIMEPOSTBEACON); + } } } } - if ((wifiMac.ucmpEnable) && (wifiMac.ucmp == wifiMac.usec)) + if ( (io.US_COMPARECNT.EnableCompare != 0) && (io.US_COMPARE == io.US_COUNT) ) { //printf("ucmp irq14\n"); WIFI_triggerIRQ(WIFI_IRQ_TIMEBEACON); } - if ((wifiMac.usec & 3) == 0) + if ((io.US_COUNT & 3) == 0) { - int slot = wifiMac.txCurSlot; - - if (wifiMac.txSlotBusy[slot]) + const WifiTXLocIndex txSlotIndex = wifi.txCurrentSlot; + bool isTXSlotBusy = false; + + switch (txSlotIndex) { - wifiMac.txSlotRemainingBytes[slot]--; - wifiMac.RXTXAddr++; - if (wifiMac.txSlotRemainingBytes[slot] == 0) - { - wifiMac.txSlotBusy[slot] = 0; - wifiMac.TXSlot[slot] &= 0x7FFF; + case WifiTXLocIndex_LOC1: isTXSlotBusy = (io.TXBUSY.Loc1 != 0); break; + //case WifiTXLocIndex_CMD: isTXSlotBusy = (io.TXBUSY.Cmd != 0); break; + case WifiTXLocIndex_LOC2: isTXSlotBusy = (io.TXBUSY.Loc2 != 0); break; + case WifiTXLocIndex_LOC3: isTXSlotBusy = (io.TXBUSY.Loc3 != 0); break; + //case WifiTXLocIndex_BEACON: isTXSlotBusy = (io.TXBUSY.Beacon != 0); break; - wifiHandler->CommSendPacket((u8 *)&wifiMac.RAM[wifiMac.txSlotAddr[slot]+6], wifiMac.txSlotLen[slot]); - - while ((wifiMac.txSlotBusy[wifiMac.txCurSlot] == 0) && (wifiMac.txCurSlot > 0)) - wifiMac.txCurSlot--; - - wifiMac.RAM[wifiMac.txSlotAddr[slot]] = 0x0001; - wifiMac.RAM[wifiMac.txSlotAddr[slot]+4] &= 0x00FF; - - wifiMac.TXStat = (0x0001 | (slot << 12)); + default: + break; + } + if (isTXSlotBusy) + { + IOREG_W_TXBUF_LOCATION *txBufLocation = NULL; + TXPacketInfo &txPacketInfo = wifiHandler->GetPacketInfoAtSlot(txSlotIndex); + + switch (txSlotIndex) + { + case WifiTXLocIndex_LOC1: txBufLocation = &io.TXBUF_LOC1; break; + //case WifiTXLocIndex_CMD: txBufLocation = &io.TXBUF_CMD; break; + case WifiTXLocIndex_LOC2: txBufLocation = &io.TXBUF_LOC2; break; + case WifiTXLocIndex_LOC3: txBufLocation = &io.TXBUF_LOC3; break; + //case WifiTXLocIndex_BEACON: txBufLocation = &io.TXBUF_BEACON; break; + + default: + break; + } + + txPacketInfo.remainingBytes--; + io.RXTX_ADDR.HalfwordAddress++; + + if (txPacketInfo.remainingBytes == 0) + { + isTXSlotBusy = false; + + switch (txSlotIndex) + { + case WifiTXLocIndex_LOC1: io.TXBUSY.Loc1 = 0; break; + //case WifiTXLocIndex_CMD: io.TXBUSY.Cmd = 0; break; + case WifiTXLocIndex_LOC2: io.TXBUSY.Loc2 = 0; break; + case WifiTXLocIndex_LOC3: io.TXBUSY.Loc3 = 0; break; + //case WifiTXLocIndex_BEACON: io.TXBUSY.Beacon = 0; break; + + default: + break; + } + + txBufLocation->TransferRequest = 0; + wifiHandler->CommSendPacket((u8 *)&wifi.RAM[txBufLocation->HalfwordAddress+6], txPacketInfo.bodyLen); + + wifi.RAM[txBufLocation->HalfwordAddress] = 0x0001; + wifi.RAM[txBufLocation->HalfwordAddress+4] &= 0x00FF; + + switch (txSlotIndex) + { + //case WifiTXLocIndex_CMD: + //case WifiTXLocIndex_BEACON: + case WifiTXLocIndex_LOC1: io.TXSTAT.PacketUpdate = 0; break; + case WifiTXLocIndex_LOC2: io.TXSTAT.PacketUpdate = 1; break; + case WifiTXLocIndex_LOC3: io.TXSTAT.PacketUpdate = 2; break; + + default: + break; + } + + io.TXSTAT.PacketCompleted = 1; + WIFI_triggerIRQ(WIFI_IRQ_TXEND); - //wifiMac.rfStatus = 0x0001; - //wifiMac.rfPins = 0x0084; - wifiMac.rfStatus = 0x0009; - wifiMac.rfPins = 0x0004; + //io.RF_STATUS.Status = 0x01; + //io.RF_PINS.RX_On = 1; + + io.RF_STATUS.Status = 0x09; + io.RF_PINS.CarrierSense = 0; + io.RF_PINS.TXMain = 0; + io.RF_PINS.UNKNOWN1 = 1; + io.RF_PINS.TX_On = 0; + io.RF_PINS.RX_On = 0; + + // Switch to the next TX slot. + while (!isTXSlotBusy && (wifi.txCurrentSlot != WifiTXLocIndex_LOC1)) + { + /*if (wifi.txCurrentSlot == WifiTXLocIndex_BEACON) + { + wifi.txCurrentSlot = WifiTXLocIndex_CMD; + isTXSlotBusy = (io.TXBUSY.Cmd != 0); + } + else if (wifi.txCurrentSlot == WifiTXLocIndex_CMD) + { + wifi.txCurrentSlot = WifiTXLocIndex_LOC3; + isTXSlotBusy = (io.TXBUSY.Loc3 != 0); + } + else */if (wifi.txCurrentSlot == WifiTXLocIndex_LOC3) + { + wifi.txCurrentSlot = WifiTXLocIndex_LOC2; + isTXSlotBusy = (io.TXBUSY.Loc2 != 0); + } + else if (wifi.txCurrentSlot == WifiTXLocIndex_LOC2) + { + wifi.txCurrentSlot = WifiTXLocIndex_LOC1; + isTXSlotBusy = (io.TXBUSY.Loc1 != 0); + } + } WIFI_LOG(3, "TX slot %i finished sending its packet. Next is slot %i. TXStat = %04X\n", - slot, wifiMac.txCurSlot, wifiMac.TXStat); + (int)txSlotIndex, (int)wifi.txCurrentSlot, io.TXSTAT.value); } } } @@ -1880,6 +3393,7 @@ void AdhocCommInterface::SendPacket(void *data, size_t len) void AdhocCommInterface::Trigger() { + WIFI_IOREG_MAP &io = wifiHandler->GetWifiData().io; socket_t &thisSocket = *((socket_t *)this->_wifiSocket); this->_usecCounter++; @@ -1929,11 +3443,11 @@ void AdhocCommInterface::Trigger() ptr += sizeof(Adhoc_FrameHeader); // If the packet is for us, send it to the wifi core - if (!WIFI_compareMAC(&ptr[10], &wifiMac.mac.bytes[0])) + if (!WIFI_compareMAC(&ptr[10], io.MACADDR)) { if (WIFI_isBroadcastMAC(&ptr[16]) || - WIFI_compareMAC(&ptr[16], &wifiMac.bss.bytes[0]) || - WIFI_isBroadcastMAC(&wifiMac.bss.bytes[0])) + WIFI_compareMAC(&ptr[16], io.BSSID) || + WIFI_isBroadcastMAC(io.BSSID)) { /* printf("packet was for us: mac=%02X:%02X.%02X.%02X.%02X.%02X, bssid=%02X:%02X.%02X.%02X.%02X.%02X\n", wifiMac.mac.bytes[0], wifiMac.mac.bytes[1], wifiMac.mac.bytes[2], wifiMac.mac.bytes[3], wifiMac.mac.bytes[4], wifiMac.mac.bytes[5], @@ -1969,10 +3483,12 @@ void AdhocCommInterface::Trigger() WIFI_RXPutWord(word); } - wifiMac.RXWriteCursor = ((wifiMac.RXWriteCursor + 1) & (~1)); - WIFI_IOREG(REG_WIFI_RXHWWRITECSR) = wifiMac.RXWriteCursor; - wifiMac.RXNum++; + io.RXBUF_WRCSR.HalfwordAddress = ((io.RXBUF_WRCSR.HalfwordAddress + 1) & (~1)); + + //wifiMac.RXNum++; WIFI_triggerIRQ(WIFI_IRQ_RXEND); + + delete [] packet; } } } @@ -2080,6 +3596,7 @@ bool SoftAPCommInterface::_IsDNSRequestToWFC(u16 ethertype, u8 *body) void SoftAPCommInterface::_Deauthenticate() { + WIFI_IOREG_MAP &io = wifiHandler->GetWifiData().io; u32 packetLen = sizeof(SoftAP_DeauthFrame); memcpy(&this->_curPacket[12], SoftAP_DeauthFrame, packetLen); @@ -2090,7 +3607,7 @@ void SoftAPCommInterface::_Deauthenticate() this->_seqNum++; u16 rxflags = 0x0010; - if (WIFI_compareMAC(wifiMac.bss.bytes, &this->_curPacket[12 + 16])) + if (WIFI_compareMAC(io.BSSID, &this->_curPacket[12 + 16])) { rxflags |= 0x8000; } @@ -2107,6 +3624,7 @@ void SoftAPCommInterface::_Deauthenticate() void SoftAPCommInterface::_SendBeacon() { + WIFI_IOREG_MAP &io = wifiHandler->GetWifiData().io; u32 packetLen = sizeof(SoftAP_Beacon); memcpy(&this->_curPacket[12], SoftAP_Beacon, packetLen); // Copy the beacon template @@ -2118,7 +3636,7 @@ void SoftAPCommInterface::_SendBeacon() *(u64 *)&this->_curPacket[12 + 24] = timestamp; // Timestamp u16 rxflags = 0x0011; - if (WIFI_compareMAC(wifiMac.bss.bytes, &this->_curPacket[12 + 16])) + if (WIFI_compareMAC(io.BSSID, &this->_curPacket[12 + 16])) rxflags |= 0x8000; WIFI_MakeRXHeader(this->_curPacket, rxflags, 20, packetLen, 0, 0); @@ -2131,6 +3649,8 @@ void SoftAPCommInterface::_SendBeacon() void SoftAPCommInterface::PacketRX(const void *pktHeader, const u8 *pktData) { + WIFI_IOREG_MAP &io = wifiHandler->GetWifiData().io; + // safety checks if ( (pktData == NULL) || (pktHeader == NULL) ) { @@ -2138,13 +3658,13 @@ void SoftAPCommInterface::PacketRX(const void *pktHeader, const u8 *pktData) } // reject the packet if it wasn't for us - if (!(WIFI_isBroadcastMAC(&pktData[0]) || WIFI_compareMAC(&pktData[0], wifiMac.mac.bytes))) + if (!(WIFI_isBroadcastMAC(&pktData[0]) || WIFI_compareMAC(&pktData[0], io.MACADDR))) { return; } // reject the packet if we just sent it - if (WIFI_compareMAC(&pktData[6], wifiMac.mac.bytes)) + if (WIFI_compareMAC(&pktData[6], io.MACADDR)) { return; } @@ -2154,7 +3674,7 @@ void SoftAPCommInterface::PacketRX(const void *pktHeader, const u8 *pktData) if (this->_curPacketSending) { - printf("crap we're gonna nuke a packet at %i/%i (%04X) (%04X)\n", this->_curPacketPos, this->_curPacketSize, *(u16 *)&this->_curPacket[12], wifiMac.RXWriteCursor<<1); + printf("crap we're gonna nuke a packet at %i/%i (%04X) (%04X)\n", this->_curPacketPos, this->_curPacketSize, *(u16 *)&this->_curPacket[12], io.RXBUF_WRCSR.HalfwordAddress<<1); } // The packet was for us. Let's process it then. @@ -2177,7 +3697,7 @@ void SoftAPCommInterface::PacketRX(const void *pktHeader, const u8 *pktData) // data[0], data[1], data[2], data[3], data[4], data[5], *(u16*)&data[12]); u16 rxflags = 0x0018; - if (WIFI_compareMAC(wifiMac.bss.bytes, (u8 *)SoftAP_MACAddr)) + if (WIFI_compareMAC(io.BSSID, (u8 *)SoftAP_MACAddr)) { rxflags |= 0x8000; } @@ -2206,8 +3726,7 @@ void SoftAPCommInterface::PacketRX(const void *pktHeader, const u8 *pktData) } // Done! - wifiMac.RXWriteCursor = ((wifiMac.RXWriteCursor + 1) & (~1)); - WIFI_IOREG(REG_WIFI_RXHWWRITECSR) = wifiMac.RXWriteCursor; + io.RXBUF_WRCSR.HalfwordAddress = ((io.RXBUF_WRCSR.HalfwordAddress + 1) & (~1)); WIFI_triggerIRQ(WIFI_IRQ_RXEND); } @@ -2383,11 +3902,13 @@ void SoftAPCommInterface::Stop() if (this->_bridgeDevice != NULL) { this->_pcap->close(this->_bridgeDevice); + this->_bridgeDevice = NULL; } } void SoftAPCommInterface::SendPacket(void *data, size_t len) { + WIFI_IOREG_MAP &io = wifiHandler->GetWifiData().io; u8 *packet = (u8 *)data; u16 frameCtl = *(u16 *)&packet[0]; @@ -2473,7 +3994,7 @@ void SoftAPCommInterface::SendPacket(void *data, size_t len) this->_seqNum++; u16 rxflags = 0x0010; - if (WIFI_compareMAC(wifiMac.bss.bytes, &this->_curPacket[12 + 16])) + if (WIFI_compareMAC(io.BSSID, &this->_curPacket[12 + 16])) { rxflags |= 0x8000; } @@ -2534,6 +4055,8 @@ void SoftAPCommInterface::SendPacket(void *data, size_t len) void SoftAPCommInterface::Trigger() { + WIFI_IOREG_MAP &io = wifiHandler->GetWifiData().io; + this->_usecCounter++; // other packets will have priority over beacons @@ -2572,9 +4095,8 @@ void SoftAPCommInterface::Trigger() this->_curPacketPos = 0; this->_curPacketSending = false; - wifiMac.RXWriteCursor = ((wifiMac.RXWriteCursor + 1) & (~1)); - WIFI_IOREG(REG_WIFI_RXHWWRITECSR) = wifiMac.RXWriteCursor; - + io.RXBUF_WRCSR.HalfwordAddress = ((io.RXBUF_WRCSR.HalfwordAddress + 1) & (~1)); + WIFI_triggerIRQ(WIFI_IRQ_RXEND); } } @@ -2629,18 +4151,35 @@ WifiHandler::~WifiHandler() void WifiHandler::Reset() { - memset(&wifiMac, 0, sizeof(wifimac_t)); + memset(&legacyWifiSF, 0, sizeof(LegacyWifiSFormat)); + memset(&_wifi, 0, sizeof(WifiData)); + WIFI_resetRF(this->_wifi.rf); - WIFI_resetRF(&wifiMac.RF); - - wifiMac.powerOn = false; - wifiMac.powerOnPending = false; - wifiMac.rfStatus = 0x0000; - wifiMac.rfPins = 0x0004; + _wifi.io.POWER_US.Disable = 1; + _wifi.io.POWERSTATE.IsPowerOff = 1; + _wifi.io.TXREQ_READ.UNKNOWN1 = 1; + _wifi.io.BB_POWER.Disable = 0x0D; + _wifi.io.BB_POWER.DisableAllPorts = 1; + _wifi.io.RF_PINS.UNKNOWN1 = 1; this->_didWarnWFCUser = false; } +WifiData& WifiHandler::GetWifiData() +{ + return this->_wifi; +} + +TXPacketInfo& WifiHandler::GetPacketInfoAtSlot(size_t txSlot) +{ + if (txSlot > 4) + { + return this->_wifi.txPacketInfo[0]; + } + + return this->_wifi.txPacketInfo[txSlot]; +} + WifiEmulationLevel WifiHandler::GetSelectedEmulationLevel() { return this->_selectedEmulationLevel; @@ -2987,3 +4526,113 @@ void WifiHandler::CopyMACFromUserValues(u8 outMAC[6]) outMAC[4] = this->_userMAC[1]; outMAC[5] = this->_userMAC[2]; } + +void WifiHandler::PrepareSaveStateWrite() +{ + WIFI_IOREG_MAP &io = this->_wifi.io; + RF2958_IOREG_MAP &rf = this->_wifi.rf; + + legacyWifiSF.powerOn = (u32)(io.POWERSTATE.IsPowerOff == 0); + legacyWifiSF.powerOnPending = (u32)(io.POWERSTATE.WillPowerOn != 0); + + legacyWifiSF.rfStatus = io.RF_STATUS.value; + legacyWifiSF.rfPins = io.RF_PINS.value; + + legacyWifiSF.IE = io.IE.value; + legacyWifiSF.IF = io.IF.value; + + legacyWifiSF.macMode = io.MODE_RST.value; + legacyWifiSF.wepMode = io.MODE_WEP.value; + legacyWifiSF.WEP_enable = io.WEP_CNT.Enable; + + legacyWifiSF.TXCnt = io.TXREQ_READ.value; + legacyWifiSF.TXStat = io.TXSTAT.value; + + legacyWifiSF.RXCnt = io.RXCNT.value; + legacyWifiSF.RXCheckCounter = 0; + + legacyWifiSF.macAddr[0] = io.MACADDR[0]; + legacyWifiSF.macAddr[1] = io.MACADDR[1]; + legacyWifiSF.macAddr[2] = io.MACADDR[2]; + legacyWifiSF.macAddr[3] = io.MACADDR[3]; + legacyWifiSF.macAddr[4] = io.MACADDR[4]; + legacyWifiSF.macAddr[5] = io.MACADDR[5]; + legacyWifiSF.bssid[0] = io.BSSID[0]; + legacyWifiSF.bssid[1] = io.BSSID[1]; + legacyWifiSF.bssid[2] = io.BSSID[2]; + legacyWifiSF.bssid[3] = io.BSSID[3]; + legacyWifiSF.bssid[4] = io.BSSID[4]; + legacyWifiSF.bssid[5] = io.BSSID[5]; + + legacyWifiSF.aid = io.AID_FULL.AssociationID; + legacyWifiSF.pid = io.AID_LOW.PlayerID; + legacyWifiSF.retryLimit = io.TX_RETRYLIMIT.value; + + legacyWifiSF.crystalEnabled = (u32)(io.POWER_US.Disable == 0); + legacyWifiSF.usec = io.US_COUNT; + legacyWifiSF.usecEnable = io.US_COUNTCNT.EnableCounter; + legacyWifiSF.ucmp = io.US_COMPARE; + legacyWifiSF.ucmpEnable = io.US_COMPARECNT.EnableCompare; + legacyWifiSF.eCount = this->_wifi.cmdCount_u32; + legacyWifiSF.eCountEnable = io.CMD_COUNTCNT.EnableCounter; + + legacyWifiSF.rf_cfg1 = rf.CFG1.value; + legacyWifiSF.rf_ifpll1 = rf.IFPLL1.value; + legacyWifiSF.rf_ifpll2 = rf.IFPLL2.value; + legacyWifiSF.rf_ifpll3 = rf.IFPLL3.value; + legacyWifiSF.rf_rfpll1 = rf.RFPLL1.value; + legacyWifiSF.rf_rfpll2 = rf.RFPLL2.value; + legacyWifiSF.rf_rfpll3 = rf.RFPLL3.value; + legacyWifiSF.rf_rfpll4 = rf.RFPLL4.value; + legacyWifiSF.rf_cal1 = rf.CAL1.value; + legacyWifiSF.rf_txrx1 = rf.TXRX1.value; + legacyWifiSF.rf_pcnt1 = rf.PCNT1.value; + legacyWifiSF.rf_pcnt2 = rf.PCNT2.value; + legacyWifiSF.rf_vcot1 = rf.VCOT1.value; + + legacyWifiSF.rfIOCnt = io.RF_CNT.value; + legacyWifiSF.rfIOStatus = io.RF_BUSY.Busy; + legacyWifiSF.rfIOData = (io.RF_DATA2.value << 16) | io.RF_DATA1.value; + legacyWifiSF.bbIOCnt = io.BB_CNT.value; + + legacyWifiSF.rxRangeBegin = io.RXBUF_BEGIN; + legacyWifiSF.rxRangeEnd = io.RXBUF_END; + legacyWifiSF.rxWriteCursor = io.RXBUF_WRCSR.HalfwordAddress; + legacyWifiSF.rxReadCursor = io.RXBUF_READCSR.HalfwordAddress; + legacyWifiSF.rxUnits = 0; + legacyWifiSF.rxBufCount = io.RXBUF_COUNT.Count; + legacyWifiSF.circBufReadAddress = io.RXBUF_RD_ADDR.ByteAddress; + legacyWifiSF.circBufWriteAddress = io.TXBUF_WR_ADDR.ByteAddress; + legacyWifiSF.circBufReadEnd = io.RXBUF_GAP.ByteAddress; + legacyWifiSF.circBufReadSkip = io.RXBUF_GAPDISP.HalfwordOffset; + legacyWifiSF.circBufWriteEnd = io.TXBUF_GAP.ByteAddress; + legacyWifiSF.circBufWriteSkip = io.TXBUF_GAPDISP.HalfwordOffset; + + legacyWifiSF.randomSeed = io.RANDOM.Random; + + memcpy(legacyWifiSF.wifiIOPorts, &this->_wifi.io, sizeof(WIFI_IOREG_MAP)); + memcpy(legacyWifiSF.bb_data, this->_wifi.bb.data, sizeof(this->_wifi.bb.data)); + memcpy(legacyWifiSF.wifiRAM, this->_wifi.RAM, sizeof(this->_wifi.RAM)); +} + +void WifiHandler::ParseSaveStateRead() +{ + RF2958_IOREG_MAP &rf = this->_wifi.rf; + rf.CFG1.value = legacyWifiSF.rf_cfg1; + rf.IFPLL1.value = legacyWifiSF.rf_ifpll1; + rf.IFPLL2.value = legacyWifiSF.rf_ifpll2; + rf.IFPLL3.value = legacyWifiSF.rf_ifpll3; + rf.RFPLL1.value = legacyWifiSF.rf_rfpll1; + rf.RFPLL2.value = legacyWifiSF.rf_rfpll2; + rf.RFPLL3.value = legacyWifiSF.rf_rfpll3; + rf.RFPLL4.value = legacyWifiSF.rf_rfpll4; + rf.CAL1.value = legacyWifiSF.rf_cal1; + rf.TXRX1.value = legacyWifiSF.rf_txrx1; + rf.PCNT1.value = legacyWifiSF.rf_pcnt1; + rf.PCNT2.value = legacyWifiSF.rf_pcnt2; + rf.VCOT1.value = legacyWifiSF.rf_vcot1; + + memcpy(&this->_wifi.io, legacyWifiSF.wifiIOPorts, sizeof(WIFI_IOREG_MAP)); + memcpy(this->_wifi.bb.data, legacyWifiSF.bb_data, sizeof(this->_wifi.bb.data)); + memcpy(this->_wifi.RAM, legacyWifiSF.wifiRAM, sizeof(this->_wifi.RAM)); +} diff --git a/desmume/src/wifi.h b/desmume/src/wifi.h index c5387bd98..080da173c 100755 --- a/desmume/src/wifi.h +++ b/desmume/src/wifi.h @@ -33,7 +33,7 @@ #define REG_WIFI_MODE 0x004 #define REG_WIFI_WEP 0x006 #define REG_WIFI_TXSTATCNT 0x008 -#define REG_WIFI_0A 0x00A +#define REG_WIFI_X_00A 0x00A #define REG_WIFI_IF 0x010 #define REG_WIFI_IE 0x012 #define REG_WIFI_MAC0 0x018 @@ -75,12 +75,13 @@ // 078 - internal #define REG_WIFI_TXLOCBEACON 0x080 +#define REG_WIFI_TXBUF_TIM 0x084 #define REG_WIFI_LISTENCOUNT 0x088 #define REG_WIFI_BEACONPERIOD 0x08C #define REG_WIFI_LISTENINT 0x08E #define REG_WIFI_TXLOCEXTRA 0x090 -// 094 - ? -// 098 - ? +#define REG_WIFI_TXBUF_REPLY1 0x094 +#define REG_WIFI_TXBUF_REPLY2 0x098 // 09C - internal #define REG_WIFI_TXLOC1 0x0A0 #define REG_WIFI_TXLOC2 0x0A4 @@ -93,18 +94,18 @@ #define REG_WIFI_TXSTAT 0x0B8 // 0BA - internal #define REG_WIFI_PREAMBLE 0x0BC -// 0C0 - ? -// 0C4 - ? +#define REG_WIFI_CMD_TOTALTIME 0x0C0 +#define REG_WIFI_CMD_REPLYTIME 0x0C4 // 0C8 - internal #define REG_WIFI_RXFILTER 0x0D0 -// 0D4 - config -// 0D8 - config -// 0DA - config +#define REG_WIFI_CONFIG_0D4 0x0D4 +#define REG_WIFI_CONFIG_0D8 0x0D8 +#define REG_WIFI_RX_LEN_CROP 0x0DA #define REG_WIFI_RXFILTER2 0x0E0 #define REG_WIFI_USCOUNTERCNT 0x0E8 #define REG_WIFI_USCOMPARECNT 0x0EA -// 0EC - config +#define REG_WIFI_CONFIG_0EC 0x0EC #define REG_WIFI_EXTRACOUNTCNT 0x0EE #define REG_WIFI_USCOMPARE0 0x0F0 #define REG_WIFI_USCOMPARE1 0x0F2 @@ -123,9 +124,22 @@ #define REG_WIFI_EXTRACOUNT 0x118 #define REG_WIFI_BEACONCOUNT1 0x11C -// 120 to 132 - config/internal ports +#define REG_WIFI_CONFIG_120 0x120 +#define REG_WIFI_CONFIG_122 0x122 +#define REG_WIFI_CONFIG_124 0x124 +#define REG_WIFI_CONFIG_128 0x128 +#define REG_WIFI_CONFIG_130 0x130 +#define REG_WIFI_CONFIG_132 0x132 #define REG_WIFI_BEACONCOUNT2 0x134 -// 140 to 154 - config ports +#define REG_WIFI_CONFIG_140 0x140 +#define REG_WIFI_CONFIG_142 0x142 +#define REG_WIFI_CONFIG_144 0x144 +#define REG_WIFI_CONFIG_146 0x146 +#define REG_WIFI_CONFIG_148 0x148 +#define REG_WIFI_CONFIG_14A 0x14A +#define REG_WIFI_CONFIG_14C 0x14C +#define REG_WIFI_CONFIG_150 0x150 +#define REG_WIFI_CONFIG_154 0x154 #define REG_WIFI_BBCNT 0x158 #define REG_WIFI_BBWRITE 0x15A @@ -142,196 +156,586 @@ #define REG_WIFI_RFCNT 0x184 // 190 - internal -// 194 - ? +#define REG_WIFI_TX_HDR_CNT 0x194 // 198 - internal #define REG_WIFI_RFPINS 0x19C -// 1A0 - internal -// 1A2 - internal -#define REG_WIFI_MAYBE_RATE 0x1A4 +#define REG_WIFI_X_1A0 0x1A0 +#define REG_WIFI_X_1A2 0x1A2 +#define REG_WIFI_X_1A4 0x1A4 #define REG_WIFI_RXSTAT_INC_IF 0x1A8 #define REG_WIFI_RXSTAT_INC_IE 0x1AA #define REG_WIFI_RXSTAT_OVF_IF 0x1AC #define REG_WIFI_RXSTAT_OVF_IE 0x1AE +#define REG_WIFI_RXSTAT0 0x1B0 +#define REG_WIFI_RXSTAT1 0x1B2 +#define REG_WIFI_RXSTAT2 0x1B4 +#define REG_WIFI_RXSTAT3 0x1B6 +#define REG_WIFI_RXSTAT4 0x1B8 +#define REG_WIFI_RXSTAT5 0x1BA +#define REG_WIFI_RXSTAT6 0x1BC +#define REG_WIFI_RXSTAT7 0x1BE #define REG_WIFI_TXERR_COUNT 0x1C0 #define REG_WIFI_RX_COUNT 0x1C4 -// 1D0 to 1DE - related to multiplayer. argh. +#define REG_WIFI_CMD_STAT0 0x1D0 +#define REG_WIFI_CMD_STAT1 0x1D2 +#define REG_WIFI_CMD_STAT2 0x1D4 +#define REG_WIFI_CMD_STAT3 0x1D6 +#define REG_WIFI_CMD_STAT4 0x1D8 +#define REG_WIFI_CMD_STAT5 0x1DA +#define REG_WIFI_CMD_STAT6 0x1DC +#define REG_WIFI_CMD_STAT7 0x1DE #define REG_WIFI_RFSTATUS 0x214 #define REG_WIFI_IF_SET 0x21C #define REG_WIFI_TXSEQNO 0x210 +#define REG_WIFI_X_228 0x228 +#define REG_WIFI_X_244 0x244 +#define REG_WIFI_CONFIG_254 0x254 +#define REG_WIFI_RXTX_ADDR 0x268 +#define REG_WIFI_X_290 0x290 #define REG_WIFI_POWERACK 0x2D0 - -#define WIFI_IOREG(reg) wifiMac.IOPorts[(reg) >> 1] - /* WIFI misc constants */ #define WIFI_CHIPID 0x1440 /* emulates "old" wifi chip, new is 0xC340 */ -/* Referenced as RF_ in dswifi: rffilter_t */ -/* based on the documentation for the RF2958 chip of RF Micro Devices */ -/* using the register names as in docs ( http://www.rfmd.com/pdfs/2958.pdf )*/ -/* even tho every register only has 18 bits we are using u32 */ -typedef struct rffilter_t +// RF2958 Register Addresses +enum RegAddrRF2958 { - union CFG1 + REG_RF2958_CFG1 = 0, + REG_RF2958_IPLL1 = 1, + REG_RF2958_IPLL2 = 2, + REG_RF2958_IPLL3 = 3, + REG_RF2958_RFPLL1 = 4, + REG_RF2958_RFPLL2 = 5, + REG_RF2958_RFPLL3 = 6, + REG_RF2958_RFPLL4 = 7, + REG_RF2958_CAL1 = 8, + REG_RF2958_TXRX1 = 9, + REG_RF2958_PCNT1 = 10, + REG_RF2958_PCNT2 = 11, + REG_RF2958_VCOT1 = 12, + REG_RF2958_TEST = 27, + REG_RF2958_RESET = 31 +}; + +typedef struct +{ + u32 powerOn; + u32 powerOnPending; + + u16 rfStatus; + u16 rfPins; + + u16 IE; + u16 IF; + + u16 macMode; + u16 wepMode; + u32 WEP_enable; + + u16 TXCnt; + u16 TXStat; + + u16 RXCnt; + u16 RXCheckCounter; + + u8 macAddr[6]; + u8 bssid[6]; + + u16 aid; + u16 pid; + u16 retryLimit; + + u32 crystalEnabled; + u64 usec; + u32 usecEnable; + u64 ucmp; + u32 ucmpEnable; + u16 eCount; + u32 eCountEnable; + + u32 rf_cfg1; + u32 rf_ifpll1; + u32 rf_ifpll2; + u32 rf_ifpll3; + u32 rf_rfpll1; + u32 rf_rfpll2; + u32 rf_rfpll3; + u32 rf_rfpll4; + u32 rf_cal1; + u32 rf_txrx1; + u32 rf_pcnt1; + u32 rf_pcnt2; + u32 rf_vcot1; + + u8 bb_data[105]; + + u16 rfIOCnt; + u16 rfIOStatus; + u32 rfIOData; + u16 bbIOCnt; + + u8 wifiRAM[0x2000]; + u16 rxRangeBegin; + u16 rxRangeEnd; + u16 rxWriteCursor; + u16 rxReadCursor; + u16 rxUnits; + u16 rxBufCount; + u16 circBufReadAddress; + u16 circBufWriteAddress; + u16 circBufReadEnd; + u16 circBufReadSkip; + u16 circBufWriteEnd; + u16 circBufWriteSkip; + + u16 wifiIOPorts[0x800]; + u16 randomSeed; +} LegacyWifiSFormat; + +typedef union +{ + u32 value; + + struct { - struct - { -/* 0*/ unsigned IF_VGA_REG_EN:1; -/* 1*/ unsigned IF_VCO_REG_EN:1; -/* 2*/ unsigned RF_VCO_REG_EN:1; -/* 3*/ unsigned HYBERNATE:1; -/* 4*/ unsigned :10; -/*14*/ unsigned REF_SEL:2; -/*16*/ unsigned :2; - } bits; - u32 val; - } CFG1; - union IFPLL1 + u32 Data:18; + u32 :14; + }; + + struct { - struct - { -/* 0*/ unsigned DAC:4; -/* 4*/ unsigned :5; -/* 9*/ unsigned P1:1; -/*10*/ unsigned LD_EN1:1; -/*11*/ unsigned AUTOCAL_EN1:1; -/*12*/ unsigned PDP1:1; -/*13*/ unsigned CPL1:1; -/*14*/ unsigned LPF1:1; -/*15*/ unsigned VTC_EN1:1; -/*16*/ unsigned KV_EN1:1; -/*17*/ unsigned PLL_EN1:1; - } bits; - u32 val; - } IFPLL1; - union IFPLL2 +#ifndef MSB_FIRST + u16 DataLSB:16; + + u16 DataMSB:2; + u16 :6; + + u16 :8; +#else + u16 DataLSB:16; + + u16 :6; + u16 DataMSB:2; + + u16 :8; +#endif + }; +} RFREG_RF2958; + +typedef union +{ + u32 value; + + struct { - struct - { -/* 0*/ unsigned IF_N:16; -/*16*/ unsigned :2; - } bits; - u32 val; - } IFPLL2; - union IFPLL3 +#ifndef MSB_FIRST + u8 IF_VGA_REG_EN:1; + u8 IF_VCO_REG_EN:1; + u8 RF_VCO_REG_EN:1; + u8 HYBERNATE:1; + u8 :4; + + u8 :6; + u8 REF_SEL:2; + + u8 reserved:2; + u8 :6; + + u8 :8; +#else + u8 :4; + u8 HYBERNATE:1; + u8 RF_VCO_REG_EN:1; + u8 IF_VCO_REG_EN:1; + u8 IF_VGA_REG_EN:1; + + u8 REF_SEL:2; + u8 :6; + + u8 :6; + u8 reserved:2; + + u8 :8; +#endif + }; +} RFREG_CFG1; + +typedef union +{ + u32 value; + + struct { - struct - { -/* 0*/ unsigned KV_DEF1:4; -/* 4*/ unsigned CT_DEF1:4; -/* 8*/ unsigned DN1:9; -/*17*/ unsigned :1; - } bits; - u32 val; - } IFPLL3; - union RFPLL1 +#ifndef MSB_FIRST + u8 DAC:4; + u8 reserved1:4; + + u8 reserved2:1; + u8 P1:1; + u8 LD_EN1:1; + u8 AUTOCAL_EN1:1; + u8 PDP1:1; + u8 CPL1:1; + u8 LPF1:1; + u8 VTC_EN1:1; + + u8 KV_EN1:1; + u8 PLL_EN1:1; + u8 :6; + + u8 :8; +#else + u8 reserved1:4; + u8 DAC:4; + + u8 VTC_EN1:1; + u8 LPF1:1; + u8 CPL1:1; + u8 PDP1:1; + u8 AUTOCAL_EN1:1; + u8 LD_EN1:1; + u8 P1:1; + u8 reserved2:1; + + u8 :6; + u8 PLL_EN1:1; + u8 KV_EN1:1; + + u8 :8; +#endif + }; +} RFREG_IFPLL1; + +typedef union +{ + u32 value; + + struct { - struct - { -/* 0*/ unsigned DAC:4; -/* 4*/ unsigned :5; -/* 9*/ unsigned P:1; -/*10*/ unsigned LD_EN:1; -/*11*/ unsigned AUTOCAL_EN:1; -/*12*/ unsigned PDP:1; -/*13*/ unsigned CPL:1; -/*14*/ unsigned LPF:1; -/*15*/ unsigned VTC_EN:1; -/*16*/ unsigned KV_EN:1; -/*17*/ unsigned PLL_EN:1; - } bits; - u32 val; - } RFPLL1; - union RFPLL2 +#ifndef MSB_FIRST + u16 IF_N:16; + + u8 reserved:2; + u8 :6; + + u8 :8; +#else + u16 IF_N:16; + + u8 :6; + u8 reserved:2; + + u8 :8; +#endif + }; +} RFREG_IFPLL2; + +typedef union +{ + u32 value; + + struct { - struct - { -/* 0*/ unsigned NUM2:6; -/* 6*/ unsigned N2:12; - } bits; - u32 val; - } RFPLL2; - union RFPLL3 +#ifndef MSB_FIRST + u8 KV_DEF1:4; + u8 CT_DEF1:4; + + u16 DN1:9; + u16 reserved:1; + u16 :6; + + u8 :8; +#else + u8 CT_DEF1:4; + u8 KV_DEF1:4; + + u16 :6; + u16 reserved:1; + u16 DN1:9; + + u8 :8; +#endif + }; +} RFREG_IFPLL3; + +typedef union +{ + u32 value; + + struct { - struct - { -/* 0*/ unsigned NUM2:18; - } bits; - u32 val; - } RFPLL3; - union RFPLL4 +#ifndef MSB_FIRST + u8 DAC:4; + u8 reserved1:4; + + u8 reserved2:1; + u8 P:1; + u8 LD_EN:1; + u8 AUTOCAL_EN:1; + u8 PDP:1; + u8 CPL:1; + u8 LPF:1; + u8 VTC_EN:1; + + u8 KV_EN:1; + u8 PLL_EN:1; + u8 :6; + + u8 :8; +#else + u8 reserved1:4; + u8 DAC:4; + + u8 VTC_EN1:1; + u8 LPF1:1; + u8 CPL1:1; + u8 PDP1:1; + u8 AUTOCAL_EN1:1; + u8 LD_EN1:1; + u8 P1:1; + u8 reserved2:1; + + u8 :6; + u8 PLL_EN1:1; + u8 KV_EN1:1; + + u8 :8; +#endif + }; +} RFREG_RFPLL1; + +typedef union +{ + u32 value; + + struct { - struct - { -/* 0*/ unsigned KV_DEF:4; -/* 4*/ unsigned CT_DEF:4; -/* 8*/ unsigned DN:9; -/*17*/ unsigned :1; - } bits; - u32 val; - } RFPLL4; - union CAL1 +#ifndef MSB_FIRST + u16 NUM2:6; + u16 N2:12; + u16 :6; + + u8 :8; +#else + u16 :6; + u16 N2:12; + u16 NUM2:6; + + u8 :8; +#endif + }; +} RFREG_RFPLL2; + +typedef union +{ + u32 value; + + struct { - struct - { -/* 0*/ unsigned LD_WINDOW:3; -/* 3*/ unsigned M_CT_VALUE:5; -/* 8*/ unsigned TLOCK:5; -/*13*/ unsigned TVCO:5; - } bits; - u32 val; - } CAL1; - union TXRX1 +#ifndef MSB_FIRST + u32 NUM2:18; + u32 :6; + + u8 :8; +#else + u32 :6; + u32 NUM2:18; + + u8 :8; +#endif + }; +} RFREG_RFPLL3; + +typedef union +{ + u32 value; + + struct { - struct - { -/* 0*/ unsigned TXBYPASS:1; -/* 1*/ unsigned INTBIASEN:1; -/* 2*/ unsigned TXENMODE:1; -/* 3*/ unsigned TXDIFFMODE:1; -/* 4*/ unsigned TXLPFBW:3; -/* 7*/ unsigned RXLPFBW:3; -/*10*/ unsigned TXVGC:5; -/*15*/ unsigned PCONTROL:2; -/*17*/ unsigned RXDCFBBYPS:1; - } bits; - u32 val; - } TXRX1; - union PCNT1 +#ifndef MSB_FIRST + u8 KV_DEF:4; + u8 CT_DEF:4; + + u16 DN:9; + u16 reserved:1; + u16 :6; + + u8 :8; +#else + u8 CT_DEF:4; + u8 KV_DEF:4; + + u16 :6; + u16 reserved:1; + u16 DN:9; + + u8 :8; +#endif + }; +} RFREG_RFPLL4; + +typedef union +{ + u32 value; + + struct { - struct - { -/* 0*/ unsigned TX_DELAY:3; -/* 3*/ unsigned PC_OFFSET:6; -/* 9*/ unsigned P_DESIRED:6; -/*15*/ unsigned MID_BIAS:3; - } bits; - u32 val; - } PCNT1; - union PCNT2 +#ifndef MSB_FIRST + u8 LD_WINDOW:3; + u8 M_CT_VALUE:5; + + u16 TLOCK:5; + u16 TVCO:5; + u16 :6; + + u8 :8; +#else + u8 M_CT_VALUE:5; + u8 LD_WINDOW:3; + + u16 :6; + u16 TVCO:5; + u16 TLOCK:5; + + u8 :8; +#endif + }; +} RFREG_CAL1; + +typedef union +{ + u32 value; + + struct { - struct - { -/* 0*/ unsigned MIN_POWER:6; -/* 6*/ unsigned MID_POWER:6; -/*12*/ unsigned MAX_POWER:6; - } bits; - u32 val; - } PCNT2; - union VCOT1 + u32 TXBYPASS:1; + u32 INTBIASEN:1; + u32 TXENMODE:1; + u32 TXDIFFMODE:1; + u32 TXLPFBW:3; + u32 RXLPFBW:3; + u32 TXVGC:5; + u32 PCONTROL:2; + u32 RXDCFBBYPS:1; + u32 :6; + + u8 :8; + }; +} RFREG_TXRX1; + +typedef union +{ + u32 value; + + struct { - struct - { -/* 0*/ unsigned :16; -/*16*/ unsigned AUX1:1; -/*17*/ unsigned AUX:1; - } bits; - u32 val; - } VCOT1; -} rffilter_t; + u32 TX_DELAY:3; + u32 PC_OFFSET:6; + u32 P_DESIRED:6; + u32 MID_BIAS:3; + u32 :6; + + u8 :8; + }; +} RFREG_PCNT1; + +typedef union +{ + u32 value; + + struct + { + u32 MIN_POWER:6; + u32 MID_POWER:6; + u32 MAX_POWER:6; + u32 :6; + + u8 :8; + }; +} RFREG_PCNT2; + +typedef union +{ + u32 value; + + struct + { +#ifndef MSB_FIRST + u16 reserved:16; + + u8 AUX1:1; + u8 AUX:1; + u8 :6; + + u8 :8; +#else + u16 reserved:16; + + u8 :6; + u8 AUX:1; + u8 AUX1:1; + + u8 :8; +#endif + }; +} RFREG_VCOT1; + +// This struct is based on the RF2958 chip from RF Micro Devices. +// All register names match the names that are on the RF2958 Datasheet: +// https://pdf1.alldatasheet.com/datasheet-pdf/view/116332/RFMD/RF2958/+0154WWVOELEbTptEC.+/datasheet.pdf +// +// Note that all the registers are 18 bits in length. However, for the sake of compatibility, +// we pad out each registers to 32 bits. + +#include "PACKED.h" +typedef union +{ + RFREG_RF2958 reg[32]; + + struct + { + RFREG_CFG1 CFG1; // 0 + RFREG_IFPLL1 IFPLL1; // 1 + RFREG_IFPLL2 IFPLL2; // 2 + RFREG_IFPLL3 IFPLL3; // 3 + RFREG_RFPLL1 RFPLL1; // 4 + RFREG_RFPLL2 RFPLL2; // 5 + RFREG_RFPLL3 RFPLL3; // 6 + RFREG_RFPLL4 RFPLL4; // 7 + RFREG_CAL1 CAL1; // 8 + RFREG_TXRX1 TXRX1; // 9 + RFREG_PCNT1 PCNT1; // 10 + RFREG_PCNT2 PCNT2; // 11 + RFREG_VCOT1 VCOT1; // 12 + + RFREG_RF2958 PADDING_13; // 13 + RFREG_RF2958 PADDING_14; // 14 + RFREG_RF2958 PADDING_15; // 15 + RFREG_RF2958 PADDING_16; // 16 + RFREG_RF2958 PADDING_17; // 17 + RFREG_RF2958 PADDING_18; // 18 + RFREG_RF2958 PADDING_19; // 19 + RFREG_RF2958 PADDING_20; // 20 + RFREG_RF2958 PADDING_21; // 21 + RFREG_RF2958 PADDING_22; // 22 + RFREG_RF2958 PADDING_23; // 23 + RFREG_RF2958 PADDING_24; // 24 + RFREG_RF2958 PADDING_25; // 25 + RFREG_RF2958 PADDING_26; // 26 + + RFREG_RF2958 TEST; // 27 + + RFREG_RF2958 PADDING_28; // 28 + RFREG_RF2958 PADDING_29; // 29 + RFREG_RF2958 PADDING_30; // 30 + + RFREG_RF2958 RESET; // 31 + }; +} RF2958_IOREG_MAP; +#include "PACKED_END.h" /* baseband chip refered as BB_, dataformat is unknown yet */ /* it has at least 105 bytes of functional data */ @@ -340,54 +744,6 @@ typedef struct u8 data[105]; } bb_t; -/* communication interface between RF,BB and the mac */ -typedef union -{ - struct { -/* 0*/ unsigned wordsize:5; -/* 5*/ unsigned :2; -/* 7*/ unsigned readOperation:1; -/* 8*/ unsigned :8; - } bits; - u16 val; -} rfIOCnt_t; - -typedef union -{ - struct { -/* 0*/ unsigned busy:1; -/* 1*/ unsigned :15; - } bits; - u16 val; -} rfIOStat_t; - -typedef union -{ - struct { -/* 0*/ unsigned content:18; -/*18*/ unsigned address:5; -/*23*/ unsigned :9; - } bits; - struct { -/* 0*/ unsigned low:16; -/*16*/ unsigned high:16; - } val16; - u16 array16[2]; - u32 val; -} rfIOData_t; - -typedef union -{ - struct { -/* 0*/ unsigned address:7; -/* 7*/ unsigned :5; -/*12*/ unsigned mode:2; -/*14*/ unsigned enable:1; -/*15*/ unsigned :1; - } bits; - u16 val; -} bbIOCnt_t; - #define WIFI_IRQ_RXEND 0 #define WIFI_IRQ_TXEND 1 #define WIFI_IRQ_RXINC 2 @@ -404,15 +760,6 @@ typedef union #define WIFI_IRQ_TIMEBEACON 14 #define WIFI_IRQ_TIMEPREBEACON 15 -typedef struct -{ - bool enabled; - u16 address; - - bool sending; - u16 remtime; -} Wifi_TXLoc; - enum EAPStatus { APStatus_Disconnected = 0, @@ -420,6 +767,15 @@ enum EAPStatus APStatus_Associated }; +enum WifiTXLocIndex +{ + WifiTXLocIndex_LOC1 = 0, + WifiTXLocIndex_CMD = 1, + WifiTXLocIndex_LOC2 = 2, + WifiTXLocIndex_LOC3 = 3, + WifiTXLocIndex_BEACON = 4 +}; + enum WifiEmulationLevel { WifiEmulationLevel_Off = 0, @@ -440,135 +796,1979 @@ enum WifiMACMode WifiMACMode_ReadFromFirmware = 2 }; -/* wifimac_t: the buildin mac (arm7 addressrange: 0x04800000-0x04FFFFFF )*/ -/* http://www.akkit.org/info/dswifi.htm#WifiIOMap */ +typedef u16 IOREG_W_PADDING; -typedef struct +typedef u16 IOREG_W_INTERNAL; +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_02E; // 0x480802E +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_034; // 0x4808034 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_078; // 0x4808078 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_09C; // 0x480809C +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_0BA; // 0x48080BA +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_0C8; // 0x48080C8 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_100; // 0x4808100 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_102; // 0x4808102 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_104; // 0x4808104 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_106; // 0x4808106 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_126; // 0x4808126 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_12A; // 0x480812A +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_16A; // 0x480816A +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_170; // 0x4808170 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_172; // 0x4808172 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_174; // 0x4808174 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_176; // 0x4808176 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_178; // 0x4808178 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_190; // 0x4808190 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_198; // 0x4808198 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_1F0; // 0x48081F0 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_204; // 0x4808204 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_208; // 0x4808208 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_20C; // 0x480820C +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_220; // 0x4808220 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_224; // 0x4808224 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_230; // 0x4808230 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_234; // 0x4808234 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_238; // 0x4808238 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_23C; // 0x480823C +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_248; // 0x4808248 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_24C; // 0x480824C +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_24E; // 0x480824E +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_250; // 0x4808250 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_258; // 0x4808258 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_25C; // 0x480825C +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_260; // 0x4808260 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_264; // 0x4808264 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_270; // 0x4808270 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_274; // 0x4808274 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_278; // 0x4808278 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_27C; // 0x480827C +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_298; // 0x4808298 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_2A0; // 0x48082A0 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_2A2; // 0x48082A2 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_2A4; // 0x48082A4 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_2A8; // 0x48082A8 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_2AC; // 0x48082AC +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_2B0; // 0x48082B0 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_2B4; // 0x48082B4 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_2B8; // 0x48082B8 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_2C0; // 0x48082C0 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_2C4; // 0x48082C4 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_2C8; // 0x48082C8 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_2CC; // 0x48082CC +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_2F0; // 0x48082F0 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_2F2; // 0x48082F2 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_2F4; // 0x48082F4 +typedef IOREG_W_INTERNAL IOREG_W_INTERNAL_2F6; // 0x48082F6 + +typedef u16 IOREG_W_CONFIG; +typedef IOREG_W_CONFIG IOREG_W_CONFIG_0D4; // 0x48080D4 +typedef IOREG_W_CONFIG IOREG_W_CONFIG_0D8; // 0x48080D8 +typedef IOREG_W_CONFIG IOREG_W_CONFIG_0EC; // 0x48080EC +typedef IOREG_W_CONFIG IOREG_W_CONFIG_120; // 0x4808120 +typedef IOREG_W_CONFIG IOREG_W_CONFIG_122; // 0x4808122 +typedef IOREG_W_CONFIG IOREG_W_CONFIG_124; // 0x4808124 +typedef IOREG_W_CONFIG IOREG_W_CONFIG_128; // 0x4808128 +typedef IOREG_W_CONFIG IOREG_W_CONFIG_130; // 0x4808130 +typedef IOREG_W_CONFIG IOREG_W_CONFIG_132; // 0x4808132 +typedef IOREG_W_CONFIG IOREG_W_CONFIG_140; // 0x4808140 +typedef IOREG_W_CONFIG IOREG_W_CONFIG_142; // 0x4808142 +typedef IOREG_W_CONFIG IOREG_W_CONFIG_144; // 0x4808144 +typedef IOREG_W_CONFIG IOREG_W_CONFIG_146; // 0x4808146 +typedef IOREG_W_CONFIG IOREG_W_CONFIG_148; // 0x4808148 +typedef IOREG_W_CONFIG IOREG_W_CONFIG_14A; // 0x480814A +typedef IOREG_W_CONFIG IOREG_W_CONFIG_14C; // 0x480814C +typedef IOREG_W_CONFIG IOREG_W_CONFIG_150; // 0x4808150 +typedef IOREG_W_CONFIG IOREG_W_CONFIG_154; // 0x4808154 +typedef IOREG_W_CONFIG IOREG_W_CONFIG_254; // 0x4808254 + +typedef u16 IOREG_W_ID; // 0x4808000 + +typedef union { - /* power */ - bool powerOn; - bool powerOnPending; + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 TXMasterEnable:1; + u16 UNKNOWN1:7; + + u16 UNKNOWN2:5; + u16 ResetPortSet1:1; + u16 ResetPortSet2:1; + u16 UNKNOWN3:1; +#else + u16 UNKNOWN1:7; + u16 TXMasterEnable:1; + + u16 UNKNOWN3:1; + u16 ResetPortSet2:1; + u16 ResetPortSet1:1; + u16 UNKNOWN2:5; +#endif + }; +} IOREG_W_MODE_RST; // 0x4808004 - /* status */ - u16 rfStatus; - u16 rfPins; +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 UNKNOWN1:3; + u16 WEPEncryptionKeySize:3; + u16 UNKNOWN2:2; + + u16 :8; +#else + u16 UNKNOWN2:2; + u16 WEPEncryptionKeySize:3; + u16 UNKNOWN1:3; + + u16 :8; +#endif + }; +} IOREG_W_MODE_WEP; // 0x4808006 - /* wifi interrupt handling */ - u16 IE; - u16 IF; +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 UNKNOWN1:8; + + u16 UNKNOWN2:5; + u16 UpdateTXStat_0B01:1; + u16 UpdateTXStat_0800:1; + u16 UpdateTXStatBeacon:1; +#else + u16 UNKNOWN1:8; + + u16 UpdateTXStatBeacon:1; + u16 UpdateTXStat_0800:1; + u16 UpdateTXStat_0B01:1; + u16 UNKNOWN2:5; +#endif + }; +} IOREG_W_TXSTATCNT; // 0x4808008 - /* modes */ - u16 macMode; - u16 wepMode; - bool WEP_enable; +typedef u16 IOREG_W_X_00A; // 0x480800A - /* sending */ - u16 TXStatCnt; - u16 TXPower; - u16 TXSlot[3]; - u16 TXCnt; - u16 TXOpt; - u16 TXStat; - u16 BeaconAddr; - bool BeaconEnable; - u16 TXSlotExtra; - u16 TXSeqNo; - u8 txCurSlot; - u8 txSlotBusy[3]; - u32 txSlotAddr[3]; - u32 txSlotLen[3]; - u32 txSlotRemainingBytes[3]; - bool ExtraSlotBusy; - u16 ExtraSlotAddr; - u16 ExtraSlotLen; - u16 ExtraSlotRemBytes; +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 RXComplete:1; + u16 TXComplete:1; + u16 RXEventIncrement:1; + u16 TXErrorIncrement:1; + u16 RXEventOverflow:1; + u16 TXErrorOverflow:1; + u16 RXStart:1; + u16 TXStart:1; + + u16 TXBufCountExpired:1; + u16 RXBufCountExpired:1; + u16 :1; + u16 RFWakeup:1; + u16 Multiplayer:1; + u16 PostBeaconTimeslot:1; + u16 BeaconTimeslot:1; + u16 PreBeaconTimeslot:1; +#else + u16 TXStart:1; + u16 RXStart:1; + u16 TXErrorOverflow:1; + u16 RXEventOverflow:1; + u16 TXErrorIncrement:1; + u16 RXEventIncrement:1; + u16 TXComplete:1; + u16 RXComplete:1; + + u16 PreBeaconTimeslot:1; + u16 BeaconTimeslot:1; + u16 PostBeaconTimeslot:1; + u16 Multiplayer:1; + u16 RFWakeup:1; + u16 :1; + u16 RXBufCountExpired:1; + u16 TXBufCountExpired:1; +#endif + }; +} IOREG_W_IF; // 0x4808010 - /* receiving */ - u16 RXCnt; - u16 RXCheckCounter; - u8 RXNum; +typedef IOREG_W_IF IOREG_W_IE; // 0x4808012 +typedef IOREG_W_IF IOREG_W_IF_SET; // 0x480821C - u16 RXTXAddr; +typedef union +{ + u16 value; + u8 component[2]; +} IOREG_W_MACADDRn; - /* addressing/handshaking */ +typedef IOREG_W_MACADDRn IOREG_W_MACADDR0; // 0x4808018 +typedef IOREG_W_MACADDRn IOREG_W_MACADDR1; // 0x480801A +typedef IOREG_W_MACADDRn IOREG_W_MACADDR2; // 0x480801C +typedef IOREG_W_MACADDRn IOREG_W_BSSID0; // 0x4808020 +typedef IOREG_W_MACADDRn IOREG_W_BSSID1; // 0x4808022 +typedef IOREG_W_MACADDRn IOREG_W_BSSID2; // 0x4808024 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 PlayerID:4; + u16 :4; + + u16 :8; +#else + u16 :4; + u16 PlayerID:4; + + u16 :8; +#endif + }; +} IOREG_W_AID_LOW; // 0x4808028 + +typedef union +{ + u16 value; + + struct + { + u16 AssociationID:11; + u16 :5; + }; +} IOREG_W_AID_FULL; // 0x480802A + +typedef union +{ + u16 value; + + struct + { + u16 Count:8; + u16 UNKNOWN1:8; + }; +} IOREG_W_TX_RETRYLIMIT; // 0x480802C + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 CopyAddrToWRCSR:1; + u16 UNKNOWN1:3; + u16 :3; + u16 CopyTXBufReply1To2:1; + + u16 UNKNOWN2:7; + u16 EnableRXFIFOQueuing:1; +#else + u16 CopyTXBufReply1To2:1; + u16 :3; + u16 UNKNOWN1:3; + u16 CopyAddrToWRCSR:1; + + u16 EnableRXFIFOQueuing:1; + u16 UNKNOWN2:7; +#endif + }; +} IOREG_W_RXCNT; // 0x4808030 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 :8; + + u16 :7; + u16 Enable:1; +#else + u16 :8; + + u16 Enable:1; + u16 :7; +#endif + }; +} IOREG_W_WEP_CNT; // 0x4808032 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 Disable:1; + u16 UNKNOWN1:1; + u16 :6; + + u16 :8; +#else + u16 :6; + u16 UNKNOWN1:1; + u16 Disable:1; + + u16 :8; +#endif + }; +} IOREG_W_POWER_US; // 0x4808036 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 AutoWakeup:1; + u16 AutoSleep:1; + u16 UNKNOWN1:1; + u16 UNKNOWN2:1; + u16 :4; + + u16 :8; +#else + u16 :4; + u16 UNKNOWN2:1; + u16 UNKNOWN1:1; + u16 AutoSleep:1; + u16 AutoWakeup:1; + + u16 :8; +#endif + }; +} IOREG_W_POWER_TX; // 0x4808038 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 UNKNOWN1:1; + u16 RequestPowerOn:1; + u16 :6; + + u16 WillPowerOn:1; + u16 IsPowerOff:1; + u16 :6; +#else + u16 :6; + u16 RequestPowerOn:1; + u16 UNKNOWN1:1; + + u16 :6; + u16 IsPowerOff:1; + u16 WillPowerOn:1; +#endif + }; +} IOREG_W_POWERSTATE; // 0x480803C + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 NewPowerOffState:1; + u16 :7; + + u16 :7; + u16 ApplyNewPowerOffState:1; +#else + u16 :7; + u16 NewPowerOffState:1; + + u16 ApplyNewPowerOffState:1; + u16 :7; +#endif + }; +} IOREG_W_POWERFORCE; // 0x4808040 + +typedef union +{ + u16 value; + + struct + { + u16 Random:11; + u16 :5; + }; +} IOREG_W_RANDOM; // 0x4808044 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 UNKNOWN1:1; + u16 UNKNOWN2:1; + u16 :6; + + u16 :8; +#else + u16 :6; + u16 UNKNOWN2:1; + u16 UNKNOWN1:1; + + u16 :8; +#endif + }; +} IOREG_W_POWER_UNKNOWN; // 0x4808048 + +typedef u16 IOREG_W_RXBUF_BEGIN; // 0x4808050 +typedef u16 IOREG_W_RXBUF_END; // 0x4808052 + +typedef union +{ + u16 value; + + struct + { + u16 HalfwordAddress:12; + u16 :4; + }; +} IOREG_W_RXBUF_WRCSR; // 0x4808054 + +typedef union +{ + u16 value; + + struct + { + u16 HalfwordAddress:12; + u16 :4; + }; +} IOREG_W_RXBUF_WR_ADDR; // 0x4808056 + +typedef union +{ + u16 value; + + struct + { + u16 ByteAddress:13; + u16 :3; + }; + + struct + { + u16 :1; + u16 HalfwordAddress:12; + u16 :3; + }; +} IOREG_W_RXBUF_RD_ADDR; // 0x4808058 + +typedef union +{ + u16 value; + + struct + { + u16 HalfwordAddress:12; + u16 :4; + }; +} IOREG_W_RXBUF_READCSR; // 0x480805A + +typedef union +{ + u16 value; + + struct + { + u16 Count:12; + u16 :4; + }; +} IOREG_W_RXBUF_COUNT; // 0x480805C + +typedef u16 IOREG_W_RXBUF_RD_DATA; // 0x4808060 + +typedef union +{ + u16 value; + + struct + { + u16 ByteAddress:13; + u16 :3; + }; + + struct + { + u16 :1; + u16 HalfwordAddress:12; + u16 :3; + }; +} IOREG_W_RXBUF_GAP; // 0x4808062 + +typedef union +{ + u16 value; + + struct + { + u16 HalfwordOffset:12; + u16 :4; + }; +} IOREG_W_RXBUF_GAPDISP; // 0x4808064 + +typedef union +{ + u16 value; + + struct + { + u16 ByteAddress:13; + u16 :3; + }; + + struct + { + u16 :1; + u16 HalfwordAddress:12; + u16 :3; + }; +} IOREG_W_TXBUF_WR_ADDR; // 0x4808068 + +typedef union +{ + u16 value; + + struct + { + u16 Count:12; + u16 :4; + }; +} IOREG_W_TXBUF_COUNT; // 0x480806C + +typedef u16 IOREG_W_TXBUF_WR_DATA; // 0x4808070 + +typedef union +{ + u16 value; + + struct + { + u16 ByteAddress:13; + u16 :3; + }; + + struct + { + u16 :1; + u16 HalfwordAddress:12; + u16 :3; + }; +} IOREG_W_TXBUF_GAP; // 0x4808074 + +typedef union +{ + u16 value; + + struct + { + u16 HalfwordOffset:12; + u16 :4; + }; +} IOREG_W_TXBUF_GAPDISP; // 0x4808076 + +typedef union +{ + u16 value; + + struct + { + u16 HalfwordAddress:12; + u16 Bit12:1; + u16 IEEESeqCtrl:1; + u16 UNKNOWN1:1; + u16 TransferRequest:1; + }; +} IOREG_W_TXBUF_LOCATION; // 0x4808080, 0x4808090, 0x48080A0, 0x48080A4, 0x48080A8 + +typedef union +{ + u16 value; + + struct + { + u16 Location:8; + u16 :8; + }; +} IOREG_W_TXBUF_TIM; // 0x4808084 + +typedef union +{ + u16 value; + + struct + { + u16 Count:8; + u16 :8; + }; +} IOREG_W_LISTENCOUNT; // 0x4808088 + +typedef union +{ + u16 value; + + struct + { + u16 Interval:10; + u16 :6; + }; +} IOREG_W_BEACONINT; // 0x480808C + +typedef union +{ + u16 value; + + struct + { + u16 Interval:8; + u16 :8; + }; +} IOREG_W_LISTENINT; // 0x480808E + +typedef union +{ + u16 value; + + struct + { + u16 HalfwordAddress:12; + u16 UNKNOWN1:3; + u16 Enable:1; + }; +} IOREG_W_TXBUF_REPLY; // 0x4808094, 0x4808098 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 Loc1:1; + u16 Cmd:1; + u16 Loc2:1; + u16 Loc3:1; + u16 UNKNOWN1:1; + u16 :3; + + u16 :8; +#else + u16 :3; + u16 UNKNOWN1:1; + u16 Loc3:1; + u16 Loc2:1; + u16 Cmd:1; + u16 Loc1:1; + + u16 :8; +#endif + }; +} IOREG_W_TXREQ_RESET; // 0x48080AC + +typedef IOREG_W_TXREQ_RESET IOREG_W_TXREQ_SET; // 0x48080AE + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 Loc1:1; + u16 Cmd:1; + u16 Loc2:1; + u16 Loc3:1; + u16 UNKNOWN1:1; + u16 :3; + + u16 :8; +#else + u16 :3; + u16 UNKNOWN1:1; + u16 Loc3:1; + u16 Loc2:1; + u16 Cmd:1; + u16 Loc1:1; + + u16 :8; +#endif + }; +} IOREG_W_TXREQ_READ; // 0x48080B0 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 Loc1:1; + u16 Cmd:1; + u16 Loc2:1; + u16 Loc3:1; + u16 UNKNOWN1:2; + u16 Reply2:1; + u16 Reply1:1; + + u16 UNKNOWN2:8; +#else + u16 Reply1:1; + u16 Reply2:1; + u16 UNKNOWN1:2; + u16 Loc3:1; + u16 Loc2:1; + u16 Cmd:1; + u16 Loc1:1; + + u16 UNKNOWN2:8; +#endif + }; +} IOREG_W_TXBUF_RESET; // 0x48080B4 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 Loc1:1; + u16 Cmd:1; + u16 Loc2:1; + u16 Loc3:1; + u16 Beacon:1; + u16 UNKNOWN1:3; + + u16 UNKNOWN2:8; +#else + u16 UNKNOWN1:3; + u16 Beacon:1; + u16 Loc3:1; + u16 Loc2:1; + u16 Cmd:1; + u16 Loc1:1; + + u16 UNKNOWN2:8; +#endif + }; +} IOREG_W_TXBUSY; // 0x48080B6 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 PacketCompleted:1; + u16 PacketFailed:1; + u16 UNKNOWN1:6; + + u16 UNKNOWN2:4; + u16 PacketUpdate:2; + u16 UNKNOWN3:2; +#else + u16 UNKNOWN1:6; + u16 PacketFailed:1; + u16 PacketCompleted:1; + + u16 UNKNOWN3:2; + u16 PacketUpdate:2; + u16 UNKNOWN2:4; +#endif + }; +} IOREG_W_TXSTAT; // 0x48080B8 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 UNKNOWN1:1; + u16 PreambleWithoutTX:1; + u16 PreambleWithTX:1; + u16 :5; + + u16 :8; +#else + u16 :5; + u16 PreambleWithTX:1; + u16 PreambleWithoutTX:1; + u16 UNKNOWN1:1; + + u16 :8; +#endif + }; +} IOREG_W_PREAMBLE; // 0x48080BC + +typedef u16 IOREG_W_CMD_TOTALTIME; // 0x48080C0 +typedef u16 IOREG_W_CMD_REPLYTIME; // 0x48080C4 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 DisableNeedBSSID:1; + u16 UNKNOWN1:6; + u16 UNKNOWN2:1; + + u16 UNKNOWN3:1; + u16 UNKNOWN4:1; + u16 UNKNOWN5:1; + u16 UNKNOWN6:1; + u16 UNKNOWN7:1; + u16 :3; +#else + u16 UNKNOWN2:1; + u16 UNKNOWN1:6; + u16 DisableNeedBSSID:1; + + u16 :3; + u16 UNKNOWN7:1; + u16 UNKNOWN6:1; + u16 UNKNOWN5:1; + u16 UNKNOWN4:1; + u16 UNKNOWN3:1; +#endif + }; +} IOREG_W_RXFILTER; // 0x48080D0 + +typedef union +{ + u16 value; + + struct + { + u16 ReduceLenForNonWEP:8; + u16 ReduceLenForWEP:8; + }; +} IOREG_W_RX_LEN_CROP; // 0x48080DA + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 UNKNOWN1:1; + u16 UNKNOWN2:1; + u16 UNKNOWN3:1; + u16 UNKNOWN4:1; + u16 :4; + + u16 :8; +#else + u16 :8; + + u16 :4; + u16 UNKNOWN4:1; + u16 UNKNOWN3:1; + u16 UNKNOWN2:1; + u16 UNKNOWN1:1; +#endif + }; +} IOREG_W_RXFILTER2; // 0x48080E0 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 EnableCounter:1; + u16 :7; + + u16 :8; +#else + u16 :8; + + u16 :7; + u16 EnableCounter:1; +#endif + }; +} IOREG_W_US_COUNTCNT; // 0x48080E8 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 EnableCompare:1; + u16 ForceIRQ14:1; + u16 :6; + + u16 :8; +#else + u16 :8; + + u16 :6; + u16 ForceIRQ14:1; + u16 EnableCompare:1; +#endif + }; +} IOREG_W_US_COMPARECNT; // 0x48080EA + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 EnableCounter:1; + u16 :7; + + u16 :8; +#else + u16 :8; + + u16 :7; + u16 EnableCounter:1; +#endif + }; +} IOREG_W_CMD_COUNTCNT; // 0x48080EE + +typedef u16 IOREG_W_CONTENTFREE; // 0x480810C + +typedef u16 IOREG_W_PRE_BEACON; // 0x4808110 + +typedef u16 IOREG_W_CMD_COUNT; // 0x4808118 + +typedef u16 IOREG_W_BEACONCOUNT1; // 0x480811C + +typedef u16 IOREG_W_BEACONCOUNT2; // 0x4808134 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 Index:8; + + u16 :4; + u16 Direction:4; +#else + u16 Direction:4; + u16 :4; + + u16 Index:8; +#endif + }; +} IOREG_W_BB_CNT; // 0x4808158 + +typedef union +{ + u16 value; + + struct + { + u8 Data:8; + u8 :8; + }; +} IOREG_W_BB_WRITE; // 0x480815A + +typedef union +{ + u16 value; + + struct + { + u8 Data:8; + u8 :8; + }; +} IOREG_W_BB_READ; // 0x480815C + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 Busy:1; + u16 :7; + + u16 :8; +#else + u16 :8; + + u16 :7; + u16 Busy:1; +#endif + }; +} IOREG_W_BB_BUSY; // 0x480815E + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 :8; + + u16 UNKNOWN1:1; + u16 :5; + u16 UNKNOWN2:1; + u16 :1; +#else + u16 :8; + + u16 :1; + u16 UNKNOWN2:1; + u16 :5; + u16 UNKNOWN1:1; +#endif + }; +} IOREG_W_BB_MODE; // 0x4808160 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 Disable:4; + u16 :4; + + u16 :7; + u16 DisableAllPorts:1; +#else + u16 :4; + u16 Disable:4; + + u16 DisableAllPorts:1; + u16 :7; +#endif + }; +} IOREG_W_BB_POWER; // 0x4808168 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 DataMSB:2; + u16 Index:5; + u16 ReadCommand:1; + + u16 :8; +#else + u16 ReadCommand:1; + u16 Index:5; + u16 DataMSB:2; + + u16 :8; +#endif + } Type2; + + struct + { +#ifndef MSB_FIRST + u16 Command:4; + u16 :4; + + u16 :8; +#else + u16 :4; + u16 Command:4; + + u16 :8; +#endif + } Type3; +} IOREG_W_RF_DATA2; // 0x480817C + +typedef union +{ + u16 value; + + struct + { + u16 DataLSB; + } Type2; + + struct + { + u8 Data:8; + u8 Index:8; + } Type3; +} IOREG_W_RF_DATA1; // 0x480817E + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 Busy:1; + u16 :7; + + u16 :8; +#else + u16 :7; + u16 Busy:1; + + u16 :8; +#endif + }; +} IOREG_W_RF_BUSY; // 0x4808180 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 TransferLen:6; + u16 :2; + + u16 UNKNOWN1:1; + u16 :5; + u16 UNKNOWN2:1; + u16 :1; +#else + u16 :2; + u16 TransferLen:6; + + u16 :1; + u16 UNKNOWN2:1; + u16 :5; + u16 UNKNOWN1:1; +#endif + }; +} IOREG_W_RF_CNT; // 0x4808184 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 Duration:1; + u16 FrameCheckSeq:1; + u16 SeqControl:1; + u16 :5; + + u16 :8; +#else + u16 :8; + + u16 :5; + u16 SeqControl:1; + u16 FrameCheckSeq:1; + u16 Duration:1; +#endif + }; +} IOREG_W_TX_HDR_CNT; // 0x4808194 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 CarrierSense:1; + u16 TXMain:1; + u16 UNKNOWN1:1; + u16 :3; + u16 TX_On:1; + u16 RX_On:1; + + u16 :8; +#else + u16 :8; + + u16 RX_On:1; + u16 TX_On:1; + u16 :3; + u16 UNKNOWN1:1; + u16 TXMain:1; + u16 CarrierSense:1; +#endif + }; +} IOREG_W_RF_PINS; // 0x480819C + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 UNKNOWN1:2; + u16 :2; + u16 UNKNOWN2:2; + u16 :2; + + u16 UNKNOWN3:1; + u16 :2; + u16 UNKNOWN4:1; + u16 :4; +#else + u16 :4; + u16 UNKNOWN4:1; + u16 :2; + u16 UNKNOWN3:1; + + u16 :2; + u16 UNKNOWN2:2; + u16 :2; + u16 UNKNOWN1:2; +#endif + }; +} IOREG_W_X_1A0; // 0x48081A0 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 UNKNOWN1:2; + u16 :6; + + u16 :8; +#else + u16 :8; + + u16 :6; + u16 UNKNOWN1:2; +#endif + }; +} IOREG_W_X_1A2; // 0x48081A2 + +typedef u16 IOREG_W_X_1A4; // 0x48081A4 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 RX0L:1; // Bit 0 + u16 RX1L:1; // Bit 1 + u16 RX1H:1; // Bit 2 + u16 RX2L:1; // Bit 3 + u16 RX2H:1; // Bit 4 + u16 RX3L:1; // Bit 5 + u16 RX3H:1; // Bit 6 + u16 RX4L:1; // Bit 7 + + u16 RX5L:1; // Bit 8 + u16 RX6L:1; // Bit 9 + u16 RX6H:1; // Bit 10 + u16 RX7L:1; // Bit 11 + u16 RX7H:1; // Bit 12 + u16 :3; +#else + u16 :3; + u16 RX7H:1; // Bit 12 + u16 RX7L:1; // Bit 11 + u16 RX6H:1; // Bit 10 + u16 RX6L:1; // Bit 9 + u16 RX5L:1; // Bit 8 + + u16 RX4L:1; // Bit 7 + u16 RX3H:1; // Bit 6 + u16 RX3L:1; // Bit 5 + u16 RX2H:1; // Bit 4 + u16 RX2L:1; // Bit 3 + u16 RX1H:1; // Bit 2 + u16 RX1L:1; // Bit 1 + u16 RX0L:1; // Bit 0 +#endif + }; +} IOREG_W_RXSTAT_INC_IF; // 0x48081A8 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 RX0L:1; // Bit 0 + u16 RX1L:1; // Bit 1 + u16 RX1H:1; // Bit 2 + u16 RX2L:1; // Bit 3 + u16 RX2H:1; // Bit 4 + u16 RX3L:1; // Bit 5 + u16 RX3H:1; // Bit 6 + u16 RX4L:1; // Bit 7 + + u16 RX5L:1; // Bit 8 + u16 RX6L:1; // Bit 9 + u16 RX6H:1; // Bit 10 + u16 RX7L:1; // Bit 11 + u16 RX7H:1; // Bit 12 + u16 UNKNOWN1:3; +#else + u16 UNKNOWN1:3; + u16 RX7H:1; // Bit 12 + u16 RX7L:1; // Bit 11 + u16 RX6H:1; // Bit 10 + u16 RX6L:1; // Bit 9 + u16 RX5L:1; // Bit 8 + + u16 RX4L:1; // Bit 7 + u16 RX3H:1; // Bit 6 + u16 RX3L:1; // Bit 5 + u16 RX2H:1; // Bit 4 + u16 RX2L:1; // Bit 3 + u16 RX1H:1; // Bit 2 + u16 RX1L:1; // Bit 1 + u16 RX0L:1; // Bit 0 +#endif + }; +} IOREG_W_RXSTAT_INC_IE; // 0x48081AA + +typedef IOREG_W_RXSTAT_INC_IF IOREG_W_RXSTAT_OVF_IF; // 0x48081AC +typedef IOREG_W_RXSTAT_INC_IE IOREG_W_RXSTAT_OVF_IE; // 0x48081AE + +typedef union +{ + u8 count[16]; + + struct + { + u16 RXSTAT_1B0; // 0x48081B0 + u16 RXSTAT_1B2; // 0x48081B2 + u16 RXSTAT_1B4; // 0x48081B4 + u16 RXSTAT_1B6; // 0x48081B6 + + u16 RXSTAT_1B8; // 0x48081B8 + u16 RXSTAT_1BA; // 0x48081BA + u16 RXSTAT_1BC; // 0x48081BC + u16 RXSTAT_1BE; // 0x48081BE + }; + + struct + { + u8 UNKNOWN1; + u8 _unused0; + u8 RateError; + u8 LengthError; + u8 BufferFullError; + u8 UNKNOWN2; + u8 WrongFCSError; + u8 PacketHeaderError; + + u8 UNKNOWN3; + u8 _unused1; + u8 UNKNOWN4; + u8 _unused2; + u8 WEPError; + u8 UNKNOWN5; + u8 SeqControl; + u8 UNKNOWN6; + }; +} IOREG_W_RXSTAT_COUNT; // 0x48081B0 - 0x48081BF + +typedef union +{ + u16 value; + + struct + { + u16 Count:8; + u16 :8; + }; +} IOREG_W_TX_ERR_COUNT; // 0x48081C0 + +typedef union +{ + u16 value; + + struct + { + u16 OkayCount:8; + u16 ErrorCount:8; + }; +} IOREG_W_RX_COUNT; // 0x48081C4 + +typedef union +{ + u8 count[16]; + + struct + { + u16 CMD_STAT_1D0; // 0x48081D0 + u16 CMD_STAT_1D2; // 0x48081D2 + u16 CMD_STAT_1D4; // 0x48081D4 + u16 CMD_STAT_1D6; // 0x48081D6 + u16 CMD_STAT_1D8; // 0x48081D8 + u16 CMD_STAT_1DA; // 0x48081DA + u16 CMD_STAT_1DC; // 0x48081DC + u16 CMD_STAT_1DE; // 0x48081DE + }; +} IOREG_W_CMD_STAT_COUNT; // 0x48081D0 - 0x48081DF + +typedef union +{ + u16 value; + + struct + { + u16 Number:12; + u16 :4; + }; +} IOREG_W_TX_SEQNO; // 0x4808210 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 Status:4; + u16 :4; + + u16 :8; +#else + u16 :8; + + u16 :4; + u16 Status:4; +#endif + }; +} IOREG_W_RF_STATUS; // 0x4808214 + +typedef u16 IOREG_W_X_228; // 0x4808228 +typedef u16 IOREG_W_X_244; // 0x4808244 + +typedef union +{ + u16 value; + + struct + { + u16 HalfwordAddress:12; + u16 :4; + }; +} IOREG_W_RXTX_ADDR; // 0x4808268 + +typedef union +{ + u16 value; + + struct + { +#ifndef MSB_FIRST + u16 UNKNOWN1:1; + u16 :7; + + u16 :8; +#else + u16 :8; + + u16 :7; + u16 UNKNOWN1:1; +#endif + }; +} IOREG_W_X_290; // 0x4808290 + +typedef u16 IOREG_W_POWERACK; // 0x48082D0 + +// WIFI_IOREG_MAP: the buildin mac (arm7 addressrange: 0x04800000-0x04FFFFFF ) +// http://www.akkit.org/info/dswifi.htm#WifiIOMap +#include "PACKED.h" +typedef struct +{ + IOREG_W_ID ID; // 0x4808000 + IOREG_W_PADDING pad_002; // 0x4808002 + IOREG_W_MODE_RST MODE_RST; // 0x4808004 + IOREG_W_MODE_WEP MODE_WEP; // 0x4808006 + IOREG_W_TXSTATCNT TXSTATCNT; // 0x4808008 + IOREG_W_X_00A X_00A; // 0x480800A + IOREG_W_PADDING pad_00C; // 0x480800C + IOREG_W_PADDING pad_00E; // 0x480800E + IOREG_W_IF IF; // 0x4808010 + IOREG_W_IE IE; // 0x4808012 + IOREG_W_PADDING pad_014; // 0x4808014 + IOREG_W_PADDING pad_016; // 0x4808016 + union { - //TODO - is this endian safe? don't think so - u16 words[3]; - u8 bytes[6]; - } mac; + u8 MACADDR[6]; // 48-bit MAC address of the console. Should be initialized from firmware. + + struct + { + IOREG_W_MACADDR0 MACADDR0; // 0x4808018 + IOREG_W_MACADDR1 MACADDR1; // 0x480801A + IOREG_W_MACADDR2 MACADDR2; // 0x480801C + }; + }; + + IOREG_W_PADDING pad_01E; // 0x480801E + union { - u16 words[3]; - u8 bytes[6]; - } bss; - u16 aid; - u16 pid; /* player ID or aid_low */ - u16 retryLimit; + u8 BSSID[6]; // 48-bit MAC address of the console. Should be initialized from firmware. + + struct + { + IOREG_W_BSSID0 BSSID0; // 0x4808020 + IOREG_W_BSSID1 BSSID1; // 0x4808022 + IOREG_W_BSSID2 BSSID2; // 0x4808024 + }; + }; + + IOREG_W_PADDING pad_026; // 0x4808026 + + IOREG_W_AID_LOW AID_LOW; // 0x4808028 + IOREG_W_AID_FULL AID_FULL; // 0x480802A + IOREG_W_TX_RETRYLIMIT TX_RETRYLIMIT; // 0x480802C + IOREG_W_INTERNAL_02E INTERNAL_02E; // 0x480802E + IOREG_W_RXCNT RXCNT; // 0x4808030 + IOREG_W_WEP_CNT WEP_CNT; // 0x4808032 + IOREG_W_INTERNAL_034 INTERNAL_034; // 0x4808034 + + IOREG_W_POWER_US POWER_US; // 0x4808036 + IOREG_W_POWER_TX POWER_TX; // 0x4808038 + IOREG_W_PADDING pad_03A; // 0x480803A + IOREG_W_POWERSTATE POWERSTATE; // 0x480803C + IOREG_W_PADDING pad_03E; // 0x480803E + IOREG_W_POWERFORCE POWERFORCE; // 0x4808040 + IOREG_W_PADDING pad_042; // 0x4808042 + IOREG_W_RANDOM RANDOM; // 0x4808044 + IOREG_W_PADDING pad_046; // 0x4808046 + IOREG_W_POWER_UNKNOWN POWER_UNKNOWN; // 0x4808048 + + IOREG_W_PADDING pad_04A; // 0x480804A + IOREG_W_PADDING pad_04C; // 0x480804C + IOREG_W_PADDING pad_04E; // 0x480804E + + IOREG_W_RXBUF_BEGIN RXBUF_BEGIN; // 0x4808050 + IOREG_W_RXBUF_END RXBUF_END; // 0x4808052 + IOREG_W_RXBUF_WRCSR RXBUF_WRCSR; // 0x4808054 + IOREG_W_RXBUF_WR_ADDR RXBUF_WR_ADDR; // 0x4808056 + IOREG_W_RXBUF_RD_ADDR RXBUF_RD_ADDR; // 0x4808058 + IOREG_W_RXBUF_READCSR RXBUF_READCSR; // 0x480805A + IOREG_W_RXBUF_COUNT RXBUF_COUNT; // 0x480805C + IOREG_W_PADDING pad_05E; // 0x480805E + IOREG_W_RXBUF_RD_DATA RXBUF_RD_DATA; // 0x4808060 + IOREG_W_RXBUF_GAP RXBUF_GAP; // 0x4808062 + IOREG_W_RXBUF_GAPDISP RXBUF_GAPDISP; // 0x4808064 + IOREG_W_PADDING pad_066; // 0x4808066 + IOREG_W_TXBUF_WR_ADDR TXBUF_WR_ADDR; // 0x4808068 + IOREG_W_PADDING pad_06A; // 0x480806A + IOREG_W_TXBUF_COUNT TXBUF_COUNT; // 0x480806C + IOREG_W_PADDING pad_06E; // 0x480806E + IOREG_W_TXBUF_WR_DATA TXBUF_WR_DATA; // 0x4808070 + IOREG_W_PADDING pad_072; // 0x4808072 + IOREG_W_TXBUF_GAP TXBUF_GAP; // 0x4808074 + IOREG_W_TXBUF_GAPDISP TXBUF_GAPDISP; // 0x4808076 + + IOREG_W_INTERNAL_078 INTERNAL_078; // 0x4808078 + IOREG_W_PADDING pad_07A; // 0x480807A + IOREG_W_PADDING pad_07C; // 0x480807C + IOREG_W_PADDING pad_07E; // 0x480807E + IOREG_W_TXBUF_LOCATION TXBUF_BEACON; // 0x4808080 + IOREG_W_PADDING pad_082; // 0x4808082 + IOREG_W_TXBUF_TIM TXBUF_TIM; // 0x4808084 + IOREG_W_PADDING pad_086; // 0x4808086 + IOREG_W_LISTENCOUNT LISTENCOUNT; // 0x4808088 + IOREG_W_PADDING pad_08A; // 0x480808A + IOREG_W_BEACONINT BEACONINT; // 0x480808C + IOREG_W_LISTENINT LISTENINT; // 0x480808E + IOREG_W_TXBUF_LOCATION TXBUF_CMD; // 0x4808090 + IOREG_W_PADDING pad_092; // 0x4808092 + IOREG_W_TXBUF_REPLY TXBUF_REPLY1; // 0x4808094 + IOREG_W_PADDING pad_096; // 0x4808096 + IOREG_W_TXBUF_REPLY TXBUF_REPLY2; // 0x4808098 + IOREG_W_PADDING pad_09A; // 0x480809A + IOREG_W_INTERNAL_09C INTERNAL_09C; // 0x480809C + IOREG_W_PADDING pad_09E; // 0x480809E + IOREG_W_TXBUF_LOCATION TXBUF_LOC1; // 0x48080A0 + IOREG_W_PADDING pad_0A2; // 0x48080A2 + IOREG_W_TXBUF_LOCATION TXBUF_LOC2; // 0x48080A4 + IOREG_W_PADDING pad_0A6; // 0x48080A6 + IOREG_W_TXBUF_LOCATION TXBUF_LOC3; // 0x48080A8 + IOREG_W_PADDING pad_0AA; // 0x48080AA + IOREG_W_TXREQ_RESET TXREQ_RESET; // 0x48080AC + IOREG_W_TXREQ_SET TXREQ_SET; // 0x48080AE + IOREG_W_TXREQ_READ TXREQ_READ; // 0x48080B0 + IOREG_W_PADDING pad_0B2; // 0x48080B2 + IOREG_W_TXBUF_RESET TXBUF_RESET; // 0x48080B4 + IOREG_W_TXBUSY TXBUSY; // 0x48080B6 + IOREG_W_TXSTAT TXSTAT; // 0x48080B8 + IOREG_W_INTERNAL_0BA INTERNAL_0BA; // 0x48080BA + IOREG_W_PREAMBLE PREAMBLE; // 0x48080BC + IOREG_W_PADDING pad_0BE; // 0x48080BE + IOREG_W_CMD_TOTALTIME CMD_TOTALTIME; // 0x48080C0 + IOREG_W_PADDING pad_0C2; // 0x48080C2 + IOREG_W_CMD_REPLYTIME CMD_REPLYTIME; // 0x48080C4 + IOREG_W_PADDING pad_0C6; // 0x48080C6 + IOREG_W_INTERNAL_0C8 INTERNAL_0C8; // 0x48080C8 + IOREG_W_PADDING pad_0CA; // 0x48080CA + IOREG_W_PADDING pad_0CC; // 0x48080CC + IOREG_W_PADDING pad_0CE; // 0x48080CE + IOREG_W_RXFILTER RXFILTER; // 0x48080D0 + IOREG_W_PADDING pad_0D2; // 0x48080D2 + IOREG_W_CONFIG_0D4 CONFIG_0D4; // 0x48080D4 + IOREG_W_PADDING pad_0D6; // 0x48080D6 + IOREG_W_CONFIG_0D8 CONFIG_0D8; // 0x48080D8 + IOREG_W_RX_LEN_CROP RX_LEN_CROP; // 0x48080DA + IOREG_W_PADDING pad_0DC; // 0x48080DC + IOREG_W_PADDING pad_0DE; // 0x48080DE + IOREG_W_RXFILTER2 RXFILTER2; // 0x48080E0 + IOREG_W_PADDING pad_0E2; // 0x48080E2 + IOREG_W_PADDING pad_0E4; // 0x48080E4 + IOREG_W_PADDING pad_0E6; // 0x48080E6 + + IOREG_W_US_COUNTCNT US_COUNTCNT; // 0x48080E8 + IOREG_W_US_COMPARECNT US_COMPARECNT; // 0x48080EA + IOREG_W_CONFIG_0EC CONFIG_0EC; // 0x48080EC + IOREG_W_CMD_COUNTCNT CMD_COUNTCNT; // 0x48080EE + + union + { + u64 US_COMPARE; // 0x48080F0 - 0x48080F7 + + struct + { + u16 US_COMPARE0; // 0x48080F0 + u16 US_COMPARE1; // 0x48080F2 + u16 US_COMPARE2; // 0x48080F4 + u16 US_COMPARE3; // 0x48080F6 + }; + + struct + { + u64 UNKNOWN1:1; + u64 :9; + u64 MS_Compare:54; + }; + }; + + union + { + u64 US_COUNT; // 0x48080F8 - 0x48080FF + + struct + { + u16 US_COUNT0; // 0x48080F8 + u16 US_COUNT1; // 0x48080FA + u16 US_COUNT2; // 0x48080FC + u16 US_COUNT3; // 0x48080FE + }; + }; + + IOREG_W_INTERNAL_100 INTERNAL_100; // 0x4808100 + IOREG_W_INTERNAL_102 INTERNAL_102; // 0x4808102 + IOREG_W_INTERNAL_104 INTERNAL_104; // 0x4808104 + IOREG_W_INTERNAL_106 INTERNAL_106; // 0x4808106 + IOREG_W_PADDING pad_108; // 0x4808108 + IOREG_W_PADDING pad_10A; // 0x480810A + IOREG_W_CONTENTFREE CONTENTFREE; // 0x480810C + IOREG_W_PADDING pad_10E; // 0x480810E + IOREG_W_PRE_BEACON PRE_BEACON; // 0x4808110 + IOREG_W_PADDING pad_112; // 0x4808112 + IOREG_W_PADDING pad_114; // 0x4808114 + IOREG_W_PADDING pad_116; // 0x4808116 + IOREG_W_CMD_COUNT CMD_COUNT; // 0x4808118 + IOREG_W_PADDING pad_11A; // 0x480811A + IOREG_W_BEACONCOUNT1 BEACONCOUNT1; // 0x480811C + IOREG_W_PADDING pad_11E; // 0x480811E + + IOREG_W_CONFIG_120 CONFIG_120; // 0x4808120 + IOREG_W_CONFIG_122 CONFIG_122; // 0x4808122 + IOREG_W_CONFIG_124 CONFIG_124; // 0x4808124 + IOREG_W_INTERNAL_126 INTERNAL_126; // 0x4808126 + IOREG_W_CONFIG_128 CONFIG_128; // 0x4808128 + IOREG_W_INTERNAL_12A INTERNAL_12A; // 0x480812A + IOREG_W_PADDING pad_12C; // 0x480812C + IOREG_W_PADDING pad_12E; // 0x480812E + IOREG_W_CONFIG_130 CONFIG_130; // 0x4808130 + IOREG_W_CONFIG_132 CONFIG_132; // 0x4808132 + IOREG_W_BEACONCOUNT2 BEACONCOUNT2; // 0x4808134 + IOREG_W_PADDING pad_136; // 0x4808136 + IOREG_W_PADDING pad_138; // 0x4808138 + IOREG_W_PADDING pad_13A; // 0x480813A + IOREG_W_PADDING pad_13C; // 0x480813C + IOREG_W_PADDING pad_13E; // 0x480813E + IOREG_W_CONFIG_140 CONFIG_140; // 0x4808140 + IOREG_W_CONFIG_142 CONFIG_142; // 0x4808142 + IOREG_W_CONFIG_144 CONFIG_144; // 0x4808144 + IOREG_W_CONFIG_146 CONFIG_146; // 0x4808146 + IOREG_W_CONFIG_148 CONFIG_148; // 0x4808148 + IOREG_W_CONFIG_14A CONFIG_14A; // 0x480814A + IOREG_W_CONFIG_14C CONFIG_14C; // 0x404814C + IOREG_W_PADDING pad_14E; // 0x480814E + IOREG_W_CONFIG_150 CONFIG_150; // 0x4808150 + IOREG_W_PADDING pad_152; // 0x4808152 + IOREG_W_CONFIG_154 CONFIG_154; // 0x4808154 + IOREG_W_PADDING pad_156; // 0x4808156 + + IOREG_W_BB_CNT BB_CNT; // 0x4808158 + IOREG_W_BB_WRITE BB_WRITE; // 0x480815A + IOREG_W_BB_READ BB_READ; // 0x480815C + IOREG_W_BB_BUSY BB_BUSY; // 0x480815E + IOREG_W_BB_MODE BB_MODE; // 0x4808160 + IOREG_W_PADDING pad_162; // 0x4808162 + IOREG_W_PADDING pad_164; // 0x4808164 + IOREG_W_PADDING pad_166; // 0x4808166 + IOREG_W_BB_POWER BB_POWER; // 0x4808168 + + IOREG_W_INTERNAL_16A INTERNAL_16A; // 0x480816A + IOREG_W_PADDING pad_16C; // 0x480816C + IOREG_W_PADDING pad_16E; // 0x480816E + IOREG_W_INTERNAL_170 INTERNAL_170; // 0x4808170 + IOREG_W_INTERNAL_172 INTERNAL_172; // 0x4808172 + IOREG_W_INTERNAL_174 INTERNAL_174; // 0x4808174 + IOREG_W_INTERNAL_176 INTERNAL_176; // 0x4808176 + IOREG_W_INTERNAL_178 INTERNAL_178; // 0x4808178 + IOREG_W_PADDING pad_17A; // 0x480817A + + IOREG_W_RF_DATA2 RF_DATA2; // 0x480817C + IOREG_W_RF_DATA1 RF_DATA1; // 0x480817E + IOREG_W_RF_BUSY RF_BUSY; // 0x4808180 + IOREG_W_PADDING pad_182; // 0x4808182 + IOREG_W_RF_CNT RF_CNT; // 0x4808184 + IOREG_W_PADDING pad_186; // 0x4808186 + IOREG_W_PADDING pad_188; // 0x4808188 + IOREG_W_PADDING pad_18A; // 0x480818A + IOREG_W_PADDING pad_18C; // 0x480818C + IOREG_W_PADDING pad_18E; // 0x480818E + + IOREG_W_INTERNAL_190 INTERNAL_190; // 0x4808190 + IOREG_W_PADDING pad_192; // 0x4808192 + IOREG_W_TX_HDR_CNT TX_HDR_CNT; // 0x4808194 + IOREG_W_PADDING pad_196; // 0x4808196 + IOREG_W_INTERNAL_198 INTERNAL_198; // 0x4808198 + IOREG_W_PADDING pad_19A; // 0x480819A + IOREG_W_RF_PINS RF_PINS; // 0x480819C + IOREG_W_PADDING pad_19E; // 0x480819E + IOREG_W_X_1A0 X_1A0; // 0x48081A0 + IOREG_W_X_1A2 X_1A2; // 0x48081A2 + IOREG_W_X_1A4 X_1A4; // 0x48081A4 + IOREG_W_PADDING pad_1A6; // 0x48081A6 + + IOREG_W_RXSTAT_INC_IF RXSTAT_INC_IF; // 0x48081A8 + IOREG_W_RXSTAT_INC_IE RXSTAT_INC_IE; // 0x48081AA + IOREG_W_RXSTAT_OVF_IF RXSTAT_OVF_IF; // 0x48081AC + IOREG_W_RXSTAT_OVF_IE RXSTAT_OVF_IE; // 0x48081AE + + IOREG_W_RXSTAT_COUNT RXSTAT_COUNT; // 0x48081B0 - 0x48081BF + + IOREG_W_TX_ERR_COUNT TX_ERR_COUNT; // 0x48081C0 + IOREG_W_PADDING pad_1C2; // 0x48081C2 + IOREG_W_RX_COUNT RX_COUNT; // 0x48081C4 + IOREG_W_PADDING pad_1C6; // 0x48081C6 + IOREG_W_PADDING pad_1C8; // 0x48081C8 + IOREG_W_PADDING pad_1CA; // 0x48081CA + IOREG_W_PADDING pad_1CC; // 0x48081CC + IOREG_W_PADDING pad_1CE; // 0x48081CE + + IOREG_W_CMD_STAT_COUNT CMD_STAT_COUNT; // 0x48081D0 - 0x48081DF + + IOREG_W_PADDING pad_1E0; // 0x48081E0 + IOREG_W_PADDING pad_1E2; // 0x48081E2 + IOREG_W_PADDING pad_1E4; // 0x48081E4 + IOREG_W_PADDING pad_1E6; // 0x48081E6 + IOREG_W_PADDING pad_1E8; // 0x48081E8 + IOREG_W_PADDING pad_1EA; // 0x48081EA + IOREG_W_PADDING pad_1EC; // 0x48081EC + IOREG_W_PADDING pad_1EE; // 0x48081EE + IOREG_W_INTERNAL_1F0 INTERNAL_1F0; // 0x48081F0 + IOREG_W_PADDING pad_1F2; // 0x48081F2 + IOREG_W_PADDING pad_1F4; // 0x48081F4 + IOREG_W_PADDING pad_1F6; // 0x48081F6 + IOREG_W_PADDING pad_1F8; // 0x48081F8 + IOREG_W_PADDING pad_1FA; // 0x48081FA + IOREG_W_PADDING pad_1FC; // 0x48081FC + IOREG_W_PADDING pad_1FE; // 0x48081FE + IOREG_W_PADDING pad_200; // 0x4808200 + IOREG_W_PADDING pad_202; // 0x4808202 + IOREG_W_INTERNAL_204 INTERNAL_204; // 0x4808204 + IOREG_W_PADDING pad_206; // 0x4808206 + IOREG_W_INTERNAL_208 INTERNAL_208; // 0x4808208 + IOREG_W_PADDING pad_20A; // 0x480820A + IOREG_W_INTERNAL_20C INTERNAL_20C; // 0x480820C + IOREG_W_PADDING pad_20E; // 0x480820E + IOREG_W_TX_SEQNO TX_SEQNO; // 0x4808210 + IOREG_W_PADDING pad_212; // 0x4808212 + IOREG_W_RF_STATUS RF_STATUS; // 0x4808214 + IOREG_W_PADDING pad_216; // 0x4808216 + IOREG_W_PADDING pad_218; // 0x4808218 + IOREG_W_PADDING pad_21A; // 0x480821A + IOREG_W_IF_SET IF_SET; // 0x480821C + IOREG_W_PADDING pad_21E; // 0x480821E + IOREG_W_INTERNAL_220 INTERNAL_220; // 0x4808220 + IOREG_W_PADDING pad_222; // 0x4808222 + IOREG_W_INTERNAL_224 INTERNAL_224; // 0x4808224 + IOREG_W_PADDING pad_226; // 0x4808226 + IOREG_W_X_228 X_228; // 0x4808228 + IOREG_W_PADDING pad_22A; // 0x480822A + IOREG_W_PADDING pad_22C; // 0x480822C + IOREG_W_PADDING pad_22E; // 0x480822E + IOREG_W_INTERNAL_230 INTERNAL_230; // 0x4808230 + IOREG_W_PADDING pad_232; // 0x4808232 + IOREG_W_INTERNAL_234 INTERNAL_234; // 0x4808234 + IOREG_W_PADDING pad_236; // 0x4808236 + IOREG_W_INTERNAL_238 INTERNAL_238; // 0x4808238 + IOREG_W_PADDING pad_23A; // 0x480823A + IOREG_W_INTERNAL_23C INTERNAL_23C; // 0x480823C + IOREG_W_PADDING pad_23E; // 0x480823E + IOREG_W_PADDING pad_240; // 0x4808240 + IOREG_W_PADDING pad_242; // 0x4808242 + IOREG_W_X_244 X_244; // 0x4808244 + IOREG_W_PADDING pad_246; // 0x4808246 + IOREG_W_INTERNAL_248 INTERNAL_248; // 0x4808248 + IOREG_W_PADDING pad_24A; // 0x480824A + IOREG_W_INTERNAL_24C INTERNAL_24C; // 0x480824C + IOREG_W_INTERNAL_24E INTERNAL_24E; // 0x480824E + IOREG_W_INTERNAL_250 INTERNAL_250; // 0x4808250 + IOREG_W_PADDING pad_252; // 0x4808252 + IOREG_W_CONFIG_254 CONFIG_254; // 0x4808254 + IOREG_W_PADDING pad_256; // 0x4808256 + IOREG_W_INTERNAL_258 INTERNAL_258; // 0x4808258 + IOREG_W_PADDING pad_25A; // 0x480825A + IOREG_W_INTERNAL_25C INTERNAL_25C; // 0x480825C + IOREG_W_PADDING pad_25E; // 0x480825E + IOREG_W_INTERNAL_260 INTERNAL_260; // 0x4808260 + IOREG_W_PADDING pad_262; // 0x4808262 + IOREG_W_INTERNAL_264 INTERNAL_264; // 0x4808264 + IOREG_W_PADDING pad_266; // 0x4808266 + IOREG_W_RXTX_ADDR RXTX_ADDR; // 0x4808268 + IOREG_W_PADDING pad_26A; // 0x480826A + IOREG_W_PADDING pad_26C; // 0x480826C + IOREG_W_PADDING pad_26E; // 0x480826E + IOREG_W_INTERNAL_270 INTERNAL_270; // 0x4808270 + IOREG_W_PADDING pad_272; // 0x4808272 + IOREG_W_INTERNAL_274 INTERNAL_274; // 0x4808274 + IOREG_W_PADDING pad_276; // 0x4808276 + IOREG_W_INTERNAL_278 INTERNAL_278; // 0x4808278 + IOREG_W_PADDING pad_27A; // 0x480827A + IOREG_W_INTERNAL_27C INTERNAL_27C; // 0x480827C + IOREG_W_PADDING pad_27E; // 0x480827E + IOREG_W_PADDING pad_280; // 0x4808280 + IOREG_W_PADDING pad_282; // 0x4808282 + IOREG_W_PADDING pad_284; // 0x4808284 + IOREG_W_PADDING pad_286; // 0x4808286 + IOREG_W_PADDING pad_288; // 0x4808288 + IOREG_W_PADDING pad_28A; // 0x480828A + IOREG_W_PADDING pad_28C; // 0x480828C + IOREG_W_PADDING pad_28E; // 0x480828E + IOREG_W_X_290 X_290; // 0x4808290 + IOREG_W_PADDING pad_292; // 0x4808292 + IOREG_W_PADDING pad_294; // 0x4808294 + IOREG_W_PADDING pad_296; // 0x4808296 + IOREG_W_INTERNAL_298 INTERNAL_298; // 0x4808298 + IOREG_W_PADDING pad_29A; // 0x480829A + IOREG_W_PADDING pad_29C; // 0x480829C + IOREG_W_PADDING pad_29E; // 0x480829E + IOREG_W_INTERNAL_2A0 INTERNAL_2A0; // 0x48082A0 + IOREG_W_INTERNAL_2A2 INTERNAL_2A2; // 0x48082A2 + IOREG_W_INTERNAL_2A4 INTERNAL_2A4; // 0x48082A4 + IOREG_W_PADDING pad_2A6; // 0x48082A6 + IOREG_W_INTERNAL_2A8 INTERNAL_2A8; // 0x48082A8 + IOREG_W_PADDING pad_2AA; // 0x48082AA + IOREG_W_INTERNAL_2AC INTERNAL_2AC; // 0x48082AC + IOREG_W_PADDING pad_2AE; // 0x48082AE + IOREG_W_INTERNAL_2B0 INTERNAL_2B0; // 0x48082B0 + IOREG_W_PADDING pad_2B2; // 0x48082B2 + IOREG_W_INTERNAL_2B4 INTERNAL_2B4; // 0x48082B4 + IOREG_W_PADDING pad_2B6; // 0x48082B6 + IOREG_W_INTERNAL_2B8 INTERNAL_2B8; // 0x48082B8 + IOREG_W_PADDING pad_2BA; // 0x48082BA + IOREG_W_PADDING pad_2BC; // 0x48082BC + IOREG_W_PADDING pad_2BE; // 0x48082BE + IOREG_W_INTERNAL_2C0 INTERNAL_2C0; // 0x48082C0 + IOREG_W_PADDING pad_2C2; // 0x48082C2 + IOREG_W_INTERNAL_2C4 INTERNAL_2C4; // 0x48082C4 + IOREG_W_PADDING pad_2C6; // 0x48082C6 + IOREG_W_INTERNAL_2C8 INTERNAL_2C8; // 0x48082C8 + IOREG_W_PADDING pad_2CA; // 0x48082CA + IOREG_W_INTERNAL_2CC INTERNAL_2CC; // 0x48082CC + IOREG_W_PADDING pad_2CE; // 0x48082CE + IOREG_W_POWERACK POWERACK; // 0x48082D0 + IOREG_W_PADDING pad_2D2; // 0x48082D2 + IOREG_W_PADDING pad_2D4; // 0x48082D4 + IOREG_W_PADDING pad_2D6; // 0x48082D6 + IOREG_W_PADDING pad_2D8; // 0x48082D8 + IOREG_W_PADDING pad_2DA; // 0x48082DA + IOREG_W_PADDING pad_2DC; // 0x48082DC + IOREG_W_PADDING pad_2DE; // 0x48082DE + IOREG_W_PADDING pad_2E0; // 0x48082E0 + IOREG_W_PADDING pad_2E2; // 0x48082E2 + IOREG_W_PADDING pad_2E4; // 0x48082E4 + IOREG_W_PADDING pad_2E6; // 0x48082E6 + IOREG_W_PADDING pad_2E8; // 0x48082E8 + IOREG_W_PADDING pad_2EA; // 0x48082EA + IOREG_W_PADDING pad_2EC; // 0x48082EC + IOREG_W_PADDING pad_2EE; // 0x48082EE + IOREG_W_INTERNAL_2F0 INTERNAL_2F0; // 0x48082F0 + IOREG_W_INTERNAL_2F2 INTERNAL_2F2; // 0x48082F2 + IOREG_W_INTERNAL_2F4 INTERNAL_2F4; // 0x48082F4 + IOREG_W_INTERNAL_2F6 INTERNAL_2F6; // 0x48082F6 +} WIFI_IOREG_MAP; +#include "PACKED_END.h" - /* timing */ - bool crystalEnabled; - u64 usec; - bool usecEnable; - u64 ucmp; - bool ucmpEnable; - u32 eCount; - bool eCountEnable; - u16 BeaconInterval; - u16 BeaconCount1; - u16 BeaconCount2; - u16 ListenInterval; - u16 ListenCount; +typedef struct +{ + size_t bodyLen; + size_t remainingBytes; +} TXPacketInfo; - /* subchips */ - rffilter_t RF; - bb_t BB; +typedef struct +{ + WIFI_IOREG_MAP io; + RF2958_IOREG_MAP rf; + bb_t bb; + u16 RAM[0x1000]; + + WifiTXLocIndex txCurrentSlot; + TXPacketInfo txPacketInfo[5]; + u32 cmdCount_u32; +} WifiData; - /* subchip communications */ - rfIOCnt_t rfIOCnt; - rfIOStat_t rfIOStatus; - rfIOData_t rfIOData; - bbIOCnt_t bbIOCnt; - - /* buffers */ - u16 RAM[0x1000]; - u16 RXRangeBegin; - u16 RXRangeEnd; - u16 RXWriteCursor; - u16 RXReadCursor; - u16 RXUnits; - u16 RXBufCount; - u16 CircBufReadAddress; - u16 CircBufWriteAddress; - u16 CircBufRdEnd; - u16 CircBufRdSkip; - u16 CircBufWrEnd; - u16 CircBufWrSkip; - - /* tx packets */ - s32 curPacketSize[3]; - s32 curPacketPos[3]; - bool curPacketSending[3]; - - /* I/O ports */ - u16 IOPorts[0x800]; - - /* others */ - u16 randomSeed; - -} wifimac_t; - -extern wifimac_t wifiMac; - -/* subchip communication IO functions */ -void WIFI_setRF_CNT(u16 val); -void WIFI_setRF_DATA(u16 val, u8 part); -u16 WIFI_getRF_DATA(u8 part); -u16 WIFI_getRF_STATUS(); - -void WIFI_setBB_CNT(u16 val); -u8 WIFI_getBB_DATA(); -void WIFI_setBB_DATA(u8 val); +extern LegacyWifiSFormat legacyWifiSF; /* wifimac io */ void WIFI_write16(u32 address, u16 val); @@ -728,6 +2928,8 @@ public: class WifiHandler { protected: + WifiData _wifi; + AdhocCommInterface *_adhocCommInterface; SoftAPCommInterface *_softAPCommInterface; @@ -756,6 +2958,10 @@ public: void Reset(); + WifiData& GetWifiData(); + + TXPacketInfo& GetPacketInfoAtSlot(size_t txSlot); + WifiEmulationLevel GetSelectedEmulationLevel(); WifiEmulationLevel GetCurrentEmulationLevel(); void SetEmulationLevel(WifiEmulationLevel emulationLevel); @@ -796,6 +3002,9 @@ public: void GenerateMACFromValues(u8 outMAC[6]); void CopyMACFromUserValues(u8 outMAC[6]); + + void PrepareSaveStateWrite(); + void ParseSaveStateRead(); }; /* wifi data to be stored in firmware, when no firmware image was loaded */