Views: 1,611,769 | Main | Rules/FAQ | Memberlist | Active users | Last posts | Calendar | Stats | Online users | Search | 12-03-24 05:45 PM |
Guest: |
0 users reading Wifi for DSi and 3DS | 1 bot |
Main - Reverse-engineering - Wifi for DSi and 3DS | Hide post layouts | New reply |
nocash |
| ||
Normal user Level: 20 Posts: 2/77 EXP: 39067 Next: 3372 Since: 10-09-15 Last post: 2110 days ago Last view: 2025 days ago |
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 |
| ||
Member Normal user Level: 11 Posts: 2/19 EXP: 4804 Next: 1181 Since: 09-17-15 Last post: 3284 days ago Last view: 3208 days ago |
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 |
| ||
Normal user Level: 20 Posts: 3/77 EXP: 39067 Next: 3372 Since: 10-09-15 Last post: 2110 days ago Last view: 2025 days ago |
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
Above is a dump of the first 4Mbytes, done by reading 8-byte units from addresses incrementing at 1000h-byte step.
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 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
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.
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 |
nocash |
| ||
Normal user Level: 20 Posts: 18/77 EXP: 39067 Next: 3372 Since: 10-09-15 Last post: 2110 days ago Last view: 2025 days ago |
Posted by nocash 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 | Hide post layouts | New reply |
Page rendered in 0.079 seconds. (2048KB of memory used) MySQL - queries: 28, rows: 71/71, time: 0.007 seconds. Acmlmboard 2.064 (2018-07-20) © 2005-2008 Acmlm, Xkeeper, blackhole89 et al. |