From 0a909c831dca8f490f45c33e472f0e5fb477e858 Mon Sep 17 00:00:00 2001 From: MightyMax Date: Thu, 1 Jan 2009 17:54:16 +0000 Subject: [PATCH] more WIFI registers implemented, some fixed to match behavior on hardware --- desmume/src/wifi.cpp | 1042 +++++++++++++++++++++++------------------- desmume/src/wifi.h | 789 ++++++++++++++++---------------- 2 files changed, 976 insertions(+), 855 deletions(-) diff --git a/desmume/src/wifi.cpp b/desmume/src/wifi.cpp index bca3ee391..e3090284e 100644 --- a/desmume/src/wifi.cpp +++ b/desmume/src/wifi.cpp @@ -192,476 +192,578 @@ FW_WFCProfile FW_WFCProfile3 = {"", #ifdef EXPERIMENTAL_WIFI -/******************************************************************************* - - RF-Chip - - *******************************************************************************/ - -void WIFI_resetRF(rffilter_t *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 ; - /* 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 ; - /* IFPLL2 */ - rf->IFPLL2.bits.IF_N = 0x22 ; - /* IFPLL3 */ - rf->IFPLL3.bits.KV_DEF1 = 8 ; - rf->IFPLL3.bits.CT_DEF1 = 7 ; - rf->IFPLL3.bits.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 ; - /* RFPLL2 */ - rf->RFPLL2.bits.NUM2 = 0 ; - rf->RFPLL2.bits.N2 = 0x5E ; - /* RFPLL3 */ - rf->RFPLL3.bits.NUM2 = 0 ; - /* RFPLL4 */ - rf->RFPLL4.bits.KV_DEF = 8 ; - rf->RFPLL4.bits.CT_DEF = 7 ; - rf->RFPLL4.bits.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 ; - /* 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 ; - /* 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 ; - /* PCNT2 */ - rf->PCNT2.bits.MIN_POWER = 0 ; - rf->PCNT2.bits.MID_POWER = 0 ; - rf->PCNT2.bits.MAX_POWER = 0 ; - /* VCOT1 */ - rf->VCOT1.bits.AUX1 = 0 ; - rf->VCOT1.bits.AUX = 0 ; -} ; - - -void WIFI_setRF_CNT(wifimac_t *wifi, u16 val) -{ - if (!wifi->rfIOStatus.bits.busy) - wifi->rfIOCnt.val = val ; -} - -void WIFI_setRF_DATA(wifimac_t *wifi, u16 val, u8 part) -{ - if (!wifi->rfIOStatus.bits.busy) - { - rfIOData_t *rfreg = (rfIOData_t *)&wifi->RF; - switch (wifi->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) - { - wifi->rfIOData.array16[part] = val ; - if (wifi->rfIOData.bits.address > (sizeof(wifi->RF) / 4)) return ; /* out of bound */ - /* get content of the addressed register */ - wifi->rfIOData.bits.content = rfreg[wifi->rfIOData.bits.address].bits.content ; - } - break ; - case 0: /* write to RF chip */ - wifi->rfIOData.array16[part] = val ; - if (wifi->rfIOData.bits.address > (sizeof(wifi->RF) / 4)) return ; /* out of bound */ - /* the actual transfer is done on high part write */ - if (part==1) - { - switch (wifi->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[wifi->rfIOData.bits.address].bits.content = wifi->rfIOData.bits.content ; - /* get the complete rfpll.n */ - channelFreqN = (u32)wifi->RF.RFPLL3.bits.NUM2 + ((u32)wifi->RF.RFPLL2.bits.NUM2) << 18 + ((u32)wifi->RF.RFPLL2.bits.N2) << 24 ; - /* frequency setting is out of range */ - if (channelFreqN<0x00A2E8BA) return ; - /* substract base frequency (channel 1) */ - channelFreqN -= 0x00A2E8BA ; - /* every channel is now ~3813000 steps further */ - WIFI_Host_CloseChannel(wifi->udpSocket) ; - wifi->channel = (wifi->udpSocket,channelFreqN / 3813000)+1 ; - WIFI_Host_OpenChannel(wifi->channel) ; - } - return ; - case 13: - /* special purpose register: TEST1, on write, the RF chip resets */ - WIFI_resetRF(&wifi->RF) ; - return ; - } - /* set content of the addressed register */ - rfreg[wifi->rfIOData.bits.address].bits.content = wifi->rfIOData.bits.content ; - } - break ; - } - } -} - -u16 WIFI_getRF_DATA(wifimac_t *wifi, u8 part) -{ - if (!wifi->rfIOStatus.bits.busy) - { - return wifi->rfIOData.array16[part] ; - } else - { /* data is not (yet) available */ - return 0 ; - } - } - -u16 WIFI_getRF_STATUS(wifimac_t *wifi) -{ - return wifi->rfIOStatus.val ; -} - -/******************************************************************************* - - BB-Chip - - *******************************************************************************/ - -void WIFI_setBB_CNT(wifimac_t *wifi,u16 val) -{ - wifi->bbIOCnt.val = val ; -} - -u8 WIFI_getBB_DATA(wifimac_t *wifi) -{ - if ((wifi->bbIOCnt.bits.mode != 2) || !(wifi->bbIOCnt.bits.enable)) return 0 ; /* not for read or disabled */ - return wifi->BB.data[wifi->bbIOCnt.bits.address] ; -} - -void WIFI_setBB_DATA(wifimac_t *wifi, u8 val) -{ - if ((wifi->bbIOCnt.bits.mode != 1) || !(wifi->bbIOCnt.bits.enable)) return ; /* not for write or disabled */ - wifi->BB.data[wifi->bbIOCnt.bits.address] = val ; -} - -/******************************************************************************* - - wifimac IO: a lot of the wifi regs are action registers, that are mirrored - without action, so the default IO via MMU.c does not seem to - be very suitable - - all registers are 16 bit - - *******************************************************************************/ - -void WIFI_triggerIRQ(wifimac_t *wifi, u8 irq) -{ - /* trigger an irq */ - u16 irqBit = 1 << irq ; - if (wifi->IE.val & irqBit) - { - wifi->IF.val |= irqBit ; - NDS_makeARM7Int(24) ; /* cascade it via arm7 wifi irq */ - } -} - -void WIFI_Init(wifimac_t *wifi) -{ - WIFI_resetRF(&wifi->RF) ; - WIFI_Host_InitSystem() ; - wifi->udpSocket = WIFI_Host_OpenChannel(1) ; -} - -void WIFI_RXPutWord(wifimac_t *wifi,u16 val) -{ - /* abort when RX data queuing is not enabled */ - if (!(wifi->RXCnt & 0x8000)) return ; - /* abort when ringbuffer is full */ - if (wifi->RXReadCursor == wifi->RXHWWriteCursor) return ; - /* write the data to cursor position */ - wifi->circularBuffer[wifi->RXHWWriteCursor & 0xFFF] ; - /* move cursor by one */ - wifi->RXHWWriteCursor++ ; - /* wrap around */ - wifi->RXHWWriteCursor %= (wifi->RXRangeEnd - wifi->RXRangeBegin) >> 1 ; -} - -void WIFI_TXStart(wifimac_t *wifi,u8 slot) -{ - if (wifi->TXSlot[slot] & 0x8000) /* is slot enabled? */ - { - u16 txLen ; - /* the address has to be somewhere in the circular buffer, so drop the other bits */ - u16 address = (wifi->TXSlot[slot] & 0x7FFF) ; - /* 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 = ntohs(wifi->circularBuffer[address+5]) ; - /* zero length */ - if (txLen==0) return ; - /* unsupported txRate */ - switch (ntohs(wifi->circularBuffer[address+4])) - { - case 10: /* 1 mbit */ - case 20: /* 2 mbit */ - break ; - default: /* other rates */ - return ; - } - - /* FIXME: calculate FCS */ - - WIFI_triggerIRQ(wifi,WIFI_IRQ_SENDSTART) ; - WIFI_Host_SendData(wifi->udpSocket,wifi->channel,(u8 *)&wifi->circularBuffer[address],txLen) ; - WIFI_triggerIRQ(wifi,WIFI_IRQ_SENDCOMPLETE) ; - } -} - -void WIFI_write16(wifimac_t *wifi,u32 address, u16 val) -{ - BOOL action = FALSE ; - if ((address & 0xFF800000) != 0x04800000) return ; /* error: the address does not describe a wiifi register */ - - /* the first 0x1000 bytes are mirrored at +0x1000,+0x2000,+0x3000,+06000,+0x7000 */ - /* only the first mirror causes an special action */ - /* the gap at +0x4000 is filled with the circular bufferspace */ - /* the so created 0x8000 byte block is then mirrored till 0x04FFFFFF */ - /* see: http://www.akkit.org/info/dswifi.htm#Wifihwcap */ - if (((address & 0x00007000) >= 0x00004000) && ((address & 0x00007000) < 0x00006000)) - { - /* access to the circular buffer */ - address &= 0x1FFFF ; - wifi->circularBuffer[address >> 1] = val ; - return ; - } - if (!(address & 0x00007000)) action = TRUE ; - /* mirrors => register address */ - address &= 0x00000FFF ; - switch (address) - { - case REG_WIFI_MODE: - wifi->macMode = val ; - break ; - case REG_WIFI_WEP: - wifi->wepMode = val ; - break ; - case REG_WIFI_IE: - wifi->IE.val = val ; - break ; - case REG_WIFI_IF: - wifi->IF.val &= ~val ; /* clear flagging bits */ - break ; - case REG_WIFI_MAC0: - case REG_WIFI_MAC1: - case REG_WIFI_MAC2: - wifi->mac.words[(address - REG_WIFI_MAC0) >> 1] = val ; - break ; - case REG_WIFI_BSS0: - case REG_WIFI_BSS1: - case REG_WIFI_BSS2: - wifi->bss.words[(address - REG_WIFI_BSS0) >> 1] = val ; - break ; - case REG_WIFI_AID: /* CHECKME: are those two really the same? */ - case REG_WIFI_AIDCPY: - wifi->aid = val ; - break ; - case REG_WIFI_RETRYLIMIT: - wifi->retryLimit = val ; - break ; - case REG_WIFI_WEPCNT: - wifi->WEP_enable = (val & 0x8000) != 0 ; - break ; - case REG_WIFI_RXRANGEBEGIN: - wifi->RXRangeBegin = val ; - break ; - case REG_WIFI_RXRANGEEND: - wifi->RXRangeEnd = val ; - break ; - case REG_WIFI_WRITECSRLATCH: - if ((action) && (wifi->RXCnt & 1)) /* only when action register and CSR change enabled */ - { - wifi->RXHWWriteCursor = val ; - } - break ; - case REG_WIFI_CIRCBUFRADR: - wifi->CircBufReadAddress = val ; - break ; - case REG_WIFI_RXREADCSR: - wifi->RXReadCursor = val ; - break ; - case REG_WIFI_CIRCBUFWADR: - wifi->CircBufWriteAddress = val ; - break ; - case REG_WIFI_CIRCBUFWRITE: - /* set value into the circ buffer, and move cursor to the next hword on action */ - wifi->circularBuffer[(wifi->CircBufWriteAddress >> 1) & 0xFFF] = val ; - if (action) - { - /* move to next hword */ - wifi->CircBufWriteAddress+=2 ; - if (wifi->CircBufWriteAddress == wifi->CircBufEnd) - { - /* on end of buffer, add skip hwords to it */ - wifi->CircBufEnd += wifi->CircBufSkip * 2 ; - } - } - break ; - case REG_WIFI_CIRCBUFWR_SKIP: - wifi->CircBufSkip = val ; - break ; - case REG_WIFI_BEACONTRANS: - wifi->BEACONSlot = val & 0x7FFF ; - wifi->BEACON_enable = (val & 0x8000) != 0 ; - break ; - case REG_WIFI_TXLOC1: - case REG_WIFI_TXLOC2: - case REG_WIFI_TXLOC3: - wifi->TXSlot[(address - REG_WIFI_TXLOC1) >> 2] = val ; - break ; - case REG_WIFI_TXOPT: - if (val == 0xFFFF) - { - /* reset TX logic */ - /* CHECKME */ - wifi->TXSlot[0] = 0 ; wifi->TXSlot[1] = 0 ; wifi->TXSlot[2] = 0 ; - wifi->TXOpt = 0 ; - wifi->TXCnt = 0 ; - } else - { - wifi->TXOpt = val ; - } - break ; - case REG_WIFI_TXCNT: - wifi->TXCnt = val ; - if (val & 0x01) WIFI_TXStart(wifi,0) ; - if (val & 0x04) WIFI_TXStart(wifi,1) ; - if (val & 0x08) WIFI_TXStart(wifi,2) ; - break ; - case REG_WIFI_RFIOCNT: - WIFI_setRF_CNT(wifi,val) ; - break ; - case REG_WIFI_RFIOBSY: - /* CHECKME: read only? */ - break ; - case REG_WIFI_RFIODATA1: - WIFI_setRF_DATA(wifi,val,0) ; - break ; - case REG_WIFI_RFIODATA2: - WIFI_setRF_DATA(wifi,val,1) ; - break ; - case REG_WIFI_USCOUNTERCNT: - wifi->usecEnable = (val & 1)==1 ; - break ; - case REG_WIFI_USCOMPARECNT: - wifi->ucmpEnable = (val & 1)==1 ; - break ; - case REG_WIFI_BBSIOCNT: - WIFI_setBB_CNT(wifi,val) ; - break ; - case REG_WIFI_BBSIOWRITE: - WIFI_setBB_DATA(wifi,val) ; - break ; - default: - val = 0 ; /* not handled yet */ - break ; - } -} - -u16 WIFI_read16(wifimac_t *wifi,u32 address) -{ - BOOL action = FALSE ; - if ((address & 0xFF800000) != 0x04800000) return 0 ; /* error: the address does not describe a wiifi register */ - - /* the first 0x1000 bytes are mirrored at +0x1000,+0x2000,+0x3000,+06000,+0x7000 */ - /* only the first mirror causes an special action */ - /* the gap at +0x4000 is filled with the circular bufferspace */ - /* the so created 0x8000 byte block is then mirrored till 0x04FFFFFF */ - /* see: http://www.akkit.org/info/dswifi.htm#Wifihwcap */ - if (((address & 0x00007000) >= 0x00004000) && ((address & 0x00007000) < 0x00006000)) - { - /* access to the circular buffer */ - return wifi->circularBuffer[(address & 0x1FFF) >> 1] ; - } - if (!(address & 0x00007000)) action = TRUE ; - /* mirrors => register address */ - address &= 0x00000FFF ; - switch (address) - { - case REG_WIFI_MODE: - return wifi->macMode ; - case REG_WIFI_WEP: - return wifi->wepMode ; - case REG_WIFI_IE: - return wifi->IE.val ; - case REG_WIFI_IF: - return wifi->IF.val ; - case REG_WIFI_RFIODATA1: - return WIFI_getRF_DATA(wifi,0) ; - case REG_WIFI_RFIODATA2: - return WIFI_getRF_DATA(wifi,1) ; - case REG_WIFI_RFIOBSY: - case REG_WIFI_BBSIOBUSY: - return 0 ; /* we are never busy :p */ - case REG_WIFI_BBSIOREAD: - return WIFI_getBB_DATA(wifi) ; - case REG_WIFI_RANDOM: - /* FIXME: random generator */ - return 0 ; - case REG_WIFI_MAC0: - case REG_WIFI_MAC1: - case REG_WIFI_MAC2: - return wifi->mac.words[(address - REG_WIFI_MAC0) >> 1] ; - case REG_WIFI_BSS0: - case REG_WIFI_BSS1: - case REG_WIFI_BSS2: - return wifi->bss.words[(address - REG_WIFI_BSS0) >> 1] ; - default: - return 0 ; - } -} - - -void WIFI_usTrigger(wifimac_t *wifi) -{ - u8 dataBuffer[0x2000] ; - u16 rcvSize ; - /* a usec (=3F03 cycles) has passed */ - if (wifi->usecEnable) - wifi->usec++ ; - if ((wifi->ucmpEnable) && (wifi->ucmp == wifi->usec)) - { - WIFI_triggerIRQ(wifi,WIFI_IRQ_TIMEBEACON) ; +/******************************************************************************* + + RF-Chip + + *******************************************************************************/ + +void WIFI_resetRF(rffilter_t *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 ; + /* 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 ; + /* IFPLL2 */ + rf->IFPLL2.bits.IF_N = 0x22 ; + /* IFPLL3 */ + rf->IFPLL3.bits.KV_DEF1 = 8 ; + rf->IFPLL3.bits.CT_DEF1 = 7 ; + rf->IFPLL3.bits.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 ; + /* RFPLL2 */ + rf->RFPLL2.bits.NUM2 = 0 ; + rf->RFPLL2.bits.N2 = 0x5E ; + /* RFPLL3 */ + rf->RFPLL3.bits.NUM2 = 0 ; + /* RFPLL4 */ + rf->RFPLL4.bits.KV_DEF = 8 ; + rf->RFPLL4.bits.CT_DEF = 7 ; + rf->RFPLL4.bits.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 ; + /* 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 ; + /* 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 ; + /* PCNT2 */ + rf->PCNT2.bits.MIN_POWER = 0 ; + rf->PCNT2.bits.MID_POWER = 0 ; + rf->PCNT2.bits.MAX_POWER = 0 ; + /* VCOT1 */ + rf->VCOT1.bits.AUX1 = 0 ; + rf->VCOT1.bits.AUX = 0 ; +} ; + + +void WIFI_setRF_CNT(wifimac_t *wifi, u16 val) +{ + if (!wifi->rfIOStatus.bits.busy) + wifi->rfIOCnt.val = val ; +} + +void WIFI_setRF_DATA(wifimac_t *wifi, u16 val, u8 part) +{ + if (!wifi->rfIOStatus.bits.busy) + { + rfIOData_t *rfreg = (rfIOData_t *)&wifi->RF; + switch (wifi->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) + { + wifi->rfIOData.array16[part] = val ; + if (wifi->rfIOData.bits.address > (sizeof(wifi->RF) / 4)) return ; /* out of bound */ + /* get content of the addressed register */ + wifi->rfIOData.bits.content = rfreg[wifi->rfIOData.bits.address].bits.content ; + } + break ; + case 0: /* write to RF chip */ + wifi->rfIOData.array16[part] = val ; + if (wifi->rfIOData.bits.address > (sizeof(wifi->RF) / 4)) return ; /* out of bound */ + /* the actual transfer is done on high part write */ + if (part==1) + { + switch (wifi->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[wifi->rfIOData.bits.address].bits.content = wifi->rfIOData.bits.content ; + /* get the complete rfpll.n */ + channelFreqN = (u32)wifi->RF.RFPLL3.bits.NUM2 + ((u32)wifi->RF.RFPLL2.bits.NUM2) << 18 + ((u32)wifi->RF.RFPLL2.bits.N2) << 24 ; + /* frequency setting is out of range */ + if (channelFreqN<0x00A2E8BA) return ; + /* substract base frequency (channel 1) */ + channelFreqN -= 0x00A2E8BA ; + /* every channel is now ~3813000 steps further */ + WIFI_Host_CloseChannel(wifi->udpSocket) ; + wifi->channel = (wifi->udpSocket,channelFreqN / 3813000)+1 ; + WIFI_Host_OpenChannel(wifi->channel) ; + } + return ; + case 13: + /* special purpose register: TEST1, on write, the RF chip resets */ + WIFI_resetRF(&wifi->RF) ; + return ; + } + /* set content of the addressed register */ + rfreg[wifi->rfIOData.bits.address].bits.content = wifi->rfIOData.bits.content ; + } + break ; + } + } +} + +u16 WIFI_getRF_DATA(wifimac_t *wifi, u8 part) +{ + if (!wifi->rfIOStatus.bits.busy) + { + return wifi->rfIOData.array16[part] ; + } else + { /* data is not (yet) available */ + return 0 ; + } + } + +u16 WIFI_getRF_STATUS(wifimac_t *wifi) +{ + return wifi->rfIOStatus.val ; +} + +/******************************************************************************* + + BB-Chip + + *******************************************************************************/ + +void WIFI_setBB_CNT(wifimac_t *wifi,u16 val) +{ + wifi->bbIOCnt.val = val ; +} + +u8 WIFI_getBB_DATA(wifimac_t *wifi) +{ + if ((wifi->bbIOCnt.bits.mode != 2) || !(wifi->bbIOCnt.bits.enable)) return 0 ; /* not for read or disabled */ + return wifi->BB.data[wifi->bbIOCnt.bits.address] ; +} + +void WIFI_setBB_DATA(wifimac_t *wifi, u8 val) +{ + if ((wifi->bbIOCnt.bits.mode != 1) || !(wifi->bbIOCnt.bits.enable)) return ; /* not for write or disabled */ + wifi->BB.data[wifi->bbIOCnt.bits.address] = val ; +} + +/******************************************************************************* + + wifimac IO: a lot of the wifi regs are action registers, that are mirrored + without action, so the default IO via MMU.c does not seem to + be very suitable + + all registers are 16 bit + + *******************************************************************************/ + +void WIFI_triggerIRQMask(wifimac_t *wifi, u16 mask) +{ + u16 oResult,nResult ; + oResult = wifi->IE.val & wifi->IF.val ; + wifi->IF.val = wifi->IF.val | (mask & ~0x0400) ; + nResult = wifi->IE.val & wifi->IF.val ; + if (!oResult && nResult) + { + NDS_makeARM7Int(24) ; /* cascade it via arm7 wifi irq */ + } +} + +void WIFI_triggerIRQ(wifimac_t *wifi, u8 irq) +{ + WIFI_triggerIRQMask(wifi,1<RF) ; + WIFI_Host_InitSystem() ; + wifi->udpSocket = WIFI_Host_OpenChannel(1) ; +} + +void WIFI_RXPutWord(wifimac_t *wifi,u16 val) +{ + /* abort when RX data queuing is not enabled */ + if (!(wifi->RXCnt & 0x8000)) return ; + /* abort when ringbuffer is full */ + if (wifi->RXReadCursor == wifi->RXHWWriteCursor) return ; + /* write the data to cursor position */ + wifi->circularBuffer[wifi->RXHWWriteCursor & 0xFFF] ; + /* move cursor by one */ + wifi->RXHWWriteCursor++ ; + /* wrap around */ + wifi->RXHWWriteCursor %= (wifi->RXRangeEnd - wifi->RXRangeBegin) >> 1 ; +} + +void WIFI_TXStart(wifimac_t *wifi,u8 slot) +{ + if (wifi->TXSlot[slot] & 0x8000) /* is slot enabled? */ + { + u16 txLen ; + /* the address has to be somewhere in the circular buffer, so drop the other bits */ + u16 address = (wifi->TXSlot[slot] & 0x7FFF) ; + /* 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 = ntohs(wifi->circularBuffer[address+5]) ; + /* zero length */ + if (txLen==0) return ; + /* unsupported txRate */ + switch (ntohs(wifi->circularBuffer[address+4])) + { + case 10: /* 1 mbit */ + case 20: /* 2 mbit */ + break ; + default: /* other rates */ + return ; + } + + /* FIXME: calculate FCS */ + + WIFI_triggerIRQ(wifi,WIFI_IRQ_SENDSTART) ; + WIFI_Host_SendData(wifi->udpSocket,wifi->channel,(u8 *)&wifi->circularBuffer[address],txLen) ; + WIFI_triggerIRQ(wifi,WIFI_IRQ_SENDCOMPLETE) ; + } +} + +void WIFI_write16(wifimac_t *wifi,u32 address, u16 val) +{ + BOOL action = FALSE ; + if (!(MMU_read32(ARMCPU_ARM7,REG_PWRCNT) & 0x0002)) return ; /* access to wifi hardware was disabled */ + if ((address & 0xFF800000) != 0x04800000) return ; /* error: the address does not describe a wiifi register */ + + /* the first 0x1000 bytes are mirrored at +0x1000,+0x2000,+0x3000,+06000,+0x7000 */ + /* only the first mirror causes an special action */ + /* the gap at +0x4000 is filled with the circular bufferspace */ + /* the so created 0x8000 byte block is then mirrored till 0x04FFFFFF */ + /* see: http://www.akkit.org/info/dswifi.htm#Wifihwcap */ + if (((address & 0x00007000) >= 0x00004000) && ((address & 0x00007000) < 0x00006000)) + { + /* access to the circular buffer */ + address &= 0x1FFF ; + wifi->circularBuffer[address >> 1] = val ; + return ; + } + if (!(address & 0x00007000)) action = TRUE ; + /* mirrors => register address */ + address &= 0x00000FFF ; + switch (address) + { + case REG_WIFI_ID: + break ; + case REG_WIFI_MODE: + if (val & 0x4000) + { + /* does some resets */ + wifi->RXRangeBegin = 0x4000 ; + /* this bit does not save */ + val &= ~0x4000 ; + } + wifi->macMode = val ; + break ; + case REG_WIFI_WEP: + wifi->wepMode = val ; + break ; + case REG_WIFI_IE: + wifi->IE.val = val ; + break ; + case REG_WIFI_IF: + wifi->IF.val &= ~val ; /* clear flagging bits */ + break ; + case REG_WIFI_MAC0: + case REG_WIFI_MAC1: + case REG_WIFI_MAC2: + wifi->mac.words[(address - REG_WIFI_MAC0) >> 1] = val ; + break ; + case REG_WIFI_BSS0: + case REG_WIFI_BSS1: + case REG_WIFI_BSS2: + wifi->bss.words[(address - REG_WIFI_BSS0) >> 1] = val ; + break ; + case REG_WIFI_RETRYLIMIT: + wifi->retryLimit = val ; + break ; + case REG_WIFI_WEPCNT: + wifi->WEP_enable = (val & 0x8000) != 0 ; + break ; + case REG_WIFI_RXRANGEBEGIN: + wifi->RXRangeBegin = val ; + break ; + case REG_WIFI_RXRANGEEND: + wifi->RXRangeEnd = val ; + break ; + case REG_WIFI_WRITECSRLATCH: + if ((action) && (wifi->RXCnt & 1)) /* only when action register and CSR change enabled */ + { + wifi->RXHWWriteCursor = val ; + } + break ; + case REG_WIFI_CIRCBUFRADR: + wifi->CircBufReadAddress = (val & 0x1FFE); + break ; + case REG_WIFI_RXREADCSR: + wifi->RXReadCursor = val ; + break ; + case REG_WIFI_CIRCBUFWADR: + wifi->CircBufWriteAddress = val ; + break ; + case REG_WIFI_CIRCBUFWRITE: + /* set value into the circ buffer, and move cursor to the next hword on action */ + wifi->circularBuffer[(wifi->CircBufWriteAddress >> 1) & 0xFFF] = val ; + if (action) + { + /* move to next hword */ + wifi->CircBufWriteAddress+=2 ; + if (wifi->CircBufWriteAddress == wifi->CircBufWrEnd) + { + /* on end of buffer, add skip hwords to it */ + wifi->CircBufWrEnd += wifi->CircBufWrSkip * 2 ; + } + } + break ; + case REG_WIFI_CIRCBUFWR_SKIP: + wifi->CircBufWrSkip = val ; + break ; + case REG_WIFI_BEACONTRANS: + wifi->BEACONSlot = val & 0x7FFF ; + wifi->BEACON_enable = (val & 0x8000) != 0 ; + break ; + case REG_WIFI_TXLOC1: + case REG_WIFI_TXLOC2: + case REG_WIFI_TXLOC3: + wifi->TXSlot[(address - REG_WIFI_TXLOC1) >> 2] = val ; + break ; + case REG_WIFI_TXOPT: + if (val == 0xFFFF) + { + /* reset TX logic */ + /* CHECKME */ + wifi->TXSlot[0] = 0 ; wifi->TXSlot[1] = 0 ; wifi->TXSlot[2] = 0 ; + wifi->TXOpt = 0 ; + wifi->TXCnt = 0 ; + } else + { + wifi->TXOpt = val ; + } + break ; + case REG_WIFI_TXCNT: + wifi->TXCnt = val ; + if (val & 0x01) WIFI_TXStart(wifi,0) ; + if (val & 0x04) WIFI_TXStart(wifi,1) ; + if (val & 0x08) WIFI_TXStart(wifi,2) ; + break ; + case REG_WIFI_RFIOCNT: + WIFI_setRF_CNT(wifi,val) ; + break ; + case REG_WIFI_RFIOBSY: + /* CHECKME: read only? */ + break ; + case REG_WIFI_RFIODATA1: + WIFI_setRF_DATA(wifi,val,0) ; + break ; + case REG_WIFI_RFIODATA2: + WIFI_setRF_DATA(wifi,val,1) ; + break ; + case REG_WIFI_USCOUNTERCNT: + wifi->usecEnable = (val & 1)==1 ; + break ; + case REG_WIFI_USCOMPARECNT: + wifi->ucmpEnable = (val & 1)==1 ; + break ; + case REG_WIFI_BBSIOCNT: + WIFI_setBB_CNT(wifi,val) ; + break ; + case REG_WIFI_BBSIOWRITE: + WIFI_setBB_DATA(wifi,val) ; + break ; + case REG_WIFI_RXBUF_COUNT: + wifi->RXBufCount = val & 0x0FFF ; + break ; + case REG_WIFI_EXTRACOUNTCNT: + wifi->eCountEnable = (val & 0x0001) ; + break ; + case REG_WIFI_EXTRACOUNT: + wifi->eCount = val ; + break ; + case REG_WIFI_POWER_US: + wifi->crystalEnabled = !(val & 0x0001) ; + break ; + case REG_WIFI_IF_SET: + WIFI_triggerIRQMask(wifi,val) ; + break ; + case REG_WIFI_CIRCBUFRD_END: + wifi->CircBufRdEnd = (val & 0x1FFE) ; + break ; + case REG_WIFI_CIRCBUFRD_SKIP: + wifi->CircBufRdSkip = val & 0xFFF ; + break ; + case REG_WIFI_AID_LOW: + wifi->pid = val & 0x0F ; + break ; + case REG_WIFI_AID_HIGH: + wifi->aid = val & 0x07FF ; + break ; + default: + val = 0 ; /* not handled yet */ + break ; + } +} + +u16 WIFI_read16(wifimac_t *wifi,u32 address) +{ + BOOL action = FALSE ; + u16 temp ; + if (!(MMU_read32(ARMCPU_ARM7,REG_PWRCNT) & 0x0002)) return 0 ; /* access to wifi hardware was disabled */ + if ((address & 0xFF800000) != 0x04800000) return 0 ; /* error: the address does not describe a wiifi register */ + + /* the first 0x1000 bytes are mirrored at +0x1000,+0x2000,+0x3000,+06000,+0x7000 */ + /* only the first mirror causes an special action */ + /* the gap at +0x4000 is filled with the circular bufferspace */ + /* the so created 0x8000 byte block is then mirrored till 0x04FFFFFF */ + /* see: http://www.akkit.org/info/dswifi.htm#Wifihwcap */ + if (((address & 0x00007000) >= 0x00004000) && ((address & 0x00007000) < 0x00006000)) + { + /* access to the circular buffer */ + return wifi->circularBuffer[(address & 0x1FFF) >> 1] ; + } + if (!(address & 0x00007000)) action = TRUE ; + /* mirrors => register address */ + address &= 0x00000FFF ; + switch (address) + { + case REG_WIFI_ID: + return WIFI_CHIPID ; + case REG_WIFI_MODE: + return wifi->macMode ; + case REG_WIFI_WEP: + return wifi->wepMode ; + case REG_WIFI_IE: + return wifi->IE.val ; + case REG_WIFI_IF: + return wifi->IF.val ; + case REG_WIFI_RFIODATA1: + return WIFI_getRF_DATA(wifi,0) ; + case REG_WIFI_RFIODATA2: + return WIFI_getRF_DATA(wifi,1) ; + case REG_WIFI_RFIOBSY: + case REG_WIFI_BBSIOBUSY: + return 0 ; /* we are never busy :p */ + case REG_WIFI_BBSIOREAD: + return WIFI_getBB_DATA(wifi) ; + case REG_WIFI_RANDOM: + /* FIXME: random generator */ + return 0 ; + case REG_WIFI_MAC0: + case REG_WIFI_MAC1: + case REG_WIFI_MAC2: + return wifi->mac.words[(address - REG_WIFI_MAC0) >> 1] ; + case REG_WIFI_BSS0: + case REG_WIFI_BSS1: + case REG_WIFI_BSS2: + return wifi->bss.words[(address - REG_WIFI_BSS0) >> 1] ; + case REG_WIFI_RXRANGEBEGIN: + return wifi->RXRangeBegin ; + case REG_WIFI_CIRCBUFREAD: + temp = wifi->circularBuffer[((wifi->RXRangeBegin + wifi->CircBufReadAddress) >> 1) & 0x0FFF] ; + if (action) + { + wifi->CircBufReadAddress += 2 ; + wifi->CircBufReadAddress &= 0x1FFE ; + if (wifi->CircBufReadAddress + wifi->RXRangeBegin == wifi->RXRangeEnd) + { + wifi->CircBufReadAddress = 0 ; + } else + { + /* skip does not fire after a reset */ + if (wifi->CircBufReadAddress == wifi->CircBufRdEnd) + { + wifi->CircBufReadAddress += wifi->CircBufRdSkip * 2 ; + wifi->CircBufReadAddress &= 0x1FFE ; + if (wifi->CircBufReadAddress + wifi->RXRangeBegin == wifi->RXRangeEnd) wifi->CircBufReadAddress = 0 ; + } + } + if (wifi->RXBufCount > 0) + { + if (wifi->RXBufCount == 1) + { + WIFI_triggerIRQ(wifi,9) ; + } + wifi->RXBufCount-- ; + } + } + return temp; + case REG_WIFI_CIRCBUFRADR: + return wifi->CircBufReadAddress ; + case REG_WIFI_RXBUF_COUNT: + return wifi->RXBufCount ; + case REG_WIFI_EXTRACOUNTCNT: + return wifi->eCountEnable?1:0 ; + case REG_WIFI_EXTRACOUNT: + return wifi->eCount ; + case REG_WIFI_POWER_US: + return wifi->crystalEnabled?0:1 ; + case REG_WIFI_CIRCBUFRD_END: + return wifi->CircBufRdEnd ; + case REG_WIFI_CIRCBUFRD_SKIP: + return wifi->CircBufRdSkip ; + case REG_WIFI_AID_LOW: + return wifi->pid ; + case REG_WIFI_AID_HIGH: + return wifi->aid ; + default: + return 0 ; + } +} + + +void WIFI_usTrigger(wifimac_t *wifi) +{ + u8 dataBuffer[0x2000] ; + u16 rcvSize ; + if (wifi->crystalEnabled) + { + /* a usec (=3F03 cycles) has passed */ + if (wifi->usecEnable) + wifi->usec++ ; + if (wifi->eCountEnable) + { + if (wifi->eCount > 0) + { + wifi->eCount-- ; + } + } + } + if ((wifi->ucmpEnable) && (wifi->ucmp == wifi->usec)) + { + WIFI_triggerIRQ(wifi,WIFI_IRQ_TIMEBEACON) ; } /* receive check, given a 2 mbit connection, 2 bits per usec can be transfered. */ /* for a packet of 32 Bytes, at least 128 usec passed, we will use the 32 byte accuracy to reduce load */ diff --git a/desmume/src/wifi.h b/desmume/src/wifi.h index bab54f47f..b25305e8a 100644 --- a/desmume/src/wifi.h +++ b/desmume/src/wifi.h @@ -26,7 +26,7 @@ /* standardize socket interface for linux and windows */ #ifdef WIN32 - #include + #include #define socket_t SOCKET #define sockaddr_t SOCKADDR #else @@ -40,390 +40,409 @@ #define BASEPORT 7000 /* channel 1: 7000 ... channel 13: 7012 */ /* FIXME: make it configureable */ -#define REG_WIFI_MODE 0x004 -#define REG_WIFI_WEP 0x006 -#define REG_WIFI_IF 0x010 -#define REG_WIFI_IE 0x012 -#define REG_WIFI_MAC0 0x018 -#define REG_WIFI_MAC1 0x01A -#define REG_WIFI_MAC2 0x01C -#define REG_WIFI_BSS0 0x020 -#define REG_WIFI_BSS1 0x022 -#define REG_WIFI_BSS2 0x024 -#define REG_WIFI_AID 0x028 -#define REG_WIFI_AIDCPY 0x02A -#define REG_WIFI_RETRYLIMIT 0x02C -#define REG_WIFI_WEPCNT 0x032 -#define REG_WIFI_POWERSTATE 0x03C -#define REG_WIFI_FORCEPS 0x040 -#define REG_WIFI_RANDOM 0x044 -#define REG_WIFI_RXRANGEBEGIN 0x050 -#define REG_WIFI_RXRANGEEND 0x052 -#define REG_WIFI_RXHWWRITECSR 0x054 -#define REG_WIFI_WRITECSRLATCH 0x056 -#define REG_WIFI_CIRCBUFRADR 0x058 -#define REG_WIFI_RXREADCSR 0x05A -#define REG_WIFI_CIRCBUFREAD 0x060 -#define REG_WIFI_CIRCBUFWADR 0x068 -#define REG_WIFI_CIRCBUFWRITE 0x070 -#define REG_WIFI_CIRCBUFWR_END 0x074 -#define REG_WIFI_CIRCBUFWR_SKIP 0x076 -#define REG_WIFI_BEACONTRANS 0x080 -#define REG_WIFI_LISTENCOUNT 0x088 -#define REG_WIFI_BEACONPERIOD 0x08C -#define REG_WIFI_LISTENINT 0x08E -#define REG_WIFI_TXLOC1 0x0A0 -#define REG_WIFI_TXLOC2 0x0A4 -#define REG_WIFI_TXLOC3 0x0A8 -#define REG_WIFI_TXOPT 0x0AC -#define REG_WIFI_TXCNT 0x0AE -#define REG_WIFI_TXSTAT 0x0B8 -#define REG_WIFI_RXFILTER 0x0D0 -#define REG_WIFI_USCOUNTERCNT 0x0E8 -#define REG_WIFI_USCOMPARECNT 0x0EA -#define REG_WIFI_USCOMPARE0 0x0F0 -#define REG_WIFI_USCOMPARE1 0x0F2 -#define REG_WIFI_USCOMPARE2 0x0F4 -#define REG_WIFI_USCOMPARE3 0x0F6 -#define REG_WIFI_USCOUNTER0 0x0F8 -#define REG_WIFI_USCOUNTER1 0x0FA -#define REG_WIFI_USCOUNTER2 0x0FC -#define REG_WIFI_USCOUNTER3 0x0FE -#define REG_WIFI_BBSIOCNT 0x158 -#define REG_WIFI_BBSIOWRITE 0x15A -#define REG_WIFI_BBSIOREAD 0x15C -#define REG_WIFI_BBSIOBUSY 0x15E -#define REG_WIFI_RFIODATA2 0x17C -#define REG_WIFI_RFIODATA1 0x17E -#define REG_WIFI_RFIOBSY 0x180 -#define REG_WIFI_RFIOCNT 0x184 - -/* 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 -{ - union CFG1 - { - 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 - { - 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 - { - struct - { -/* 0*/ unsigned IF_N:16; -/*16*/ unsigned :2; - } bits ; - u32 val ; - } IFPLL2 ; - union IFPLL3 - { - struct - { -/* 0*/ unsigned KV_DEF1:4; -/* 4*/ unsigned CT_DEF1:4; -/* 8*/ unsigned DN1:9; -/*17*/ unsigned :1; - } bits ; - u32 val ; - } IFPLL3 ; - union RFPLL1 - { - 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 - { - struct - { -/* 0*/ unsigned NUM2:6; -/* 6*/ unsigned N2:12; - } bits ; - u32 val ; - } RFPLL2 ; - union RFPLL3 - { - struct - { -/* 0*/ unsigned NUM2:18; - } bits ; - u32 val ; - } RFPLL3 ; - union RFPLL4 - { - struct - { -/* 0*/ unsigned KV_DEF:4; -/* 4*/ unsigned CT_DEF:4; -/* 8*/ unsigned DN:9; -/*17*/ unsigned :1; - } bits ; - u32 val ; - } RFPLL4 ; - union CAL1 - { - 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 - { - 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 - { - 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 - { - struct - { -/* 0*/ unsigned MIN_POWER:6; -/* 6*/ unsigned MID_POWER:6; -/*12*/ unsigned MAX_POWER:6; - } bits ; - } PCNT2 ; - union VCOT1 - { - struct - { -/* 0*/ unsigned :16; -/*16*/ unsigned AUX1:1; -/*17*/ unsigned AUX:1; - } bits ; - u32 val ; - } VCOT1 ; -} rffilter_t ; - -/* baseband chip refered as BB_, dataformat is unknown yet */ -/* it has at least 105 bytes of functional data */ -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_RECVCOMPLETE 0x0001 -#define WIFI_IRQ_SENDCOMPLETE 0x0002 -#define WIFI_IRQ_COUNTUP 0x0004 -#define WIFI_IRQ_SENDERROR 0x0008 -#define WIFI_IRQ_STATCOUNTUP 0x0010 -#define WIFI_IRQ_STATACKUP 0x0020 -#define WIFI_IRQ_RECVSTART 0x0040 -#define WIFI_IRQ_SENDSTART 0x0080 -#define WIFI_IRQ_RFWAKEUP 0x0800 -#define WIFI_IRQ_TIMEBEACON 0x4000 -#define WIFI_IRQ_TIMEPREBEACON 0x8000 - -/* definition of the irq bitfields for wifi irq's (cascaded at arm7 irq #24) */ -typedef union -{ - struct - { -/* 0*/ unsigned recv_complete:1; -/* 1*/ unsigned send_complete:1; -/* 2*/ unsigned recv_countup:1; -/* 3*/ unsigned send_error:1; -/* 4*/ unsigned stat_countup:1; -/* 5*/ unsigned stat_ackup:1; -/* 6*/ unsigned recv_start:1; -/* 7*/ unsigned send_start:1; -/* 8*/ unsigned :3; -/*11*/ unsigned rf_wakeup:1; -/*12*/ unsigned :2; -/*14*/ unsigned time_beacon:1; -/*15*/ unsigned time_prebeacon:1; - } bits ; - u16 val ; -} wifiirq_t ; - -/* wifimac_t: the buildin mac (arm7 addressrange: 0x04800000-0x04FFFFFF )*/ -/* http://www.akkit.org/info/dswifi.htm#WifiIOMap */ -typedef struct -{ - /* wifi interrupt handling */ - wifiirq_t IE ; - wifiirq_t IF ; - - /* modes */ - u16 macMode ; - u16 wepMode ; - BOOL WEP_enable ; - - /* sending */ - u16 TXSlot[3] ; - u16 TXCnt ; - u16 TXOpt ; - u16 BEACONSlot ; - BOOL BEACON_enable ; - - /* receiving */ - u16 RXCnt ; - u16 RXCheckCounter ; - - /* addressing/handshaking */ - union - { - u16 words[3] ; - u8 bytes[6] ; - } mac ; - union - { - u16 words[3] ; - u8 bytes[6] ; - } bss ; - u16 aid ; - u16 retryLimit ; - - /* timing */ - u64 usec ; - BOOL usecEnable ; - u64 ucmp ; - BOOL ucmpEnable ; - - /* subchips */ - rffilter_t RF ; - bb_t BB ; - - /* subchip communications */ - rfIOCnt_t rfIOCnt ; - rfIOStat_t rfIOStatus ; - rfIOData_t rfIOData ; - bbIOCnt_t bbIOCnt ; - - /* buffers */ - u16 circularBuffer[0x1000] ; - u16 RXRangeBegin ; - u16 RXRangeEnd ; - u16 RXHWWriteCursor ; - u16 RXReadCursor ; - u16 RXUnits ; - u16 CircBufReadAddress ; - u16 CircBufWriteAddress ; - u16 CircBufEnd ; - u16 CircBufSkip ; - - /* others */ - u16 randomSeed ; - - /* desmume host communication */ - socket_t udpSocket ; - u8 channel ; - -} wifimac_t ; +#define REG_WIFI_ID 0x000 +#define REG_WIFI_MODE 0x004 +#define REG_WIFI_WEP 0x006 +#define REG_WIFI_IF 0x010 +#define REG_WIFI_IE 0x012 +#define REG_WIFI_MAC0 0x018 +#define REG_WIFI_MAC1 0x01A +#define REG_WIFI_MAC2 0x01C +#define REG_WIFI_BSS0 0x020 +#define REG_WIFI_BSS1 0x022 +#define REG_WIFI_BSS2 0x024 +#define REG_WIFI_AID_LOW 0x028 +#define REG_WIFI_AID_HIGH 0x02A +#define REG_WIFI_RETRYLIMIT 0x02C +#define REG_WIFI_WEPCNT 0x032 +#define REG_WIFI_POWER_US 0x036 +#define REG_WIFI_POWERSTATE 0x03C +#define REG_WIFI_FORCEPS 0x040 +#define REG_WIFI_RANDOM 0x044 +#define REG_WIFI_RXRANGEBEGIN 0x050 +#define REG_WIFI_RXRANGEEND 0x052 +#define REG_WIFI_RXHWWRITECSR 0x054 +#define REG_WIFI_WRITECSRLATCH 0x056 +#define REG_WIFI_CIRCBUFRADR 0x058 +#define REG_WIFI_RXREADCSR 0x05A +#define REG_WIFI_RXBUF_COUNT 0x05C +#define REG_WIFI_CIRCBUFREAD 0x060 +#define REG_WIFI_CIRCBUFRD_END 0x062 +#define REG_WIFI_CIRCBUFRD_SKIP 0x064 +#define REG_WIFI_CIRCBUFWADR 0x068 +#define REG_WIFI_CIRCBUFWRITE 0x070 +#define REG_WIFI_CIRCBUFWR_END 0x074 +#define REG_WIFI_CIRCBUFWR_SKIP 0x076 +#define REG_WIFI_BEACONTRANS 0x080 +#define REG_WIFI_LISTENCOUNT 0x088 +#define REG_WIFI_BEACONPERIOD 0x08C +#define REG_WIFI_LISTENINT 0x08E +#define REG_WIFI_TXLOC1 0x0A0 +#define REG_WIFI_TXLOC2 0x0A4 +#define REG_WIFI_TXLOC3 0x0A8 +#define REG_WIFI_TXOPT 0x0AC +#define REG_WIFI_TXCNT 0x0AE +#define REG_WIFI_TXSTAT 0x0B8 +#define REG_WIFI_RXFILTER 0x0D0 +#define REG_WIFI_USCOUNTERCNT 0x0E8 +#define REG_WIFI_USCOMPARECNT 0x0EA +#define REG_WIFI_EXTRACOUNTCNT 0x0EE +#define REG_WIFI_USCOMPARE0 0x0F0 +#define REG_WIFI_USCOMPARE1 0x0F2 +#define REG_WIFI_USCOMPARE2 0x0F4 +#define REG_WIFI_USCOMPARE3 0x0F6 +#define REG_WIFI_USCOUNTER0 0x0F8 +#define REG_WIFI_USCOUNTER1 0x0FA +#define REG_WIFI_USCOUNTER2 0x0FC +#define REG_WIFI_USCOUNTER3 0x0FE +#define REG_WIFI_EXTRACOUNT 0x118 +#define REG_WIFI_BBSIOCNT 0x158 +#define REG_WIFI_BBSIOWRITE 0x15A +#define REG_WIFI_BBSIOREAD 0x15C +#define REG_WIFI_BBSIOBUSY 0x15E +#define REG_WIFI_RFIODATA2 0x17C +#define REG_WIFI_RFIODATA1 0x17E +#define REG_WIFI_RFIOBSY 0x180 +#define REG_WIFI_RFIOCNT 0x184 +#define REG_WIFI_IF_SET 0x21C + +/* WIFI misc constants */ +#define WIFI_CHIPID 0x1440 /* emulates "old" wifi chip, new is 0xC340 */ +#define REG_PWRCNT 0x04000304 + +/* 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 +{ + union CFG1 + { + 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 + { + 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 + { + struct + { +/* 0*/ unsigned IF_N:16; +/*16*/ unsigned :2; + } bits ; + u32 val ; + } IFPLL2 ; + union IFPLL3 + { + struct + { +/* 0*/ unsigned KV_DEF1:4; +/* 4*/ unsigned CT_DEF1:4; +/* 8*/ unsigned DN1:9; +/*17*/ unsigned :1; + } bits ; + u32 val ; + } IFPLL3 ; + union RFPLL1 + { + 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 + { + struct + { +/* 0*/ unsigned NUM2:6; +/* 6*/ unsigned N2:12; + } bits ; + u32 val ; + } RFPLL2 ; + union RFPLL3 + { + struct + { +/* 0*/ unsigned NUM2:18; + } bits ; + u32 val ; + } RFPLL3 ; + union RFPLL4 + { + struct + { +/* 0*/ unsigned KV_DEF:4; +/* 4*/ unsigned CT_DEF:4; +/* 8*/ unsigned DN:9; +/*17*/ unsigned :1; + } bits ; + u32 val ; + } RFPLL4 ; + union CAL1 + { + 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 + { + 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 + { + 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 + { + struct + { +/* 0*/ unsigned MIN_POWER:6; +/* 6*/ unsigned MID_POWER:6; +/*12*/ unsigned MAX_POWER:6; + } bits ; + } PCNT2 ; + union VCOT1 + { + struct + { +/* 0*/ unsigned :16; +/*16*/ unsigned AUX1:1; +/*17*/ unsigned AUX:1; + } bits ; + u32 val ; + } VCOT1 ; +} rffilter_t ; + +/* baseband chip refered as BB_, dataformat is unknown yet */ +/* it has at least 105 bytes of functional data */ +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_RECVCOMPLETE 0x0001 +#define WIFI_IRQ_SENDCOMPLETE 0x0002 +#define WIFI_IRQ_COUNTUP 0x0004 +#define WIFI_IRQ_SENDERROR 0x0008 +#define WIFI_IRQ_STATCOUNTUP 0x0010 +#define WIFI_IRQ_STATACKUP 0x0020 +#define WIFI_IRQ_RECVSTART 0x0040 +#define WIFI_IRQ_SENDSTART 0x0080 +#define WIFI_IRQ_RFWAKEUP 0x0800 +#define WIFI_IRQ_TIMEBEACON 0x4000 +#define WIFI_IRQ_TIMEPREBEACON 0x8000 + +/* definition of the irq bitfields for wifi irq's (cascaded at arm7 irq #24) */ +typedef union +{ + struct + { +/* 0*/ unsigned recv_complete:1; +/* 1*/ unsigned send_complete:1; +/* 2*/ unsigned recv_countup:1; +/* 3*/ unsigned send_error:1; +/* 4*/ unsigned stat_countup:1; +/* 5*/ unsigned stat_ackup:1; +/* 6*/ unsigned recv_start:1; +/* 7*/ unsigned send_start:1; +/* 8*/ unsigned :3; +/*11*/ unsigned rf_wakeup:1; +/*12*/ unsigned :2; +/*14*/ unsigned time_beacon:1; +/*15*/ unsigned time_prebeacon:1; + } bits ; + u16 val ; +} wifiirq_t ; + +/* wifimac_t: the buildin mac (arm7 addressrange: 0x04800000-0x04FFFFFF )*/ +/* http://www.akkit.org/info/dswifi.htm#WifiIOMap */ +typedef struct +{ + /* wifi interrupt handling */ + wifiirq_t IE ; + wifiirq_t IF ; + + /* modes */ + u16 macMode ; + u16 wepMode ; + BOOL WEP_enable ; + + /* sending */ + u16 TXSlot[3] ; + u16 TXCnt ; + u16 TXOpt ; + u16 BEACONSlot ; + BOOL BEACON_enable ; + + /* receiving */ + u16 RXCnt ; + u16 RXCheckCounter ; + + /* addressing/handshaking */ + union + { + u16 words[3] ; + u8 bytes[6] ; + } mac ; + union + { + u16 words[3] ; + u8 bytes[6] ; + } bss ; + u16 aid ; + u16 pid ; /* player ID or aid_low */ + u16 retryLimit ; + + /* timing */ + BOOL crystalEnabled ; + u64 usec ; + BOOL usecEnable ; + u64 ucmp ; + BOOL ucmpEnable ; + u16 eCount ; + BOOL eCountEnable ; + + /* subchips */ + rffilter_t RF ; + bb_t BB ; + + /* subchip communications */ + rfIOCnt_t rfIOCnt ; + rfIOStat_t rfIOStatus ; + rfIOData_t rfIOData ; + bbIOCnt_t bbIOCnt ; + + /* buffers */ + u16 circularBuffer[0x1000] ; + u16 RXRangeBegin ; + u16 RXRangeEnd ; + u16 RXHWWriteCursor ; + u16 RXReadCursor ; + u16 RXUnits ; + u16 RXBufCount ; + u16 CircBufReadAddress ; + u16 CircBufWriteAddress ; + u16 CircBufRdEnd ; + u16 CircBufRdSkip ; + u16 CircBufWrEnd ; + u16 CircBufWrSkip ; + + /* others */ + u16 randomSeed ; + + /* desmume host communication */ + socket_t udpSocket ; + u8 channel ; + +} wifimac_t ; extern wifimac_t wifiMac ;