4dsdev
Views: 592,363 Main | Rules/FAQ | Memberlist | Active users | Last posts | Calendar | Stats | Online users | Search 08-23-17 12:07 AM
Guest:

0 users reading Wifi for DSi and 3DS | 1 bot

Main - Reverse-engineering - Wifi for DSi and 3DS New reply


nocash
Posted on 10-09-15 05:29 PM Link | #469
Just wondering how far homebrew Wifi is possible on different consoles yet.

First of, there are a two different Wifi controller/modes:
1) the old NDS mode (with max 2Mbit/s, the controller is apparently contained in the main CPU chip since it's accessed via direct I/O)
2) the new SDIO mode (with faster transfers, the controller is located in the DWM-W0xx Wifi daughterboard, and accessed via SDIO bus)

And, different daughterboards:
DWM-W015 with AR6002G-AC1B chip in old DSi's
DWM-W024 with AR6013G-AL1C chip in later DSi's
DWM-W028 reportedly with AR6014 chip in 3DS
(and maybe further variants in later 3DS revisiosns)

The old NDS mode can be used on DSi's with DWM-W015 boards (eg. for uploading code via "dslink").
But I don't know if it's also working with other daughterboards. Can somebody confirm that, ie. is dslink working on later DSi with DWM-W024 boards, and on 3DS (in DSi mode)?
And btw. is there a similar wifi-upload utility for 3DS in 3DS mode?

And the new SDIO mode, did anybody figure out how to use that yet?
On the DSi, the ARM7 firmware is uploading WLANFIRM firmware to the AR600xx chip via SDIO, and the games are then supposed to communicate with that uploaded WLAN firmware (plus further undumped code in a ROM inside of the AR600xx chip) - but the communication protocol seems to be still unknown (at least on DSi, maybe there's more known on 3DS).

plutoo
Posted on 10-09-15 06:10 PM Link | #470
On the New3DS model, there is no WiFi daughterboard. Instead, the AR6014G is placed directly on the motherboard. For compatibility reasons with DS(i), I assume the AR6014 has to be backwardscompatible with AR6013.

For 3DS homebrew we can just re-use Nintendo's driver. It is called NWM (Nintendo Wifi Manager?) and includes an SDIO driver. It also does all the rest of the communication with the wifi chip. The actual protocol has not been reversed as far as I know.

Having a quick glance at NWM, it looks like it contains 3 different versions of wlan firmware, labeled 1, 4 and 5. Not sure what determines which one to use (hw revision maybe?). Unlike the NDS, the 3DS OS provides the wifi firmware behind the scenes, and the game/application never have to mess with it.

If you want a code dump for NWM I can provide it, but it is lacking strings/symbols, and is written (at least partially) in C++ with all that vtable goodness.

nocash
Posted on 10-11-15 10:55 AM (rev. 4 of 10-11-15 11:10 AM) Link | #480
I've dumped the ROM from the AR6002G-AC1B chip. It's 80Kbytes (as specified in the datasheet), located at 8E0000h (as indicated by the vectors in RAM).
The CRC32 for the ROM image is 04573BB0h. There are also some ASCII strings in the ROM image: "Athos/Xt BSP", "Nov 23 2007", "00:20:38".

ROMs for other AR60xx chips aren't dumped yet, as far as I know. If you want to dump those chips, it can be done via these two SDIO Function Registers (sent via SDIO CMD53) (CMD52 doesn't seem to work for them):
- WINDOW_DATA (32bit, SDIO Function 1:00474h)
- WINDOW_READ_ADDR (32bit, SDIO Function 1:0047Ch)
First, write the upper-3-bytes of the address to (WINDOW_READ_ADDR+1..3), then write the lower-byte to (WINDOW_READ_ADDR+0), then read the addressed 4-bytes from (WINDOW_DATA+0..3).
If needed, I can post some messy source code for doing the above stuff.

