From 1adc920a0223954bc086474b15de8f37c2879c0f Mon Sep 17 00:00:00 2001 From: Extrems Date: Fri, 25 Oct 2024 18:58:55 -0400 Subject: [PATCH] - Add basic forward-only W5500 driver in hypervisor. --- cube/patches/Makefile | 78 ++++++--- cube/patches/bba/enc28j60.c | 35 ++-- cube/patches/bba/w5500.c | 270 +++++++++++++++++++++++++++++++ cube/patches/bba/w5500.h | 301 +++++++++++++++++++++++++++++++++++ cube/swiss/include/patcher.h | 18 ++- cube/swiss/source/bba.c | 2 +- cube/swiss/source/patcher.c | 46 ++++-- 7 files changed, 692 insertions(+), 58 deletions(-) create mode 100644 cube/patches/bba/w5500.c create mode 100644 cube/patches/bba/w5500.h diff --git a/cube/patches/Makefile b/cube/patches/Makefile index 827f434e..e3c1f3be 100644 --- a/cube/patches/Makefile +++ b/cube/patches/Makefile @@ -157,14 +157,19 @@ sd-v1.eth.bin: @$(CC) -Os $(OPTS) -c sdgecko/sd.c -DDMA_READ=0 -DISR_READ=1 -DWRITE=0 @$(CC) -Os $(OPTS) -c sdgecko/sd_isr.S @$(CC) -Os $(OPTS) -c bba/enc28j60.c + @$(CC) -Os $(OPTS) -c bba/w5500.c @$(CC) -Os $(OPTS) -c usbgecko/uart.c @$(CC) -Os $(OPTS) -c base/dolphin/os.c @$(CC) -Os $(OPTS) -c base/memcpy.S - @$(CC) -Os $(OPTS) -o sd-v1.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o blockdevice.o sd.o sd_isr.o enc28j60.o uart.o os.o memcpy.o + @$(CC) -Os $(OPTS) -o sd-v1-enc28j60.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o blockdevice.o sd.o sd_isr.o enc28j60.o uart.o os.o memcpy.o + @$(CC) -Os $(OPTS) -o sd-v1-w5500.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o blockdevice.o sd.o sd_isr.o w5500.o uart.o os.o memcpy.o @mkdir -p $(DISASM) - @$(OBJDUMP) -D sd-v1.eth.elf > $(DISASM)/sd-v1.eth.txt - @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents sd-v1.eth.elf sd-v1.eth.bin - @$(BIN2S) -H $(DEST)/sd_v1_eth_bin.h sd-v1.eth.bin > $(DEST)/sd-v1.eth.bin.s + @$(OBJDUMP) -D sd-v1-enc28j60.eth.elf > $(DISASM)/sd-v1-enc28j60.eth.txt + @$(OBJDUMP) -D sd-v1-w5500.eth.elf > $(DISASM)/sd-v1-w5500.eth.txt + @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents sd-v1-enc28j60.eth.elf sd-v1-enc28j60.eth.bin + @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents sd-v1-w5500.eth.elf sd-v1-w5500.eth.bin + @$(BIN2S) -H $(DEST)/sd_v1_enc28j60_eth_bin.h sd-v1-enc28j60.eth.bin > $(DEST)/sd-v1-enc28j60.eth.bin.s + @$(BIN2S) -H $(DEST)/sd_v1_w5500_eth_bin.h sd-v1-w5500.eth.bin > $(DEST)/sd-v1-w5500.eth.bin.s @rm -f *.bin *.elf *.o sd-v2.bin: @@ -246,14 +251,19 @@ sd-v2.eth.bin: @$(CC) -Os $(OPTS) -c sdgecko/sd.c -DDMA_READ=1 -DISR_READ=1 -DWRITE=0 @$(CC) -Os $(OPTS) -c sdgecko/sd_isr.S -DDMA @$(CC) -Os $(OPTS) -c bba/enc28j60.c + @$(CC) -Os $(OPTS) -c bba/w5500.c @$(CC) -Os $(OPTS) -c usbgecko/uart.c @$(CC) -Os $(OPTS) -c base/dolphin/os.c @$(CC) -Os $(OPTS) -c base/memcpy.S - @$(CC) -Os $(OPTS) -o sd-v2.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o blockdevice.o sd.o sd_isr.o enc28j60.o uart.o os.o memcpy.o + @$(CC) -Os $(OPTS) -o sd-v2-enc28j60.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o blockdevice.o sd.o sd_isr.o enc28j60.o uart.o os.o memcpy.o + @$(CC) -Os $(OPTS) -o sd-v2-w5500.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o blockdevice.o sd.o sd_isr.o w5500.o uart.o os.o memcpy.o @mkdir -p $(DISASM) - @$(OBJDUMP) -D sd-v2.eth.elf > $(DISASM)/sd-v2.eth.txt - @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents sd-v2.eth.elf sd-v2.eth.bin - @$(BIN2S) -H $(DEST)/sd_v2_eth_bin.h sd-v2.eth.bin > $(DEST)/sd-v2.eth.bin.s + @$(OBJDUMP) -D sd-v2-enc28j60.eth.elf > $(DISASM)/sd-v2-enc28j60.eth.txt + @$(OBJDUMP) -D sd-v2-w5500.eth.elf > $(DISASM)/sd-v2-w5500.eth.txt + @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents sd-v2-enc28j60.eth.elf sd-v2-enc28j60.eth.bin + @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents sd-v2-w5500.eth.elf sd-v2-w5500.eth.bin + @$(BIN2S) -H $(DEST)/sd_v2_enc28j60_eth_bin.h sd-v2-enc28j60.eth.bin > $(DEST)/sd-v2-enc28j60.eth.bin.s + @$(BIN2S) -H $(DEST)/sd_v2_w5500_eth_bin.h sd-v2-w5500.eth.bin > $(DEST)/sd-v2-w5500.eth.bin.s @rm -f *.bin *.elf *.o ideexi-v1.bin: @@ -335,14 +345,19 @@ ideexi-v1.eth.bin: @$(CC) -Os $(OPTS) -c ide-exi/ata.c -DDMA_READ=0 -DISR_READ=1 -DWRITE=0 @$(CC) -Os $(OPTS) -c ide-exi/ata_isr.S @$(CC) -Os $(OPTS) -c bba/enc28j60.c + @$(CC) -Os $(OPTS) -c bba/w5500.c @$(CC) -Os $(OPTS) -c usbgecko/uart.c @$(CC) -Os $(OPTS) -c base/dolphin/os.c @$(CC) -Os $(OPTS) -c base/memcpy.S - @$(CC) -Os $(OPTS) -o ideexi-v1.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o blockdevice.o ata.o ata_isr.o enc28j60.o uart.o os.o memcpy.o + @$(CC) -Os $(OPTS) -o ideexi-v1-enc28j60.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o blockdevice.o ata.o ata_isr.o enc28j60.o uart.o os.o memcpy.o + @$(CC) -Os $(OPTS) -o ideexi-v1-w5500.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o blockdevice.o ata.o ata_isr.o w5500.o uart.o os.o memcpy.o @mkdir -p $(DISASM) - @$(OBJDUMP) -D ideexi-v1.eth.elf > $(DISASM)/ideexi-v1.eth.txt - @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents ideexi-v1.eth.elf ideexi-v1.eth.bin - @$(BIN2S) -H $(DEST)/ideexi_v1_eth_bin.h ideexi-v1.eth.bin > $(DEST)/ideexi-v1.eth.bin.s + @$(OBJDUMP) -D ideexi-v1-enc28j60.eth.elf > $(DISASM)/ideexi-v1-enc28j60.eth.txt + @$(OBJDUMP) -D ideexi-v1-w5500.eth.elf > $(DISASM)/ideexi-v1-w5500.eth.txt + @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents ideexi-v1-enc28j60.eth.elf ideexi-v1-enc28j60.eth.bin + @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents ideexi-v1-w5500.eth.elf ideexi-v1-w5500.eth.bin + @$(BIN2S) -H $(DEST)/ideexi_v1_enc28j60_eth_bin.h ideexi-v1-enc28j60.eth.bin > $(DEST)/ideexi-v1-enc28j60.eth.bin.s + @$(BIN2S) -H $(DEST)/ideexi_v1_w5500_eth_bin.h ideexi-v1-w5500.eth.bin > $(DEST)/ideexi-v1-w5500.eth.bin.s @rm -f *.bin *.elf *.o ideexi-v2.bin: @@ -424,14 +439,19 @@ ideexi-v2.eth.bin: @$(CC) -Os $(OPTS) -c ide-exi/ata.c -DDMA_READ=1 -DISR_READ=1 -DWRITE=0 @$(CC) -Os $(OPTS) -c ide-exi/ata_isr.S -DDMA @$(CC) -Os $(OPTS) -c bba/enc28j60.c + @$(CC) -Os $(OPTS) -c bba/w5500.c @$(CC) -Os $(OPTS) -c usbgecko/uart.c @$(CC) -Os $(OPTS) -c base/dolphin/os.c @$(CC) -Os $(OPTS) -c base/memcpy.S - @$(CC) -Os $(OPTS) -o ideexi-v2.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o blockdevice.o ata.o ata_isr.o enc28j60.o uart.o os.o memcpy.o + @$(CC) -Os $(OPTS) -o ideexi-v2-enc28j60.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o blockdevice.o ata.o ata_isr.o enc28j60.o uart.o os.o memcpy.o + @$(CC) -Os $(OPTS) -o ideexi-v2-w5500.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o blockdevice.o ata.o ata_isr.o w5500.o uart.o os.o memcpy.o @mkdir -p $(DISASM) - @$(OBJDUMP) -D ideexi-v2.eth.elf > $(DISASM)/ideexi-v2.eth.txt - @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents ideexi-v2.eth.elf ideexi-v2.eth.bin - @$(BIN2S) -H $(DEST)/ideexi_v2_eth_bin.h ideexi-v2.eth.bin > $(DEST)/ideexi-v2.eth.bin.s + @$(OBJDUMP) -D ideexi-v2-enc28j60.eth.elf > $(DISASM)/ideexi-v2-enc28j60.eth.txt + @$(OBJDUMP) -D ideexi-v2-w5500.eth.elf > $(DISASM)/ideexi-v2-w5500.eth.txt + @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents ideexi-v2-enc28j60.eth.elf ideexi-v2-enc28j60.eth.bin + @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents ideexi-v2-w5500.eth.elf ideexi-v2-w5500.eth.bin + @$(BIN2S) -H $(DEST)/ideexi_v2_enc28j60_eth_bin.h ideexi-v2-enc28j60.eth.bin > $(DEST)/ideexi-v2-enc28j60.eth.bin.s + @$(BIN2S) -H $(DEST)/ideexi_v2_w5500_eth_bin.h ideexi-v2-w5500.eth.bin > $(DEST)/ideexi-v2-w5500.eth.bin.s @rm -f *.bin *.elf *.o dvd.bin: @@ -736,14 +756,19 @@ gcloader-v2.eth.bin: @$(CC) -Os $(OPTS) -c base/ipl.c @$(CC) -Os $(OPTS) -c gcloader/gcloader.c @$(CC) -Os $(OPTS) -c bba/enc28j60.c + @$(CC) -Os $(OPTS) -c bba/w5500.c @$(CC) -Os $(OPTS) -c usbgecko/uart.c @$(CC) -Os $(OPTS) -c base/dolphin/os.c @$(CC) -Os $(OPTS) -c base/memcpy.S - @$(CC) -Os $(OPTS) -o gcloader-v2.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o gcloader.o enc28j60.o uart.o os.o memcpy.o + @$(CC) -Os $(OPTS) -o gcloader-v2-enc28j60.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o gcloader.o enc28j60.o uart.o os.o memcpy.o + @$(CC) -Os $(OPTS) -o gcloader-v2-w5500.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o gcloader.o w5500.o uart.o os.o memcpy.o @mkdir -p $(DISASM) - @$(OBJDUMP) -D gcloader-v2.eth.elf > $(DISASM)/gcloader-v2.eth.txt - @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents gcloader-v2.eth.elf gcloader-v2.eth.bin - @$(BIN2S) -H $(DEST)/gcloader_v2_eth_bin.h gcloader-v2.eth.bin > $(DEST)/gcloader-v2.eth.bin.s + @$(OBJDUMP) -D gcloader-v2-enc28j60.eth.elf > $(DISASM)/gcloader-v2-enc28j60.eth.txt + @$(OBJDUMP) -D gcloader-v2-w5500.eth.elf > $(DISASM)/gcloader-v2-w5500.eth.txt + @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents gcloader-v2-enc28j60.eth.elf gcloader-v2-enc28j60.eth.bin + @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents gcloader-v2-w5500.eth.elf gcloader-v2-w5500.eth.bin + @$(BIN2S) -H $(DEST)/gcloader_v2_enc28j60_eth_bin.h gcloader-v2-enc28j60.eth.bin > $(DEST)/gcloader-v2-enc28j60.eth.bin.s + @$(BIN2S) -H $(DEST)/gcloader_v2_w5500_eth_bin.h gcloader-v2-w5500.eth.bin > $(DEST)/gcloader-v2-w5500.eth.bin.s @rm -f *.bin *.elf *.o flippy.bin: @@ -797,12 +822,17 @@ flippy.eth.bin: @$(CC) -Os $(OPTS) -c base/ipl.c @$(CC) -Os $(OPTS) -c flippydrive/flippy.c @$(CC) -Os $(OPTS) -c bba/enc28j60.c + @$(CC) -Os $(OPTS) -c bba/w5500.c @$(CC) -Os $(OPTS) -c usbgecko/uart.c @$(CC) -Os $(OPTS) -c base/dolphin/os.c @$(CC) -Os $(OPTS) -c base/memcpy.S - @$(CC) -Os $(OPTS) -o flippy.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o flippy.o enc28j60.o uart.o os.o memcpy.o + @$(CC) -Os $(OPTS) -o flippy-enc28j60.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o flippy.o enc28j60.o uart.o os.o memcpy.o + @$(CC) -Os $(OPTS) -o flippy-w5500.eth.elf -T base/base.ld -T base/common.ld -T base/dolphin/os.ld base.o emulator.o emulator_eth.o frag.o interrupt.o ipl.o flippy.o w5500.o uart.o os.o memcpy.o @mkdir -p $(DISASM) - @$(OBJDUMP) -D flippy.eth.elf > $(DISASM)/flippy.eth.txt - @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents flippy.eth.elf flippy.eth.bin - @$(BIN2S) -H $(DEST)/flippy_eth_bin.h flippy.eth.bin > $(DEST)/flippy.eth.bin.s + @$(OBJDUMP) -D flippy-enc28j60.eth.elf > $(DISASM)/flippy-enc28j60.eth.txt + @$(OBJDUMP) -D flippy-w5500.eth.elf > $(DISASM)/flippy-w5500.eth.txt + @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents flippy-enc28j60.eth.elf flippy-enc28j60.eth.bin + @$(OBJCOPY) -O binary --set-section-flags .bss.*=alloc,load,contents flippy-w5500.eth.elf flippy-w5500.eth.bin + @$(BIN2S) -H $(DEST)/flippy_enc28j60_eth_bin.h flippy-enc28j60.eth.bin > $(DEST)/flippy-enc28j60.eth.bin.s + @$(BIN2S) -H $(DEST)/flippy_w5500_eth_bin.h flippy-w5500.eth.bin > $(DEST)/flippy-w5500.eth.bin.s @rm -f *.bin *.elf *.o diff --git a/cube/patches/bba/enc28j60.c b/cube/patches/bba/enc28j60.c index 983ba6ec..ca2adeac 100644 --- a/cube/patches/bba/enc28j60.c +++ b/cube/patches/bba/enc28j60.c @@ -41,7 +41,7 @@ static struct { size_t size; bba_callback callback; } output; -} _bba; +} enc28j60; static void exi_clear_interrupts(bool exi, bool tc, bool ext) { @@ -121,11 +121,11 @@ static void enc28j60_select_bank(uint8_t addr) { uint8_t bank = addr >> 5; - if (_bba.bank != bank && bank < 4) { - enc28j60_clear_bits(ENC28J60_ECON1, ENC28J60_ECON1_BSEL(_bba.bank)); + if (enc28j60.bank != bank && bank < 4) { + enc28j60_clear_bits(ENC28J60_ECON1, ENC28J60_ECON1_BSEL(enc28j60.bank)); enc28j60_set_bits(ENC28J60_ECON1, ENC28J60_ECON1_BSEL(bank)); - _bba.bank = bank; + enc28j60.bank = bank; } } @@ -158,11 +158,11 @@ static void enc28j60_interrupt(void) uint16_t byte_count = rsv[1]; //uint16_t status = rsv[2]; - DCInvalidateRange(__builtin_assume_aligned(_bba.page, 32), byte_count); - exi_dma_read(_bba.page, byte_count, true); + DCInvalidateRange(__builtin_assume_aligned(enc28j60.page, 32), byte_count); + exi_dma_read(enc28j60.page, byte_count, true); exi_deselect(); - eth_mac_receive(_bba.page, byte_count - 4); + eth_mac_receive(enc28j60.page, byte_count - 4); enc28j60_write_reg16(ENC28J60_ERDPT, next_packet); enc28j60_write_reg16(ENC28J60_ERXRDPT, next_packet == ENC28J60_INIT_ERXST ? ENC28J60_INIT_ERXND : next_packet - 1); @@ -176,13 +176,14 @@ static void enc28j60_interrupt(void) static void exi_callback() { if (EXILock(exi_channel, exi_device, exi_callback)) { - if (_bba.output.callback) { - bba_output(_bba.output.data, _bba.output.size); - _bba.output.callback(); - _bba.output.callback = NULL; + enc28j60_interrupt(); + + if (enc28j60.output.callback) { + bba_output(enc28j60.output.data, enc28j60.output.size); + enc28j60.output.callback(); + enc28j60.output.callback = NULL; } - enc28j60_interrupt(); EXIUnlock(exi_channel); } } @@ -219,20 +220,20 @@ void bba_output(const void *data, size_t size) void bba_output_async(const void *data, size_t size, bba_callback callback) { - _bba.output.data = (void *)data; - _bba.output.size = size; - _bba.output.callback = callback; + enc28j60.output.data = (void *)data; + enc28j60.output.size = size; + enc28j60.output.callback = callback; exi_callback(); } void bba_init(void **arenaLo, void **arenaHi) { - *arenaHi -= sizeof(*_bba.page); _bba.page = *arenaHi; - enc28j60_clear_bits(ENC28J60_EIE, 0xFF); enc28j60_set_bits(ENC28J60_EIE, ENC28J60_EIE_INTIE | ENC28J60_EIE_PKTIE); + *arenaHi -= sizeof(*enc28j60.page); enc28j60.page = *arenaHi; + if (exi_channel < EXI_CHANNEL_2) { OSInterrupt interrupt = OS_INTERRUPT_EXI_0_EXI + (3 * exi_channel); set_interrupt_handler(interrupt, exi_interrupt_handler); diff --git a/cube/patches/bba/w5500.c b/cube/patches/bba/w5500.c new file mode 100644 index 00000000..cce5beeb --- /dev/null +++ b/cube/patches/bba/w5500.c @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2024, Extrems + * + * This file is part of Swiss. + * + * Swiss is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Swiss is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * with Swiss. If not, see . + */ + +#include +#include +#include +#include +#include "bba.h" +#include "common.h" +#include "dolphin/exi.h" +#include "dolphin/os.h" +#include "emulator_eth.h" +#include "interrupt.h" +#include "w5500.h" + +#define exi_channel ((*VAR_EXI_SLOT & 0x30) >> 4) +#define exi_device ((*VAR_EXI_SLOT & 0xC0) >> 6) +#define exi_regs (*(volatile uint32_t **)VAR_EXI2_REGS) + +static struct { + bool sendok; + uint16_t wr; + uint16_t rd; + bba_page_t (*page)[8]; + struct { + void *data; + size_t size; + bba_callback callback; + } output; +} w5500; + +static void exi_clear_interrupts(bool exi, bool tc, bool ext) +{ + exi_regs[0] = (exi_regs[0] & (0x3FFF & ~0x80A)) | (ext << 11) | (tc << 3) | (exi << 1); +} + +static void exi_select(void) +{ + exi_regs[0] = (exi_regs[0] & 0x405) | ((1 << EXI_DEVICE_0) << 7) | (EXI_SPEED_32MHZ << 4); +} + +static void exi_deselect(void) +{ + exi_regs[0] &= 0x405; +} + +static void exi_imm_write(uint32_t data, uint32_t len) +{ + exi_regs[4] = data; + exi_regs[3] = ((len - 1) << 4) | (EXI_WRITE << 2) | 0b01; + while (exi_regs[3] & 0b01); +} + +static uint32_t exi_imm_read(uint32_t len) +{ + exi_regs[3] = ((len - 1) << 4) | (EXI_READ << 2) | 0b01; + while (exi_regs[3] & 0b01); + return exi_regs[4] >> ((4 - len) * 8); +} + +static uint32_t exi_imm_read_write(uint32_t data, uint32_t len) +{ + exi_regs[4] = data; + exi_regs[3] = ((len - 1) << 4) | (EXI_READ_WRITE << 2) | 0b01; + while (exi_regs[3] & 0b01); + return exi_regs[4] >> ((4 - len) * 8); +} + +static void exi_dma_write(const void *buf, uint32_t len, bool sync) +{ + exi_regs[1] = (uint32_t)buf; + exi_regs[2] = OSRoundUp32B(len); + exi_regs[3] = (EXI_WRITE << 2) | 0b11; + while (sync && (exi_regs[3] & 0b01)); +} + +static void exi_dma_read(void *buf, uint32_t len, bool sync) +{ + exi_regs[1] = (uint32_t)buf; + exi_regs[2] = OSRoundUp32B(len); + exi_regs[3] = (EXI_READ << 2) | 0b11; + while (sync && (exi_regs[3] & 0b01)); +} + +static void w5500_read_cmd(uint32_t cmd, void *buf, uint32_t len) +{ + cmd &= ~W5500_RWB; + cmd = (cmd << 16) | (cmd >> 16); + + exi_select(); + exi_imm_write(cmd, 3); + exi_dma_read(buf, len, true); + exi_deselect(); +} + +static void w5500_write_cmd(uint32_t cmd, const void *buf, uint32_t len) +{ + cmd |= W5500_RWB; + cmd = (cmd << 16) | (cmd >> 16); + + exi_select(); + exi_imm_write(cmd, 3); + exi_dma_write(buf, len, true); + exi_deselect(); +} + +static uint8_t w5500_read_reg8(W5500Reg addr) +{ + uint8_t data; + uint32_t cmd = W5500_OM(1) | addr; + + cmd = (cmd << 16) | (cmd >> 16); + + exi_select(); + data = exi_imm_read_write(cmd, 4); + exi_deselect(); + + return data; +} + +static void w5500_write_reg8(W5500Reg addr, uint8_t data) +{ + uint32_t cmd = W5500_RWB | W5500_OM(1) | addr; + + cmd = (cmd << 16) | (cmd >> 16); + + exi_select(); + exi_imm_read_write(cmd | data, 4); + exi_deselect(); +} + +static uint16_t w5500_read_reg16(W5500Reg16 addr) +{ + uint16_t data; + uint32_t cmd = W5500_OM(2) | addr; + + cmd = (cmd << 16) | (cmd >> 16); + + exi_select(); + exi_imm_write(cmd, 3); + data = exi_imm_read(2); + exi_deselect(); + + return data; +} + +static void w5500_write_reg16(W5500Reg16 addr, uint16_t data) +{ + uint32_t cmd = W5500_RWB | W5500_OM(2) | addr; + + cmd = (cmd << 16) | (cmd >> 16); + + exi_select(); + exi_imm_write(cmd, 3); + exi_imm_write(data << 16, 2); + exi_deselect(); +} + +static void w5500_interrupt(void) +{ + w5500_write_reg8(W5500_SIMR, 0); + uint8_t ir = w5500_read_reg8(W5500_S0_IR); + + if (ir & W5500_Sn_IR_SENDOK) { + w5500_write_reg8(W5500_S0_IR, W5500_Sn_IR_SENDOK); + w5500.sendok = true; + } + + if (ir & W5500_Sn_IR_RECV) { + w5500_write_reg8(W5500_S0_IR, W5500_Sn_IR_RECV); + + uint16_t rd = w5500.rd; + uint16_t rs = w5500_read_reg16(W5500_RXBUF_S(0, rd)); + w5500.rd = rd + rs; + + rd += sizeof(rs); + rs -= sizeof(rs); + + DCInvalidateRange(__builtin_assume_aligned(w5500.page, 32), rs); + w5500_read_cmd(W5500_RXBUF_S(0, rd), w5500.page, rs); + eth_mac_receive(w5500.page, rs); + + w5500_write_reg16(W5500_S0_RX_RD, w5500.rd); + w5500_write_reg8(W5500_S0_CR, W5500_Sn_CR_RECV); + } + + w5500_write_reg8(W5500_SIMR, W5500_SIMR_S(0)); +} + +static void exi_callback() +{ + if (EXILock(exi_channel, exi_device, exi_callback)) { + w5500_interrupt(); + + if (w5500.output.callback && w5500.sendok) { + bba_output(w5500.output.data, w5500.output.size); + w5500.output.callback(); + w5500.output.callback = NULL; + } + + EXIUnlock(exi_channel); + } +} + +static void exi_interrupt_handler(OSInterrupt interrupt, OSContext *context) +{ + exi_clear_interrupts(true, false, false); + exi_callback(); +} + +static void debug_interrupt_handler(OSInterrupt interrupt, OSContext *context) +{ + PI[0] = 1 << 12; + exi_callback(); +} + +void bba_output(const void *data, size_t size) +{ + DCStoreRange(__builtin_assume_aligned(data, 32), size); + w5500_write_cmd(W5500_TXBUF_S(0, w5500.wr), data, size); + w5500.wr += size; + + w5500_write_reg16(W5500_S0_TX_WR, w5500.wr); + w5500_write_reg8(W5500_S0_CR, W5500_Sn_CR_SEND); + w5500.sendok = false; +} + +void bba_output_async(const void *data, size_t size, bba_callback callback) +{ + w5500.output.data = (void *)data; + w5500.output.size = size; + w5500.output.callback = callback; + + exi_callback(); +} + +void bba_init(void **arenaLo, void **arenaHi) +{ + w5500.sendok = w5500_read_reg16(W5500_S0_TX_FSR) == W5500_TX_BUFSIZE; + + w5500.wr = w5500_read_reg16(W5500_S0_TX_WR); + w5500.rd = w5500_read_reg16(W5500_S0_RX_RD); + + *arenaHi -= sizeof(*w5500.page); w5500.page = *arenaHi; + + if (exi_channel < EXI_CHANNEL_2) { + OSInterrupt interrupt = OS_INTERRUPT_EXI_0_EXI + (3 * exi_channel); + set_interrupt_handler(interrupt, exi_interrupt_handler); + unmask_interrupts(OS_INTERRUPTMASK(interrupt) & (OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_1_EXI)); + } else { + set_interrupt_handler(OS_INTERRUPT_PI_DEBUG, debug_interrupt_handler); + unmask_interrupts(OS_INTERRUPTMASK_PI_DEBUG); + } +} diff --git a/cube/patches/bba/w5500.h b/cube/patches/bba/w5500.h new file mode 100644 index 00000000..7265ed6e --- /dev/null +++ b/cube/patches/bba/w5500.h @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2024, Extrems + * + * This file is part of Swiss. + * + * Swiss is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Swiss is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * with Swiss. If not, see . + */ + +#ifndef W5500_H +#define W5500_H + +#define W5500_BSB(x) (((x) & 0x1F) << 27) // Block Select Bits +#define W5500_RWB (1 << 26) // Read/Write Access Mode Bit +#define W5500_OM(x) (((x) & 0x3) << 24) // SPI Operation Mode Bits +#define W5500_ADDR(x) ((x) & 0xFFFF) // Offset Address + +#define W5500_REG(addr) (W5500_BSB(0) | W5500_ADDR(addr)) +#define W5500_REG_S(n, addr) (W5500_BSB(n * 4 + 1) | W5500_ADDR(addr)) +#define W5500_TXBUF_S(n, addr) (W5500_BSB(n * 4 + 2) | W5500_ADDR(addr)) +#define W5500_RXBUF_S(n, addr) (W5500_BSB(n * 4 + 3) | W5500_ADDR(addr)) + +#define W5500_INIT_S0_RXBUF_SIZE (16) +#define W5500_INIT_S0_TXBUF_SIZE (16) + +enum { + Sn_MR = 0x00, // Socket n Mode Register + Sn_CR, // Socket n Command Register + Sn_IR, // Socket n Interrupt Register + Sn_SR, // Socket n Status Register + Sn_PORT, // Socket n Source Port Register + Sn_DHAR = 0x06, // Socket n Destination Hardware Address Register + Sn_DIPR = 0x0C, // Socket n Destination IP Address Register + Sn_DPORT = 0x10, // Socket n Destination Port Register + Sn_MSSR = 0x12, // Socket n Maximum Segment Size Register + Sn_TOS = 0x15, // Socket n IP TOS Register + Sn_TTL, // Socket n IP TTL Register + Sn_RXBUF_SIZE = 0x1E, // Socket n RX Buffer Size Register + Sn_TXBUF_SIZE, // Socket n TX Buffer Size Register + Sn_TX_FSR, // Socket n TX Free Buffer Size Register + Sn_TX_RD = 0x22, // Socket n TX Read Pointer Register + Sn_TX_WR = 0x24, // Socket n TX Write Pointer Register + Sn_RX_RSR = 0x26, // Socket n RX Received Size Register + Sn_RX_RD = 0x28, // Socket n RX Read Pointer Register + Sn_RX_WR = 0x2A, // Socket n RX Write Pointer Register + Sn_IMR = 0x2C, // Socket n Interrupt Mask Register + Sn_FRAG, // Socket n Fragment Offset in IP Header Register + Sn_KPALVTR = 0x2F, // Socket n Keepalive Time Register +}; + +typedef enum { + W5500_MR = W5500_REG(0x00), // Mode Register + W5500_GAR0, // Gateway IP Address Register 0 + W5500_GAR1, // Gateway IP Address Register 1 + W5500_GAR2, // Gateway IP Address Register 2 + W5500_GAR3, // Gateway IP Address Register 3 + W5500_SUBR0, // Subnet Mask Register 0 + W5500_SUBR1, // Subnet Mask Register 1 + W5500_SUBR2, // Subnet Mask Register 2 + W5500_SUBR3, // Subnet Mask Register 3 + W5500_SHAR0, // Source Hardware Address Register 0 + W5500_SHAR1, // Source Hardware Address Register 1 + W5500_SHAR2, // Source Hardware Address Register 2 + W5500_SHAR3, // Source Hardware Address Register 3 + W5500_SHAR4, // Source Hardware Address Register 4 + W5500_SHAR5, // Source Hardware Address Register 5 + W5500_SIPR0, // Source IP Address Register 0 + W5500_SIPR1, // Source IP Address Register 1 + W5500_SIPR2, // Source IP Address Register 2 + W5500_SIPR3, // Source IP Address Register 3 + W5500_INTLEVEL0, // Interrupt Low-Level Timer Register 0 + W5500_INTLEVEL1, // Interrupt Low-Level Timer Register 1 + W5500_IR, // Interrupt Register + W5500_IMR, // Interrupt Mask Register + W5500_SIR, // Socket Interrupt Register + W5500_SIMR, // Socket Interrupt Mask Register + W5500_RTR0, // Retransmission Time Register 0 + W5500_RTR1, // Retransmission Time Register 1 + W5500_RCR, // Retransmission Count Register + W5500_PTIMER, // PPP LCP Request Timer Register + W5500_PMAGIC, // PPP LCP Magic Number Register + W5500_PHAR0, // PPPoE Server Hardware Address Register 0 + W5500_PHAR1, // PPPoE Server Hardware Address Register 1 + W5500_PHAR2, // PPPoE Server Hardware Address Register 2 + W5500_PHAR3, // PPPoE Server Hardware Address Register 3 + W5500_PHAR4, // PPPoE Server Hardware Address Register 4 + W5500_PHAR5, // PPPoE Server Hardware Address Register 5 + W5500_PSID0, // PPPoE Session ID Register 0 + W5500_PSID1, // PPPoE Session ID Register 1 + W5500_PMRU0, // PPPoE Maximum Receive Unit Register 0 + W5500_PMRU1, // PPPoE Maximum Receive Unit Register 1 + W5500_UIPR0, // Unreachable IP Address Register 0 + W5500_UIPR1, // Unreachable IP Address Register 1 + W5500_UIPR2, // Unreachable IP Address Register 2 + W5500_UIPR3, // Unreachable IP Address Register 3 + W5500_UPORTR0, // Unreachable Port Register 0 + W5500_UPORTR1, // Unreachable Port Register 1 + W5500_PHYCFGR, // PHY Configuration Register + W5500_VERSIONR = W5500_REG(0x39), // Chip Version Register + +#define W5500_S(n) \ + W5500_S##n##_MR = W5500_REG_S(n, Sn_MR), \ + W5500_S##n##_CR, \ + W5500_S##n##_IR, \ + W5500_S##n##_SR, \ + W5500_S##n##_PORT0, \ + W5500_S##n##_PORT1, \ + W5500_S##n##_DHAR0, \ + W5500_S##n##_DHAR1, \ + W5500_S##n##_DHAR2, \ + W5500_S##n##_DHAR3, \ + W5500_S##n##_DHAR4, \ + W5500_S##n##_DHAR5, \ + W5500_S##n##_DIPR0, \ + W5500_S##n##_DIPR1, \ + W5500_S##n##_DIPR2, \ + W5500_S##n##_DIPR3, \ + W5500_S##n##_DPORT0, \ + W5500_S##n##_DPORT1, \ + W5500_S##n##_MSSR0, \ + W5500_S##n##_MSSR1, \ + W5500_S##n##_TOS = W5500_REG_S(n, Sn_TOS), \ + W5500_S##n##_TTL, \ + W5500_S##n##_RXBUF_SIZE = W5500_REG_S(n, Sn_RXBUF_SIZE), \ + W5500_S##n##_TXBUF_SIZE, \ + W5500_S##n##_TX_FSR0, \ + W5500_S##n##_TX_FSR1, \ + W5500_S##n##_TX_RD0, \ + W5500_S##n##_TX_RD1, \ + W5500_S##n##_TX_WR0, \ + W5500_S##n##_TX_WR1, \ + W5500_S##n##_RX_RSR0, \ + W5500_S##n##_RX_RSR1, \ + W5500_S##n##_RX_RD0, \ + W5500_S##n##_RX_RD1, \ + W5500_S##n##_RX_WR0, \ + W5500_S##n##_RX_WR1, \ + W5500_S##n##_IMR, \ + W5500_S##n##_FRAG0, \ + W5500_S##n##_FRAG1, \ + W5500_S##n##_KPALVTR, \ + +W5500_S(0) +W5500_S(1) +W5500_S(2) +W5500_S(3) +W5500_S(4) +W5500_S(5) +W5500_S(6) +W5500_S(7) +#undef W5500_S +} W5500Reg; + +typedef enum { + W5500_INTLEVEL = W5500_REG(0x13), // Interrupt Low-Level Timer Register + W5500_RTR = W5500_REG(0x19), // Retransmission Time Register + W5500_PSID = W5500_REG(0x24), // PPPoE Session ID Register + W5500_PMRU = W5500_REG(0x26), // PPPoE Maximum Receive Unit Register + W5500_UPORTR = W5500_REG(0x2C), // Unreachable Port Register + +#define W5500_S(n) \ + W5500_S##n##_PORT = W5500_REG_S(n, Sn_PORT), \ + W5500_S##n##_DPORT = W5500_REG_S(n, Sn_DPORT), \ + W5500_S##n##_MSSR = W5500_REG_S(n, Sn_MSSR), \ + W5500_S##n##_TX_FSR = W5500_REG_S(n, Sn_TX_FSR), \ + W5500_S##n##_TX_RD = W5500_REG_S(n, Sn_TX_RD), \ + W5500_S##n##_TX_WR = W5500_REG_S(n, Sn_TX_WR), \ + W5500_S##n##_RX_RSR = W5500_REG_S(n, Sn_RX_RSR), \ + W5500_S##n##_RX_RD = W5500_REG_S(n, Sn_RX_RD), \ + W5500_S##n##_RX_WR = W5500_REG_S(n, Sn_RX_WR), \ + W5500_S##n##_FRAG = W5500_REG_S(n, Sn_FRAG), \ + +W5500_S(0) +W5500_S(1) +W5500_S(2) +W5500_S(3) +W5500_S(4) +W5500_S(5) +W5500_S(6) +W5500_S(7) +#undef W5500_S +} W5500Reg16; + +typedef enum { + W5500_GAR = W5500_REG(0x01), // Gateway IP Address Register + W5500_SUBR = W5500_REG(0x05), // Subnet Mask Register + W5500_SIPR = W5500_REG(0x0F), // Source IP Address Register + W5500_UIPR = W5500_REG(0x28), // Unreachable IP Address Register + +#define W5500_S(n) \ + W5500_S##n##_DIPR = W5500_REG_S(n, Sn_DIPR), \ + +W5500_S(0) +W5500_S(1) +W5500_S(2) +W5500_S(3) +W5500_S(4) +W5500_S(5) +W5500_S(6) +W5500_S(7) +#undef W5500_S +} W5500Reg32; + +#define W5500_MR_RST (1 << 7) // Software Reset +#define W5500_MR_WOL (1 << 5) // Wake-on-LAN +#define W5500_MR_PB (1 << 4) // Ping Reply Block +#define W5500_MR_PPPOE (1 << 3) // PPPoE Mode +#define W5500_MR_FARP (1 << 1) // Force ARP + +#define W5500_IR_CONFLICT (1 << 7) // IP Conflict Interrupt +#define W5500_IR_UNREACH (1 << 6) // Destination Port Unreachable Interrupt +#define W5500_IR_PPPOE (1 << 5) // PPPoE Terminated Interrupt +#define W5500_IR_MP (1 << 4) // WOL Magic Packet Interrupt + +#define W5500_IMR_CONFLICT (1 << 7) // IP Conflict Interrupt Mask +#define W5500_IMR_UNREACH (1 << 6) // Destination Port Unreachable Interrupt Mask +#define W5500_IMR_PPPOE (1 << 5) // PPPoE Terminated Interrupt Mask +#define W5500_IMR_MP (1 << 4) // WOL Magic Packet Interrupt Mask + +#define W5500_SIR_S(n) (1 << (n)) // Socket n Interrupt + +#define W5500_SIMR_S(n) (1 << (n)) // Socket n Interrupt Mask + +#define W5500_PHYCFGR_RST (1 << 7) // PHY Reset +#define W5500_PHYCFGR_OPMD (1 << 6) // Configure PHY Operation Mode +#define W5500_PHYCFGR_OPMDC(x) (((x) & 0x7) << 3) // PHY Operation Mode Configuration +#define W5500_PHYCFGR_DPX (1 << 2) // PHY Duplex Status +#define W5500_PHYCFGR_SPD (1 << 1) // PHY Speed Status +#define W5500_PHYCFGR_LNK (1 << 0) // PHY Link Status + +#define W5500_Sn_MR_MULTI (1 << 7) // Multicast Mode +#define W5500_Sn_MR_MFEN (1 << 7) // MAC Filter Enable +#define W5500_Sn_MR_BCASTB (1 << 6) // Broadcast Block +#define W5500_Sn_MR_ND (1 << 5) // No Delayed ACK +#define W5500_Sn_MR_MC (1 << 5) // Multicast IGMP Version +#define W5500_Sn_MR_MMB (1 << 5) // Multicast Block in MACRAW Mode +#define W5500_Sn_MR_UCASTB (1 << 4) // Unicast Block +#define W5500_Sn_MR_MIP6B (1 << 4) // IPv6 Block in MACRAW Mode +#define W5500_Sn_MR_P(x) (((x) & 0xF) << 0) // Protocol Mode + +enum { + W5500_Sn_MR_CLOSE = 0x00, + W5500_Sn_MR_TCP, + W5500_Sn_MR_UDP, + W5500_Sn_MR_MACRAW = 0x04, +}; + +enum { + W5500_Sn_CR_OPEN = 0x01, + W5500_Sn_CR_LISTEN, + W5500_Sn_CR_CONNECT = 0x04, + W5500_Sn_CR_DISCON = 0x08, + W5500_Sn_CR_CLOSE = 0x10, + W5500_Sn_CR_SEND = 0x20, + W5500_Sn_CR_SEND_MAC, + W5500_Sn_CR_SEND_KEEP, + W5500_Sn_CR_RECV = 0x40, +}; + +#define W5500_Sn_IR_SENDOK (1 << 4) // SEND OK Interrupt +#define W5500_Sn_IR_TIMEOUT (1 << 3) // TIMEOUT Interrupt +#define W5500_Sn_IR_RECV (1 << 2) // RECEIVED Interrupt +#define W5500_Sn_IR_DISCON (1 << 1) // DISCONNECTED Interrupt +#define W5500_Sn_IR_CON (1 << 0) // CONNECTED Interrupt + +enum { + W5500_Sn_SR_CLOSED = 0x00, + W5500_Sn_SR_INIT = 0x13, + W5500_Sn_SR_LISTEN, + W5500_Sn_SR_SYNSENT, + W5500_Sn_SR_SYNRECV, + W5500_Sn_SR_ESTABLISHED, + W5500_Sn_SR_FIN_WAIT, + W5500_Sn_SR_CLOSING = 0x1A, + W5500_Sn_SR_TIME_WAIT, + W5500_Sn_SR_CLOSE_WAIT, + W5500_Sn_SR_LAST_ACK, + W5500_Sn_SR_UDP = 0x22, + W5500_Sn_SR_MACRAW = 0x42, +}; + +#define W5500_Sn_IMR_SENDOK (1 << 4) // SEND OK Interrupt Mask +#define W5500_Sn_IMR_TIMEOUT (1 << 3) // TIMEOUT Interrupt Mask +#define W5500_Sn_IMR_RECV (1 << 2) // RECEIVED Interrupt Mask +#define W5500_Sn_IMR_DISCON (1 << 1) // DISCONNECTED Interrupt Mask +#define W5500_Sn_IMR_CON (1 << 0) // CONNECTED Interrupt Mask + +#define W5500_TX_BUFSIZE (W5500_INIT_S0_TXBUF_SIZE * 1024) +#define W5500_TX_QUEUELEN ((W5500_TX_BUFSIZE * 27) / (1536 * 20)) + +#endif /* W5500_H */ diff --git a/cube/swiss/include/patcher.h b/cube/swiss/include/patcher.h index 30da5ac2..0f0579ec 100644 --- a/cube/swiss/include/patcher.h +++ b/cube/swiss/include/patcher.h @@ -22,19 +22,23 @@ typedef struct FuncPattern #include "sd_v1_bin.h" #include "sd_v1_card_bin.h" #include "sd_v1_dtk_bin.h" -#include "sd_v1_eth_bin.h" +#include "sd_v1_enc28j60_eth_bin.h" +#include "sd_v1_w5500_eth_bin.h" #include "sd_v2_bin.h" #include "sd_v2_card_bin.h" #include "sd_v2_dtk_bin.h" -#include "sd_v2_eth_bin.h" +#include "sd_v2_enc28j60_eth_bin.h" +#include "sd_v2_w5500_eth_bin.h" #include "ideexi_v1_bin.h" #include "ideexi_v1_card_bin.h" #include "ideexi_v1_dtk_bin.h" -#include "ideexi_v1_eth_bin.h" +#include "ideexi_v1_enc28j60_eth_bin.h" +#include "ideexi_v1_w5500_eth_bin.h" #include "ideexi_v2_bin.h" #include "ideexi_v2_card_bin.h" #include "ideexi_v2_dtk_bin.h" -#include "ideexi_v2_eth_bin.h" +#include "ideexi_v2_enc28j60_eth_bin.h" +#include "ideexi_v2_w5500_eth_bin.h" #include "dvd_bin.h" #include "dvd_card_bin.h" #include "usbgecko_bin.h" @@ -49,10 +53,12 @@ typedef struct FuncPattern #include "gcloader_v2_bin.h" #include "gcloader_v2_card_bin.h" #include "gcloader_v2_dtk_bin.h" -#include "gcloader_v2_eth_bin.h" +#include "gcloader_v2_enc28j60_eth_bin.h" +#include "gcloader_v2_w5500_eth_bin.h" #include "flippy_bin.h" #include "flippy_card_bin.h" -#include "flippy_eth_bin.h" +#include "flippy_enc28j60_eth_bin.h" +#include "flippy_w5500_eth_bin.h" /* SDK patches */ #include "backwards_memcpy_bin.h" diff --git a/cube/swiss/source/bba.c b/cube/swiss/source/bba.c index ccdeffbc..a79fe46f 100644 --- a/cube/swiss/source/bba.c +++ b/cube/swiss/source/bba.c @@ -53,7 +53,7 @@ static void *net_thread_func(void *arg) } else if (ifname[0] == 'e') bba_location = LOC_SERIAL_PORT_1; - if (ifname[0] == 'E' && strchr("2AB", ifname[1])) { + if (strchr("EW", ifname[0]) && strchr("2AB", ifname[1])) { __device_flippy.emulable |= EMU_ETHERNET; __device_flippyflash.emulable |= EMU_ETHERNET; if (__device_gcloader.features & FEAT_PATCHES) diff --git a/cube/swiss/source/patcher.c b/cube/swiss/source/patcher.c index b7b29742..c584b573 100644 --- a/cube/swiss/source/patcher.c +++ b/cube/swiss/source/patcher.c @@ -21,6 +21,7 @@ #include "sidestep.h" #include "elf.h" #include "ata.h" +#include "bba.h" #include "cheats.h" char VAR_AREA[0x3100]; @@ -184,8 +185,13 @@ int install_code(int final) patchSize = !_ideexi_version ? ideexi_v1_card_bin_size : ideexi_v2_card_bin_size; break; case EMU_READ | EMU_ETHERNET | EMU_BUS_ARBITER | EMU_NO_PAUSING: - patch = !_ideexi_version ? ideexi_v1_eth_bin : ideexi_v2_eth_bin; - patchSize = !_ideexi_version ? ideexi_v1_eth_bin_size : ideexi_v2_eth_bin_size; + if (!strcmp(bba_device_str, "ENC28J60")) { + patch = !_ideexi_version ? ideexi_v1_enc28j60_eth_bin : ideexi_v2_enc28j60_eth_bin; + patchSize = !_ideexi_version ? ideexi_v1_enc28j60_eth_bin_size : ideexi_v2_enc28j60_eth_bin_size; + } else if (!strcmp(bba_device_str, "WIZnet W5500")) { + patch = !_ideexi_version ? ideexi_v1_w5500_eth_bin : ideexi_v2_w5500_eth_bin; + patchSize = !_ideexi_version ? ideexi_v1_w5500_eth_bin_size : ideexi_v2_w5500_eth_bin_size; + } break; default: return 0; @@ -210,8 +216,13 @@ int install_code(int final) patchSize = sd_v1_card_bin_size; break; case EMU_READ | EMU_ETHERNET | EMU_BUS_ARBITER | EMU_NO_PAUSING: - patch = sd_v1_eth_bin; - patchSize = sd_v1_eth_bin_size; + if (!strcmp(bba_device_str, "ENC28J60")) { + patch = sd_v1_enc28j60_eth_bin; + patchSize = sd_v1_enc28j60_eth_bin_size; + } else if (!strcmp(bba_device_str, "WIZnet W5500")) { + patch = sd_v1_w5500_eth_bin; + patchSize = sd_v1_w5500_eth_bin_size; + } break; default: return 0; @@ -232,8 +243,13 @@ int install_code(int final) patchSize = sd_v2_card_bin_size; break; case EMU_READ | EMU_ETHERNET | EMU_BUS_ARBITER | EMU_NO_PAUSING: - patch = sd_v2_eth_bin; - patchSize = sd_v2_eth_bin_size; + if (!strcmp(bba_device_str, "ENC28J60")) { + patch = sd_v2_enc28j60_eth_bin; + patchSize = sd_v2_enc28j60_eth_bin_size; + } else if (!strcmp(bba_device_str, "WIZnet W5500")) { + patch = sd_v2_w5500_eth_bin; + patchSize = sd_v2_w5500_eth_bin_size; + } break; default: return 0; @@ -357,8 +373,13 @@ int install_code(int final) patchSize = gcloader_v2_card_bin_size; break; case EMU_READ | EMU_ETHERNET | EMU_BUS_ARBITER | EMU_NO_PAUSING: - patch = gcloader_v2_eth_bin; - patchSize = gcloader_v2_eth_bin_size; + if (!strcmp(bba_device_str, "ENC28J60")) { + patch = gcloader_v2_enc28j60_eth_bin; + patchSize = gcloader_v2_enc28j60_eth_bin_size; + } else if (!strcmp(bba_device_str, "WIZnet W5500")) { + patch = gcloader_v2_w5500_eth_bin; + patchSize = gcloader_v2_w5500_eth_bin_size; + } break; default: return 0; @@ -379,8 +400,13 @@ int install_code(int final) patchSize = flippy_card_bin_size; break; case EMU_READ | EMU_ETHERNET | EMU_BUS_ARBITER | EMU_NO_PAUSING: - patch = flippy_eth_bin; - patchSize = flippy_eth_bin_size; + if (!strcmp(bba_device_str, "ENC28J60")) { + patch = flippy_enc28j60_eth_bin; + patchSize = flippy_enc28j60_eth_bin_size; + } else if (!strcmp(bba_device_str, "WIZnet W5500")) { + patch = flippy_w5500_eth_bin; + patchSize = flippy_w5500_eth_bin_size; + } break; default: return 0;