Serial Interface

From N64brew Wiki
Jump to navigation Jump to search

The Serial Interface (or SI) is one of multiple I/O interfaces in the RCP, which is used to communicate with the PIF-NUS and in turn, Joybus devices.

Memory mapped registers are used to configure the Serial Interface and initiate DMA reads and writes. The base address for these registers is 0x0480 0000, also known as SI_BASE. However, because all memory accesses in the CPU are made using virtual addresses, the following addresses must be offset appropriately. For non-cached reads/writes, add 0xA000 0000 to the address. As an example, to directly write to the SI_DRAM_ADDR register, use address 0xA480 0000.

In addition to these registers, SI is also in charge of handling the memory mapping of PIF-ROM and PIF-RAM to VR4300. These memories are mapped at physical address 0x1FC0 0000 (and normally accessed via the uncached segment at 0xBFC0 0000).

Mapped PIF-ROM and PIF-RAM

When the VR4300 access the physical area at 0x1FC0 0000 - 0x1FC0 0FFF, RCP handles the request via SI; the memory access performed via standard MIPS opcode like LW or SW is converted into a I/O communication with PIF, using the serial bus.

Read accesses to the mapped area works as 32-bit, 16-bit or 8-bit loads. 64-bit loads freeze the VR4300 instead, so they must be avoided. All read accesses are blocking: the VR4300 will be locked until the data is read via serial from PIF. In general, it is preferable to use DMA instead so that the transfer can happen in background.

Reading from the PIF_ROM area (0x1FC0 0000 - 0x1FC0 0FC0) will simply return 0 after boot is finished, because the PIF locks PIF_ROM accesses for security reasons. This is not something that SI is aware of: it will still request the data via the serial bus to PIF, and PIF will simply return 0.

Write accesses to the mapped area are meant to be done as 32-bit words. 16-bit and 8-bit writes behave in a non-standard way, as they affect the whole 32-bit word they are written to: higher bits are sign-extended, while lower bits are reset to 0. For instance, writing the 8-bit value 0xAB at offset 2 in PIF_RAM has the same effect as writing the 32-bit word 0xFFFFAB00 to offset 0 in PIF_RAM. This is the same behavior of write accesses to IMEM/DMEM in RSP. 64-bit writes only actually write the higher 32-bit word into the written location, so the second half of the write is basically ignored.

Write accesses are non-blocking: the value to be written is cached by the SI interface, and the VR4300 is released. The actual write is performed in background. During the write, the "I/O busy" bit in the SI_STATUS register is set 1. While the bit is set, no further writes, reads or DMAs should be performed as that might cause bus conflicts and thus unwanted results.

Writing to the PIF_ROM area works at the SI level, but the write is then discarded by the PIF.

Registers

Table Notation:

R = Readable bit
W = Writable bit
U = Undefined/Unused bit
-n = Default value n at power on
[x:y] = Specifies bits x to y, inclusively

0x0480 0000 - SI_DRAM_ADDR


SI_DRAM_ADDR 0x0480 0000
31:24 U-0 U-0 U-0 U-0 U-0 U-0 U-0 U-0
23:16 RW-0 RW-0 RW-0 RW-0 RW-0 RW-0 RW-0 RW-0
DRAM_ADDR[23:16]
15:8 RW-0 RW-0 RW-0 RW-0 RW-0 RW-0 RW-0 RW-0
DRAM_ADDR[15:8]
7:0 RW-0 RW-0 RW-0 RW-0 RW-0 RW-0 RW-0 RW-0
DRAM_ADDR[7:0]
bit 31-24 Undefined: Initialized to 0
bit 23-0 DRAM_ADDR[23:0]: RDRAM address used in SI DMAs

0x0480 0004 - SI_PIF_AD_RD64B


SI_PIF_AD_RD64B 0x0480 0004

TODO

0x0480 0008 - SI_PIF_AD_WR4B


SI_PIF_AD_WR4B 0x0480 0008

TODO

0x0480 0010 - SI_PIF_AD_WR64B


SI_PIF_AD_WR64B 0x0480 0010

TODO

0x0480 0014 - SI_PIF_AD_RD4B


SI_PIF_AD_RD4B 0x0480 0014
31:24 U-0 U-0 U-0 U-0 U-0 U-0 U-0 U-0
23:16 U-0 U-0 U-0 U-0 U-0 U-0 U-0 U-0
15:8 RW-0 RW-0 RW-0 RW-0 RW-0 RW-0 RW-0 RW-0
- - - - - PIF_ADDR[10:8]
7:0 RW-0 RW-0 RW-0 RW-0 RW-0 RW-0 U-0 U-0
PIF_ADDR[7:2] 0 0
bit 31-11 Undefined: Initialized to 0
bit 10-2 PIF_ADDR[10:2]: Address in PIF_ROM/PIF_RAM to read data from. Writing to this field should start the DMA transfer, but it actually doesn't work (nothing is transferred).

This register is broken and doesn't work. It was meant to execute a DMA transfer with a RD4B serial frame with PIF (to read 4 bytes from either PIF-ROM or PIF-RAM), but for some reason it does not work, and nothing is transferred. It is still documented here from completeness.

Any read from this register always returns 0. Also, the SI_DRAM_ADDR register is not modified after a write to SI_PIF_AD_RD4B, as the DMA is not performed.

Notice that VR4300 can still do a 32-bit read from PIF-ROM/PIF-RAM using a direct memory read in the memory mapped space (physical address 0x1FC0 0000 - 0x1FC0 07FF and it will work correctly, though it will be a blocking read that will keep the VR4300 blocked as the serial transfer happens.


0x0480 0018 - SI_STATUS


SI_STATUS 0x0480 0018
31:24 U-0 U-0 U-0 U-0 U-0 U-0 U-0 U-0
23:16 U-0 U-0 U-0 U-0 U-0 U-0 U-0 U-0
15:8 U-0 U-0 U-0 R-0 U-0 U-0 U-0 U-0
INTERRUPT DMA_STATE[3:0]
7:0 U-0 U-0 U-0 U-0 R-0 R-0 R-0 R-0
PCH_STATE[3:0] DMA_ERROR READ_PENDING IO_BUSY DMA_BUSY
bit 31-13 Undefined: Initialized to 0
bit 12 INTERRUPT: Copy of SI interrupt flag from MIPS Interface, which is also seen in the RCP Interrupt Cause register.
    Writing any value to SI_STATUS clears this bit in all three locations.
    SI interrupts occur when either a DMA or IO write finishes.
bit 11-8 DMA_STATE[3:0]: Internal-only (likely not readable). Non-zero values indicate activity.
bit 7-4 PCH_STATE[3:0]: Internal-only (likely not readable). Non-zero values indicate activity.
bit 3 DMA_ERROR: Set when overlapping DMA requests occur. Can only be cleared with a power reset.
bit 2 READ_PENDING: Set when an IO read occurs, while an IO or DMA write is in progress.
bit 1 IO_BUSY: Set when a direct memory write to PIF_RAM is in progress.
bit 0 DMA_BUSY: Set when a read or write DMA, or an IO write, is in progress.