Some background info on the "internal" atheros I/O ports and its "external" SDIO registers is found in these older posts: http://ngemu.com/threads/dsi-wifi-hardware-discovered.173033/ (the attachments contain quite detailed register specs, extracted from 'official' AR6002 source code).

I have also tried to dump the whole internal atheros memory space. Reading certain addresses crashes the SDIO interface (making it impossine to do any further SDIO reads without rebooting), but after skipping those "dangerous" addresses, I got this overall memory map puzzled together:
000000 Deadc0de
004000 sth (01 00 00 00, 00 00 00 00) ;"RTC" fragment?
005000 Deadc0de
008000 sth (00 00 00 00, 00 00 00 00) ;"VMC?"
009000 Deadc0de
014000 sth (00 00 00 00, 00 00 00 00) (--crash-- at 0140cx) ;"GPIO?"
015000 Deadc0de
018000 sth (00 01 0E 00, 00 01 0E 00) ;\MBOX
019000 sth (00 01 0E 00, 00 01 0E 00) ;/
01A000 sth (00 01 0E 00, 00 01 0E 00) ;\MBOX:HOST_IF?
01B000 sth (--crash-- at 01B00x) ;/
01C000 sth (00 00 14 00, D8 48 45 0E) ;-ANALOG?
01D000 Deadc0de
020000 sth (00's) ;\DMA?
021000 sth (01 00 00 00, 02 00 00 00) ;/
022000 sth (00's) ;\ ;\same as
023000 sth (01 00 00 00, 02 00 00 00) ; ;/DMA?
024000 sth (00's) ; ??
025000 sth (00's) ;
026000 sth (00's) ;
027000 sth (00's) ;/
028000 sth (00 23 CC 70, 82 43 86 38) ;\MAC_PCU?
029000 sth (14 E1 38 8A, 80 73 00 00) ;/ ;\
02A000 sth (00's) ; BB at 29800h?
02B000 sth (00's) ;/
02C000 sth (00's) ;-UART maybe?
02D000 sth (00's) ;-UART debug?
02E000 sth (00's) ;-UMBOX?
02F000 sth (00's) ;-?? (not SI?)
030000 Deadc0de ;RDMA?? and (not?) EFUSE??
040000 Deadbeef
050000 Deadbeef
060000 Deadbeef
070000 Deadbeef
080000 004F1B74
090000 004F1B74
0A0000 004F1B74
0B0000 004F1B74
0C0000 004F1B74
0D0000 004F1B74
0E0000 sth (06 10 00 00, 21 22 22 22) ;\80K ROM (14000h bytes)
0F0000 sth (00 00 05 60, FF DF FF FF) ;/
0F4000 004F1B74
100000 sth (48 0F 8E 00, 70 14 50 00) ;\
110000 sth ; 184K RAM (2E000h bytes)
120000 sth ;/
12E000 98A8A2AA
...
1FF000 98A8A2AA
200000 Deadbeef
300000 Deadbeef
...
3FF000 Deadbeef
Above is a dump of the first 4Mbytes, done by reading 8-byte units from addresses incrementing at 1000h-byte step.
The comments are showing which memory and I/O regions are assumed to be mapped at the separate addresses.
Some I/O regions that are claimed to be located at 00xxxxh seem to be actually located at 02xxxxh (namely, the ports at 9800h..E000h seem to be at 29800h..2E000h).

After the first 4Mbyte, the following memory seems to be just containing mirrors of the first 4Mbyte. I've tested some addresses...
00400000 looks like mirror of 000000
0041B000 looks like mirror of 01B000 --crash--
... probably more mirrors...
FFC00000 looks like mirror of 000000
FFC1B000 looks like mirror of 01B000 --crash--
... probably more mirrors till FFFFFFFF
The ROM and RAM seem to be actually accessed via mirrors (RAM at 500000h and ROM at 8E0000h). Don't know why... maybe write-access & execute-access is permitted only in certain mirrors.

nocash
Posted on 10-25-15 08:28 AM Link | #557
Posted by nocash
If needed, I can post some messy source code for doing the above stuff.

Okay, I will just post the source code, so you have no excuse that you didn't got told how to do it.

First of, init sdio like so (parts of it probably not realy required, and parts are relying on pre-initializations by firmware):
sdio_init:
push lr
ldr r9,=4004a00h
;---part1
ldrh r0,[r9,0e0h] ;\
bic r0,3 ; SDIO_SOFT_RESET clear bit0-1
strh r0,[r9,0e0h] ;/
ldrh r0,[r9,0e0h] ;\
orr r0,3 ; SDIO_SOFT_RESET set bit0-1
strh r0,[r9,0e0h] ;/
ldrh r0,[r9,008h] ;\
bic r0,1 ; SDIO_STOP_INTERNAL clear bit0
strh r0,[r9,008h] ;/
ldr r0,=80d0h ;\SDIO_CARD_OPTION = 80D0h
strh r0,[r9,028h] ;/
;---part2a
mov r0,0040h ;\SDIO_CARD_CLK_CTL = 0040h
strh r0,[r9,024h] ;/
ldrh r0,[r9,028h] ;\
orr r0,8000h ; SDIO_CARD_OPTION set bit15
bic r0,8000h ;clear --> want 4bit DATA mode !!!
strh r0,[r9,028h] ;/
;---part2b
ldrh r0,[r9,028h] ;\
orr r0,0100h ; SDIO_CARD_OPTION set bit8
strh r0,[r9,028h] ;/
ldrh r0,[r9,028h] ;\
bic r0,0100h ; SDIO_CARD_OPTION clear bit8
strh r0,[r9,028h] ;/
;---part3a
mov r0,0100h ;\SDIO_CARD_CLK_CTL set bit8
strh r0,[r9,024h] ;/
pop pc

This is dumping wifi memory 8C0000h..94FFFFh (the ROM is probably at 8E0000h and up, and RAM at 900000h or 920000h, depending on what AR60xx chip you have), the dumped area is a bit bigger to see which regions are actually occupied by ROM/RAM.
push r1-r12,lr
mov r10,8c0000h ;src index
mov r12,90000h ;len
@@dir_sector_lop:
mov r2,200h ;\
ldr r3,=sdmmc_sector_buf ;dst ; read SDIO data
@@rd_sdio_lop: ; (based on "sdio_dump_internal_registers")
push r0-r12
tst r10,0ffh ;\output addr.MSBs only
bne @@skip_addr_msbs ;/at start of 256-byte areas
mov r0,r10,lsr 8 ;\
ldr r1,=1000047dh ; addr.bit8-15
bl sdio_cmd53_write_r0_to_register_r1 ;/
mov r0,r10,lsr 16 ;\
ldr r1,=1000047eh ; addr.bit16-23
bl sdio_cmd53_write_r0_to_register_r1 ;/
mov r0,r10,lsr 24 ;\
ldr r1,=1000047fh ; addr.bit24-31
bl sdio_cmd53_write_r0_to_register_r1 ;/
@@skip_addr_msbs:
mov r0,r10,lsr 0 ;\
;and r0,0fch ;hardware is ignoring LSBs anyways; addr.bit0-7 (this last?)
ldr r1,=1000047ch ;
bl sdio_cmd53_write_r0_to_register_r1 ;/
pop r0-r12
ldr r1,=10000474h ;\read 4byte data
bl sdio_cmd53_read_32bit_register_r1 ;/
str r0,[r3],4 ;\
add r10,4 ; store and lop next 4byte
subs r2,4 ;
bne @@rd_sdio_lop ;/

... write 200h bytes from "sdmmc_sector_buf" to file ...

subs r12,200h ;len
bne @@dir_sector_lop ;/
pop r1-r12,pc

The read 32bit subfunction:
;------------------
sdio_cmd53_read_32bit_register_r1: ;in: r1=addr(bit0-16)+func(bit28-30)
push r1-r12,lr
;;;@@param equ (04000100h + (@@func shl 28))
;---part3b
mov r0,r1,lsl 9 ;data(NONE), addr(bit9-25)
and r2,r1,(7 shl 28);func(bit28-30)
orr r0,r0,r2 ;func(bit28-30)
orr r0,1 shl 26 ;increasing address

bic r0,0ffh ;strip data
orr r0,04h ;replace by len (4 bytes)
ldr r9,=4004a00h
str r0,[r9,004h] ;SDIO_CMD_PARAM

ldr r0,[r9,01ch] ;\SDIO_IRQ_STAT
bic r0,83000000h ; clear bit31,25,24 (error, txrq, rxrdy)
bic r0,007f0000h ; clear bit22..16 (error)
bic r0,00000005h ; clear bit2,0 (dataend,cmdrespend)
str r0,[r9,01ch] ;/
ldrh r0,[r9,008h] ;\
bic r0,1 ; SDIO_STOP_INTERNAL clear bit0
strh r0,[r9,008h] ;/
mov r0,4 ;\SDIO_BLKLEN16
strh r0,[r9,026h] ;/
mov r0,1 ;\SDIO_NUMBLK16
strh r0,[r9,00ah] ;/
ldr r0,=5c35h ;cmd.rd ;\SDIO_CMD
strh r0,[r9,000h] ;/
;- - -
mov r2,10000h ;\
@@wait_rxrdy: ;
subs r2,1 ;
beq @@error_sw_timeout ; wait for data
ldrh r0,[r9,01eh] ;SDIO_IRQ_STAT_HI ;
tst r0,100h ;rxrdy ;
beq @@wait_rxrdy ;/
ldrh r0,[r9,030h] ;SDIO_DATA16 ;\
ldrh r1,[r9,030h] ;SDIO_DATA16 ; fetch data (2x16bit)
orr r0,r0,r1,lsl 16 ;/
@@wait_dataend: ;\
subs r2,1 ;
beq @@error_sw_timeout ; wait for end
ldrh r1,[r9,01ch] ;SDIO_IRQ_STAT_LO ;
tst r1,4 ;dataend ; (works BETTER with this!)
beq @@wait_dataend ;/
@@error_sw_timeout:
pop r1-r12,pc

And, very messy, the 8bit write function:
;------------------
sdio_cmd53_write_r0_to_register_r1: ;in: r0=data(8bit), r1=addr(bit0-16)+func(bit28-30)
push r2,lr
;---part3b
and r0,0ffh ;data
orr r0,r0,r1,lsl 9 ;data(bit0-7), addr(bit9-25)
and r2,r1,(7 shl 28);func(bit28-30)
orr r0,r0,r2 ;func(bit28-30)
orr r0,1 shl 31 ;writeflag(bit31)
b sdio_cmd53_access_register_core_inj
;------------------
sdio_cmd53_access_register_core_inj: ;in: r0=param, out: r0=data (if reading)
push r8
and r8,r0,0ffh ;-memorize data (for write)
bic r0,0ffh ;strip data
orr r0,01h ;replace by len (1 byte)
ldr r9,=4004a00h
strh r0,[r9,004h] ;\
mov r0,r0,lsr 16 ; SDIO_CMD_PARAM
strh r0,[r9,06h] ;/
ldr r0,[r9,01ch] ;\SDIO_IRQ_STAT
bic r0,83000000h ; clear bit31,25,24 (error, txrq, rxrdy)
bic r0,007f0000h ; clear bit22..16 (error)
bic r0,00000005h ; clear bit2,0 (dataend,cmdrespend)
str r0,[r9,01ch] ;/
ldrh r0,[r9,008h] ;\
bic r0,1 ; SDIO_STOP_INTERNAL clear bit0
strh r0,[r9,008h] ;/
mov r0,1 ;\SDIO_BLKLEN16
strh r0,[r9,026h] ;/
mov r0,1 ;\SDIO_NUMBLK16
strh r0,[r9,00ah] ;/

ldrh r0,[r9,06h] ;\SDIO_CMD_PARAM (MSB=write)
tst r0,8000h ;/
ldrne r0,=4c35h ;cmd.wr;\
ldreq r0,=5c35h ;cmd.rd; SDIO_CMD
strh r0,[r9,000h] ;/
;- - -
mov r2,100000h ;timeout (ca. 1 Million) ;<-- ENDLESS SLOW (at least several MINUTES... or HOURS) (ie. in fact NEVER)
mov r2,1000h ;<-- REASONABLE SLOW (hmmm, even for 256-bytes, this is WAYS FASTER than above delay, which is 256-times slower, how is THAT possible??)
mov r2,10000h
@@busy_lop:
ldrh r0,[r9,02ch] ;\SDIO_ERROR_DETAIL_LO
tst r0,005h ; bit0, CMD CmdIndex-Error
tsteq r0,100h ; bit2, CMD End-Bit-Error
bne @@error_detail ;/ bit8, CMD CRC-Error
ldrh r0,[r9,01ch] ;\SDIO_IRQ_STAT_LO
tst r0,1 ; bit0, CMDRESPEND
bne @@busy_done ;/
subs r2,1 ;\lop next, till timeout
bne @@busy_lop ;/
b @@error_sw_timeout ;XXX accessing DISABLED function 1 does HANG (rather than reaching timeout?)
;---
@@busy_done:
ldrh r0,[r9,01eh] ;\SDIO_IRQ_STAT_HI
tst r0,40h ; bit22, CMDTIMEOUT
bne @@error_hw_timeout;/
ldr r0,[r9,00ch] ;\SDIO_REPLY (00001000h, ie. state = "dis"; if it's "CSR")
and r0,00ffh ;/
ldrh r0,[r9,06h] ;\SDIO_CMD_PARAM (MSB=write)
tst r0,8000h ;
bne @@write ;/
@@wait_rxrdy: ;\
subs r2,1 ;
beq @@error_sw_timeout ;
ldrh r0,[r9,01eh] ; SDIO_IRQ_STAT_HI
tst r0,100h ;rxrdy ;
beq @@wait_rxrdy ;/
ldrh r0,[r9,030h] ;\SDIO_DATA16
and r0,00ffh ;/
b @@finish
@@write:
@@wait_txrq: ;\
subs r2,1 ;
beq @@error_sw_timeout ;
ldrh r0,[r9,01eh] ; SDIO_IRQ_STAT_HI
tst r0,200h ;txrq ;
beq @@wait_txrq ;/
strh r8,[r9,030h] ;-SDIO_DATA16
mov r0,0 ;return 0=dummy
b @@finish
@@finish:
push r0
@@wait_dataend: ;\
subs r2,1 ;
beq @@error_sw_timeout_pop;
ldrh r0,[r9,01ch] ; SDIO_IRQ_STAT_LO
tst r0,4 ;dataend ; (works BETTER with this!)
beq @@wait_dataend ;/
pop r0

@@done:
pop r8
pop r2,pc
;---
@@error_sw_timeout_pop:
pop r0 ;flush
@@error_detail:
@@error_sw_timeout:
@@error_hw_timeout:
mov r0,-1
b @@done

The code should be working on DSi (or on 3DS in DSi mode).
For 3DS (in 3DS mode), the 4004a00h I/O base address would need to be changed accordingly.



Main - Reverse-engineering - Wifi for DSi and 3DS New reply

Page rendered in 0.028 seconds. (2048KB of memory used)
MySQL - queries: 26, rows: 69/69, time: 0.017 seconds.
[powered by Acmlm] Acmlmboard 2.064 (2015-10-07)
© 2005-2008 Acmlm, Xkeeper, blackhole89 et al.