From ae12bf4318141ee216da3524ba94dacd68ad2e3f Mon Sep 17 00:00:00 2001 From: wilkovatch <29335145+wilkovatch@users.noreply.github.com> Date: Fri, 21 Mar 2025 22:37:41 +0100 Subject: [PATCH 01/47] vl: Always pass dvd_path to the driver and handle errors --- system/vl.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/system/vl.c b/system/vl.c index 580d0cfd28..d32b6e2d0a 100644 --- a/system/vl.c +++ b/system/vl.c @@ -651,8 +651,20 @@ static int cleanup_add_fd(void *opaque, QemuOpts *opts, Error **errp) static int drive_init_func(void *opaque, QemuOpts *opts, Error **errp) { BlockInterfaceType *block_default_type = opaque; + const char *file_path = qemu_opt_get(opts, "file"); + bool is_cdrom_with_file = !strcmp(qemu_opt_get(opts, "media"), "cdrom") && strlen(file_path) > 0; - return drive_new(opts, *block_default_type, errp) == NULL; + bool failed = drive_new(opts, *block_default_type, is_cdrom_with_file ? &error_warn : errp) == NULL; + + if (failed && is_cdrom_with_file) { + char *msg = g_strdup_printf("Failed to open DVD image file '%s'. Please check machine settings.", file_path); + xemu_queue_error_message(msg); + g_free(msg); + qemu_opt_set(opts, "file", "", errp); + failed = drive_new(opts, *block_default_type, errp) == NULL; + } + + return failed; } static int drive_enable_snapshot(void *opaque, QemuOpts *opts, Error **errp) @@ -2972,15 +2984,6 @@ void qemu_init(int argc, char **argv) } } - if (strlen(dvd_path) > 0) { - if (xemu_check_file(dvd_path) || strcmp(dvd_path, hdd_path) == 0) { - char *msg = g_strdup_printf("Failed to open DVD image file '%s'. Please check machine settings.", dvd_path); - xemu_queue_error_message(msg); - g_free(msg); - dvd_path = ""; - } - } - // Always populate DVD drive. If disc path is the empty string, drive is // connected but no media present. fake_argv[fake_argc++] = strdup("-drive"); From 4b4bef8bb91ffc26c7cf5001fcc262b842837f54 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 03:34:58 +0000 Subject: [PATCH 02/47] ci: bump softprops/action-gh-release from 2.2.2 to 2.3.2 Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.2.2 to 2.3.2. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/da05d552573ad5aba039eaac05058a918a7bf631...72f2c25fcb47643c292f7107632f7a47c1df5cd8) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-version: 2.3.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7b57efd6be..118f850806 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -420,7 +420,7 @@ jobs: run: | cp dist/xemu-win-x86_64-release-pdb/xemu-win-x86_64-release.zip dist/xemu-win-x86_64-release-pdb/xemu-win-release.zip - name: Publish release - uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # v2.2.2 + uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8 # v2.3.2 with: tag_name: v${{ env.XEMU_VERSION }} name: v${{ env.XEMU_VERSION }} From 381bcfcf635cb8546383aea946945fef09613293 Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Tue, 17 Jun 2025 11:57:13 -0700 Subject: [PATCH 03/47] ui: Add .xiso to load disc file filter --- ui/xui/actions.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/xui/actions.cc b/ui/xui/actions.cc index dc2c830c50..1d42d78643 100644 --- a/ui/xui/actions.cc +++ b/ui/xui/actions.cc @@ -38,7 +38,8 @@ void ActionLoadDisc(void) { Error *err = NULL; - const char *iso_file_filters = ".iso Files\0*.iso\0All Files\0*.*\0"; + const char *iso_file_filters = + "Disc Image Files (*.iso, *.xiso)\0*.iso;*.xiso\0All Files\0*.*\0"; const char *new_disc_path = PausedFileOpen(NOC_FILE_DIALOG_OPEN, iso_file_filters, g_config.sys.files.dvd_path, NULL); From 2027d5bc67e8868105d070a2b7512f79a3438c10 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 04/47] nvnet: Use hw/net/mii.h hw/net/mii.h provides common definitions for MII. --- hw/xbox/mcpx/nvnet/nvnet.c | 23 ++++++++++++----------- hw/xbox/mcpx/nvnet/nvnet_regs.h | 15 --------------- 2 files changed, 12 insertions(+), 26 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index fef42f0360..90e63294e2 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -21,6 +21,7 @@ #include "qemu/osdep.h" #include "trace.h" #include "hw/hw.h" +#include "hw/net/mii.h" #include "hw/pci/pci.h" #include "hw/pci/pci_device.h" #include "hw/qdev-properties.h" @@ -254,17 +255,17 @@ static int nvnet_mii_rw(NvNetState *s, uint64_t val) switch (reg) { case MII_BMSR: - /* Phy initialization code waits for BIT2 to be set.. If not set, - * software may report controller as not running */ - retval = BMSR_ANEGCOMPLETE | BMSR_BIT2; + /* Phy initialization code waits for MII_BMSR_LINK_ST to be set.. If not + set, software may report controller as not running */ + retval = MII_BMSR_AN_COMP | MII_BMSR_LINK_ST; break; - case MII_ADVERTISE: + case MII_ANAR: /* Fall through... */ - case MII_LPA: - retval = LPA_10HALF | LPA_10FULL; - retval |= LPA_100HALF | LPA_100FULL | LPA_100BASE4; + case MII_ANLPAR: + retval = MII_ANLPAR_10 | MII_ANLPAR_10FD | MII_ANLPAR_TX | + MII_ANLPAR_TXFD | MII_ANLPAR_T4; break; default: @@ -882,12 +883,12 @@ static const char *nvnet_get_reg_name(hwaddr addr) static const char *nvnet_get_mii_reg_name(uint8_t reg) { switch (reg) { - case MII_PHYSID1: return "MII_PHYSID1"; - case MII_PHYSID2: return "MII_PHYSID2"; + case MII_PHYID1: return "MII_PHYID1"; + case MII_PHYID2: return "MII_PHYID2"; case MII_BMCR: return "MII_BMCR"; case MII_BMSR: return "MII_BMSR"; - case MII_ADVERTISE: return "MII_ADVERTISE"; - case MII_LPA: return "MII_LPA"; + case MII_ANAR: return "MII_ANAR"; + case MII_ANLPAR: return "MII_ANLPAR"; default: return "Unknown"; } } diff --git a/hw/xbox/mcpx/nvnet/nvnet_regs.h b/hw/xbox/mcpx/nvnet/nvnet_regs.h index 7a1744f7bc..c99f5b2b0a 100644 --- a/hw/xbox/mcpx/nvnet/nvnet_regs.h +++ b/hw/xbox/mcpx/nvnet/nvnet_regs.h @@ -271,26 +271,11 @@ enum { #define POLL_WAIT (1 + HZ / 100) #define MII_READ (-1) -#define MII_PHYSID1 0x02 /* PHYS ID 1 */ -#define MII_PHYSID2 0x03 /* PHYS ID 2 */ -#define MII_BMCR 0x00 /* Basic mode control register */ -#define MII_BMSR 0x01 /* Basic mode status register */ -#define MII_ADVERTISE 0x04 /* Advertisement control reg */ -#define MII_LPA 0x05 /* Link partner ability reg */ - -#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */ -#define BMSR_BIT2 0x0004 /* Unknown... */ /* Link partner ability register. */ #define LPA_SLCT 0x001f /* Same as advertise selector */ -#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */ -#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */ -#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */ -#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */ -#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */ #define LPA_RESV 0x1c00 /* Unused... */ #define LPA_RFAULT 0x2000 /* Link partner faulted */ -#define LPA_LPACK 0x4000 /* Link partner acked us */ #define LPA_NPAGE 0x8000 /* Next page bit */ // clang-format off From 928be451d9c75e0dc43a11564e74045f08a36abe Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 05/47] nvnet: Drop unnecessary comment --- hw/xbox/mcpx/nvnet/nvnet.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 90e63294e2..82777fe910 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -255,8 +255,6 @@ static int nvnet_mii_rw(NvNetState *s, uint64_t val) switch (reg) { case MII_BMSR: - /* Phy initialization code waits for MII_BMSR_LINK_ST to be set.. If not - set, software may report controller as not running */ retval = MII_BMSR_AN_COMP | MII_BMSR_LINK_ST; break; From bc4dbcf4bb1e465e3b2177f5243e9749a6cb508e Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 06/47] nvnet: Fix mii inuse/write bits --- hw/xbox/mcpx/nvnet/nvnet_regs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet_regs.h b/hw/xbox/mcpx/nvnet/nvnet_regs.h index c99f5b2b0a..6a82bbc3da 100644 --- a/hw/xbox/mcpx/nvnet/nvnet_regs.h +++ b/hw/xbox/mcpx/nvnet/nvnet_regs.h @@ -176,8 +176,8 @@ enum { # define NVREG_MIISPEED_BIT8 (1 << 8) # define NVREG_MIIDELAY 5 NvRegMIIControl = 0x190, -# define NVREG_MIICTL_INUSE 0x10000 -# define NVREG_MIICTL_WRITE 0x08000 +# define NVREG_MIICTL_INUSE 0x8000 +# define NVREG_MIICTL_WRITE 0x0400 # define NVREG_MIICTL_ADDRSHIFT 5 NvRegMIIData = 0x194, NvRegWakeUpFlags = 0x200, From 12127b469d7da4c1f44c94b27663d1aa79cabc67 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 07/47] nvnet: Clean up mii read and write handling --- hw/xbox/mcpx/nvnet/nvnet.c | 80 +++++++++++++++++---------------- hw/xbox/mcpx/nvnet/nvnet_regs.h | 9 ++-- hw/xbox/mcpx/nvnet/trace-events | 4 +- 3 files changed, 47 insertions(+), 46 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 82777fe910..93ae9a6978 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -34,6 +34,8 @@ #define IOPORT_SIZE 0x8 #define MMIO_SIZE 0x400 +#define GET_MASK(v, mask) (((v) & (mask)) >> ctz32(mask)) + static const uint8_t bcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; // #define DEBUG @@ -115,8 +117,6 @@ static uint64_t nvnet_io_read(void *opaque, hwaddr addr, unsigned int size); static void nvnet_io_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size); -static int nvnet_mii_rw(NvNetState *s, - uint64_t val); /* Link State */ static void nvnet_link_down(NvNetState *s); @@ -233,51 +233,57 @@ static void nvnet_set_reg(NvNetState *s, /* * Read from PHY. */ -static int nvnet_mii_rw(NvNetState *s, uint64_t val) +static void nvnet_mii_read(NvNetState *s) { - uint32_t mii_ctl; - int write, retval, phy_addr, reg; - - retval = 0; - mii_ctl = nvnet_get_reg(s, NvRegMIIControl, 4); - phy_addr = (mii_ctl >> NVREG_MIICTL_ADDRSHIFT) & 0x1f; - reg = mii_ctl & ((1 << NVREG_MIICTL_ADDRSHIFT) - 1); - write = mii_ctl & NVREG_MIICTL_WRITE; + uint32_t mii_ctl = nvnet_get_reg(s, NvRegMIIControl, 4); + uint32_t mii_data = -1; + uint32_t phy_addr = GET_MASK(mii_ctl, NVREG_MIICTL_PHYADDR); + uint32_t phy_reg = GET_MASK(mii_ctl, NVREG_MIICTL_PHYREG); if (phy_addr != 1) { - retval = -1; goto out; } - if (write) { - goto out; - } - - switch (reg) { + switch (phy_reg) { case MII_BMSR: - retval = MII_BMSR_AN_COMP | MII_BMSR_LINK_ST; + mii_data = MII_BMSR_AN_COMP | MII_BMSR_LINK_ST; break; case MII_ANAR: /* Fall through... */ case MII_ANLPAR: - retval = MII_ANLPAR_10 | MII_ANLPAR_10FD | MII_ANLPAR_TX | - MII_ANLPAR_TXFD | MII_ANLPAR_T4; + mii_data = MII_ANLPAR_10 | MII_ANLPAR_10FD | MII_ANLPAR_TX | + MII_ANLPAR_TXFD | MII_ANLPAR_T4; break; default: + mii_data = 0; break; } out: - if (write) { - trace_nvnet_mii_write(phy_addr, reg, nvnet_get_mii_reg_name(reg), val); - } else { - trace_nvnet_mii_read(phy_addr, reg, nvnet_get_mii_reg_name(reg), - retval); - } - return retval; + mii_ctl &= ~NVREG_MIICTL_INUSE; + nvnet_set_reg(s, NvRegMIIControl, mii_ctl, 4); + nvnet_set_reg(s, NvRegMIIData, mii_data, 4); + trace_nvnet_mii_read(phy_addr, phy_reg, nvnet_get_mii_reg_name(phy_reg), + mii_data); +} + +/* + * Write to PHY. + */ +static void nvnet_mii_write(NvNetState *s) +{ + uint32_t mii_ctl = nvnet_get_reg(s, NvRegMIIControl, 4); + uint32_t mii_data = nvnet_get_reg(s, NvRegMIIData, 4); + uint32_t phy_addr = GET_MASK(mii_ctl, NVREG_MIICTL_PHYADDR); + uint32_t phy_reg = GET_MASK(mii_ctl, NVREG_MIICTL_PHYREG); + + mii_ctl &= ~NVREG_MIICTL_INUSE; + nvnet_set_reg(s, NvRegMIIControl, mii_ctl, 4); + trace_nvnet_mii_write(phy_addr, phy_reg, nvnet_get_mii_reg_name(phy_reg), + mii_data); } /******************************************************************************* @@ -293,16 +299,6 @@ static uint64_t nvnet_mmio_read(void *opaque, hwaddr addr, unsigned int size) uint64_t retval; switch (addr) { - case NvRegMIIData: - assert(size == 4); - retval = nvnet_mii_rw(s, MII_READ); - break; - - case NvRegMIIControl: - retval = nvnet_get_reg(s, addr, size); - retval &= ~NVREG_MIICTL_INUSE; - break; - case NvRegMIIStatus: retval = 0; break; @@ -334,8 +330,14 @@ static void nvnet_mmio_write(void *opaque, hwaddr addr, s->tx_ring_size = ((val >> NVREG_RINGSZ_TXSHIFT) & 0xffff) + 1; break; - case NvRegMIIData: - nvnet_mii_rw(s, val); + case NvRegMIIControl: + assert(size == 4); + nvnet_set_reg(s, addr, val, size); + if (val & NVREG_MIICTL_WRITE) { + nvnet_mii_write(s); + } else { + nvnet_mii_read(s); + } break; case NvRegTxRxControl: diff --git a/hw/xbox/mcpx/nvnet/nvnet_regs.h b/hw/xbox/mcpx/nvnet/nvnet_regs.h index 6a82bbc3da..b311b87278 100644 --- a/hw/xbox/mcpx/nvnet/nvnet_regs.h +++ b/hw/xbox/mcpx/nvnet/nvnet_regs.h @@ -176,9 +176,10 @@ enum { # define NVREG_MIISPEED_BIT8 (1 << 8) # define NVREG_MIIDELAY 5 NvRegMIIControl = 0x190, -# define NVREG_MIICTL_INUSE 0x8000 -# define NVREG_MIICTL_WRITE 0x0400 -# define NVREG_MIICTL_ADDRSHIFT 5 +# define NVREG_MIICTL_INUSE 0x8000 +# define NVREG_MIICTL_WRITE 0x0400 +# define NVREG_MIICTL_PHYADDR 0x03e0 +# define NVREG_MIICTL_PHYREG 0x001f NvRegMIIData = 0x194, NvRegWakeUpFlags = 0x200, # define NVREG_WAKEUPFLAGS_VAL 0x7770 @@ -270,8 +271,6 @@ enum { #define OOM_REFILL (1 + HZ / 20) #define POLL_WAIT (1 + HZ / 100) -#define MII_READ (-1) - /* Link partner ability register. */ #define LPA_SLCT 0x001f /* Same as advertise selector */ #define LPA_RESV 0x1c00 /* Unused... */ diff --git a/hw/xbox/mcpx/nvnet/trace-events b/hw/xbox/mcpx/nvnet/trace-events index fbda278fe7..4115e4e7eb 100644 --- a/hw/xbox/mcpx/nvnet/trace-events +++ b/hw/xbox/mcpx/nvnet/trace-events @@ -1,8 +1,8 @@ # See docs/devel/tracing.rst for syntax documentation. # nvnet.c -nvnet_mii_read(unsigned int phy_addr, uint32_t addr, const char *name, uint64_t val) "phy %d addr 0x%"PRIx32" %s val 0x%"PRIx64 -nvnet_mii_write(unsigned int phy_addr, uint32_t addr, const char *name, uint64_t val) "phy %d addr 0x%"PRIx32" %s val 0x%"PRIx64 +nvnet_mii_read(unsigned int phy_addr, uint32_t addr, const char *name, uint32_t val) "phy %d addr 0x%"PRIx32" %s val 0x%"PRIx32 +nvnet_mii_write(unsigned int phy_addr, uint32_t addr, const char *name, uint32_t val) "phy %d addr 0x%"PRIx32" %s val 0x%"PRIx32 nvnet_reg_read(uint32_t addr, const char *name, unsigned int size, uint64_t val) "addr 0x%"PRIx32" %s size %d val 0x%"PRIx64 nvnet_reg_write(uint32_t addr, const char *name, unsigned int size, uint64_t val) "addr 0x%"PRIx32" %s size %d val 0x%"PRIx64 nvnet_io_read(uint32_t addr, unsigned int size, uint64_t val) "addr 0x%"PRIx32" size %d val 0x%"PRIx64 From ea6d2fc05054674cd453373b4da3556e27fef9e2 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 08/47] nvnet: Drop some useless protos --- hw/xbox/mcpx/nvnet/nvnet.c | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 93ae9a6978..6e11841acf 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -95,46 +95,14 @@ struct RingDesc { * Prototypes ******************************************************************************/ -/* Init */ -static void nvnet_realize(PCIDevice *dev, Error **errp); -static void nvnet_uninit(PCIDevice *dev); -static void nvnet_class_init(ObjectClass *klass, void *data); -static void nvnet_cleanup(NetClientState *nc); -static void nvnet_reset(void *opaque); -static void nvnet_reset_hold(Object *obj, ResetType type); -static void nvnet_register(void); - /* MMIO / IO / Phy / Device Register Access */ -static uint64_t nvnet_mmio_read(void *opaque, - hwaddr addr, unsigned int size); -static void nvnet_mmio_write(void *opaque, - hwaddr addr, uint64_t val, unsigned int size); static uint32_t nvnet_get_reg(NvNetState *s, hwaddr addr, unsigned int size); -static void nvnet_set_reg(NvNetState *s, - hwaddr addr, uint32_t val, unsigned int size); -static uint64_t nvnet_io_read(void *opaque, - hwaddr addr, unsigned int size); -static void nvnet_io_write(void *opaque, - hwaddr addr, uint64_t val, unsigned int size); - -/* Link State */ -static void nvnet_link_down(NvNetState *s); -static void nvnet_link_up(NvNetState *s); -static void nvnet_set_link_status(NetClientState *nc); - -/* Interrupts */ -static void nvnet_update_irq(NvNetState *s); /* Packet Tx / Rx */ -static void nvnet_send_packet(NvNetState *s, - const uint8_t *buf, int size); static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, const uint8_t *buf, size_t size); static ssize_t nvnet_dma_packet_from_guest(NvNetState *s); -static bool nvnet_can_receive(NetClientState *nc); -static ssize_t nvnet_receive(NetClientState *nc, - const uint8_t *buf, size_t size); static ssize_t nvnet_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt); From 92bc16f015b7202ce70e93a5830d0b7896c21116 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 09/47] nvnet: Reorganize for more prototype elimination --- hw/xbox/mcpx/nvnet/nvnet.c | 851 ++++++++++++++++++------------------- 1 file changed, 413 insertions(+), 438 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 6e11841acf..ea83e9e666 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -92,51 +92,150 @@ struct RingDesc { OBJECT_CHECK(NvNetState, (obj), "nvnet") /******************************************************************************* - * Prototypes + * Utility Functions ******************************************************************************/ -/* MMIO / IO / Phy / Device Register Access */ -static uint32_t nvnet_get_reg(NvNetState *s, - hwaddr addr, unsigned int size); - -/* Packet Tx / Rx */ -static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, - const uint8_t *buf, size_t size); -static ssize_t nvnet_dma_packet_from_guest(NvNetState *s); -static ssize_t nvnet_receive_iov(NetClientState *nc, - const struct iovec *iov, int iovcnt); - -/* Utility Functions */ -static void nvnet_hex_dump(NvNetState *s, const uint8_t *buf, int size); - -static const char *nvnet_get_reg_name(hwaddr addr); -static const char *nvnet_get_mii_reg_name(uint8_t reg); -#ifdef DEBUG -static void nvnet_dump_ring_descriptors(NvNetState *s); -#endif - -/******************************************************************************* - * IRQ - ******************************************************************************/ - -/* - * Update IRQ status - */ -static void nvnet_update_irq(NvNetState *s) +static void hex_dump(FILE *f, const uint8_t *buf, int size) { - PCIDevice *d = PCI_DEVICE(s); + int len, i, j, c; - uint32_t irq_mask = nvnet_get_reg(s, NvRegIrqMask, 4); - uint32_t irq_status = nvnet_get_reg(s, NvRegIrqStatus, 4); - - if (irq_mask & irq_status) { - NVNET_DPRINTF("Asserting IRQ\n"); - pci_irq_assert(d); - } else { - pci_irq_deassert(d); + for (i = 0; i < size; i += 16) { + len = size - i; + if (len > 16) { + len = 16; + } + fprintf(f, "%08x ", i); + for (j = 0; j < 16; j++) { + if (j < len) { + fprintf(f, " %02x", buf[i + j]); + } else { + fprintf(f, " "); + } + } + fprintf(f, " "); + for (j = 0; j < len; j++) { + c = buf[i + j]; + if (c < ' ' || c > '~') { + c = '.'; + } + fprintf(f, "%c", c); + } + fprintf(f, "\n"); } } +static void nvnet_hex_dump(NvNetState *s, const uint8_t *buf, int size) +{ +#ifdef NVNET_DUMP_PACKETS_TO_SCREEN + hex_dump(stdout, buf, size); +#endif + if (s->packet_dump_file) { + hex_dump(s->packet_dump_file, buf, size); + } +} + +/* + * Return register name given the offset of the device register. + */ +static const char *nvnet_get_reg_name(hwaddr addr) +{ + switch (addr) { + case NvRegIrqStatus: return "NvRegIrqStatus"; + case NvRegIrqMask: return "NvRegIrqMask"; + case NvRegUnknownSetupReg6: return "NvRegUnknownSetupReg6"; + case NvRegPollingInterval: return "NvRegPollingInterval"; + case NvRegMisc1: return "NvRegMisc1"; + case NvRegTransmitterControl: return "NvRegTransmitterControl"; + case NvRegTransmitterStatus: return "NvRegTransmitterStatus"; + case NvRegPacketFilterFlags: return "NvRegPacketFilterFlags"; + case NvRegOffloadConfig: return "NvRegOffloadConfig"; + case NvRegReceiverControl: return "NvRegReceiverControl"; + case NvRegReceiverStatus: return "NvRegReceiverStatus"; + case NvRegRandomSeed: return "NvRegRandomSeed"; + case NvRegUnknownSetupReg1: return "NvRegUnknownSetupReg1"; + case NvRegUnknownSetupReg2: return "NvRegUnknownSetupReg2"; + case NvRegMacAddrA: return "NvRegMacAddrA"; + case NvRegMacAddrB: return "NvRegMacAddrB"; + case NvRegMulticastAddrA: return "NvRegMulticastAddrA"; + case NvRegMulticastAddrB: return "NvRegMulticastAddrB"; + case NvRegMulticastMaskA: return "NvRegMulticastMaskA"; + case NvRegMulticastMaskB: return "NvRegMulticastMaskB"; + case NvRegTxRingPhysAddr: return "NvRegTxRingPhysAddr"; + case NvRegRxRingPhysAddr: return "NvRegRxRingPhysAddr"; + case NvRegRingSizes: return "NvRegRingSizes"; + case NvRegUnknownTransmitterReg: return "NvRegUnknownTransmitterReg"; + case NvRegLinkSpeed: return "NvRegLinkSpeed"; + case NvRegUnknownSetupReg5: return "NvRegUnknownSetupReg5"; + case NvRegUnknownSetupReg3: return "NvRegUnknownSetupReg3"; + case NvRegUnknownSetupReg8: return "NvRegUnknownSetupReg8"; + case NvRegUnknownSetupReg7: return "NvRegUnknownSetupReg7"; + case NvRegTxRxControl: return "NvRegTxRxControl"; + case NvRegMIIStatus: return "NvRegMIIStatus"; + case NvRegUnknownSetupReg4: return "NvRegUnknownSetupReg4"; + case NvRegAdapterControl: return "NvRegAdapterControl"; + case NvRegMIISpeed: return "NvRegMIISpeed"; + case NvRegMIIControl: return "NvRegMIIControl"; + case NvRegMIIData: return "NvRegMIIData"; + case NvRegWakeUpFlags: return "NvRegWakeUpFlags"; + case NvRegPatternCRC: return "NvRegPatternCRC"; + case NvRegPatternMask: return "NvRegPatternMask"; + case NvRegPowerCap: return "NvRegPowerCap"; + case NvRegPowerState: return "NvRegPowerState"; + default: return "Unknown"; + } +} + +/* + * Get PHY register name. + */ +static const char *nvnet_get_mii_reg_name(uint8_t reg) +{ + switch (reg) { + case MII_PHYID1: return "MII_PHYID1"; + case MII_PHYID2: return "MII_PHYID2"; + case MII_BMCR: return "MII_BMCR"; + case MII_BMSR: return "MII_BMSR"; + case MII_ANAR: return "MII_ANAR"; + case MII_ANLPAR: return "MII_ANLPAR"; + default: return "Unknown"; + } +} + +#ifdef DEBUG +static void nvnet_dump_ring_descriptors(NvNetState *s) +{ + struct RingDesc desc; + PCIDevice *d = PCI_DEVICE(s); + + NVNET_DPRINTF("------------------------------------------------\n"); + for (int i = 0; i < s->tx_ring_size; i++) { + /* Read ring descriptor */ + dma_addr_t tx_ring_addr = nvnet_get_reg(s, NvRegTxRingPhysAddr, 4); + tx_ring_addr += i * sizeof(desc); + pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); + NVNET_DPRINTF("TX: Dumping ring desc %d (%" HWADDR_PRIx "): ", + i, tx_ring_addr); + NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); + NVNET_DPRINTF("Length: 0x%x, ", desc.length); + NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); + } + NVNET_DPRINTF("------------------------------------------------\n"); + + for (int i = 0; i < s->rx_ring_size; i++) { + /* Read ring descriptor */ + dma_addr_t rx_ring_addr = nvnet_get_reg(s, NvRegRxRingPhysAddr, 4); + rx_ring_addr += i * sizeof(desc); + pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); + NVNET_DPRINTF("RX: Dumping ring desc %d (%" HWADDR_PRIx "): ", + i, rx_ring_addr); + NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); + NVNET_DPRINTF("Length: 0x%x, ", desc.length); + NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); + } + NVNET_DPRINTF("------------------------------------------------\n"); +} +#endif + /******************************************************************************* * Register Control ******************************************************************************/ @@ -194,6 +293,281 @@ static void nvnet_set_reg(NvNetState *s, } } +/******************************************************************************* + * IRQ + ******************************************************************************/ + +/* + * Update IRQ status + */ +static void nvnet_update_irq(NvNetState *s) +{ + PCIDevice *d = PCI_DEVICE(s); + + uint32_t irq_mask = nvnet_get_reg(s, NvRegIrqMask, 4); + uint32_t irq_status = nvnet_get_reg(s, NvRegIrqStatus, 4); + + if (irq_mask & irq_status) { + NVNET_DPRINTF("Asserting IRQ\n"); + pci_irq_assert(d); + } else { + pci_irq_deassert(d); + } +} + +/******************************************************************************* + * Packet TX / RX + ******************************************************************************/ + +static void nvnet_send_packet(NvNetState *s, const uint8_t *buf, int size) +{ + NetClientState *nc = qemu_get_queue(s->nic); + + NVNET_DPRINTF("nvnet: Sending packet!\n"); + nvnet_hex_dump(s, buf, size); + qemu_send_packet(nc, buf, size); +} + +static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, + const uint8_t *buf, size_t size) +{ + PCIDevice *d = PCI_DEVICE(s); + bool did_receive = false; + + nvnet_set_reg(s, NvRegTxRxControl, + nvnet_get_reg(s, NvRegTxRxControl, 4) & ~NVREG_TXRXCTL_IDLE, + 4); + + for (int i = 0; i < s->rx_ring_size; i++) { + /* Read current ring descriptor */ + struct RingDesc desc; + s->rx_ring_index %= s->rx_ring_size; + dma_addr_t rx_ring_addr = nvnet_get_reg(s, NvRegRxRingPhysAddr, 4); + rx_ring_addr += s->rx_ring_index * sizeof(desc); + pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); + NVNET_DPRINTF("RX: Looking at ring descriptor %d (0x%" HWADDR_PRIx "): ", + s->rx_ring_index, rx_ring_addr); + NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); + NVNET_DPRINTF("Length: 0x%x, ", desc.length); + NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); + + if (!(desc.flags & NV_RX_AVAIL)) { + break; + } + + assert((desc.length+1) >= size); // FIXME + + s->rx_ring_index += 1; + + /* Transfer packet from device to memory */ + NVNET_DPRINTF("Transferring packet, size 0x%zx, to memory at 0x%x\n", + size, desc.packet_buffer); + pci_dma_write(d, desc.packet_buffer, buf, size); + + /* Update descriptor indicating the packet is waiting */ + desc.length = size; + desc.flags = NV_RX_BIT4 | NV_RX_DESCRIPTORVALID; + pci_dma_write(d, rx_ring_addr, &desc, sizeof(desc)); + NVNET_DPRINTF("Updated ring descriptor: "); + NVNET_DPRINTF("Length: 0x%x, ", desc.length); + NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); + + /* Trigger interrupt */ + NVNET_DPRINTF("Triggering interrupt\n"); + uint32_t irq_status = nvnet_get_reg(s, NvRegIrqStatus, 4); + nvnet_set_reg(s, NvRegIrqStatus, irq_status | NVREG_IRQSTAT_BIT1, 4); + nvnet_update_irq(s); + did_receive = true; + break; + } + + nvnet_set_reg(s, NvRegTxRxControl, + nvnet_get_reg(s, NvRegTxRxControl, 4) | NVREG_TXRXCTL_IDLE, + 4); + + if (did_receive) { + return size; + } else { + /* Could not find free buffer, or packet too large. */ + NVNET_DPRINTF("Could not find free buffer!\n"); + return -1; + } +} + +static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) +{ + PCIDevice *d = PCI_DEVICE(s); + bool packet_sent = false; + + nvnet_set_reg(s, NvRegTxRxControl, + nvnet_get_reg(s, NvRegTxRxControl, 4) & ~NVREG_TXRXCTL_IDLE, + 4); + + for (int i = 0; i < s->tx_ring_size; i++) { + /* Read ring descriptor */ + struct RingDesc desc; + s->tx_ring_index %= s->tx_ring_size; + dma_addr_t tx_ring_addr = nvnet_get_reg(s, NvRegTxRingPhysAddr, 4); + tx_ring_addr += s->tx_ring_index * sizeof(desc); + pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); + NVNET_DPRINTF("TX: Looking at ring desc %d (%" HWADDR_PRIx "): ", + s->tx_ring_index, tx_ring_addr); + NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); + NVNET_DPRINTF("Length: 0x%x, ", desc.length); + NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); + + if (!(desc.flags & NV_TX_VALID)) { + break; + } + + s->tx_ring_index += 1; + + /* Transfer packet from guest memory */ + assert((s->tx_dma_buf_offset + desc.length + 1) <= sizeof(s->tx_dma_buf)); + pci_dma_read(d, desc.packet_buffer, + &s->tx_dma_buf[s->tx_dma_buf_offset], + desc.length + 1); + s->tx_dma_buf_offset += desc.length + 1; + + /* Update descriptor */ + bool is_last_packet = desc.flags & NV_TX_LASTPACKET; + if (is_last_packet) { + NVNET_DPRINTF("Sending packet...\n"); + nvnet_send_packet(s, s->tx_dma_buf, s->tx_dma_buf_offset); + s->tx_dma_buf_offset = 0; + packet_sent = true; + } + + desc.flags &= ~(NV_TX_VALID | NV_TX_RETRYERROR | NV_TX_DEFERRED | + NV_TX_CARRIERLOST | NV_TX_LATECOLLISION | NV_TX_UNDERFLOW | + NV_TX_ERROR); + desc.length = desc.length + 5; + pci_dma_write(d, tx_ring_addr, &desc, sizeof(desc)); + + if (is_last_packet) { + // FIXME + break; + } + } + + /* Trigger interrupt */ + if (packet_sent) { + NVNET_DPRINTF("Triggering interrupt\n"); + uint32_t irq_status = nvnet_get_reg(s, NvRegIrqStatus, 4); + nvnet_set_reg(s, NvRegIrqStatus, irq_status | NVREG_IRQSTAT_BIT4, 4); + nvnet_update_irq(s); + } + + nvnet_set_reg(s, NvRegTxRxControl, + nvnet_get_reg(s, NvRegTxRxControl, 4) | NVREG_TXRXCTL_IDLE, + 4); + + return 0; +} + +static bool nvnet_can_receive(NetClientState *nc) +{ + NVNET_DPRINTF("nvnet_can_receive called\n"); + return true; +} + +static bool nvnet_is_packet_oversized(size_t size) +{ + return size > RX_ALLOC_BUFSIZE; +} + +static bool receive_filter(NvNetState *s, const uint8_t *buf, int size) +{ + if (size < 6) { + return false; + } + + uint32_t rctl = nvnet_get_reg(s, NvRegPacketFilterFlags, 4); + int isbcast = !memcmp(buf, bcast, sizeof bcast); + + /* Broadcast */ + if (isbcast) { + /* FIXME: bcast filtering */ + trace_nvnet_rx_filter_bcast_match(); + return true; + } + + if (!(rctl & NVREG_PFF_MYADDR)) { + /* FIXME: Confirm PFF_MYADDR filters mcast */ + return true; + } + + /* Multicast */ + uint32_t addr[2]; + addr[0] = cpu_to_le32(nvnet_get_reg(s, NvRegMulticastAddrA, 4)); + addr[1] = cpu_to_le32(nvnet_get_reg(s, NvRegMulticastAddrB, 4)); + if (memcmp(addr, bcast, sizeof bcast)) { + uint32_t dest_addr[2]; + memcpy(dest_addr, buf, 6); + dest_addr[0] &= cpu_to_le32(nvnet_get_reg(s, NvRegMulticastMaskA, 4)); + dest_addr[1] &= cpu_to_le32(nvnet_get_reg(s, NvRegMulticastMaskB, 4)); + + if (!memcmp(dest_addr, addr, 6)) { + trace_nvnet_rx_filter_mcast_match(MAC_ARG(dest_addr)); + return true; + } else { + trace_nvnet_rx_filter_mcast_mismatch(MAC_ARG(dest_addr)); + } + } + + /* Unicast */ + addr[0] = cpu_to_le32(nvnet_get_reg(s, NvRegMacAddrA, 4)); + addr[1] = cpu_to_le32(nvnet_get_reg(s, NvRegMacAddrB, 4)); + if (!memcmp(buf, addr, 6)) { + trace_nvnet_rx_filter_ucast_match(MAC_ARG(buf)); + return true; + } else { + trace_nvnet_rx_filter_ucast_mismatch(MAC_ARG(buf)); + } + + return false; +} + +static ssize_t nvnet_receive_iov(NetClientState *nc, + const struct iovec *iov, int iovcnt) +{ + NvNetState *s = qemu_get_nic_opaque(nc); + size_t size = iov_size(iov, iovcnt); + + NVNET_DPRINTF("nvnet: Packet received!\n"); + + if (nvnet_is_packet_oversized(size)) { + /* Drop */ + NVNET_DPRINTF("%s packet too large!\n", __func__); + trace_nvnet_rx_oversized(size); + return size; + } + + iov_to_buf(iov, iovcnt, 0, s->rx_dma_buf, size); + + if (!receive_filter(s, s->rx_dma_buf, size)) { + trace_nvnet_rx_filter_dropped(); + return size; + } + +#ifdef DEBUG + nvnet_hex_dump(s, s->rx_dma_buf, size); +#endif + return nvnet_dma_packet_to_guest(s, s->rx_dma_buf, size); +} + +static ssize_t nvnet_receive(NetClientState *nc, + const uint8_t *buf, size_t size) +{ + const struct iovec iov = { + .iov_base = (uint8_t *)buf, + .iov_len = size + }; + + NVNET_DPRINTF("nvnet_receive called\n"); + return nvnet_receive_iov(nc, &iov, 1); +} + /******************************************************************************* * PHY Control ******************************************************************************/ @@ -366,260 +740,6 @@ static const MemoryRegionOps nvnet_mmio_ops = { .write = nvnet_mmio_write, }; -/******************************************************************************* - * Packet TX / RX - ******************************************************************************/ - -static void nvnet_send_packet(NvNetState *s, const uint8_t *buf, int size) -{ - NetClientState *nc = qemu_get_queue(s->nic); - - NVNET_DPRINTF("nvnet: Sending packet!\n"); - nvnet_hex_dump(s, buf, size); - qemu_send_packet(nc, buf, size); -} - -static bool nvnet_can_receive(NetClientState *nc) -{ - NVNET_DPRINTF("nvnet_can_receive called\n"); - return true; -} - -static ssize_t nvnet_receive(NetClientState *nc, - const uint8_t *buf, size_t size) -{ - const struct iovec iov = { - .iov_base = (uint8_t *)buf, - .iov_len = size - }; - - NVNET_DPRINTF("nvnet_receive called\n"); - return nvnet_receive_iov(nc, &iov, 1); -} - -static bool nvnet_is_packet_oversized(size_t size) -{ - return size > RX_ALLOC_BUFSIZE; -} - -static bool receive_filter(NvNetState *s, const uint8_t *buf, int size) -{ - if (size < 6) { - return false; - } - - uint32_t rctl = nvnet_get_reg(s, NvRegPacketFilterFlags, 4); - int isbcast = !memcmp(buf, bcast, sizeof bcast); - - /* Broadcast */ - if (isbcast) { - /* FIXME: bcast filtering */ - trace_nvnet_rx_filter_bcast_match(); - return true; - } - - if (!(rctl & NVREG_PFF_MYADDR)) { - /* FIXME: Confirm PFF_MYADDR filters mcast */ - return true; - } - - /* Multicast */ - uint32_t addr[2]; - addr[0] = cpu_to_le32(nvnet_get_reg(s, NvRegMulticastAddrA, 4)); - addr[1] = cpu_to_le32(nvnet_get_reg(s, NvRegMulticastAddrB, 4)); - if (memcmp(addr, bcast, sizeof bcast)) { - uint32_t dest_addr[2]; - memcpy(dest_addr, buf, 6); - dest_addr[0] &= cpu_to_le32(nvnet_get_reg(s, NvRegMulticastMaskA, 4)); - dest_addr[1] &= cpu_to_le32(nvnet_get_reg(s, NvRegMulticastMaskB, 4)); - - if (!memcmp(dest_addr, addr, 6)) { - trace_nvnet_rx_filter_mcast_match(MAC_ARG(dest_addr)); - return true; - } else { - trace_nvnet_rx_filter_mcast_mismatch(MAC_ARG(dest_addr)); - } - } - - /* Unicast */ - addr[0] = cpu_to_le32(nvnet_get_reg(s, NvRegMacAddrA, 4)); - addr[1] = cpu_to_le32(nvnet_get_reg(s, NvRegMacAddrB, 4)); - if (!memcmp(buf, addr, 6)) { - trace_nvnet_rx_filter_ucast_match(MAC_ARG(buf)); - return true; - } else { - trace_nvnet_rx_filter_ucast_mismatch(MAC_ARG(buf)); - } - - return false; -} - -static ssize_t nvnet_receive_iov(NetClientState *nc, - const struct iovec *iov, int iovcnt) -{ - NvNetState *s = qemu_get_nic_opaque(nc); - size_t size = iov_size(iov, iovcnt); - - NVNET_DPRINTF("nvnet: Packet received!\n"); - - if (nvnet_is_packet_oversized(size)) { - /* Drop */ - NVNET_DPRINTF("%s packet too large!\n", __func__); - trace_nvnet_rx_oversized(size); - return size; - } - - iov_to_buf(iov, iovcnt, 0, s->rx_dma_buf, size); - - if (!receive_filter(s, s->rx_dma_buf, size)) { - trace_nvnet_rx_filter_dropped(); - return size; - } - -#ifdef DEBUG - nvnet_hex_dump(s, s->rx_dma_buf, size); -#endif - return nvnet_dma_packet_to_guest(s, s->rx_dma_buf, size); -} - - -static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, - const uint8_t *buf, size_t size) -{ - PCIDevice *d = PCI_DEVICE(s); - bool did_receive = false; - - nvnet_set_reg(s, NvRegTxRxControl, - nvnet_get_reg(s, NvRegTxRxControl, 4) & ~NVREG_TXRXCTL_IDLE, - 4); - - for (int i = 0; i < s->rx_ring_size; i++) { - /* Read current ring descriptor */ - struct RingDesc desc; - s->rx_ring_index %= s->rx_ring_size; - dma_addr_t rx_ring_addr = nvnet_get_reg(s, NvRegRxRingPhysAddr, 4); - rx_ring_addr += s->rx_ring_index * sizeof(desc); - pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); - NVNET_DPRINTF("RX: Looking at ring descriptor %d (0x%" HWADDR_PRIx "): ", - s->rx_ring_index, rx_ring_addr); - NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); - NVNET_DPRINTF("Length: 0x%x, ", desc.length); - NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); - - if (!(desc.flags & NV_RX_AVAIL)) { - break; - } - - assert((desc.length+1) >= size); // FIXME - - s->rx_ring_index += 1; - - /* Transfer packet from device to memory */ - NVNET_DPRINTF("Transferring packet, size 0x%zx, to memory at 0x%x\n", - size, desc.packet_buffer); - pci_dma_write(d, desc.packet_buffer, buf, size); - - /* Update descriptor indicating the packet is waiting */ - desc.length = size; - desc.flags = NV_RX_BIT4 | NV_RX_DESCRIPTORVALID; - pci_dma_write(d, rx_ring_addr, &desc, sizeof(desc)); - NVNET_DPRINTF("Updated ring descriptor: "); - NVNET_DPRINTF("Length: 0x%x, ", desc.length); - NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); - - /* Trigger interrupt */ - NVNET_DPRINTF("Triggering interrupt\n"); - uint32_t irq_status = nvnet_get_reg(s, NvRegIrqStatus, 4); - nvnet_set_reg(s, NvRegIrqStatus, irq_status | NVREG_IRQSTAT_BIT1, 4); - nvnet_update_irq(s); - did_receive = true; - break; - } - - nvnet_set_reg(s, NvRegTxRxControl, - nvnet_get_reg(s, NvRegTxRxControl, 4) | NVREG_TXRXCTL_IDLE, - 4); - - if (did_receive) { - return size; - } else { - /* Could not find free buffer, or packet too large. */ - NVNET_DPRINTF("Could not find free buffer!\n"); - return -1; - } -} - -static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) -{ - PCIDevice *d = PCI_DEVICE(s); - bool packet_sent = false; - - nvnet_set_reg(s, NvRegTxRxControl, - nvnet_get_reg(s, NvRegTxRxControl, 4) & ~NVREG_TXRXCTL_IDLE, - 4); - - for (int i = 0; i < s->tx_ring_size; i++) { - /* Read ring descriptor */ - struct RingDesc desc; - s->tx_ring_index %= s->tx_ring_size; - dma_addr_t tx_ring_addr = nvnet_get_reg(s, NvRegTxRingPhysAddr, 4); - tx_ring_addr += s->tx_ring_index * sizeof(desc); - pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); - NVNET_DPRINTF("TX: Looking at ring desc %d (%" HWADDR_PRIx "): ", - s->tx_ring_index, tx_ring_addr); - NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); - NVNET_DPRINTF("Length: 0x%x, ", desc.length); - NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); - - if (!(desc.flags & NV_TX_VALID)) { - break; - } - - s->tx_ring_index += 1; - - /* Transfer packet from guest memory */ - assert((s->tx_dma_buf_offset + desc.length + 1) <= sizeof(s->tx_dma_buf)); - pci_dma_read(d, desc.packet_buffer, - &s->tx_dma_buf[s->tx_dma_buf_offset], - desc.length + 1); - s->tx_dma_buf_offset += desc.length + 1; - - /* Update descriptor */ - bool is_last_packet = desc.flags & NV_TX_LASTPACKET; - if (is_last_packet) { - NVNET_DPRINTF("Sending packet...\n"); - nvnet_send_packet(s, s->tx_dma_buf, s->tx_dma_buf_offset); - s->tx_dma_buf_offset = 0; - packet_sent = true; - } - - desc.flags &= ~(NV_TX_VALID | NV_TX_RETRYERROR | NV_TX_DEFERRED | - NV_TX_CARRIERLOST | NV_TX_LATECOLLISION | NV_TX_UNDERFLOW | - NV_TX_ERROR); - desc.length = desc.length + 5; - pci_dma_write(d, tx_ring_addr, &desc, sizeof(desc)); - - if (is_last_packet) { - // FIXME - break; - } - } - - /* Trigger interrupt */ - if (packet_sent) { - NVNET_DPRINTF("Triggering interrupt\n"); - uint32_t irq_status = nvnet_get_reg(s, NvRegIrqStatus, 4); - nvnet_set_reg(s, NvRegIrqStatus, irq_status | NVREG_IRQSTAT_BIT4, 4); - nvnet_update_irq(s); - } - - nvnet_set_reg(s, NvRegTxRxControl, - nvnet_get_reg(s, NvRegTxRxControl, 4) | NVREG_TXRXCTL_IDLE, - 4); - - return 0; -} - /******************************************************************************* * Link Status Control ******************************************************************************/ @@ -722,7 +842,7 @@ static void nvnet_uninit(PCIDevice *dev) qemu_del_nic(s->nic); } -void nvnet_cleanup(NetClientState *nc) +static void nvnet_cleanup(NetClientState *nc) { } @@ -751,151 +871,6 @@ static void nvnet_reset_hold(Object *obj, ResetType type) nvnet_reset(s); } -/******************************************************************************* - * Utility Functions - ******************************************************************************/ - -static void hex_dump(FILE *f, const uint8_t *buf, int size) -{ - int len, i, j, c; - - for (i = 0; i < size; i += 16) { - len = size - i; - if (len > 16) { - len = 16; - } - fprintf(f, "%08x ", i); - for (j = 0; j < 16; j++) { - if (j < len) { - fprintf(f, " %02x", buf[i + j]); - } else { - fprintf(f, " "); - } - } - fprintf(f, " "); - for (j = 0; j < len; j++) { - c = buf[i + j]; - if (c < ' ' || c > '~') { - c = '.'; - } - fprintf(f, "%c", c); - } - fprintf(f, "\n"); - } -} - -static void nvnet_hex_dump(NvNetState *s, const uint8_t *buf, int size) -{ -#ifdef NVNET_DUMP_PACKETS_TO_SCREEN - hex_dump(stdout, buf, size); -#endif - if (s->packet_dump_file) { - hex_dump(s->packet_dump_file, buf, size); - } -} - -/* - * Return register name given the offset of the device register. - */ -static const char *nvnet_get_reg_name(hwaddr addr) -{ - switch (addr) { - case NvRegIrqStatus: return "NvRegIrqStatus"; - case NvRegIrqMask: return "NvRegIrqMask"; - case NvRegUnknownSetupReg6: return "NvRegUnknownSetupReg6"; - case NvRegPollingInterval: return "NvRegPollingInterval"; - case NvRegMisc1: return "NvRegMisc1"; - case NvRegTransmitterControl: return "NvRegTransmitterControl"; - case NvRegTransmitterStatus: return "NvRegTransmitterStatus"; - case NvRegPacketFilterFlags: return "NvRegPacketFilterFlags"; - case NvRegOffloadConfig: return "NvRegOffloadConfig"; - case NvRegReceiverControl: return "NvRegReceiverControl"; - case NvRegReceiverStatus: return "NvRegReceiverStatus"; - case NvRegRandomSeed: return "NvRegRandomSeed"; - case NvRegUnknownSetupReg1: return "NvRegUnknownSetupReg1"; - case NvRegUnknownSetupReg2: return "NvRegUnknownSetupReg2"; - case NvRegMacAddrA: return "NvRegMacAddrA"; - case NvRegMacAddrB: return "NvRegMacAddrB"; - case NvRegMulticastAddrA: return "NvRegMulticastAddrA"; - case NvRegMulticastAddrB: return "NvRegMulticastAddrB"; - case NvRegMulticastMaskA: return "NvRegMulticastMaskA"; - case NvRegMulticastMaskB: return "NvRegMulticastMaskB"; - case NvRegTxRingPhysAddr: return "NvRegTxRingPhysAddr"; - case NvRegRxRingPhysAddr: return "NvRegRxRingPhysAddr"; - case NvRegRingSizes: return "NvRegRingSizes"; - case NvRegUnknownTransmitterReg: return "NvRegUnknownTransmitterReg"; - case NvRegLinkSpeed: return "NvRegLinkSpeed"; - case NvRegUnknownSetupReg5: return "NvRegUnknownSetupReg5"; - case NvRegUnknownSetupReg3: return "NvRegUnknownSetupReg3"; - case NvRegUnknownSetupReg8: return "NvRegUnknownSetupReg8"; - case NvRegUnknownSetupReg7: return "NvRegUnknownSetupReg7"; - case NvRegTxRxControl: return "NvRegTxRxControl"; - case NvRegMIIStatus: return "NvRegMIIStatus"; - case NvRegUnknownSetupReg4: return "NvRegUnknownSetupReg4"; - case NvRegAdapterControl: return "NvRegAdapterControl"; - case NvRegMIISpeed: return "NvRegMIISpeed"; - case NvRegMIIControl: return "NvRegMIIControl"; - case NvRegMIIData: return "NvRegMIIData"; - case NvRegWakeUpFlags: return "NvRegWakeUpFlags"; - case NvRegPatternCRC: return "NvRegPatternCRC"; - case NvRegPatternMask: return "NvRegPatternMask"; - case NvRegPowerCap: return "NvRegPowerCap"; - case NvRegPowerState: return "NvRegPowerState"; - default: return "Unknown"; - } -} - -/* - * Get PHY register name. - */ -static const char *nvnet_get_mii_reg_name(uint8_t reg) -{ - switch (reg) { - case MII_PHYID1: return "MII_PHYID1"; - case MII_PHYID2: return "MII_PHYID2"; - case MII_BMCR: return "MII_BMCR"; - case MII_BMSR: return "MII_BMSR"; - case MII_ANAR: return "MII_ANAR"; - case MII_ANLPAR: return "MII_ANLPAR"; - default: return "Unknown"; - } -} - -#ifdef DEBUG -static void nvnet_dump_ring_descriptors(NvNetState *s) -{ - struct RingDesc desc; - PCIDevice *d = PCI_DEVICE(s); - - NVNET_DPRINTF("------------------------------------------------\n"); - for (int i = 0; i < s->tx_ring_size; i++) { - /* Read ring descriptor */ - dma_addr_t tx_ring_addr = nvnet_get_reg(s, NvRegTxRingPhysAddr, 4); - tx_ring_addr += i * sizeof(desc); - pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); - NVNET_DPRINTF("TX: Dumping ring desc %d (%" HWADDR_PRIx "): ", - i, tx_ring_addr); - NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); - NVNET_DPRINTF("Length: 0x%x, ", desc.length); - NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); - } - NVNET_DPRINTF("------------------------------------------------\n"); - - for (int i = 0; i < s->rx_ring_size; i++) { - /* Read ring descriptor */ - dma_addr_t rx_ring_addr = nvnet_get_reg(s, NvRegRxRingPhysAddr, 4); - rx_ring_addr += i * sizeof(desc); - pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); - NVNET_DPRINTF("RX: Dumping ring desc %d (%" HWADDR_PRIx "): ", - i, rx_ring_addr); - NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); - NVNET_DPRINTF("Length: 0x%x, ", desc.length); - NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); - } - NVNET_DPRINTF("------------------------------------------------\n"); -} -#endif - /******************************************************************************* * Properties ******************************************************************************/ From 62b8e789f46711aedd03e250ece199216f203ac1 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 10/47] nvnet: Move NVNET_DEVICE macro up --- hw/xbox/mcpx/nvnet/nvnet.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index ea83e9e666..4abda91dfd 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -76,6 +76,9 @@ typedef struct NvNetState { char *packet_dump_path; } NvNetState; +#define NVNET_DEVICE(obj) \ + OBJECT_CHECK(NvNetState, (obj), "nvnet") + #pragma pack(1) struct RingDesc { uint32_t packet_buffer; @@ -84,13 +87,6 @@ struct RingDesc { }; #pragma pack() -/******************************************************************************* - * Helper Macros - ******************************************************************************/ - -#define NVNET_DEVICE(obj) \ - OBJECT_CHECK(NvNetState, (obj), "nvnet") - /******************************************************************************* * Utility Functions ******************************************************************************/ From 1312b7e683d809967470309ba00a1e2dd743630c Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 11/47] nvnet: Drop some useless comments --- hw/xbox/mcpx/nvnet/nvnet.c | 71 -------------------------------------- 1 file changed, 71 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 4abda91dfd..2cb3573229 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -49,10 +49,6 @@ static const uint8_t bcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; static NetClientInfo net_nvnet_info; static Property nvnet_properties[]; -/******************************************************************************* - * Primary State Structure - ******************************************************************************/ - typedef struct NvNetState { /*< private >*/ PCIDevice parent_obj; @@ -87,10 +83,6 @@ struct RingDesc { }; #pragma pack() -/******************************************************************************* - * Utility Functions - ******************************************************************************/ - static void hex_dump(FILE *f, const uint8_t *buf, int size) { int len, i, j, c; @@ -130,9 +122,6 @@ static void nvnet_hex_dump(NvNetState *s, const uint8_t *buf, int size) } } -/* - * Return register name given the offset of the device register. - */ static const char *nvnet_get_reg_name(hwaddr addr) { switch (addr) { @@ -181,9 +170,6 @@ static const char *nvnet_get_reg_name(hwaddr addr) } } -/* - * Get PHY register name. - */ static const char *nvnet_get_mii_reg_name(uint8_t reg) { switch (reg) { @@ -232,13 +218,6 @@ static void nvnet_dump_ring_descriptors(NvNetState *s) } #endif -/******************************************************************************* - * Register Control - ******************************************************************************/ - -/* - * Read backing store for a device register. - */ static uint32_t nvnet_get_reg(NvNetState *s, hwaddr addr, unsigned int size) { assert(addr < MMIO_SIZE); @@ -261,9 +240,6 @@ static uint32_t nvnet_get_reg(NvNetState *s, hwaddr addr, unsigned int size) } } -/* - * Write backing store for a device register. - */ static void nvnet_set_reg(NvNetState *s, hwaddr addr, uint32_t val, unsigned int size) { @@ -289,13 +265,6 @@ static void nvnet_set_reg(NvNetState *s, } } -/******************************************************************************* - * IRQ - ******************************************************************************/ - -/* - * Update IRQ status - */ static void nvnet_update_irq(NvNetState *s) { PCIDevice *d = PCI_DEVICE(s); @@ -311,10 +280,6 @@ static void nvnet_update_irq(NvNetState *s) } } -/******************************************************************************* - * Packet TX / RX - ******************************************************************************/ - static void nvnet_send_packet(NvNetState *s, const uint8_t *buf, int size) { NetClientState *nc = qemu_get_queue(s->nic); @@ -564,13 +529,6 @@ static ssize_t nvnet_receive(NetClientState *nc, return nvnet_receive_iov(nc, &iov, 1); } -/******************************************************************************* - * PHY Control - ******************************************************************************/ - -/* - * Read from PHY. - */ static void nvnet_mii_read(NvNetState *s) { uint32_t mii_ctl = nvnet_get_reg(s, NvRegMIIControl, 4); @@ -608,9 +566,6 @@ out: mii_data); } -/* - * Write to PHY. - */ static void nvnet_mii_write(NvNetState *s) { uint32_t mii_ctl = nvnet_get_reg(s, NvRegMIIControl, 4); @@ -624,13 +579,6 @@ static void nvnet_mii_write(NvNetState *s) mii_data); } -/******************************************************************************* - * MMIO Read / Write - ******************************************************************************/ - -/* - * Handler for guest reads from MMIO ranges owned by this device. - */ static uint64_t nvnet_mmio_read(void *opaque, hwaddr addr, unsigned int size) { NvNetState *s = NVNET_DEVICE(opaque); @@ -650,9 +598,6 @@ static uint64_t nvnet_mmio_read(void *opaque, hwaddr addr, unsigned int size) return retval; } -/* - * Handler for guest writes to MMIO ranges owned by this device. - */ static void nvnet_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { @@ -736,10 +681,6 @@ static const MemoryRegionOps nvnet_mmio_ops = { .write = nvnet_mmio_write, }; -/******************************************************************************* - * Link Status Control - ******************************************************************************/ - static void nvnet_link_down(NvNetState *s) { NVNET_DPRINTF("nvnet_link_down called\n"); @@ -760,10 +701,6 @@ static void nvnet_set_link_status(NetClientState *nc) } } -/******************************************************************************* - * IO Read / Write - ******************************************************************************/ - static uint64_t nvnet_io_read(void *opaque, hwaddr addr, unsigned int size) { uint64_t r = 0; @@ -782,10 +719,6 @@ static const MemoryRegionOps nvnet_io_ops = { .write = nvnet_io_write, }; -/******************************************************************************* - * Init - ******************************************************************************/ - static void nvnet_realize(PCIDevice *pci_dev, Error **errp) { DeviceState *dev = DEVICE(pci_dev); @@ -867,10 +800,6 @@ static void nvnet_reset_hold(Object *obj, ResetType type) nvnet_reset(s); } -/******************************************************************************* - * Properties - ******************************************************************************/ - static const VMStateDescription vmstate_nvnet = { .name = "nvnet", .version_id = 1, From c9f794c277ebc10b36bb78c5bac92964bd52576a Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 12/47] nvnet: Use is_broadcast_ether_addr --- hw/xbox/mcpx/nvnet/nvnet.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 2cb3573229..c2bf96a17d 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -26,6 +26,7 @@ #include "hw/pci/pci_device.h" #include "hw/qdev-properties.h" #include "net/net.h" +#include "net/eth.h" #include "qemu/bswap.h" #include "qemu/iov.h" #include "migration/vmstate.h" @@ -36,8 +37,6 @@ #define GET_MASK(v, mask) (((v) & (mask)) >> ctz32(mask)) -static const uint8_t bcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - // #define DEBUG #ifdef DEBUG # define NVNET_DPRINTF(format, ...) printf(format, ## __VA_ARGS__) @@ -444,10 +443,9 @@ static bool receive_filter(NvNetState *s, const uint8_t *buf, int size) } uint32_t rctl = nvnet_get_reg(s, NvRegPacketFilterFlags, 4); - int isbcast = !memcmp(buf, bcast, sizeof bcast); /* Broadcast */ - if (isbcast) { + if (is_broadcast_ether_addr(buf)) { /* FIXME: bcast filtering */ trace_nvnet_rx_filter_bcast_match(); return true; @@ -462,7 +460,7 @@ static bool receive_filter(NvNetState *s, const uint8_t *buf, int size) uint32_t addr[2]; addr[0] = cpu_to_le32(nvnet_get_reg(s, NvRegMulticastAddrA, 4)); addr[1] = cpu_to_le32(nvnet_get_reg(s, NvRegMulticastAddrB, 4)); - if (memcmp(addr, bcast, sizeof bcast)) { + if (!is_broadcast_ether_addr((uint8_t *)addr)) { uint32_t dest_addr[2]; memcpy(dest_addr, buf, 6); dest_addr[0] &= cpu_to_le32(nvnet_get_reg(s, NvRegMulticastMaskA, 4)); From 6fc9925dc94ff725a436623e0883e52f6e6c0ae2 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 13/47] nvnet: Drop custom packet hexdump --- hw/xbox/mcpx/nvnet/nvnet.c | 62 -------------------------------------- 1 file changed, 62 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index c2bf96a17d..15d4a720fe 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -40,7 +40,6 @@ // #define DEBUG #ifdef DEBUG # define NVNET_DPRINTF(format, ...) printf(format, ## __VA_ARGS__) -# define NVNET_DUMP_PACKETS_TO_SCREEN #else # define NVNET_DPRINTF(format, ...) do { } while (0) #endif @@ -66,9 +65,6 @@ typedef struct NvNetState { uint8_t tx_dma_buf[TX_ALLOC_BUFSIZE]; uint32_t tx_dma_buf_offset; uint8_t rx_dma_buf[RX_ALLOC_BUFSIZE]; - - FILE *packet_dump_file; - char *packet_dump_path; } NvNetState; #define NVNET_DEVICE(obj) \ @@ -82,45 +78,6 @@ struct RingDesc { }; #pragma pack() -static void hex_dump(FILE *f, const uint8_t *buf, int size) -{ - int len, i, j, c; - - for (i = 0; i < size; i += 16) { - len = size - i; - if (len > 16) { - len = 16; - } - fprintf(f, "%08x ", i); - for (j = 0; j < 16; j++) { - if (j < len) { - fprintf(f, " %02x", buf[i + j]); - } else { - fprintf(f, " "); - } - } - fprintf(f, " "); - for (j = 0; j < len; j++) { - c = buf[i + j]; - if (c < ' ' || c > '~') { - c = '.'; - } - fprintf(f, "%c", c); - } - fprintf(f, "\n"); - } -} - -static void nvnet_hex_dump(NvNetState *s, const uint8_t *buf, int size) -{ -#ifdef NVNET_DUMP_PACKETS_TO_SCREEN - hex_dump(stdout, buf, size); -#endif - if (s->packet_dump_file) { - hex_dump(s->packet_dump_file, buf, size); - } -} - static const char *nvnet_get_reg_name(hwaddr addr) { switch (addr) { @@ -284,7 +241,6 @@ static void nvnet_send_packet(NvNetState *s, const uint8_t *buf, int size) NetClientState *nc = qemu_get_queue(s->nic); NVNET_DPRINTF("nvnet: Sending packet!\n"); - nvnet_hex_dump(s, buf, size); qemu_send_packet(nc, buf, size); } @@ -509,9 +465,6 @@ static ssize_t nvnet_receive_iov(NetClientState *nc, return size; } -#ifdef DEBUG - nvnet_hex_dump(s, s->rx_dma_buf, size); -#endif return nvnet_dma_packet_to_guest(s, s->rx_dma_buf, size); } @@ -725,16 +678,6 @@ static void nvnet_realize(PCIDevice *pci_dev, Error **errp) pci_dev->config[PCI_INTERRUPT_PIN] = 0x01; - s->packet_dump_file = NULL; - if (s->packet_dump_path && *s->packet_dump_path != '\x00') { - s->packet_dump_file = fopen(s->packet_dump_path, "wb"); - if (!s->packet_dump_file) { - fprintf(stderr, "Failed to open %s for writing!\n", - s->packet_dump_path); - exit(1); - } - } - memset(s->regs, 0, sizeof(s->regs)); s->rx_ring_index = 0; @@ -760,10 +703,6 @@ static void nvnet_uninit(PCIDevice *dev) { NvNetState *s = NVNET_DEVICE(dev); - if (s->packet_dump_file) { - fclose(s->packet_dump_file); - } - // memory_region_destroy(&s->mmio); // memory_region_destroy(&s->io); qemu_del_nic(s->nic); @@ -837,7 +776,6 @@ static void nvnet_class_init(ObjectClass *klass, void *data) static Property nvnet_properties[] = { DEFINE_NIC_PROPERTIES(NvNetState, conf), - DEFINE_PROP_STRING("dump", NvNetState, packet_dump_path), DEFINE_PROP_END_OF_LIST(), }; From 361809d6237ba24b9a1ceeb003ce8e08245075dc Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 14/47] nvnet: Use OBJECT_DECLARE_SIMPLE_TYPE --- hw/xbox/mcpx/nvnet/nvnet.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 15d4a720fe..ceec52deb1 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -47,6 +47,9 @@ static NetClientInfo net_nvnet_info; static Property nvnet_properties[]; +#define TYPE_NVNET "nvnet" +OBJECT_DECLARE_SIMPLE_TYPE(NvNetState, NVNET) + typedef struct NvNetState { /*< private >*/ PCIDevice parent_obj; @@ -67,9 +70,6 @@ typedef struct NvNetState { uint8_t rx_dma_buf[RX_ALLOC_BUFSIZE]; } NvNetState; -#define NVNET_DEVICE(obj) \ - OBJECT_CHECK(NvNetState, (obj), "nvnet") - #pragma pack(1) struct RingDesc { uint32_t packet_buffer; @@ -532,7 +532,7 @@ static void nvnet_mii_write(NvNetState *s) static uint64_t nvnet_mmio_read(void *opaque, hwaddr addr, unsigned int size) { - NvNetState *s = NVNET_DEVICE(opaque); + NvNetState *s = NVNET(opaque); uint64_t retval; switch (addr) { @@ -552,7 +552,7 @@ static uint64_t nvnet_mmio_read(void *opaque, hwaddr addr, unsigned int size) static void nvnet_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { - NvNetState *s = NVNET_DEVICE(opaque); + NvNetState *s = NVNET(opaque); uint32_t temp; trace_nvnet_reg_write(addr, nvnet_get_reg_name(addr & ~3), size, val); @@ -673,7 +673,7 @@ static const MemoryRegionOps nvnet_io_ops = { static void nvnet_realize(PCIDevice *pci_dev, Error **errp) { DeviceState *dev = DEVICE(pci_dev); - NvNetState *s = NVNET_DEVICE(pci_dev); + NvNetState *s = NVNET(pci_dev); PCIDevice *d = PCI_DEVICE(s); pci_dev->config[PCI_INTERRUPT_PIN] = 0x01; @@ -701,7 +701,7 @@ static void nvnet_realize(PCIDevice *pci_dev, Error **errp) static void nvnet_uninit(PCIDevice *dev) { - NvNetState *s = NVNET_DEVICE(dev); + NvNetState *s = NVNET(dev); // memory_region_destroy(&s->mmio); // memory_region_destroy(&s->io); @@ -733,7 +733,7 @@ static void nvnet_reset(void *opaque) static void nvnet_reset_hold(Object *obj, ResetType type) { - NvNetState *s = NVNET_DEVICE(obj); + NvNetState *s = NVNET(obj); nvnet_reset(s); } From bf76e3f6664d20b73b80a7cc9169095bbb89fe1a Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 15/47] nvnet: Eliminate redundant declarations --- hw/xbox/mcpx/nvnet/nvnet.c | 39 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index ceec52deb1..e89d6cb4f5 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -44,9 +44,6 @@ # define NVNET_DPRINTF(format, ...) do { } while (0) #endif -static NetClientInfo net_nvnet_info; -static Property nvnet_properties[]; - #define TYPE_NVNET "nvnet" OBJECT_DECLARE_SIMPLE_TYPE(NvNetState, NVNET) @@ -670,6 +667,15 @@ static const MemoryRegionOps nvnet_io_ops = { .write = nvnet_io_write, }; +static NetClientInfo net_nvnet_info = { + .type = NET_CLIENT_DRIVER_NIC, + .size = sizeof(NICState), + .can_receive = nvnet_can_receive, + .receive = nvnet_receive, + .receive_iov = nvnet_receive_iov, + .link_status_changed = nvnet_set_link_status, +}; + static void nvnet_realize(PCIDevice *pci_dev, Error **errp) { DeviceState *dev = DEVICE(pci_dev); @@ -708,10 +714,6 @@ static void nvnet_uninit(PCIDevice *dev) qemu_del_nic(s->nic); } -static void nvnet_cleanup(NetClientState *nc) -{ -} - static void nvnet_reset(void *opaque) { NvNetState *s = opaque; @@ -753,6 +755,11 @@ static const VMStateDescription vmstate_nvnet = { }, }; +static Property nvnet_properties[] = { + DEFINE_NIC_PROPERTIES(NvNetState, conf), + DEFINE_PROP_END_OF_LIST(), +}; + static void nvnet_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -774,21 +781,6 @@ static void nvnet_class_init(ObjectClass *klass, void *data) device_class_set_props(dc, nvnet_properties); } -static Property nvnet_properties[] = { - DEFINE_NIC_PROPERTIES(NvNetState, conf), - DEFINE_PROP_END_OF_LIST(), -}; - -static NetClientInfo net_nvnet_info = { - .type = NET_CLIENT_DRIVER_NIC, - .size = sizeof(NICState), - .can_receive = nvnet_can_receive, - .receive = nvnet_receive, - .receive_iov = nvnet_receive_iov, - .cleanup = nvnet_cleanup, - .link_status_changed = nvnet_set_link_status, -}; - static const TypeInfo nvnet_info = { .name = "nvnet", .parent = TYPE_PCI_DEVICE, @@ -804,4 +796,5 @@ static void nvnet_register(void) { type_register_static(&nvnet_info); } -type_init(nvnet_register); + +type_init(nvnet_register) From 1fd4cc7dd4f9e693e05cf94f638009f1b7d5fdcc Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 16/47] nvnet: Simplify debug macro --- hw/xbox/mcpx/nvnet/nvnet.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index e89d6cb4f5..f9129c81fa 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -37,13 +37,17 @@ #define GET_MASK(v, mask) (((v) & (mask)) >> ctz32(mask)) -// #define DEBUG -#ifdef DEBUG -# define NVNET_DPRINTF(format, ...) printf(format, ## __VA_ARGS__) -#else -# define NVNET_DPRINTF(format, ...) do { } while (0) +#ifndef DEBUG_NVNET +#define DEBUG_NVNET 0 #endif +#define NVNET_DPRINTF(fmt, ...) \ + do { \ + if (DEBUG_NVNET) { \ + fprintf(stderr, fmt, ##__VA_ARGS__); \ + } \ + } while (0); + #define TYPE_NVNET "nvnet" OBJECT_DECLARE_SIMPLE_TYPE(NvNetState, NVNET) @@ -136,9 +140,9 @@ static const char *nvnet_get_mii_reg_name(uint8_t reg) } } -#ifdef DEBUG static void nvnet_dump_ring_descriptors(NvNetState *s) { +#if NVNET_DEBUG struct RingDesc desc; PCIDevice *d = PCI_DEVICE(s); @@ -168,8 +172,8 @@ static void nvnet_dump_ring_descriptors(NvNetState *s) NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); } NVNET_DPRINTF("------------------------------------------------\n"); -} #endif +} static uint32_t nvnet_get_reg(NvNetState *s, hwaddr addr, unsigned int size) { @@ -574,9 +578,7 @@ static void nvnet_mmio_write(void *opaque, hwaddr addr, case NvRegTxRxControl: if (val == NVREG_TXRXCTL_KICK) { NVNET_DPRINTF("NvRegTxRxControl = NVREG_TXRXCTL_KICK!\n"); -#ifdef DEBUG nvnet_dump_ring_descriptors(s); -#endif nvnet_dma_packet_from_guest(s); } From 936730bb98dfe795c0a88169b41bd20f9c847d82 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 17/47] nvnet: Drop dead code --- hw/xbox/mcpx/nvnet/nvnet.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index f9129c81fa..a0cf45b7dd 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -710,9 +710,6 @@ static void nvnet_realize(PCIDevice *pci_dev, Error **errp) static void nvnet_uninit(PCIDevice *dev) { NvNetState *s = NVNET(dev); - - // memory_region_destroy(&s->mmio); - // memory_region_destroy(&s->io); qemu_del_nic(s->nic); } From 8d2ea10ef054398a1fe06ac727aa8b009d3adaa3 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 18/47] nvnet: Use QEMU_PACKED macro --- hw/xbox/mcpx/nvnet/nvnet.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index a0cf45b7dd..75a6894d4a 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -71,13 +71,11 @@ typedef struct NvNetState { uint8_t rx_dma_buf[RX_ALLOC_BUFSIZE]; } NvNetState; -#pragma pack(1) struct RingDesc { uint32_t packet_buffer; uint16_t length; uint16_t flags; -}; -#pragma pack() +} QEMU_PACKED; static const char *nvnet_get_reg_name(hwaddr addr) { From e180a11d04d60a6dda250b99ce8d1e1271b6c805 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 19/47] nvnet: Simplify register stringification --- hw/xbox/mcpx/nvnet/nvnet.c | 104 ++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 49 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 75a6894d4a..0dbf409036 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -77,67 +77,73 @@ struct RingDesc { uint16_t flags; } QEMU_PACKED; +#define R(r) case r: return #r; + static const char *nvnet_get_reg_name(hwaddr addr) { switch (addr) { - case NvRegIrqStatus: return "NvRegIrqStatus"; - case NvRegIrqMask: return "NvRegIrqMask"; - case NvRegUnknownSetupReg6: return "NvRegUnknownSetupReg6"; - case NvRegPollingInterval: return "NvRegPollingInterval"; - case NvRegMisc1: return "NvRegMisc1"; - case NvRegTransmitterControl: return "NvRegTransmitterControl"; - case NvRegTransmitterStatus: return "NvRegTransmitterStatus"; - case NvRegPacketFilterFlags: return "NvRegPacketFilterFlags"; - case NvRegOffloadConfig: return "NvRegOffloadConfig"; - case NvRegReceiverControl: return "NvRegReceiverControl"; - case NvRegReceiverStatus: return "NvRegReceiverStatus"; - case NvRegRandomSeed: return "NvRegRandomSeed"; - case NvRegUnknownSetupReg1: return "NvRegUnknownSetupReg1"; - case NvRegUnknownSetupReg2: return "NvRegUnknownSetupReg2"; - case NvRegMacAddrA: return "NvRegMacAddrA"; - case NvRegMacAddrB: return "NvRegMacAddrB"; - case NvRegMulticastAddrA: return "NvRegMulticastAddrA"; - case NvRegMulticastAddrB: return "NvRegMulticastAddrB"; - case NvRegMulticastMaskA: return "NvRegMulticastMaskA"; - case NvRegMulticastMaskB: return "NvRegMulticastMaskB"; - case NvRegTxRingPhysAddr: return "NvRegTxRingPhysAddr"; - case NvRegRxRingPhysAddr: return "NvRegRxRingPhysAddr"; - case NvRegRingSizes: return "NvRegRingSizes"; - case NvRegUnknownTransmitterReg: return "NvRegUnknownTransmitterReg"; - case NvRegLinkSpeed: return "NvRegLinkSpeed"; - case NvRegUnknownSetupReg5: return "NvRegUnknownSetupReg5"; - case NvRegUnknownSetupReg3: return "NvRegUnknownSetupReg3"; - case NvRegUnknownSetupReg8: return "NvRegUnknownSetupReg8"; - case NvRegUnknownSetupReg7: return "NvRegUnknownSetupReg7"; - case NvRegTxRxControl: return "NvRegTxRxControl"; - case NvRegMIIStatus: return "NvRegMIIStatus"; - case NvRegUnknownSetupReg4: return "NvRegUnknownSetupReg4"; - case NvRegAdapterControl: return "NvRegAdapterControl"; - case NvRegMIISpeed: return "NvRegMIISpeed"; - case NvRegMIIControl: return "NvRegMIIControl"; - case NvRegMIIData: return "NvRegMIIData"; - case NvRegWakeUpFlags: return "NvRegWakeUpFlags"; - case NvRegPatternCRC: return "NvRegPatternCRC"; - case NvRegPatternMask: return "NvRegPatternMask"; - case NvRegPowerCap: return "NvRegPowerCap"; - case NvRegPowerState: return "NvRegPowerState"; - default: return "Unknown"; + R(NvRegIrqStatus) + R(NvRegIrqMask) + R(NvRegUnknownSetupReg6) + R(NvRegPollingInterval) + R(NvRegMisc1) + R(NvRegTransmitterControl) + R(NvRegTransmitterStatus) + R(NvRegPacketFilterFlags) + R(NvRegOffloadConfig) + R(NvRegReceiverControl) + R(NvRegReceiverStatus) + R(NvRegRandomSeed) + R(NvRegUnknownSetupReg1) + R(NvRegUnknownSetupReg2) + R(NvRegMacAddrA) + R(NvRegMacAddrB) + R(NvRegMulticastAddrA) + R(NvRegMulticastAddrB) + R(NvRegMulticastMaskA) + R(NvRegMulticastMaskB) + R(NvRegTxRingPhysAddr) + R(NvRegRxRingPhysAddr) + R(NvRegRingSizes) + R(NvRegUnknownTransmitterReg) + R(NvRegLinkSpeed) + R(NvRegUnknownSetupReg5) + R(NvRegUnknownSetupReg3) + R(NvRegUnknownSetupReg8) + R(NvRegUnknownSetupReg7) + R(NvRegTxRxControl) + R(NvRegMIIStatus) + R(NvRegUnknownSetupReg4) + R(NvRegAdapterControl) + R(NvRegMIISpeed) + R(NvRegMIIControl) + R(NvRegMIIData) + R(NvRegWakeUpFlags) + R(NvRegPatternCRC) + R(NvRegPatternMask) + R(NvRegPowerCap) + R(NvRegPowerState) + default: + return "Unknown"; } } static const char *nvnet_get_mii_reg_name(uint8_t reg) { switch (reg) { - case MII_PHYID1: return "MII_PHYID1"; - case MII_PHYID2: return "MII_PHYID2"; - case MII_BMCR: return "MII_BMCR"; - case MII_BMSR: return "MII_BMSR"; - case MII_ANAR: return "MII_ANAR"; - case MII_ANLPAR: return "MII_ANLPAR"; - default: return "Unknown"; + R(MII_PHYID1) + R(MII_PHYID2) + R(MII_BMCR) + R(MII_BMSR) + R(MII_ANAR) + R(MII_ANLPAR) + default: + return "Unknown"; } } +#undef R + static void nvnet_dump_ring_descriptors(NvNetState *s) { #if NVNET_DEBUG From 144d3049a92ccc6d5c09aa10593cf35636e2ed77 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 20/47] nvnet: Drop more useless comments --- hw/xbox/mcpx/nvnet/nvnet.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 0dbf409036..d859533f4a 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -152,7 +152,6 @@ static void nvnet_dump_ring_descriptors(NvNetState *s) NVNET_DPRINTF("------------------------------------------------\n"); for (int i = 0; i < s->tx_ring_size; i++) { - /* Read ring descriptor */ dma_addr_t tx_ring_addr = nvnet_get_reg(s, NvRegTxRingPhysAddr, 4); tx_ring_addr += i * sizeof(desc); pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); @@ -165,7 +164,6 @@ static void nvnet_dump_ring_descriptors(NvNetState *s) NVNET_DPRINTF("------------------------------------------------\n"); for (int i = 0; i < s->rx_ring_size; i++) { - /* Read ring descriptor */ dma_addr_t rx_ring_addr = nvnet_get_reg(s, NvRegRxRingPhysAddr, 4); rx_ring_addr += i * sizeof(desc); pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); @@ -185,18 +183,18 @@ static uint32_t nvnet_get_reg(NvNetState *s, hwaddr addr, unsigned int size) switch (size) { case 4: - assert((addr & 3) == 0); /* Unaligned register access. */ + assert((addr & 3) == 0); return ((uint32_t *)s->regs)[addr >> 2]; case 2: - assert((addr & 1) == 0); /* Unaligned register access. */ + assert((addr & 1) == 0); return ((uint16_t *)s->regs)[addr >> 1]; case 1: return s->regs[addr]; default: - assert(0); /* Unsupported register access. */ + assert(!"Unsupported register access"); return 0; } } @@ -208,12 +206,12 @@ static void nvnet_set_reg(NvNetState *s, switch (size) { case 4: - assert((addr & 3) == 0); /* Unaligned register access. */ + assert((addr & 3) == 0); ((uint32_t *)s->regs)[addr >> 2] = val; break; case 2: - assert((addr & 1) == 0); /* Unaligned register access. */ + assert((addr & 1) == 0); ((uint16_t *)s->regs)[addr >> 1] = (uint16_t)val; break; @@ -222,7 +220,7 @@ static void nvnet_set_reg(NvNetState *s, break; default: - assert(0); /* Unsupported register access. */ + assert(!"Unsupported register access"); } } @@ -260,12 +258,12 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, 4); for (int i = 0; i < s->rx_ring_size; i++) { - /* Read current ring descriptor */ struct RingDesc desc; s->rx_ring_index %= s->rx_ring_size; dma_addr_t rx_ring_addr = nvnet_get_reg(s, NvRegRxRingPhysAddr, 4); rx_ring_addr += s->rx_ring_index * sizeof(desc); pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); + NVNET_DPRINTF("RX: Looking at ring descriptor %d (0x%" HWADDR_PRIx "): ", s->rx_ring_index, rx_ring_addr); NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); @@ -280,15 +278,14 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, s->rx_ring_index += 1; - /* Transfer packet from device to memory */ NVNET_DPRINTF("Transferring packet, size 0x%zx, to memory at 0x%x\n", size, desc.packet_buffer); pci_dma_write(d, desc.packet_buffer, buf, size); - /* Update descriptor indicating the packet is waiting */ desc.length = size; desc.flags = NV_RX_BIT4 | NV_RX_DESCRIPTORVALID; pci_dma_write(d, rx_ring_addr, &desc, sizeof(desc)); + NVNET_DPRINTF("Updated ring descriptor: "); NVNET_DPRINTF("Length: 0x%x, ", desc.length); NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); @@ -309,7 +306,6 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, if (did_receive) { return size; } else { - /* Could not find free buffer, or packet too large. */ NVNET_DPRINTF("Could not find free buffer!\n"); return -1; } @@ -331,6 +327,7 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) dma_addr_t tx_ring_addr = nvnet_get_reg(s, NvRegTxRingPhysAddr, 4); tx_ring_addr += s->tx_ring_index * sizeof(desc); pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); + NVNET_DPRINTF("TX: Looking at ring desc %d (%" HWADDR_PRIx "): ", s->tx_ring_index, tx_ring_addr); NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); @@ -343,14 +340,12 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) s->tx_ring_index += 1; - /* Transfer packet from guest memory */ assert((s->tx_dma_buf_offset + desc.length + 1) <= sizeof(s->tx_dma_buf)); pci_dma_read(d, desc.packet_buffer, &s->tx_dma_buf[s->tx_dma_buf_offset], desc.length + 1); s->tx_dma_buf_offset += desc.length + 1; - /* Update descriptor */ bool is_last_packet = desc.flags & NV_TX_LASTPACKET; if (is_last_packet) { NVNET_DPRINTF("Sending packet...\n"); @@ -371,7 +366,6 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) } } - /* Trigger interrupt */ if (packet_sent) { NVNET_DPRINTF("Triggering interrupt\n"); uint32_t irq_status = nvnet_get_reg(s, NvRegIrqStatus, 4); @@ -457,7 +451,6 @@ static ssize_t nvnet_receive_iov(NetClientState *nc, NVNET_DPRINTF("nvnet: Packet received!\n"); if (nvnet_is_packet_oversized(size)) { - /* Drop */ NVNET_DPRINTF("%s packet too large!\n", __func__); trace_nvnet_rx_oversized(size); return size; From f4ab3ab830be8c024da0bd19e59f45ebd46fa677 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 21/47] nvnet: Format the register list --- hw/xbox/mcpx/nvnet/nvnet.c | 200 +++++++++++------------ hw/xbox/mcpx/nvnet/nvnet_regs.h | 273 +++++++++++++++----------------- 2 files changed, 227 insertions(+), 246 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index d859533f4a..0a6bf219f5 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -82,47 +82,47 @@ struct RingDesc { static const char *nvnet_get_reg_name(hwaddr addr) { switch (addr) { - R(NvRegIrqStatus) - R(NvRegIrqMask) - R(NvRegUnknownSetupReg6) - R(NvRegPollingInterval) - R(NvRegMisc1) - R(NvRegTransmitterControl) - R(NvRegTransmitterStatus) - R(NvRegPacketFilterFlags) - R(NvRegOffloadConfig) - R(NvRegReceiverControl) - R(NvRegReceiverStatus) - R(NvRegRandomSeed) - R(NvRegUnknownSetupReg1) - R(NvRegUnknownSetupReg2) - R(NvRegMacAddrA) - R(NvRegMacAddrB) - R(NvRegMulticastAddrA) - R(NvRegMulticastAddrB) - R(NvRegMulticastMaskA) - R(NvRegMulticastMaskB) - R(NvRegTxRingPhysAddr) - R(NvRegRxRingPhysAddr) - R(NvRegRingSizes) - R(NvRegUnknownTransmitterReg) - R(NvRegLinkSpeed) - R(NvRegUnknownSetupReg5) - R(NvRegUnknownSetupReg3) - R(NvRegUnknownSetupReg8) - R(NvRegUnknownSetupReg7) - R(NvRegTxRxControl) - R(NvRegMIIStatus) - R(NvRegUnknownSetupReg4) - R(NvRegAdapterControl) - R(NvRegMIISpeed) - R(NvRegMIIControl) - R(NvRegMIIData) - R(NvRegWakeUpFlags) - R(NvRegPatternCRC) - R(NvRegPatternMask) - R(NvRegPowerCap) - R(NvRegPowerState) + R(NVNET_IRQ_STATUS) + R(NVNET_IRQ_MASK) + R(NVNET_UNKNOWN_SETUP_REG6) + R(NVNET_POLLING_INTERVAL) + R(NVNET_MISC1) + R(NVNET_TRANSMITTER_CONTROL) + R(NVNET_TRANSMITTER_STATUS) + R(NVNET_PACKET_FILTER) + R(NVNET_OFFLOAD) + R(NVNET_RECEIVER_CONTROL) + R(NVNET_RECEIVER_STATUS) + R(NVNET_RANDOM_SEED) + R(NVNET_UNKNOWN_SETUP_REG1) + R(NVNET_UNKNOWN_SETUP_REG2) + R(NVNET_MAC_ADDR_A) + R(NVNET_MAC_ADDR_B) + R(NVNET_MULTICAST_ADDR_A) + R(NVNET_MULTICAST_ADDR_B) + R(NVNET_MULTICAST_MASK_A) + R(NVNET_MULTICAST_MASK_B) + R(NVNET_TX_RING_PHYS_ADDR) + R(NVNET_RX_RING_PHYS_ADDR) + R(NVNET_RING_SIZE) + R(NVNET_UNKNOWN_TRANSMITTER_REG) + R(NVNET_LINKSPEED) + R(NVNET_UNKNOWN_SETUP_REG5) + R(NVNET_UNKNOWN_SETUP_REG3) + R(NVNET_UNKNOWN_SETUP_REG8) + R(NVNET_UNKNOWN_SETUP_REG7) + R(NVNET_TX_RX_CONTROL) + R(NVNET_MII_STATUS) + R(NVNET_UNKNOWN_SETUP_REG4) + R(NVNET_ADAPTER_CONTROL) + R(NVNET_MII_SPEED) + R(NVNET_MII_CONTROL) + R(NVNET_MII_DATA) + R(NVNET_WAKEUPFLAGS) + R(NVNET_PATTERN_CRC) + R(NVNET_PATTERN_MASK) + R(NVNET_POWERCAP) + R(NVNET_POWERSTATE) default: return "Unknown"; } @@ -152,7 +152,7 @@ static void nvnet_dump_ring_descriptors(NvNetState *s) NVNET_DPRINTF("------------------------------------------------\n"); for (int i = 0; i < s->tx_ring_size; i++) { - dma_addr_t tx_ring_addr = nvnet_get_reg(s, NvRegTxRingPhysAddr, 4); + dma_addr_t tx_ring_addr = nvnet_get_reg(s, NVNET_TX_RING_PHYS_ADDR, 4); tx_ring_addr += i * sizeof(desc); pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); NVNET_DPRINTF("TX: Dumping ring desc %d (%" HWADDR_PRIx "): ", @@ -164,7 +164,7 @@ static void nvnet_dump_ring_descriptors(NvNetState *s) NVNET_DPRINTF("------------------------------------------------\n"); for (int i = 0; i < s->rx_ring_size; i++) { - dma_addr_t rx_ring_addr = nvnet_get_reg(s, NvRegRxRingPhysAddr, 4); + dma_addr_t rx_ring_addr = nvnet_get_reg(s, NVNET_RX_RING_PHYS_ADDR, 4); rx_ring_addr += i * sizeof(desc); pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); NVNET_DPRINTF("RX: Dumping ring desc %d (%" HWADDR_PRIx "): ", @@ -228,8 +228,8 @@ static void nvnet_update_irq(NvNetState *s) { PCIDevice *d = PCI_DEVICE(s); - uint32_t irq_mask = nvnet_get_reg(s, NvRegIrqMask, 4); - uint32_t irq_status = nvnet_get_reg(s, NvRegIrqStatus, 4); + uint32_t irq_mask = nvnet_get_reg(s, NVNET_IRQ_MASK, 4); + uint32_t irq_status = nvnet_get_reg(s, NVNET_IRQ_STATUS, 4); if (irq_mask & irq_status) { NVNET_DPRINTF("Asserting IRQ\n"); @@ -253,14 +253,14 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, PCIDevice *d = PCI_DEVICE(s); bool did_receive = false; - nvnet_set_reg(s, NvRegTxRxControl, - nvnet_get_reg(s, NvRegTxRxControl, 4) & ~NVREG_TXRXCTL_IDLE, + nvnet_set_reg(s, NVNET_TX_RX_CONTROL, + nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4) & ~NVNET_TX_RX_CONTROL_IDLE, 4); for (int i = 0; i < s->rx_ring_size; i++) { struct RingDesc desc; s->rx_ring_index %= s->rx_ring_size; - dma_addr_t rx_ring_addr = nvnet_get_reg(s, NvRegRxRingPhysAddr, 4); + dma_addr_t rx_ring_addr = nvnet_get_reg(s, NVNET_RX_RING_PHYS_ADDR, 4); rx_ring_addr += s->rx_ring_index * sizeof(desc); pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); @@ -292,15 +292,15 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, /* Trigger interrupt */ NVNET_DPRINTF("Triggering interrupt\n"); - uint32_t irq_status = nvnet_get_reg(s, NvRegIrqStatus, 4); - nvnet_set_reg(s, NvRegIrqStatus, irq_status | NVREG_IRQSTAT_BIT1, 4); + uint32_t irq_status = nvnet_get_reg(s, NVNET_IRQ_STATUS, 4); + nvnet_set_reg(s, NVNET_IRQ_STATUS, irq_status | NVNET_IRQ_STATUS_RX, 4); nvnet_update_irq(s); did_receive = true; break; } - nvnet_set_reg(s, NvRegTxRxControl, - nvnet_get_reg(s, NvRegTxRxControl, 4) | NVREG_TXRXCTL_IDLE, + nvnet_set_reg(s, NVNET_TX_RX_CONTROL, + nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4) | NVNET_TX_RX_CONTROL_IDLE, 4); if (did_receive) { @@ -316,15 +316,15 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) PCIDevice *d = PCI_DEVICE(s); bool packet_sent = false; - nvnet_set_reg(s, NvRegTxRxControl, - nvnet_get_reg(s, NvRegTxRxControl, 4) & ~NVREG_TXRXCTL_IDLE, + nvnet_set_reg(s, NVNET_TX_RX_CONTROL, + nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4) & ~NVNET_TX_RX_CONTROL_IDLE, 4); for (int i = 0; i < s->tx_ring_size; i++) { /* Read ring descriptor */ struct RingDesc desc; s->tx_ring_index %= s->tx_ring_size; - dma_addr_t tx_ring_addr = nvnet_get_reg(s, NvRegTxRingPhysAddr, 4); + dma_addr_t tx_ring_addr = nvnet_get_reg(s, NVNET_TX_RING_PHYS_ADDR, 4); tx_ring_addr += s->tx_ring_index * sizeof(desc); pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); @@ -368,13 +368,13 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) if (packet_sent) { NVNET_DPRINTF("Triggering interrupt\n"); - uint32_t irq_status = nvnet_get_reg(s, NvRegIrqStatus, 4); - nvnet_set_reg(s, NvRegIrqStatus, irq_status | NVREG_IRQSTAT_BIT4, 4); + uint32_t irq_status = nvnet_get_reg(s, NVNET_IRQ_STATUS, 4); + nvnet_set_reg(s, NVNET_IRQ_STATUS, irq_status | NVNET_IRQ_STATUS_TX, 4); nvnet_update_irq(s); } - nvnet_set_reg(s, NvRegTxRxControl, - nvnet_get_reg(s, NvRegTxRxControl, 4) | NVREG_TXRXCTL_IDLE, + nvnet_set_reg(s, NVNET_TX_RX_CONTROL, + nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4) | NVNET_TX_RX_CONTROL_IDLE, 4); return 0; @@ -397,7 +397,7 @@ static bool receive_filter(NvNetState *s, const uint8_t *buf, int size) return false; } - uint32_t rctl = nvnet_get_reg(s, NvRegPacketFilterFlags, 4); + uint32_t rctl = nvnet_get_reg(s, NVNET_PACKET_FILTER, 4); /* Broadcast */ if (is_broadcast_ether_addr(buf)) { @@ -406,20 +406,20 @@ static bool receive_filter(NvNetState *s, const uint8_t *buf, int size) return true; } - if (!(rctl & NVREG_PFF_MYADDR)) { + if (!(rctl & NVNET_PACKET_FILTER_MYADDR)) { /* FIXME: Confirm PFF_MYADDR filters mcast */ return true; } /* Multicast */ uint32_t addr[2]; - addr[0] = cpu_to_le32(nvnet_get_reg(s, NvRegMulticastAddrA, 4)); - addr[1] = cpu_to_le32(nvnet_get_reg(s, NvRegMulticastAddrB, 4)); + addr[0] = cpu_to_le32(nvnet_get_reg(s, NVNET_MULTICAST_ADDR_A, 4)); + addr[1] = cpu_to_le32(nvnet_get_reg(s, NVNET_MULTICAST_ADDR_B, 4)); if (!is_broadcast_ether_addr((uint8_t *)addr)) { uint32_t dest_addr[2]; memcpy(dest_addr, buf, 6); - dest_addr[0] &= cpu_to_le32(nvnet_get_reg(s, NvRegMulticastMaskA, 4)); - dest_addr[1] &= cpu_to_le32(nvnet_get_reg(s, NvRegMulticastMaskB, 4)); + dest_addr[0] &= cpu_to_le32(nvnet_get_reg(s, NVNET_MULTICAST_MASK_A, 4)); + dest_addr[1] &= cpu_to_le32(nvnet_get_reg(s, NVNET_MULTICAST_MASK_B, 4)); if (!memcmp(dest_addr, addr, 6)) { trace_nvnet_rx_filter_mcast_match(MAC_ARG(dest_addr)); @@ -430,8 +430,8 @@ static bool receive_filter(NvNetState *s, const uint8_t *buf, int size) } /* Unicast */ - addr[0] = cpu_to_le32(nvnet_get_reg(s, NvRegMacAddrA, 4)); - addr[1] = cpu_to_le32(nvnet_get_reg(s, NvRegMacAddrB, 4)); + addr[0] = cpu_to_le32(nvnet_get_reg(s, NVNET_MAC_ADDR_A, 4)); + addr[1] = cpu_to_le32(nvnet_get_reg(s, NVNET_MAC_ADDR_B, 4)); if (!memcmp(buf, addr, 6)) { trace_nvnet_rx_filter_ucast_match(MAC_ARG(buf)); return true; @@ -480,10 +480,10 @@ static ssize_t nvnet_receive(NetClientState *nc, static void nvnet_mii_read(NvNetState *s) { - uint32_t mii_ctl = nvnet_get_reg(s, NvRegMIIControl, 4); + uint32_t mii_ctl = nvnet_get_reg(s, NVNET_MII_CONTROL, 4); uint32_t mii_data = -1; - uint32_t phy_addr = GET_MASK(mii_ctl, NVREG_MIICTL_PHYADDR); - uint32_t phy_reg = GET_MASK(mii_ctl, NVREG_MIICTL_PHYREG); + uint32_t phy_addr = GET_MASK(mii_ctl, NVNET_MII_CONTROL_PHYADDR); + uint32_t phy_reg = GET_MASK(mii_ctl, NVNET_MII_CONTROL_PHYREG); if (phy_addr != 1) { goto out; @@ -508,22 +508,22 @@ static void nvnet_mii_read(NvNetState *s) } out: - mii_ctl &= ~NVREG_MIICTL_INUSE; - nvnet_set_reg(s, NvRegMIIControl, mii_ctl, 4); - nvnet_set_reg(s, NvRegMIIData, mii_data, 4); + mii_ctl &= ~NVNET_MII_CONTROL_INUSE; + nvnet_set_reg(s, NVNET_MII_CONTROL, mii_ctl, 4); + nvnet_set_reg(s, NVNET_MII_DATA, mii_data, 4); trace_nvnet_mii_read(phy_addr, phy_reg, nvnet_get_mii_reg_name(phy_reg), mii_data); } static void nvnet_mii_write(NvNetState *s) { - uint32_t mii_ctl = nvnet_get_reg(s, NvRegMIIControl, 4); - uint32_t mii_data = nvnet_get_reg(s, NvRegMIIData, 4); - uint32_t phy_addr = GET_MASK(mii_ctl, NVREG_MIICTL_PHYADDR); - uint32_t phy_reg = GET_MASK(mii_ctl, NVREG_MIICTL_PHYREG); + uint32_t mii_ctl = nvnet_get_reg(s, NVNET_MII_CONTROL, 4); + uint32_t mii_data = nvnet_get_reg(s, NVNET_MII_DATA, 4); + uint32_t phy_addr = GET_MASK(mii_ctl, NVNET_MII_CONTROL_PHYADDR); + uint32_t phy_reg = GET_MASK(mii_ctl, NVNET_MII_CONTROL_PHYREG); - mii_ctl &= ~NVREG_MIICTL_INUSE; - nvnet_set_reg(s, NvRegMIIControl, mii_ctl, 4); + mii_ctl &= ~NVNET_MII_CONTROL_INUSE; + nvnet_set_reg(s, NVNET_MII_CONTROL, mii_ctl, 4); trace_nvnet_mii_write(phy_addr, phy_reg, nvnet_get_mii_reg_name(phy_reg), mii_data); } @@ -534,7 +534,7 @@ static uint64_t nvnet_mmio_read(void *opaque, hwaddr addr, unsigned int size) uint64_t retval; switch (addr) { - case NvRegMIIStatus: + case NVNET_MII_STATUS: retval = 0; break; @@ -556,63 +556,63 @@ static void nvnet_mmio_write(void *opaque, hwaddr addr, trace_nvnet_reg_write(addr, nvnet_get_reg_name(addr & ~3), size, val); switch (addr) { - case NvRegRingSizes: + case NVNET_RING_SIZE: nvnet_set_reg(s, addr, val, size); - s->rx_ring_size = ((val >> NVREG_RINGSZ_RXSHIFT) & 0xffff) + 1; - s->tx_ring_size = ((val >> NVREG_RINGSZ_TXSHIFT) & 0xffff) + 1; + s->rx_ring_size = ((val >> NVNET_RING_SIZE_RXSHIFT) & 0xffff) + 1; + s->tx_ring_size = ((val >> NVNET_RING_SIZE_TXSHIFT) & 0xffff) + 1; break; - case NvRegMIIControl: + case NVNET_MII_CONTROL: assert(size == 4); nvnet_set_reg(s, addr, val, size); - if (val & NVREG_MIICTL_WRITE) { + if (val & NVNET_MII_CONTROL_WRITE) { nvnet_mii_write(s); } else { nvnet_mii_read(s); } break; - case NvRegTxRxControl: - if (val == NVREG_TXRXCTL_KICK) { - NVNET_DPRINTF("NvRegTxRxControl = NVREG_TXRXCTL_KICK!\n"); + case NVNET_TX_RX_CONTROL: + if (val == NVNET_TX_RX_CONTROL_KICK) { + NVNET_DPRINTF("NVNET_TX_RX_CONTROL = NVNET_TX_RX_CONTROL_KICK!\n"); nvnet_dump_ring_descriptors(s); nvnet_dma_packet_from_guest(s); } - if (val & NVREG_TXRXCTL_BIT2) { - nvnet_set_reg(s, NvRegTxRxControl, NVREG_TXRXCTL_IDLE, 4); + if (val & NVNET_TX_RX_CONTROL_BIT2) { + nvnet_set_reg(s, NVNET_TX_RX_CONTROL, NVNET_TX_RX_CONTROL_IDLE, 4); break; } - if (val & NVREG_TXRXCTL_RESET) { + if (val & NVNET_TX_RX_CONTROL_RESET) { s->tx_ring_index = 0; s->rx_ring_index = 0; s->tx_dma_buf_offset = 0; } - if (val & NVREG_TXRXCTL_BIT1) { + if (val & NVNET_TX_RX_CONTROL_BIT1) { // FIXME - nvnet_set_reg(s, NvRegIrqStatus, 0, 4); + nvnet_set_reg(s, NVNET_IRQ_STATUS, 0, 4); break; } else if (val == 0) { - temp = nvnet_get_reg(s, NvRegUnknownSetupReg3, 4); - if (temp == NVREG_UNKSETUP3_VAL1) { + temp = nvnet_get_reg(s, NVNET_UNKNOWN_SETUP_REG3, 4); + if (temp == NVNET_UNKNOWN_SETUP_REG3_VAL1) { /* forcedeth waits for this bit to be set... */ - nvnet_set_reg(s, NvRegUnknownSetupReg5, - NVREG_UNKSETUP5_BIT31, 4); + nvnet_set_reg(s, NVNET_UNKNOWN_SETUP_REG5, + NVNET_UNKNOWN_SETUP_REG5_BIT31, 4); break; } } - nvnet_set_reg(s, NvRegTxRxControl, val, size); + nvnet_set_reg(s, NVNET_TX_RX_CONTROL, val, size); break; - case NvRegIrqMask: + case NVNET_IRQ_MASK: nvnet_set_reg(s, addr, val, size); nvnet_update_irq(s); break; - case NvRegIrqStatus: + case NVNET_IRQ_STATUS: nvnet_set_reg(s, addr, nvnet_get_reg(s, addr, size) & ~val, size); nvnet_update_irq(s); break; diff --git a/hw/xbox/mcpx/nvnet/nvnet_regs.h b/hw/xbox/mcpx/nvnet/nvnet_regs.h index b311b87278..2e46d36897 100644 --- a/hw/xbox/mcpx/nvnet/nvnet_regs.h +++ b/hw/xbox/mcpx/nvnet/nvnet_regs.h @@ -22,8 +22,8 @@ * Most definitions are based on forcedeth.c, taken from cromwell project. * Original forcedeth.c license follows: * - * -- - * forcedeth.c -- Etherboot device driver for the NVIDIA nForce + * -- + * forcedeth.c -- Etherboot device driver for the NVIDIA nForce * media access controllers. * * Note: This driver is based on the Linux driver that was based on @@ -53,160 +53,141 @@ * * (C) 2003 Manfred Spraul * See Linux Driver for full information - * + * * Linux Driver Version 0.22, 19 Jan 2004 - * - * + * + * * REVISION HISTORY: * ================ * v1.0 01-31-2004 timlegge Initial port of Linux driver - * v1.1 02-03-2004 timlegge Large Clean up, first release - * + * v1.1 02-03-2004 timlegge Large Clean up, first release + * * Indent Options: indent -kr -i8 ***************************************************************************/ #ifndef HW_NVNET_REGS_H #define HW_NVNET_REGS_H -// clang-format on +// clang-format off -#define DEV_NEED_LASTPACKET1 0x0001 -#define DEV_IRQMASK_1 0x0002 -#define DEV_IRQMASK_2 0x0004 -#define DEV_NEED_TIMERIRQ 0x0008 - -enum { - NvRegIrqStatus = 0x000, -# define NVREG_IRQSTAT_BIT1 0x002 -# define NVREG_IRQSTAT_BIT4 0x010 -# define NVREG_IRQSTAT_MIIEVENT 0x040 -# define NVREG_IRQSTAT_MASK 0x1ff - NvRegIrqMask = 0x004, -# define NVREG_IRQ_RX 0x0002 -# define NVREG_IRQ_RX_NOBUF 0x0004 -# define NVREG_IRQ_TX_ERR 0x0008 -# define NVREG_IRQ_TX2 0x0010 -# define NVREG_IRQ_TIMER 0x0020 -# define NVREG_IRQ_LINK 0x0040 -# define NVREG_IRQ_TX1 0x0100 -# define NVREG_IRQMASK_WANTED_1 0x005f -# define NVREG_IRQMASK_WANTED_2 0x0147 -# define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX | NVREG_IRQ_RX_NOBUF | \ - NVREG_IRQ_TX_ERR | NVREG_IRQ_TX2 | NVREG_IRQ_TIMER | NVREG_IRQ_LINK | \ - NVREG_IRQ_TX1)) - NvRegUnknownSetupReg6 = 0x008, -# define NVREG_UNKSETUP6_VAL 3 +#define NVNET_IRQ_STATUS 0x000 +# define NVNET_IRQ_STATUS_RX 0x00000002 +# define NVNET_IRQ_STATUS_RX_NOBUF 0x00000004 +# define NVNET_IRQ_STATUS_TX_ERR 0x00000008 +# define NVNET_IRQ_STATUS_TX 0x00000010 +# define NVNET_IRQ_STATUS_TIMER 0x00000020 +# define NVNET_IRQ_STATUS_MIIEVENT 0x00000040 +#define NVNET_IRQ_MASK 0x004 +#define NVNET_UNKNOWN_SETUP_REG6 0x008 +# define NVNET_UNKNOWN_SETUP_REG6_VAL 3 /* - * NVREG_POLL_DEFAULT is the interval length of the timer source on the nic - * NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms + * NVNET_POLLING_INTERVAL_DEFAULT is the interval length of the timer source on the nic + * NVNET_POLLING_INTERVAL_DEFAULT=97 would result in an interval length of 1 ms */ - NvRegPollingInterval = 0x00c, -# define NVREG_POLL_DEFAULT 970 - NvRegMisc1 = 0x080, -# define NVREG_MISC1_HD 0x02 -# define NVREG_MISC1_FORCE 0x3b0f3c - NvRegTransmitterControl = 0x084, -# define NVREG_XMITCTL_START 0x01 - NvRegTransmitterStatus = 0x088, -# define NVREG_XMITSTAT_BUSY 0x01 - NvRegPacketFilterFlags = 0x8c, -# define NVREG_PFF_ALWAYS 0x7F0008 -# define NVREG_PFF_PROMISC 0x80 -# define NVREG_PFF_MYADDR 0x20 - NvRegOffloadConfig = 0x90, -# define NVREG_OFFLOAD_HOMEPHY 0x601 -# define NVREG_OFFLOAD_NORMAL 0x5ee - NvRegReceiverControl = 0x094, -# define NVREG_RCVCTL_START 0x01 - NvRegReceiverStatus = 0x98, -# define NVREG_RCVSTAT_BUSY 0x01 - NvRegRandomSeed = 0x9c, -# define NVREG_RNDSEED_MASK 0x00ff -# define NVREG_RNDSEED_FORCE 0x7f00 - NvRegUnknownSetupReg1 = 0xA0, -# define NVREG_UNKSETUP1_VAL 0x16070f - NvRegUnknownSetupReg2 = 0xA4, -# define NVREG_UNKSETUP2_VAL 0x16 - NvRegMacAddrA = 0xA8, - NvRegMacAddrB = 0xAC, - NvRegMulticastAddrA = 0xB0, -# define NVREG_MCASTADDRA_FORCE 0x01 - NvRegMulticastAddrB = 0xB4, - NvRegMulticastMaskA = 0xB8, - NvRegMulticastMaskB = 0xBC, - NvRegTxRingPhysAddr = 0x100, - NvRegRxRingPhysAddr = 0x104, - NvRegRingSizes = 0x108, -# define NVREG_RINGSZ_TXSHIFT 0 -# define NVREG_RINGSZ_RXSHIFT 16 - NvRegUnknownTransmitterReg = 0x10c, - NvRegLinkSpeed = 0x110, -# define NVREG_LINKSPEED_FORCE 0x10000 -# define NVREG_LINKSPEED_10 10 -# define NVREG_LINKSPEED_100 100 -# define NVREG_LINKSPEED_1000 1000 - NvRegUnknownSetupReg5 = 0x130, -# define NVREG_UNKSETUP5_BIT31 (1 << 31) - NvRegUnknownSetupReg3 = 0x134, -# define NVREG_UNKSETUP3_VAL1 0x200010 - NvRegUnknownSetupReg8 = 0x13C, -# define NVREG_UNKSETUP8_VAL1 0x300010 - NvRegUnknownSetupReg7 = 0x140, -# define NVREG_UNKSETUP7_VAL 0x300010 - NvRegTxRxControl = 0x144, -# define NVREG_TXRXCTL_KICK 0x0001 -# define NVREG_TXRXCTL_BIT1 0x0002 -# define NVREG_TXRXCTL_BIT2 0x0004 -# define NVREG_TXRXCTL_IDLE 0x0008 -# define NVREG_TXRXCTL_RESET 0x0010 - NvRegMIIStatus = 0x180, -# define NVREG_MIISTAT_ERROR 0x0001 -# define NVREG_MIISTAT_LINKCHANGE 0x0008 -# define NVREG_MIISTAT_MASK 0x000f -# define NVREG_MIISTAT_MASK2 0x000f - NvRegUnknownSetupReg4 = 0x184, -# define NVREG_UNKSETUP4_VAL 8 - NvRegAdapterControl = 0x188, -# define NVREG_ADAPTCTL_START 0x02 -# define NVREG_ADAPTCTL_LINKUP 0x04 -# define NVREG_ADAPTCTL_PHYVALID 0x4000 -# define NVREG_ADAPTCTL_RUNNING 0x100000 -# define NVREG_ADAPTCTL_PHYSHIFT 24 - NvRegMIISpeed = 0x18c, -# define NVREG_MIISPEED_BIT8 (1 << 8) -# define NVREG_MIIDELAY 5 - NvRegMIIControl = 0x190, -# define NVREG_MIICTL_INUSE 0x8000 -# define NVREG_MIICTL_WRITE 0x0400 -# define NVREG_MIICTL_PHYADDR 0x03e0 -# define NVREG_MIICTL_PHYREG 0x001f - NvRegMIIData = 0x194, - NvRegWakeUpFlags = 0x200, -# define NVREG_WAKEUPFLAGS_VAL 0x7770 -# define NVREG_WAKEUPFLAGS_BUSYSHIFT 24 -# define NVREG_WAKEUPFLAGS_ENABLESHIFT 16 -# define NVREG_WAKEUPFLAGS_D3SHIFT 12 -# define NVREG_WAKEUPFLAGS_D2SHIFT 8 -# define NVREG_WAKEUPFLAGS_D1SHIFT 4 -# define NVREG_WAKEUPFLAGS_D0SHIFT 0 -# define NVREG_WAKEUPFLAGS_ACCEPT_MAGPAT 0x01 -# define NVREG_WAKEUPFLAGS_ACCEPT_WAKEUPPAT 0x02 -# define NVREG_WAKEUPFLAGS_ACCEPT_LINKCHANGE 0x04 - NvRegPatternCRC = 0x204, - NvRegPatternMask = 0x208, - NvRegPowerCap = 0x268, -# define NVREG_POWERCAP_D3SUPP (1 << 30) -# define NVREG_POWERCAP_D2SUPP (1 << 26) -# define NVREG_POWERCAP_D1SUPP (1 << 25) - NvRegPowerState = 0x26c, -# define NVREG_POWERSTATE_POWEREDUP 0x8000 -# define NVREG_POWERSTATE_VALID 0x0100 -# define NVREG_POWERSTATE_MASK 0x0003 -# define NVREG_POWERSTATE_D0 0x0000 -# define NVREG_POWERSTATE_D1 0x0001 -# define NVREG_POWERSTATE_D2 0x0002 -# define NVREG_POWERSTATE_D3 0x0003 -}; +#define NVNET_POLLING_INTERVAL 0x00C +# define NVNET_POLLING_INTERVAL_DEFAULT 970 +#define NVNET_MISC1 0x080 +# define NVNET_MISC1_HD 0x00000002 +# define NVNET_MISC1_FORCE 0x003B0F3C +#define NVNET_TRANSMITTER_CONTROL 0x084 +# define NVNET_TRANSMITTER_CONTROL_START 0x00000001 +#define NVNET_TRANSMITTER_STATUS 0x088 +# define NVNET_TRANSMITTER_STATUS_BUSY 0x00000001 +#define NVNET_PACKET_FILTER 0x08C +# define NVNET_PACKET_FILTER_ALWAYS 0x007F0008 +# define NVNET_PACKET_FILTER_PROMISC 0x00000080 +# define NVNET_PACKET_FILTER_MYADDR 0x00000020 +#define NVNET_OFFLOAD 0x090 +# define NVNET_OFFLOAD_HOMEPHY 0x00000601 +# define NVNET_OFFLOAD_NORMAL 0x000005EE +#define NVNET_RECEIVER_CONTROL 0x094 +# define NVNET_RECEIVER_CONTROL_START 0x00000001 +#define NVNET_RECEIVER_STATUS 0x098 +# define NVNET_RECEIVER_STATUS_BUSY 0x00000001 +#define NVNET_RANDOM_SEED 0x09C +# define NVNET_RANDOM_SEED_MASK 0x000000FF +# define NVNET_RANDOM_SEED_FORCE 0x00007F00 +#define NVNET_UNKNOWN_SETUP_REG1 0x0A0 +# define NVNET_UNKNOWN_SETUP_REG1_VAL 0x0016070F +#define NVNET_UNKNOWN_SETUP_REG2 0x0A4 +# define NVNET_UNKNOWN_SETUP_REG2_VAL 0x00000016 +#define NVNET_MAC_ADDR_A 0x0A8 +#define NVNET_MAC_ADDR_B 0x0AC +#define NVNET_MULTICAST_ADDR_A 0x0B0 +# define NVNET_MULTICAST_ADDR_A_FORCE 0x00000001 +#define NVNET_MULTICAST_ADDR_B 0x0B4 +#define NVNET_MULTICAST_MASK_A 0x0B8 +#define NVNET_MULTICAST_MASK_B 0x0BC +#define NVNET_TX_RING_PHYS_ADDR 0x100 +#define NVNET_RX_RING_PHYS_ADDR 0x104 +#define NVNET_RING_SIZE 0x108 +# define NVNET_RING_SIZE_TXSHIFT 0 +# define NVNET_RING_SIZE_RXSHIFT 16 +#define NVNET_UNKNOWN_TRANSMITTER_REG 0x10C +#define NVNET_LINKSPEED 0x110 +# define NVNET_LINKSPEED_FORCE 0x00010000 +# define NVNET_LINKSPEED_10 10 +# define NVNET_LINKSPEED_100 100 +# define NVNET_LINKSPEED_1000 1000 +#define NVNET_UNKNOWN_SETUP_REG5 0x130 +# define NVNET_UNKNOWN_SETUP_REG5_BIT31 (1 << 31) +#define NVNET_UNKNOWN_SETUP_REG3 0x134 +# define NVNET_UNKNOWN_SETUP_REG3_VAL1 0x00200010 +#define NVNET_UNKNOWN_SETUP_REG8 0x13C +# define NVNET_UNKNOWN_SETUP_REG8_VAL1 0x00300010 +#define NVNET_UNKNOWN_SETUP_REG7 0x140 +# define NVNET_UNKNOWN_SETUP_REG7_VAL 0x00300010 +#define NVNET_TX_RX_CONTROL 0x144 +# define NVNET_TX_RX_CONTROL_KICK 0x00000001 +# define NVNET_TX_RX_CONTROL_BIT1 0x00000002 +# define NVNET_TX_RX_CONTROL_BIT2 0x00000004 +# define NVNET_TX_RX_CONTROL_IDLE 0x00000008 +# define NVNET_TX_RX_CONTROL_RESET 0x00000010 +#define NVNET_MII_STATUS 0x180 +# define NVNET_MII_STATUS_ERROR 0x00000001 +# define NVNET_MII_STATUS_LINKCHANGE 0x00000008 +#define NVNET_UNKNOWN_SETUP_REG4 0x184 +# define NVNET_UNKNOWN_SETUP_REG4_VAL 8 +#define NVNET_ADAPTER_CONTROL 0x188 +# define NVNET_ADAPTER_CONTROL_START 0x00000002 +# define NVNET_ADAPTER_CONTROL_LINKUP 0x00000004 +# define NVNET_ADAPTER_CONTROL_PHYVALID 0x00004000 +# define NVNET_ADAPTER_CONTROL_RUNNING 0x00100000 +# define NVNET_ADAPTER_CONTROL_PHYSHIFT 24 +#define NVNET_MII_SPEED 0x18C +# define NVNET_MII_SPEED_BIT8 (1 << 8) +# define NVNET_MII_SPEED_DELAY 5 +#define NVNET_MII_CONTROL 0x190 +# define NVNET_MII_CONTROL_INUSE 0x00008000 +# define NVNET_MII_CONTROL_WRITE 0x00000400 +# define NVNET_MII_CONTROL_PHYADDR 0x000003E0 +# define NVNET_MII_CONTROL_PHYREG 0x0000001F +#define NVNET_MII_DATA 0x194 +#define NVNET_WAKEUPFLAGS 0x200 +# define NVNET_WAKEUPFLAGS_VAL 0x00007770 +# define NVNET_WAKEUPFLAGS_BUSYSHIFT 24 +# define NVNET_WAKEUPFLAGS_ENABLESHIFT 16 +# define NVNET_WAKEUPFLAGS_D3SHIFT 12 +# define NVNET_WAKEUPFLAGS_D2SHIFT 8 +# define NVNET_WAKEUPFLAGS_D1SHIFT 4 +# define NVNET_WAKEUPFLAGS_D0SHIFT 0 +# define NVNET_WAKEUPFLAGS_ACCEPT_MAGPAT 0x00000001 +# define NVNET_WAKEUPFLAGS_ACCEPT_WAKEUPPAT 0x00000002 +# define NVNET_WAKEUPFLAGS_ACCEPT_LINKCHANGE 0x00000004 +#define NVNET_PATTERN_CRC 0x204 +#define NVNET_PATTERN_MASK 0x208 +#define NVNET_POWERCAP 0x268 +# define NVNET_POWERCAP_D3SUPP (1 << 30) +# define NVNET_POWERCAP_D2SUPP (1 << 26) +# define NVNET_POWERCAP_D1SUPP (1 << 25) +#define NVNET_POWERSTATE 0x26C +# define NVNET_POWERSTATE_POWEREDUP 0x00008000 +# define NVNET_POWERSTATE_VALID 0x00000100 +# define NVNET_POWERSTATE_MASK 0x00000003 +# define NVNET_POWERSTATE_D0 0x00000000 +# define NVNET_POWERSTATE_D1 0x00000001 +# define NVNET_POWERSTATE_D2 0x00000002 +# define NVNET_POWERSTATE_D3 0x00000003 #define NV_TX_LASTPACKET (1 << 0) #define NV_TX_RETRYERROR (1 << 3) @@ -272,11 +253,11 @@ enum { #define POLL_WAIT (1 + HZ / 100) /* Link partner ability register. */ -#define LPA_SLCT 0x001f /* Same as advertise selector */ -#define LPA_RESV 0x1c00 /* Unused... */ +#define LPA_SLCT 0x001F /* Same as advertise selector */ +#define LPA_RESV 0x1C00 /* Unused... */ #define LPA_RFAULT 0x2000 /* Link partner faulted */ #define LPA_NPAGE 0x8000 /* Next page bit */ -// clang-format off +// clang-format on #endif /* HW_NVNET_REGS_H */ From 04bd92df400b22f774d4b7ee139dc23260a5bdcd Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 22/47] nvnet: Migrate ring size shifts to GET_MASK macro --- hw/xbox/mcpx/nvnet/nvnet.c | 4 ++-- hw/xbox/mcpx/nvnet/nvnet_regs.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 0a6bf219f5..c44ba307a3 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -558,8 +558,8 @@ static void nvnet_mmio_write(void *opaque, hwaddr addr, switch (addr) { case NVNET_RING_SIZE: nvnet_set_reg(s, addr, val, size); - s->rx_ring_size = ((val >> NVNET_RING_SIZE_RXSHIFT) & 0xffff) + 1; - s->tx_ring_size = ((val >> NVNET_RING_SIZE_TXSHIFT) & 0xffff) + 1; + s->rx_ring_size = GET_MASK(val, NVNET_RING_SIZE_RX) + 1; + s->tx_ring_size = GET_MASK(val, NVNET_RING_SIZE_TX) + 1; break; case NVNET_MII_CONTROL: diff --git a/hw/xbox/mcpx/nvnet/nvnet_regs.h b/hw/xbox/mcpx/nvnet/nvnet_regs.h index 2e46d36897..c9b54fae18 100644 --- a/hw/xbox/mcpx/nvnet/nvnet_regs.h +++ b/hw/xbox/mcpx/nvnet/nvnet_regs.h @@ -121,8 +121,8 @@ #define NVNET_TX_RING_PHYS_ADDR 0x100 #define NVNET_RX_RING_PHYS_ADDR 0x104 #define NVNET_RING_SIZE 0x108 -# define NVNET_RING_SIZE_TXSHIFT 0 -# define NVNET_RING_SIZE_RXSHIFT 16 +# define NVNET_RING_SIZE_TX 0x0000FFFF +# define NVNET_RING_SIZE_RX 0xFFFF0000 #define NVNET_UNKNOWN_TRANSMITTER_REG 0x10C #define NVNET_LINKSPEED 0x110 # define NVNET_LINKSPEED_FORCE 0x00010000 From f640a9969aec095194a15d741db04a2056a34278 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 23/47] nvnet: Rename mdio addr/data registers --- hw/xbox/mcpx/nvnet/nvnet.c | 52 ++++++++++++++++----------------- hw/xbox/mcpx/nvnet/nvnet_regs.h | 12 ++++---- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index c44ba307a3..ad2a260a63 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -116,8 +116,8 @@ static const char *nvnet_get_reg_name(hwaddr addr) R(NVNET_UNKNOWN_SETUP_REG4) R(NVNET_ADAPTER_CONTROL) R(NVNET_MII_SPEED) - R(NVNET_MII_CONTROL) - R(NVNET_MII_DATA) + R(NVNET_MDIO_ADDR) + R(NVNET_MDIO_DATA) R(NVNET_WAKEUPFLAGS) R(NVNET_PATTERN_CRC) R(NVNET_PATTERN_MASK) @@ -478,12 +478,12 @@ static ssize_t nvnet_receive(NetClientState *nc, return nvnet_receive_iov(nc, &iov, 1); } -static void nvnet_mii_read(NvNetState *s) +static void nvnet_mdio_read(NvNetState *s) { - uint32_t mii_ctl = nvnet_get_reg(s, NVNET_MII_CONTROL, 4); - uint32_t mii_data = -1; - uint32_t phy_addr = GET_MASK(mii_ctl, NVNET_MII_CONTROL_PHYADDR); - uint32_t phy_reg = GET_MASK(mii_ctl, NVNET_MII_CONTROL_PHYREG); + uint32_t mdio_addr = nvnet_get_reg(s, NVNET_MDIO_ADDR, 4); + uint32_t mdio_data = -1; + uint32_t phy_addr = GET_MASK(mdio_addr, NVNET_MDIO_ADDR_PHYADDR); + uint32_t phy_reg = GET_MASK(mdio_addr, NVNET_MDIO_ADDR_PHYREG); if (phy_addr != 1) { goto out; @@ -491,41 +491,41 @@ static void nvnet_mii_read(NvNetState *s) switch (phy_reg) { case MII_BMSR: - mii_data = MII_BMSR_AN_COMP | MII_BMSR_LINK_ST; + mdio_data = MII_BMSR_AN_COMP | MII_BMSR_LINK_ST; break; case MII_ANAR: /* Fall through... */ case MII_ANLPAR: - mii_data = MII_ANLPAR_10 | MII_ANLPAR_10FD | MII_ANLPAR_TX | + mdio_data = MII_ANLPAR_10 | MII_ANLPAR_10FD | MII_ANLPAR_TX | MII_ANLPAR_TXFD | MII_ANLPAR_T4; break; default: - mii_data = 0; + mdio_data = 0; break; } out: - mii_ctl &= ~NVNET_MII_CONTROL_INUSE; - nvnet_set_reg(s, NVNET_MII_CONTROL, mii_ctl, 4); - nvnet_set_reg(s, NVNET_MII_DATA, mii_data, 4); + mdio_addr &= ~NVNET_MDIO_ADDR_INUSE; + nvnet_set_reg(s, NVNET_MDIO_ADDR, mdio_addr, 4); + nvnet_set_reg(s, NVNET_MDIO_DATA, mdio_data, 4); trace_nvnet_mii_read(phy_addr, phy_reg, nvnet_get_mii_reg_name(phy_reg), - mii_data); + mdio_data); } -static void nvnet_mii_write(NvNetState *s) +static void nvnet_mdio_write(NvNetState *s) { - uint32_t mii_ctl = nvnet_get_reg(s, NVNET_MII_CONTROL, 4); - uint32_t mii_data = nvnet_get_reg(s, NVNET_MII_DATA, 4); - uint32_t phy_addr = GET_MASK(mii_ctl, NVNET_MII_CONTROL_PHYADDR); - uint32_t phy_reg = GET_MASK(mii_ctl, NVNET_MII_CONTROL_PHYREG); + uint32_t mdio_addr = nvnet_get_reg(s, NVNET_MDIO_ADDR, 4); + uint32_t mdio_data = nvnet_get_reg(s, NVNET_MDIO_DATA, 4); + uint32_t phy_addr = GET_MASK(mdio_addr, NVNET_MDIO_ADDR_PHYADDR); + uint32_t phy_reg = GET_MASK(mdio_addr, NVNET_MDIO_ADDR_PHYREG); - mii_ctl &= ~NVNET_MII_CONTROL_INUSE; - nvnet_set_reg(s, NVNET_MII_CONTROL, mii_ctl, 4); + mdio_addr &= ~NVNET_MDIO_ADDR_INUSE; + nvnet_set_reg(s, NVNET_MDIO_ADDR, mdio_addr, 4); trace_nvnet_mii_write(phy_addr, phy_reg, nvnet_get_mii_reg_name(phy_reg), - mii_data); + mdio_data); } static uint64_t nvnet_mmio_read(void *opaque, hwaddr addr, unsigned int size) @@ -562,13 +562,13 @@ static void nvnet_mmio_write(void *opaque, hwaddr addr, s->tx_ring_size = GET_MASK(val, NVNET_RING_SIZE_TX) + 1; break; - case NVNET_MII_CONTROL: + case NVNET_MDIO_ADDR: assert(size == 4); nvnet_set_reg(s, addr, val, size); - if (val & NVNET_MII_CONTROL_WRITE) { - nvnet_mii_write(s); + if (val & NVNET_MDIO_ADDR_WRITE) { + nvnet_mdio_write(s); } else { - nvnet_mii_read(s); + nvnet_mdio_read(s); } break; diff --git a/hw/xbox/mcpx/nvnet/nvnet_regs.h b/hw/xbox/mcpx/nvnet/nvnet_regs.h index c9b54fae18..930efe57d9 100644 --- a/hw/xbox/mcpx/nvnet/nvnet_regs.h +++ b/hw/xbox/mcpx/nvnet/nvnet_regs.h @@ -157,12 +157,12 @@ #define NVNET_MII_SPEED 0x18C # define NVNET_MII_SPEED_BIT8 (1 << 8) # define NVNET_MII_SPEED_DELAY 5 -#define NVNET_MII_CONTROL 0x190 -# define NVNET_MII_CONTROL_INUSE 0x00008000 -# define NVNET_MII_CONTROL_WRITE 0x00000400 -# define NVNET_MII_CONTROL_PHYADDR 0x000003E0 -# define NVNET_MII_CONTROL_PHYREG 0x0000001F -#define NVNET_MII_DATA 0x194 +#define NVNET_MDIO_ADDR 0x190 +# define NVNET_MDIO_ADDR_INUSE 0x00008000 +# define NVNET_MDIO_ADDR_WRITE 0x00000400 +# define NVNET_MDIO_ADDR_PHYADDR 0x000003E0 +# define NVNET_MDIO_ADDR_PHYREG 0x0000001F +#define NVNET_MDIO_DATA 0x194 #define NVNET_WAKEUPFLAGS 0x200 # define NVNET_WAKEUPFLAGS_VAL 0x00007770 # define NVNET_WAKEUPFLAGS_BUSYSHIFT 24 From 3649593c7332420c007550c52a0d83368a206878 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 24/47] nvnet: Factor out phy register read/write from mdio --- hw/xbox/mcpx/nvnet/nvnet.c | 63 +++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index ad2a260a63..129b9f2d9f 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -34,6 +34,7 @@ #define IOPORT_SIZE 0x8 #define MMIO_SIZE 0x400 +#define PHY_ADDR 1 #define GET_MASK(v, mask) (((v) & (mask)) >> ctz32(mask)) @@ -478,6 +479,37 @@ static ssize_t nvnet_receive(NetClientState *nc, return nvnet_receive_iov(nc, &iov, 1); } +static uint32_t nvnet_phy_reg_read(NvNetState *s, uint8_t reg) +{ + uint32_t value; + + switch (reg) { + case MII_BMSR: + value = MII_BMSR_AN_COMP | MII_BMSR_LINK_ST; + break; + + case MII_ANAR: + /* Fall through... */ + + case MII_ANLPAR: + value = MII_ANLPAR_10 | MII_ANLPAR_10FD | MII_ANLPAR_TX | + MII_ANLPAR_TXFD | MII_ANLPAR_T4; + break; + + default: + value = 0; + break; + } + + trace_nvnet_mii_read(PHY_ADDR, reg, nvnet_get_mii_reg_name(reg), value); + return value; +} + +static void nvnet_phy_reg_write(NvNetState *s, uint8_t reg, uint32_t value) +{ + trace_nvnet_mii_write(PHY_ADDR, reg, nvnet_get_mii_reg_name(reg), value); +} + static void nvnet_mdio_read(NvNetState *s) { uint32_t mdio_addr = nvnet_get_reg(s, NVNET_MDIO_ADDR, 4); @@ -485,34 +517,13 @@ static void nvnet_mdio_read(NvNetState *s) uint32_t phy_addr = GET_MASK(mdio_addr, NVNET_MDIO_ADDR_PHYADDR); uint32_t phy_reg = GET_MASK(mdio_addr, NVNET_MDIO_ADDR_PHYREG); - if (phy_addr != 1) { - goto out; + if (phy_addr == PHY_ADDR) { + mdio_data = nvnet_phy_reg_read(s, phy_reg); } - switch (phy_reg) { - case MII_BMSR: - mdio_data = MII_BMSR_AN_COMP | MII_BMSR_LINK_ST; - break; - - case MII_ANAR: - /* Fall through... */ - - case MII_ANLPAR: - mdio_data = MII_ANLPAR_10 | MII_ANLPAR_10FD | MII_ANLPAR_TX | - MII_ANLPAR_TXFD | MII_ANLPAR_T4; - break; - - default: - mdio_data = 0; - break; - } - -out: mdio_addr &= ~NVNET_MDIO_ADDR_INUSE; nvnet_set_reg(s, NVNET_MDIO_ADDR, mdio_addr, 4); nvnet_set_reg(s, NVNET_MDIO_DATA, mdio_data, 4); - trace_nvnet_mii_read(phy_addr, phy_reg, nvnet_get_mii_reg_name(phy_reg), - mdio_data); } static void nvnet_mdio_write(NvNetState *s) @@ -522,10 +533,12 @@ static void nvnet_mdio_write(NvNetState *s) uint32_t phy_addr = GET_MASK(mdio_addr, NVNET_MDIO_ADDR_PHYADDR); uint32_t phy_reg = GET_MASK(mdio_addr, NVNET_MDIO_ADDR_PHYREG); + if (phy_addr == PHY_ADDR) { + nvnet_phy_reg_write(s, phy_reg, mdio_data); + } + mdio_addr &= ~NVNET_MDIO_ADDR_INUSE; nvnet_set_reg(s, NVNET_MDIO_ADDR, mdio_addr, 4); - trace_nvnet_mii_write(phy_addr, phy_reg, nvnet_get_mii_reg_name(phy_reg), - mdio_data); } static uint64_t nvnet_mmio_read(void *opaque, hwaddr addr, unsigned int size) From bd7a6d7b3181390be80c2d5284c2be7f1a288a13 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 25/47] nvnet: Make phy registers 16b --- hw/xbox/mcpx/nvnet/nvnet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 129b9f2d9f..378b0c4dd8 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -479,9 +479,9 @@ static ssize_t nvnet_receive(NetClientState *nc, return nvnet_receive_iov(nc, &iov, 1); } -static uint32_t nvnet_phy_reg_read(NvNetState *s, uint8_t reg) +static uint16_t nvnet_phy_reg_read(NvNetState *s, uint8_t reg) { - uint32_t value; + uint16_t value; switch (reg) { case MII_BMSR: @@ -505,7 +505,7 @@ static uint32_t nvnet_phy_reg_read(NvNetState *s, uint8_t reg) return value; } -static void nvnet_phy_reg_write(NvNetState *s, uint8_t reg, uint32_t value) +static void nvnet_phy_reg_write(NvNetState *s, uint8_t reg, uint16_t value) { trace_nvnet_mii_write(PHY_ADDR, reg, nvnet_get_mii_reg_name(reg), value); } From 3eff7dd7feaaac695a235d0319f78befd2e64b3c Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 26/47] nvnet: Run clang-format --- hw/xbox/mcpx/nvnet/nvnet.c | 179 +++++++++++++++++++------------------ 1 file changed, 92 insertions(+), 87 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 378b0c4dd8..05b272d375 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -33,8 +33,8 @@ #include "nvnet_regs.h" #define IOPORT_SIZE 0x8 -#define MMIO_SIZE 0x400 -#define PHY_ADDR 1 +#define MMIO_SIZE 0x400 +#define PHY_ADDR 1 #define GET_MASK(v, mask) (((v) & (mask)) >> ctz32(mask)) @@ -57,19 +57,19 @@ typedef struct NvNetState { PCIDevice parent_obj; /*< public >*/ - NICState *nic; - NICConf conf; + NICState *nic; + NICConf conf; MemoryRegion mmio, io; - uint8_t regs[MMIO_SIZE]; - uint32_t phy_regs[6]; - uint8_t tx_ring_index; - uint8_t tx_ring_size; - uint8_t rx_ring_index; - uint8_t rx_ring_size; - uint8_t tx_dma_buf[TX_ALLOC_BUFSIZE]; - uint32_t tx_dma_buf_offset; - uint8_t rx_dma_buf[RX_ALLOC_BUFSIZE]; + uint8_t regs[MMIO_SIZE]; + uint32_t phy_regs[6]; + uint8_t tx_ring_index; + uint8_t tx_ring_size; + uint8_t rx_ring_index; + uint8_t rx_ring_size; + uint8_t tx_dma_buf[TX_ALLOC_BUFSIZE]; + uint32_t tx_dma_buf_offset; + uint8_t rx_dma_buf[RX_ALLOC_BUFSIZE]; } NvNetState; struct RingDesc { @@ -78,7 +78,9 @@ struct RingDesc { uint16_t flags; } QEMU_PACKED; -#define R(r) case r: return #r; +#define R(r) \ + case r: \ + return stringify(r); static const char *nvnet_get_reg_name(hwaddr addr) { @@ -156,8 +158,8 @@ static void nvnet_dump_ring_descriptors(NvNetState *s) dma_addr_t tx_ring_addr = nvnet_get_reg(s, NVNET_TX_RING_PHYS_ADDR, 4); tx_ring_addr += i * sizeof(desc); pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); - NVNET_DPRINTF("TX: Dumping ring desc %d (%" HWADDR_PRIx "): ", - i, tx_ring_addr); + NVNET_DPRINTF("TX: Dumping ring desc %d (%" HWADDR_PRIx "): ", i, + tx_ring_addr); NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); NVNET_DPRINTF("Length: 0x%x, ", desc.length); NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); @@ -168,8 +170,8 @@ static void nvnet_dump_ring_descriptors(NvNetState *s) dma_addr_t rx_ring_addr = nvnet_get_reg(s, NVNET_RX_RING_PHYS_ADDR, 4); rx_ring_addr += i * sizeof(desc); pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); - NVNET_DPRINTF("RX: Dumping ring desc %d (%" HWADDR_PRIx "): ", - i, rx_ring_addr); + NVNET_DPRINTF("RX: Dumping ring desc %d (%" HWADDR_PRIx "): ", i, + rx_ring_addr); NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); NVNET_DPRINTF("Length: 0x%x, ", desc.length); NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); @@ -200,8 +202,8 @@ static uint32_t nvnet_get_reg(NvNetState *s, hwaddr addr, unsigned int size) } } -static void nvnet_set_reg(NvNetState *s, - hwaddr addr, uint32_t val, unsigned int size) +static void nvnet_set_reg(NvNetState *s, hwaddr addr, uint32_t val, + unsigned int size) { assert(addr < MMIO_SIZE); @@ -248,15 +250,16 @@ static void nvnet_send_packet(NvNetState *s, const uint8_t *buf, int size) qemu_send_packet(nc, buf, size); } -static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, - const uint8_t *buf, size_t size) +static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, const uint8_t *buf, + size_t size) { PCIDevice *d = PCI_DEVICE(s); bool did_receive = false; nvnet_set_reg(s, NVNET_TX_RX_CONTROL, - nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4) & ~NVNET_TX_RX_CONTROL_IDLE, - 4); + nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4) & + ~NVNET_TX_RX_CONTROL_IDLE, + 4); for (int i = 0; i < s->rx_ring_size; i++) { struct RingDesc desc; @@ -265,7 +268,8 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, rx_ring_addr += s->rx_ring_index * sizeof(desc); pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); - NVNET_DPRINTF("RX: Looking at ring descriptor %d (0x%" HWADDR_PRIx "): ", + NVNET_DPRINTF("RX: Looking at ring descriptor %d (0x%" HWADDR_PRIx + "): ", s->rx_ring_index, rx_ring_addr); NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); NVNET_DPRINTF("Length: 0x%x, ", desc.length); @@ -275,7 +279,7 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, break; } - assert((desc.length+1) >= size); // FIXME + assert((desc.length + 1) >= size); // FIXME s->rx_ring_index += 1; @@ -284,7 +288,7 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, pci_dma_write(d, desc.packet_buffer, buf, size); desc.length = size; - desc.flags = NV_RX_BIT4 | NV_RX_DESCRIPTORVALID; + desc.flags = NV_RX_BIT4 | NV_RX_DESCRIPTORVALID; pci_dma_write(d, rx_ring_addr, &desc, sizeof(desc)); NVNET_DPRINTF("Updated ring descriptor: "); @@ -300,9 +304,9 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, break; } - nvnet_set_reg(s, NVNET_TX_RX_CONTROL, - nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4) | NVNET_TX_RX_CONTROL_IDLE, - 4); + nvnet_set_reg( + s, NVNET_TX_RX_CONTROL, + nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4) | NVNET_TX_RX_CONTROL_IDLE, 4); if (did_receive) { return size; @@ -318,8 +322,9 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) bool packet_sent = false; nvnet_set_reg(s, NVNET_TX_RX_CONTROL, - nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4) & ~NVNET_TX_RX_CONTROL_IDLE, - 4); + nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4) & + ~NVNET_TX_RX_CONTROL_IDLE, + 4); for (int i = 0; i < s->tx_ring_size; i++) { /* Read ring descriptor */ @@ -341,10 +346,10 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) s->tx_ring_index += 1; - assert((s->tx_dma_buf_offset + desc.length + 1) <= sizeof(s->tx_dma_buf)); + assert((s->tx_dma_buf_offset + desc.length + 1) <= + sizeof(s->tx_dma_buf)); pci_dma_read(d, desc.packet_buffer, - &s->tx_dma_buf[s->tx_dma_buf_offset], - desc.length + 1); + &s->tx_dma_buf[s->tx_dma_buf_offset], desc.length + 1); s->tx_dma_buf_offset += desc.length + 1; bool is_last_packet = desc.flags & NV_TX_LASTPACKET; @@ -356,8 +361,8 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) } desc.flags &= ~(NV_TX_VALID | NV_TX_RETRYERROR | NV_TX_DEFERRED | - NV_TX_CARRIERLOST | NV_TX_LATECOLLISION | NV_TX_UNDERFLOW | - NV_TX_ERROR); + NV_TX_CARRIERLOST | NV_TX_LATECOLLISION | + NV_TX_UNDERFLOW | NV_TX_ERROR); desc.length = desc.length + 5; pci_dma_write(d, tx_ring_addr, &desc, sizeof(desc)); @@ -374,9 +379,9 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) nvnet_update_irq(s); } - nvnet_set_reg(s, NVNET_TX_RX_CONTROL, - nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4) | NVNET_TX_RX_CONTROL_IDLE, - 4); + nvnet_set_reg( + s, NVNET_TX_RX_CONTROL, + nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4) | NVNET_TX_RX_CONTROL_IDLE, 4); return 0; } @@ -419,8 +424,10 @@ static bool receive_filter(NvNetState *s, const uint8_t *buf, int size) if (!is_broadcast_ether_addr((uint8_t *)addr)) { uint32_t dest_addr[2]; memcpy(dest_addr, buf, 6); - dest_addr[0] &= cpu_to_le32(nvnet_get_reg(s, NVNET_MULTICAST_MASK_A, 4)); - dest_addr[1] &= cpu_to_le32(nvnet_get_reg(s, NVNET_MULTICAST_MASK_B, 4)); + dest_addr[0] &= + cpu_to_le32(nvnet_get_reg(s, NVNET_MULTICAST_MASK_A, 4)); + dest_addr[1] &= + cpu_to_le32(nvnet_get_reg(s, NVNET_MULTICAST_MASK_B, 4)); if (!memcmp(dest_addr, addr, 6)) { trace_nvnet_rx_filter_mcast_match(MAC_ARG(dest_addr)); @@ -443,8 +450,8 @@ static bool receive_filter(NvNetState *s, const uint8_t *buf, int size) return false; } -static ssize_t nvnet_receive_iov(NetClientState *nc, - const struct iovec *iov, int iovcnt) +static ssize_t nvnet_receive_iov(NetClientState *nc, const struct iovec *iov, + int iovcnt) { NvNetState *s = qemu_get_nic_opaque(nc); size_t size = iov_size(iov, iovcnt); @@ -467,13 +474,10 @@ static ssize_t nvnet_receive_iov(NetClientState *nc, return nvnet_dma_packet_to_guest(s, s->rx_dma_buf, size); } -static ssize_t nvnet_receive(NetClientState *nc, - const uint8_t *buf, size_t size) +static ssize_t nvnet_receive(NetClientState *nc, const uint8_t *buf, + size_t size) { - const struct iovec iov = { - .iov_base = (uint8_t *)buf, - .iov_len = size - }; + const struct iovec iov = { .iov_base = (uint8_t *)buf, .iov_len = size }; NVNET_DPRINTF("nvnet_receive called\n"); return nvnet_receive_iov(nc, &iov, 1); @@ -493,7 +497,7 @@ static uint16_t nvnet_phy_reg_read(NvNetState *s, uint8_t reg) case MII_ANLPAR: value = MII_ANLPAR_10 | MII_ANLPAR_10FD | MII_ANLPAR_TX | - MII_ANLPAR_TXFD | MII_ANLPAR_T4; + MII_ANLPAR_TXFD | MII_ANLPAR_T4; break; default: @@ -560,8 +564,8 @@ static uint64_t nvnet_mmio_read(void *opaque, hwaddr addr, unsigned int size) return retval; } -static void nvnet_mmio_write(void *opaque, hwaddr addr, - uint64_t val, unsigned int size) +static void nvnet_mmio_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int size) { NvNetState *s = NVNET(opaque); uint32_t temp; @@ -612,7 +616,7 @@ static void nvnet_mmio_write(void *opaque, hwaddr addr, if (temp == NVNET_UNKNOWN_SETUP_REG3_VAL1) { /* forcedeth waits for this bit to be set... */ nvnet_set_reg(s, NVNET_UNKNOWN_SETUP_REG5, - NVNET_UNKNOWN_SETUP_REG5_BIT31, 4); + NVNET_UNKNOWN_SETUP_REG5_BIT31, 4); break; } } @@ -668,23 +672,23 @@ static uint64_t nvnet_io_read(void *opaque, hwaddr addr, unsigned int size) return r; } -static void nvnet_io_write(void *opaque, - hwaddr addr, uint64_t val, unsigned int size) +static void nvnet_io_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int size) { trace_nvnet_io_write(addr, size, val); } static const MemoryRegionOps nvnet_io_ops = { - .read = nvnet_io_read, + .read = nvnet_io_read, .write = nvnet_io_write, }; static NetClientInfo net_nvnet_info = { - .type = NET_CLIENT_DRIVER_NIC, - .size = sizeof(NICState), - .can_receive = nvnet_can_receive, - .receive = nvnet_receive, - .receive_iov = nvnet_receive_iov, + .type = NET_CLIENT_DRIVER_NIC, + .size = sizeof(NICState), + .can_receive = nvnet_can_receive, + .receive = nvnet_receive, + .receive_iov = nvnet_receive_iov, .link_status_changed = nvnet_set_link_status, }; @@ -699,21 +703,22 @@ static void nvnet_realize(PCIDevice *pci_dev, Error **errp) memset(s->regs, 0, sizeof(s->regs)); s->rx_ring_index = 0; - s->rx_ring_size = 0; + s->rx_ring_size = 0; s->tx_ring_index = 0; - s->tx_ring_size = 0; + s->tx_ring_size = 0; memory_region_init_io(&s->mmio, OBJECT(dev), &nvnet_mmio_ops, s, - "nvnet-mmio", MMIO_SIZE); + "nvnet-mmio", MMIO_SIZE); pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio); - memory_region_init_io(&s->io, OBJECT(dev), &nvnet_io_ops, s, - "nvnet-io", IOPORT_SIZE); + memory_region_init_io(&s->io, OBJECT(dev), &nvnet_io_ops, s, "nvnet-io", + IOPORT_SIZE); pci_register_bar(d, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io); qemu_macaddr_default_if_unset(&s->conf.macaddr); - s->nic = qemu_new_nic(&net_nvnet_info, &s->conf, - object_get_typename(OBJECT(s)), dev->id, &dev->mem_reentrancy_guard, s); + s->nic = + qemu_new_nic(&net_nvnet_info, &s->conf, object_get_typename(OBJECT(s)), + dev->id, &dev->mem_reentrancy_guard, s); assert(s->nic); } @@ -752,16 +757,15 @@ static const VMStateDescription vmstate_nvnet = { .name = "nvnet", .version_id = 1, .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_PCI_DEVICE(parent_obj, NvNetState), - VMSTATE_UINT8_ARRAY(regs, NvNetState, MMIO_SIZE), - VMSTATE_UINT32_ARRAY(phy_regs, NvNetState, 6), - VMSTATE_UINT8(tx_ring_index, NvNetState), - VMSTATE_UINT8(tx_ring_size, NvNetState), - VMSTATE_UINT8(rx_ring_index, NvNetState), - VMSTATE_UINT8(rx_ring_size, NvNetState), - VMSTATE_END_OF_LIST() - }, + .fields = + (VMStateField[]){ VMSTATE_PCI_DEVICE(parent_obj, NvNetState), + VMSTATE_UINT8_ARRAY(regs, NvNetState, MMIO_SIZE), + VMSTATE_UINT32_ARRAY(phy_regs, NvNetState, 6), + VMSTATE_UINT8(tx_ring_index, NvNetState), + VMSTATE_UINT8(tx_ring_size, NvNetState), + VMSTATE_UINT8(rx_ring_index, NvNetState), + VMSTATE_UINT8(rx_ring_size, NvNetState), + VMSTATE_END_OF_LIST() }, }; static Property nvnet_properties[] = { @@ -791,14 +795,15 @@ static void nvnet_class_init(ObjectClass *klass, void *data) } static const TypeInfo nvnet_info = { - .name = "nvnet", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(NvNetState), - .class_init = nvnet_class_init, - .interfaces = (InterfaceInfo[]) { - { INTERFACE_CONVENTIONAL_PCI_DEVICE }, - { }, - }, + .name = "nvnet", + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(NvNetState), + .class_init = nvnet_class_init, + .interfaces = + (InterfaceInfo[]){ + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + {}, + }, }; static void nvnet_register(void) From c0fa7e9ec4a63938dff46237dd52339790d930d1 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 27/47] nvnet: Rename mii reg traces to nvnet_phy_reg_{read,write} --- hw/xbox/mcpx/nvnet/nvnet.c | 6 +++--- hw/xbox/mcpx/nvnet/trace-events | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 05b272d375..d0382f12d3 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -131,7 +131,7 @@ static const char *nvnet_get_reg_name(hwaddr addr) } } -static const char *nvnet_get_mii_reg_name(uint8_t reg) +static const char *nvnet_get_phy_reg_name(uint8_t reg) { switch (reg) { R(MII_PHYID1) @@ -505,13 +505,13 @@ static uint16_t nvnet_phy_reg_read(NvNetState *s, uint8_t reg) break; } - trace_nvnet_mii_read(PHY_ADDR, reg, nvnet_get_mii_reg_name(reg), value); + trace_nvnet_phy_reg_read(PHY_ADDR, reg, nvnet_get_phy_reg_name(reg), value); return value; } static void nvnet_phy_reg_write(NvNetState *s, uint8_t reg, uint16_t value) { - trace_nvnet_mii_write(PHY_ADDR, reg, nvnet_get_mii_reg_name(reg), value); + trace_nvnet_phy_reg_write(PHY_ADDR, reg, nvnet_get_phy_reg_name(reg), value); } static void nvnet_mdio_read(NvNetState *s) diff --git a/hw/xbox/mcpx/nvnet/trace-events b/hw/xbox/mcpx/nvnet/trace-events index 4115e4e7eb..d1a1c63aa7 100644 --- a/hw/xbox/mcpx/nvnet/trace-events +++ b/hw/xbox/mcpx/nvnet/trace-events @@ -1,8 +1,8 @@ # See docs/devel/tracing.rst for syntax documentation. # nvnet.c -nvnet_mii_read(unsigned int phy_addr, uint32_t addr, const char *name, uint32_t val) "phy %d addr 0x%"PRIx32" %s val 0x%"PRIx32 -nvnet_mii_write(unsigned int phy_addr, uint32_t addr, const char *name, uint32_t val) "phy %d addr 0x%"PRIx32" %s val 0x%"PRIx32 +nvnet_phy_reg_read(unsigned int phy_addr, uint32_t addr, const char *name, uint32_t val) "phy %d addr 0x%"PRIx32" %s val 0x%"PRIx32 +nvnet_phy_reg_write(unsigned int phy_addr, uint32_t addr, const char *name, uint32_t val) "phy %d addr 0x%"PRIx32" %s val 0x%"PRIx32 nvnet_reg_read(uint32_t addr, const char *name, unsigned int size, uint64_t val) "addr 0x%"PRIx32" %s size %d val 0x%"PRIx64 nvnet_reg_write(uint32_t addr, const char *name, unsigned int size, uint64_t val) "addr 0x%"PRIx32" %s size %d val 0x%"PRIx64 nvnet_io_read(uint32_t addr, unsigned int size, uint64_t val) "addr 0x%"PRIx32" size %d val 0x%"PRIx64 From 4e5a1fa157f870b3b6f7037e4f318792b9a1309e Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 28/47] nvnet: Copyright update --- hw/xbox/mcpx/nvnet/nvnet_regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet_regs.h b/hw/xbox/mcpx/nvnet/nvnet_regs.h index 930efe57d9..d521c97cca 100644 --- a/hw/xbox/mcpx/nvnet/nvnet_regs.h +++ b/hw/xbox/mcpx/nvnet/nvnet_regs.h @@ -2,7 +2,7 @@ * QEMU nForce Ethernet Controller register definitions * * Copyright (c) 2013 espes - * Copyright (c) 2015-2021 Matt Borgerson + * Copyright (c) 2015-2025 Matt Borgerson * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public From 5e4d7a1dba0430b3b4418978675625f379a49703 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 29/47] nvnet: Fix nvnet_phy_reg_* trace addr/value size --- hw/xbox/mcpx/nvnet/trace-events | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/trace-events b/hw/xbox/mcpx/nvnet/trace-events index d1a1c63aa7..027058f909 100644 --- a/hw/xbox/mcpx/nvnet/trace-events +++ b/hw/xbox/mcpx/nvnet/trace-events @@ -1,8 +1,8 @@ # See docs/devel/tracing.rst for syntax documentation. # nvnet.c -nvnet_phy_reg_read(unsigned int phy_addr, uint32_t addr, const char *name, uint32_t val) "phy %d addr 0x%"PRIx32" %s val 0x%"PRIx32 -nvnet_phy_reg_write(unsigned int phy_addr, uint32_t addr, const char *name, uint32_t val) "phy %d addr 0x%"PRIx32" %s val 0x%"PRIx32 +nvnet_phy_reg_read(unsigned int phy_addr, uint8_t addr, const char *name, uint16_t val) "phy %d addr 0x%"PRIx8" %s val 0x%"PRIx16 +nvnet_phy_reg_write(unsigned int phy_addr, uint8_t addr, const char *name, uint16_t val) "phy %d addr 0x%"PRIx8" %s val 0x%"PRIx16 nvnet_reg_read(uint32_t addr, const char *name, unsigned int size, uint64_t val) "addr 0x%"PRIx32" %s size %d val 0x%"PRIx64 nvnet_reg_write(uint32_t addr, const char *name, unsigned int size, uint64_t val) "addr 0x%"PRIx32" %s size %d val 0x%"PRIx64 nvnet_io_read(uint32_t addr, unsigned int size, uint64_t val) "addr 0x%"PRIx32" size %d val 0x%"PRIx64 From 2e8a08b5e597a40c3f8f06437c7e82d9e4f4e49b Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 30/47] nvnet: Fix spacing in NvNetState --- hw/xbox/mcpx/nvnet/nvnet.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index d0382f12d3..c90ce51984 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -59,10 +59,12 @@ typedef struct NvNetState { NICState *nic; NICConf conf; + MemoryRegion mmio, io; uint8_t regs[MMIO_SIZE]; uint32_t phy_regs[6]; + uint8_t tx_ring_index; uint8_t tx_ring_size; uint8_t rx_ring_index; From 59cec6599df8010554e54132f2eb264ffbc7e97d Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 18 Jun 2025 00:59:51 -0700 Subject: [PATCH 31/47] nvnet: Move NetClientInfo handlers up --- hw/xbox/mcpx/nvnet/nvnet.c | 58 +++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index c90ce51984..01ee0c9849 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -485,6 +485,35 @@ static ssize_t nvnet_receive(NetClientState *nc, const uint8_t *buf, return nvnet_receive_iov(nc, &iov, 1); } +static void nvnet_link_down(NvNetState *s) +{ + NVNET_DPRINTF("nvnet_link_down called\n"); +} + +static void nvnet_link_up(NvNetState *s) +{ + NVNET_DPRINTF("nvnet_link_up called\n"); +} + +static void nvnet_set_link_status(NetClientState *nc) +{ + NvNetState *s = qemu_get_nic_opaque(nc); + if (nc->link_down) { + nvnet_link_down(s); + } else { + nvnet_link_up(s); + } +} + +static NetClientInfo net_nvnet_info = { + .type = NET_CLIENT_DRIVER_NIC, + .size = sizeof(NICState), + .can_receive = nvnet_can_receive, + .receive = nvnet_receive, + .receive_iov = nvnet_receive_iov, + .link_status_changed = nvnet_set_link_status, +}; + static uint16_t nvnet_phy_reg_read(NvNetState *s, uint8_t reg) { uint16_t value; @@ -647,26 +676,6 @@ static const MemoryRegionOps nvnet_mmio_ops = { .write = nvnet_mmio_write, }; -static void nvnet_link_down(NvNetState *s) -{ - NVNET_DPRINTF("nvnet_link_down called\n"); -} - -static void nvnet_link_up(NvNetState *s) -{ - NVNET_DPRINTF("nvnet_link_up called\n"); -} - -static void nvnet_set_link_status(NetClientState *nc) -{ - NvNetState *s = qemu_get_nic_opaque(nc); - if (nc->link_down) { - nvnet_link_down(s); - } else { - nvnet_link_up(s); - } -} - static uint64_t nvnet_io_read(void *opaque, hwaddr addr, unsigned int size) { uint64_t r = 0; @@ -685,15 +694,6 @@ static const MemoryRegionOps nvnet_io_ops = { .write = nvnet_io_write, }; -static NetClientInfo net_nvnet_info = { - .type = NET_CLIENT_DRIVER_NIC, - .size = sizeof(NICState), - .can_receive = nvnet_can_receive, - .receive = nvnet_receive, - .receive_iov = nvnet_receive_iov, - .link_status_changed = nvnet_set_link_status, -}; - static void nvnet_realize(PCIDevice *pci_dev, Error **errp) { DeviceState *dev = DEVICE(pci_dev); From 86cda64f7016647b1677d76e96ba2dded9941b4a Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 19 Jun 2025 01:55:06 -0700 Subject: [PATCH 32/47] nvnet: Fix register stringification --- hw/xbox/mcpx/nvnet/nvnet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 01ee0c9849..2a4007f921 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -82,7 +82,7 @@ struct RingDesc { #define R(r) \ case r: \ - return stringify(r); + return #r; static const char *nvnet_get_reg_name(hwaddr addr) { From 14a95ddb7f68fc8327e026204710f6300b3ed8a6 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 19 Jun 2025 01:55:06 -0700 Subject: [PATCH 33/47] nvnet: Move nvnet_dump_ring_descriptors down --- hw/xbox/mcpx/nvnet/nvnet.c | 66 +++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 2a4007f921..17bf2a8286 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -149,39 +149,6 @@ static const char *nvnet_get_phy_reg_name(uint8_t reg) #undef R -static void nvnet_dump_ring_descriptors(NvNetState *s) -{ -#if NVNET_DEBUG - struct RingDesc desc; - PCIDevice *d = PCI_DEVICE(s); - - NVNET_DPRINTF("------------------------------------------------\n"); - for (int i = 0; i < s->tx_ring_size; i++) { - dma_addr_t tx_ring_addr = nvnet_get_reg(s, NVNET_TX_RING_PHYS_ADDR, 4); - tx_ring_addr += i * sizeof(desc); - pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); - NVNET_DPRINTF("TX: Dumping ring desc %d (%" HWADDR_PRIx "): ", i, - tx_ring_addr); - NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); - NVNET_DPRINTF("Length: 0x%x, ", desc.length); - NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); - } - NVNET_DPRINTF("------------------------------------------------\n"); - - for (int i = 0; i < s->rx_ring_size; i++) { - dma_addr_t rx_ring_addr = nvnet_get_reg(s, NVNET_RX_RING_PHYS_ADDR, 4); - rx_ring_addr += i * sizeof(desc); - pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); - NVNET_DPRINTF("RX: Dumping ring desc %d (%" HWADDR_PRIx "): ", i, - rx_ring_addr); - NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); - NVNET_DPRINTF("Length: 0x%x, ", desc.length); - NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); - } - NVNET_DPRINTF("------------------------------------------------\n"); -#endif -} - static uint32_t nvnet_get_reg(NvNetState *s, hwaddr addr, unsigned int size) { assert(addr < MMIO_SIZE); @@ -595,6 +562,39 @@ static uint64_t nvnet_mmio_read(void *opaque, hwaddr addr, unsigned int size) return retval; } +static void nvnet_dump_ring_descriptors(NvNetState *s) +{ +#if NVNET_DEBUG + struct RingDesc desc; + PCIDevice *d = PCI_DEVICE(s); + + NVNET_DPRINTF("------------------------------------------------\n"); + for (int i = 0; i < s->tx_ring_size; i++) { + dma_addr_t tx_ring_addr = nvnet_get_reg(s, NVNET_TX_RING_PHYS_ADDR, 4); + tx_ring_addr += i * sizeof(desc); + pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); + NVNET_DPRINTF("TX: Dumping ring desc %d (%" HWADDR_PRIx "): ", i, + tx_ring_addr); + NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); + NVNET_DPRINTF("Length: 0x%x, ", desc.length); + NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); + } + NVNET_DPRINTF("------------------------------------------------\n"); + + for (int i = 0; i < s->rx_ring_size; i++) { + dma_addr_t rx_ring_addr = nvnet_get_reg(s, NVNET_RX_RING_PHYS_ADDR, 4); + rx_ring_addr += i * sizeof(desc); + pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); + NVNET_DPRINTF("RX: Dumping ring desc %d (%" HWADDR_PRIx "): ", i, + rx_ring_addr); + NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); + NVNET_DPRINTF("Length: 0x%x, ", desc.length); + NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); + } + NVNET_DPRINTF("------------------------------------------------\n"); +#endif +} + static void nvnet_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { From e43cf90c74e493d327063611a6a52745c0d54f51 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 19 Jun 2025 01:55:06 -0700 Subject: [PATCH 34/47] nvnet: Simplify nvnet_mmio_write --- hw/xbox/mcpx/nvnet/nvnet.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 17bf2a8286..7fc6acac82 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -599,20 +599,18 @@ static void nvnet_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { NvNetState *s = NVNET(opaque); - uint32_t temp; + nvnet_set_reg(s, addr, val, size); trace_nvnet_reg_write(addr, nvnet_get_reg_name(addr & ~3), size, val); switch (addr) { case NVNET_RING_SIZE: - nvnet_set_reg(s, addr, val, size); s->rx_ring_size = GET_MASK(val, NVNET_RING_SIZE_RX) + 1; s->tx_ring_size = GET_MASK(val, NVNET_RING_SIZE_TX) + 1; break; case NVNET_MDIO_ADDR: assert(size == 4); - nvnet_set_reg(s, addr, val, size); if (val & NVNET_MDIO_ADDR_WRITE) { nvnet_mdio_write(s); } else { @@ -643,7 +641,7 @@ static void nvnet_mmio_write(void *opaque, hwaddr addr, uint64_t val, nvnet_set_reg(s, NVNET_IRQ_STATUS, 0, 4); break; } else if (val == 0) { - temp = nvnet_get_reg(s, NVNET_UNKNOWN_SETUP_REG3, 4); + uint32_t temp = nvnet_get_reg(s, NVNET_UNKNOWN_SETUP_REG3, 4); if (temp == NVNET_UNKNOWN_SETUP_REG3_VAL1) { /* forcedeth waits for this bit to be set... */ nvnet_set_reg(s, NVNET_UNKNOWN_SETUP_REG5, @@ -651,12 +649,9 @@ static void nvnet_mmio_write(void *opaque, hwaddr addr, uint64_t val, break; } } - - nvnet_set_reg(s, NVNET_TX_RX_CONTROL, val, size); break; case NVNET_IRQ_MASK: - nvnet_set_reg(s, addr, val, size); nvnet_update_irq(s); break; @@ -666,7 +661,6 @@ static void nvnet_mmio_write(void *opaque, hwaddr addr, uint64_t val, break; default: - nvnet_set_reg(s, addr, val, size); break; } } From 3fc128d929a35be533c237fd4f815043e040ebc4 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 19 Jun 2025 01:55:06 -0700 Subject: [PATCH 35/47] nvnet: Fix phy_{addr,reg} sizes in nvnet_mdio_{read,write} --- hw/xbox/mcpx/nvnet/nvnet.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 7fc6acac82..963a2540a5 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -516,8 +516,8 @@ static void nvnet_mdio_read(NvNetState *s) { uint32_t mdio_addr = nvnet_get_reg(s, NVNET_MDIO_ADDR, 4); uint32_t mdio_data = -1; - uint32_t phy_addr = GET_MASK(mdio_addr, NVNET_MDIO_ADDR_PHYADDR); - uint32_t phy_reg = GET_MASK(mdio_addr, NVNET_MDIO_ADDR_PHYREG); + uint8_t phy_addr = GET_MASK(mdio_addr, NVNET_MDIO_ADDR_PHYADDR); + uint8_t phy_reg = GET_MASK(mdio_addr, NVNET_MDIO_ADDR_PHYREG); if (phy_addr == PHY_ADDR) { mdio_data = nvnet_phy_reg_read(s, phy_reg); @@ -532,8 +532,8 @@ static void nvnet_mdio_write(NvNetState *s) { uint32_t mdio_addr = nvnet_get_reg(s, NVNET_MDIO_ADDR, 4); uint32_t mdio_data = nvnet_get_reg(s, NVNET_MDIO_DATA, 4); - uint32_t phy_addr = GET_MASK(mdio_addr, NVNET_MDIO_ADDR_PHYADDR); - uint32_t phy_reg = GET_MASK(mdio_addr, NVNET_MDIO_ADDR_PHYREG); + uint8_t phy_addr = GET_MASK(mdio_addr, NVNET_MDIO_ADDR_PHYADDR); + uint8_t phy_reg = GET_MASK(mdio_addr, NVNET_MDIO_ADDR_PHYREG); if (phy_addr == PHY_ADDR) { nvnet_phy_reg_write(s, phy_reg, mdio_data); From bf72b3b33ac4724988f531d6fdfc2633336b8e47 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 19 Jun 2025 01:55:06 -0700 Subject: [PATCH 36/47] nvnet: Remove more useless comments --- hw/xbox/mcpx/nvnet/nvnet.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 963a2540a5..c18506aae4 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -264,7 +264,6 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, const uint8_t *buf, NVNET_DPRINTF("Length: 0x%x, ", desc.length); NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); - /* Trigger interrupt */ NVNET_DPRINTF("Triggering interrupt\n"); uint32_t irq_status = nvnet_get_reg(s, NVNET_IRQ_STATUS, 4); nvnet_set_reg(s, NVNET_IRQ_STATUS, irq_status | NVNET_IRQ_STATUS_RX, 4); @@ -296,7 +295,6 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) 4); for (int i = 0; i < s->tx_ring_size; i++) { - /* Read ring descriptor */ struct RingDesc desc; s->tx_ring_index %= s->tx_ring_size; dma_addr_t tx_ring_addr = nvnet_get_reg(s, NVNET_TX_RING_PHYS_ADDR, 4); From fded775222f337d0fd2483d4cd1a89392204a6ee Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 19 Jun 2025 01:55:06 -0700 Subject: [PATCH 37/47] nvnet: Clean up idle bit management --- hw/xbox/mcpx/nvnet/nvnet.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index c18506aae4..2fc4303b41 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -225,10 +225,8 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, const uint8_t *buf, PCIDevice *d = PCI_DEVICE(s); bool did_receive = false; - nvnet_set_reg(s, NVNET_TX_RX_CONTROL, - nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4) & - ~NVNET_TX_RX_CONTROL_IDLE, - 4); + uint32_t ctrl = nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4); + nvnet_set_reg(s, NVNET_TX_RX_CONTROL, ctrl & ~NVNET_TX_RX_CONTROL_IDLE, 4); for (int i = 0; i < s->rx_ring_size; i++) { struct RingDesc desc; @@ -272,9 +270,8 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, const uint8_t *buf, break; } - nvnet_set_reg( - s, NVNET_TX_RX_CONTROL, - nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4) | NVNET_TX_RX_CONTROL_IDLE, 4); + ctrl = nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4); + nvnet_set_reg(s, NVNET_TX_RX_CONTROL, ctrl | NVNET_TX_RX_CONTROL_IDLE, 4); if (did_receive) { return size; @@ -289,10 +286,8 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) PCIDevice *d = PCI_DEVICE(s); bool packet_sent = false; - nvnet_set_reg(s, NVNET_TX_RX_CONTROL, - nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4) & - ~NVNET_TX_RX_CONTROL_IDLE, - 4); + uint32_t ctrl = nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4); + nvnet_set_reg(s, NVNET_TX_RX_CONTROL, ctrl & ~NVNET_TX_RX_CONTROL_IDLE, 4); for (int i = 0; i < s->tx_ring_size; i++) { struct RingDesc desc; @@ -346,9 +341,8 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) nvnet_update_irq(s); } - nvnet_set_reg( - s, NVNET_TX_RX_CONTROL, - nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4) | NVNET_TX_RX_CONTROL_IDLE, 4); + ctrl = nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4); + nvnet_set_reg(s, NVNET_TX_RX_CONTROL, ctrl | NVNET_TX_RX_CONTROL_IDLE, 4); return 0; } From 1dbda16970bda6602449c123c2668c9120cd0de2 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 19 Jun 2025 01:55:06 -0700 Subject: [PATCH 38/47] nvnet: Simplify nvnet_dma_packet_to_guest --- hw/xbox/mcpx/nvnet/nvnet.c | 46 ++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 2fc4303b41..52ca4157e4 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -223,33 +223,26 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, const uint8_t *buf, size_t size) { PCIDevice *d = PCI_DEVICE(s); - bool did_receive = false; + ssize_t rval; uint32_t ctrl = nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4); nvnet_set_reg(s, NVNET_TX_RX_CONTROL, ctrl & ~NVNET_TX_RX_CONTROL_IDLE, 4); - for (int i = 0; i < s->rx_ring_size; i++) { - struct RingDesc desc; - s->rx_ring_index %= s->rx_ring_size; - dma_addr_t rx_ring_addr = nvnet_get_reg(s, NVNET_RX_RING_PHYS_ADDR, 4); - rx_ring_addr += s->rx_ring_index * sizeof(desc); - pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); + struct RingDesc desc; + s->rx_ring_index %= s->rx_ring_size; + dma_addr_t rx_ring_addr = nvnet_get_reg(s, NVNET_RX_RING_PHYS_ADDR, 4); + rx_ring_addr += s->rx_ring_index * sizeof(desc); + pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); - NVNET_DPRINTF("RX: Looking at ring descriptor %d (0x%" HWADDR_PRIx - "): ", - s->rx_ring_index, rx_ring_addr); - NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); - NVNET_DPRINTF("Length: 0x%x, ", desc.length); - NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); - - if (!(desc.flags & NV_RX_AVAIL)) { - break; - } + NVNET_DPRINTF("RX: Looking at ring descriptor %d (0x%" HWADDR_PRIx "): ", + s->rx_ring_index, rx_ring_addr); + NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); + NVNET_DPRINTF("Length: 0x%x, ", desc.length); + NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); + if (desc.flags & NV_RX_AVAIL) { assert((desc.length + 1) >= size); // FIXME - s->rx_ring_index += 1; - NVNET_DPRINTF("Transferring packet, size 0x%zx, to memory at 0x%x\n", size, desc.packet_buffer); pci_dma_write(d, desc.packet_buffer, buf, size); @@ -266,19 +259,18 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, const uint8_t *buf, uint32_t irq_status = nvnet_get_reg(s, NVNET_IRQ_STATUS, 4); nvnet_set_reg(s, NVNET_IRQ_STATUS, irq_status | NVNET_IRQ_STATUS_RX, 4); nvnet_update_irq(s); - did_receive = true; - break; + + s->rx_ring_index += 1; + rval = size; + } else { + NVNET_DPRINTF("Could not find free buffer!\n"); + rval = -1; } ctrl = nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4); nvnet_set_reg(s, NVNET_TX_RX_CONTROL, ctrl | NVNET_TX_RX_CONTROL_IDLE, 4); - if (did_receive) { - return size; - } else { - NVNET_DPRINTF("Could not find free buffer!\n"); - return -1; - } + return rval; } static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) From 3fd776d98e17ead3e34bdd8053fbac10f71e8813 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 19 Jun 2025 01:55:06 -0700 Subject: [PATCH 39/47] nvnet: Convert descriptor fields to host byte order and back --- hw/xbox/mcpx/nvnet/nvnet.c | 74 ++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 52ca4157e4..922956941b 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -234,26 +234,33 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, const uint8_t *buf, rx_ring_addr += s->rx_ring_index * sizeof(desc); pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); + uint32_t packet_buffer = le32_to_cpu(desc.packet_buffer); + uint16_t length = le16_to_cpu(desc.length); + uint16_t flags = le16_to_cpu(desc.flags); + NVNET_DPRINTF("RX: Looking at ring descriptor %d (0x%" HWADDR_PRIx "): ", s->rx_ring_index, rx_ring_addr); - NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); - NVNET_DPRINTF("Length: 0x%x, ", desc.length); - NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); + NVNET_DPRINTF("Buffer: 0x%x, ", packet_buffer); + NVNET_DPRINTF("Length: 0x%x, ", length); + NVNET_DPRINTF("Flags: 0x%x\n", flags); - if (desc.flags & NV_RX_AVAIL) { - assert((desc.length + 1) >= size); // FIXME + if (flags & NV_RX_AVAIL) { + assert((length + 1) >= size); // FIXME NVNET_DPRINTF("Transferring packet, size 0x%zx, to memory at 0x%x\n", - size, desc.packet_buffer); - pci_dma_write(d, desc.packet_buffer, buf, size); + size, packet_buffer); + pci_dma_write(d, packet_buffer, buf, size); - desc.length = size; - desc.flags = NV_RX_BIT4 | NV_RX_DESCRIPTORVALID; + length = size; + flags = NV_RX_BIT4 | NV_RX_DESCRIPTORVALID; + + desc.length = cpu_to_le16(length); + desc.flags = cpu_to_le16(flags); pci_dma_write(d, rx_ring_addr, &desc, sizeof(desc)); NVNET_DPRINTF("Updated ring descriptor: "); - NVNET_DPRINTF("Length: 0x%x, ", desc.length); - NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); + NVNET_DPRINTF("Length: 0x%x, ", length); + NVNET_DPRINTF("Flags: 0x%x\n", flags); NVNET_DPRINTF("Triggering interrupt\n"); uint32_t irq_status = nvnet_get_reg(s, NVNET_IRQ_STATUS, 4); @@ -288,25 +295,29 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) tx_ring_addr += s->tx_ring_index * sizeof(desc); pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); + uint32_t packet_buffer = le32_to_cpu(desc.packet_buffer); + uint16_t length = le16_to_cpu(desc.length); + uint16_t flags = le16_to_cpu(desc.flags); + NVNET_DPRINTF("TX: Looking at ring desc %d (%" HWADDR_PRIx "): ", s->tx_ring_index, tx_ring_addr); - NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); - NVNET_DPRINTF("Length: 0x%x, ", desc.length); - NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); + NVNET_DPRINTF("Buffer: 0x%x, ", packet_buffer); + NVNET_DPRINTF("Length: 0x%x, ", length); + NVNET_DPRINTF("Flags: 0x%x\n", flags); - if (!(desc.flags & NV_TX_VALID)) { + if (!(flags & NV_TX_VALID)) { break; } s->tx_ring_index += 1; - assert((s->tx_dma_buf_offset + desc.length + 1) <= + assert((s->tx_dma_buf_offset + length + 1) <= sizeof(s->tx_dma_buf)); - pci_dma_read(d, desc.packet_buffer, - &s->tx_dma_buf[s->tx_dma_buf_offset], desc.length + 1); - s->tx_dma_buf_offset += desc.length + 1; + pci_dma_read(d, packet_buffer, &s->tx_dma_buf[s->tx_dma_buf_offset], + length + 1); + s->tx_dma_buf_offset += length + 1; - bool is_last_packet = desc.flags & NV_TX_LASTPACKET; + bool is_last_packet = flags & NV_TX_LASTPACKET; if (is_last_packet) { NVNET_DPRINTF("Sending packet...\n"); nvnet_send_packet(s, s->tx_dma_buf, s->tx_dma_buf_offset); @@ -314,10 +325,13 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) packet_sent = true; } - desc.flags &= ~(NV_TX_VALID | NV_TX_RETRYERROR | NV_TX_DEFERRED | - NV_TX_CARRIERLOST | NV_TX_LATECOLLISION | - NV_TX_UNDERFLOW | NV_TX_ERROR); - desc.length = desc.length + 5; + flags &= ~(NV_TX_VALID | NV_TX_RETRYERROR | NV_TX_DEFERRED | + NV_TX_CARRIERLOST | NV_TX_LATECOLLISION | NV_TX_UNDERFLOW | + NV_TX_ERROR); + length += 5; // FIXME + + desc.flags = cpu_to_le16(flags); + desc.length = cpu_to_le16(length); pci_dma_write(d, tx_ring_addr, &desc, sizeof(desc)); if (is_last_packet) { @@ -559,9 +573,9 @@ static void nvnet_dump_ring_descriptors(NvNetState *s) pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); NVNET_DPRINTF("TX: Dumping ring desc %d (%" HWADDR_PRIx "): ", i, tx_ring_addr); - NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); - NVNET_DPRINTF("Length: 0x%x, ", desc.length); - NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); + NVNET_DPRINTF("Buffer: 0x%x, ", le32_to_cpu(desc.packet_buffer)); + NVNET_DPRINTF("Length: 0x%x, ", le16_to_cpu(desc.length)); + NVNET_DPRINTF("Flags: 0x%x\n", le16_to_cpu(desc.flags)); } NVNET_DPRINTF("------------------------------------------------\n"); @@ -571,9 +585,9 @@ static void nvnet_dump_ring_descriptors(NvNetState *s) pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); NVNET_DPRINTF("RX: Dumping ring desc %d (%" HWADDR_PRIx "): ", i, rx_ring_addr); - NVNET_DPRINTF("Buffer: 0x%x, ", desc.packet_buffer); - NVNET_DPRINTF("Length: 0x%x, ", desc.length); - NVNET_DPRINTF("Flags: 0x%x\n", desc.flags); + NVNET_DPRINTF("Buffer: 0x%x, ", le32_to_cpu(desc.packet_buffer)); + NVNET_DPRINTF("Length: 0x%x, ", le16_to_cpu(desc.length)); + NVNET_DPRINTF("Flags: 0x%x\n", le16_to_cpu(desc.flags)); } NVNET_DPRINTF("------------------------------------------------\n"); #endif From bfe9f659d26fdfd9507ea6759e512546e472b37a Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 19 Jun 2025 01:55:06 -0700 Subject: [PATCH 40/47] nvnet: Shrink some debug printfs --- hw/xbox/mcpx/nvnet/nvnet.c | 48 ++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 922956941b..3b32acb46c 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -238,11 +238,9 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, const uint8_t *buf, uint16_t length = le16_to_cpu(desc.length); uint16_t flags = le16_to_cpu(desc.flags); - NVNET_DPRINTF("RX: Looking at ring descriptor %d (0x%" HWADDR_PRIx "): ", - s->rx_ring_index, rx_ring_addr); - NVNET_DPRINTF("Buffer: 0x%x, ", packet_buffer); - NVNET_DPRINTF("Length: 0x%x, ", length); - NVNET_DPRINTF("Flags: 0x%x\n", flags); + NVNET_DPRINTF("RX: Looking at ring descriptor %d (0x%" HWADDR_PRIx "): " + "Buffer: 0x%x, Length: 0x%x, Flags: 0x%x\n", + s->rx_ring_index, rx_ring_addr, packet_buffer, length, flags); if (flags & NV_RX_AVAIL) { assert((length + 1) >= size); // FIXME @@ -258,9 +256,8 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, const uint8_t *buf, desc.flags = cpu_to_le16(flags); pci_dma_write(d, rx_ring_addr, &desc, sizeof(desc)); - NVNET_DPRINTF("Updated ring descriptor: "); - NVNET_DPRINTF("Length: 0x%x, ", length); - NVNET_DPRINTF("Flags: 0x%x\n", flags); + NVNET_DPRINTF("Updated ring descriptor: Length: 0x%x, Flags: 0x%x\n", + length, flags); NVNET_DPRINTF("Triggering interrupt\n"); uint32_t irq_status = nvnet_get_reg(s, NVNET_IRQ_STATUS, 4); @@ -299,11 +296,10 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) uint16_t length = le16_to_cpu(desc.length); uint16_t flags = le16_to_cpu(desc.flags); - NVNET_DPRINTF("TX: Looking at ring desc %d (%" HWADDR_PRIx "): ", - s->tx_ring_index, tx_ring_addr); - NVNET_DPRINTF("Buffer: 0x%x, ", packet_buffer); - NVNET_DPRINTF("Length: 0x%x, ", length); - NVNET_DPRINTF("Flags: 0x%x\n", flags); + NVNET_DPRINTF("TX: Looking at ring desc %d (%" HWADDR_PRIx "): " + "Buffer: 0x%x, Length: 0x%x, Flags: 0x%x\n", + s->tx_ring_index, tx_ring_addr, packet_buffer, length, + flags); if (!(flags & NV_TX_VALID)) { break; @@ -562,33 +558,35 @@ static uint64_t nvnet_mmio_read(void *opaque, hwaddr addr, unsigned int size) static void nvnet_dump_ring_descriptors(NvNetState *s) { -#if NVNET_DEBUG - struct RingDesc desc; +#if DEBUG_NVNET PCIDevice *d = PCI_DEVICE(s); NVNET_DPRINTF("------------------------------------------------\n"); + for (int i = 0; i < s->tx_ring_size; i++) { + struct RingDesc desc; dma_addr_t tx_ring_addr = nvnet_get_reg(s, NVNET_TX_RING_PHYS_ADDR, 4); tx_ring_addr += i * sizeof(desc); pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); - NVNET_DPRINTF("TX: Dumping ring desc %d (%" HWADDR_PRIx "): ", i, - tx_ring_addr); - NVNET_DPRINTF("Buffer: 0x%x, ", le32_to_cpu(desc.packet_buffer)); - NVNET_DPRINTF("Length: 0x%x, ", le16_to_cpu(desc.length)); - NVNET_DPRINTF("Flags: 0x%x\n", le16_to_cpu(desc.flags)); + NVNET_DPRINTF("TX desc %d (%" HWADDR_PRIx "): " + "Buffer: 0x%x, Length: 0x%x, Flags: 0x%x\n", + i, tx_ring_addr, le32_to_cpu(desc.packet_buffer), + le16_to_cpu(desc.length), le16_to_cpu(desc.flags)); } + NVNET_DPRINTF("------------------------------------------------\n"); for (int i = 0; i < s->rx_ring_size; i++) { + struct RingDesc desc; dma_addr_t rx_ring_addr = nvnet_get_reg(s, NVNET_RX_RING_PHYS_ADDR, 4); rx_ring_addr += i * sizeof(desc); pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); - NVNET_DPRINTF("RX: Dumping ring desc %d (%" HWADDR_PRIx "): ", i, - rx_ring_addr); - NVNET_DPRINTF("Buffer: 0x%x, ", le32_to_cpu(desc.packet_buffer)); - NVNET_DPRINTF("Length: 0x%x, ", le16_to_cpu(desc.length)); - NVNET_DPRINTF("Flags: 0x%x\n", le16_to_cpu(desc.flags)); + NVNET_DPRINTF("RX desc %d (%" HWADDR_PRIx "): " + "Buffer: 0x%x, Length: 0x%x, Flags: 0x%x\n", + i, rx_ring_addr, le32_to_cpu(desc.packet_buffer), + le16_to_cpu(desc.length), le16_to_cpu(desc.flags)); } + NVNET_DPRINTF("------------------------------------------------\n"); #endif } From 9e00beaffabf9a527a31fbda4637f15475d87c13 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 19 Jun 2025 01:55:06 -0700 Subject: [PATCH 41/47] nvnet: Migrate ring size tracking to registers --- hw/xbox/mcpx/nvnet/nvnet.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 3b32acb46c..bcbb766d2e 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -66,9 +66,7 @@ typedef struct NvNetState { uint32_t phy_regs[6]; uint8_t tx_ring_index; - uint8_t tx_ring_size; uint8_t rx_ring_index; - uint8_t rx_ring_size; uint8_t tx_dma_buf[TX_ALLOC_BUFSIZE]; uint32_t tx_dma_buf_offset; uint8_t rx_dma_buf[RX_ALLOC_BUFSIZE]; @@ -219,6 +217,18 @@ static void nvnet_send_packet(NvNetState *s, const uint8_t *buf, int size) qemu_send_packet(nc, buf, size); } +static uint16_t get_tx_ring_size(NvNetState *s) +{ + uint32_t ring_size = nvnet_get_reg(s, NVNET_RING_SIZE, 4); + return GET_MASK(ring_size, NVNET_RING_SIZE_TX) + 1; +} + +static uint16_t get_rx_ring_size(NvNetState *s) +{ + uint32_t ring_size = nvnet_get_reg(s, NVNET_RING_SIZE, 4); + return GET_MASK(ring_size, NVNET_RING_SIZE_RX) + 1; +} + static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, const uint8_t *buf, size_t size) { @@ -229,7 +239,7 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, const uint8_t *buf, nvnet_set_reg(s, NVNET_TX_RX_CONTROL, ctrl & ~NVNET_TX_RX_CONTROL_IDLE, 4); struct RingDesc desc; - s->rx_ring_index %= s->rx_ring_size; + s->rx_ring_index %= get_rx_ring_size(s); dma_addr_t rx_ring_addr = nvnet_get_reg(s, NVNET_RX_RING_PHYS_ADDR, 4); rx_ring_addr += s->rx_ring_index * sizeof(desc); pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); @@ -285,9 +295,9 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) uint32_t ctrl = nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4); nvnet_set_reg(s, NVNET_TX_RX_CONTROL, ctrl & ~NVNET_TX_RX_CONTROL_IDLE, 4); - for (int i = 0; i < s->tx_ring_size; i++) { + for (int i = 0; i < get_tx_ring_size(s); i++) { struct RingDesc desc; - s->tx_ring_index %= s->tx_ring_size; + s->tx_ring_index %= get_tx_ring_size(s); dma_addr_t tx_ring_addr = nvnet_get_reg(s, NVNET_TX_RING_PHYS_ADDR, 4); tx_ring_addr += s->tx_ring_index * sizeof(desc); pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); @@ -563,7 +573,7 @@ static void nvnet_dump_ring_descriptors(NvNetState *s) NVNET_DPRINTF("------------------------------------------------\n"); - for (int i = 0; i < s->tx_ring_size; i++) { + for (int i = 0; i < get_tx_ring_size(s); i++) { struct RingDesc desc; dma_addr_t tx_ring_addr = nvnet_get_reg(s, NVNET_TX_RING_PHYS_ADDR, 4); tx_ring_addr += i * sizeof(desc); @@ -576,7 +586,7 @@ static void nvnet_dump_ring_descriptors(NvNetState *s) NVNET_DPRINTF("------------------------------------------------\n"); - for (int i = 0; i < s->rx_ring_size; i++) { + for (int i = 0; i < get_rx_ring_size(s); i++) { struct RingDesc desc; dma_addr_t rx_ring_addr = nvnet_get_reg(s, NVNET_RX_RING_PHYS_ADDR, 4); rx_ring_addr += i * sizeof(desc); @@ -600,11 +610,6 @@ static void nvnet_mmio_write(void *opaque, hwaddr addr, uint64_t val, trace_nvnet_reg_write(addr, nvnet_get_reg_name(addr & ~3), size, val); switch (addr) { - case NVNET_RING_SIZE: - s->rx_ring_size = GET_MASK(val, NVNET_RING_SIZE_RX) + 1; - s->tx_ring_size = GET_MASK(val, NVNET_RING_SIZE_TX) + 1; - break; - case NVNET_MDIO_ADDR: assert(size == 4); if (val & NVNET_MDIO_ADDR_WRITE) { @@ -695,9 +700,7 @@ static void nvnet_realize(PCIDevice *pci_dev, Error **errp) memset(s->regs, 0, sizeof(s->regs)); s->rx_ring_index = 0; - s->rx_ring_size = 0; s->tx_ring_index = 0; - s->tx_ring_size = 0; memory_region_init_io(&s->mmio, OBJECT(dev), &nvnet_mmio_ops, s, "nvnet-mmio", MMIO_SIZE); @@ -731,9 +734,7 @@ static void nvnet_reset(void *opaque) memset(&s->regs, 0, sizeof(s->regs)); memset(&s->phy_regs, 0, sizeof(s->phy_regs)); s->tx_ring_index = 0; - s->tx_ring_size = 0; s->rx_ring_index = 0; - s->rx_ring_size = 0; memset(&s->tx_dma_buf, 0, sizeof(s->tx_dma_buf)); s->tx_dma_buf_offset = 0; memset(&s->rx_dma_buf, 0, sizeof(s->rx_dma_buf)); @@ -754,9 +755,9 @@ static const VMStateDescription vmstate_nvnet = { VMSTATE_UINT8_ARRAY(regs, NvNetState, MMIO_SIZE), VMSTATE_UINT32_ARRAY(phy_regs, NvNetState, 6), VMSTATE_UINT8(tx_ring_index, NvNetState), - VMSTATE_UINT8(tx_ring_size, NvNetState), + VMSTATE_UNUSED(1), VMSTATE_UINT8(rx_ring_index, NvNetState), - VMSTATE_UINT8(rx_ring_size, NvNetState), + VMSTATE_UNUSED(1), VMSTATE_END_OF_LIST() }, }; From 389f7ad577b2a32b94375f7831562be7401374f8 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 19 Jun 2025 01:55:06 -0700 Subject: [PATCH 42/47] nvnet: Rename RingDesc::packet_buffer -> buffer_addr --- hw/xbox/mcpx/nvnet/nvnet.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index bcbb766d2e..f00fafb64b 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -73,7 +73,7 @@ typedef struct NvNetState { } NvNetState; struct RingDesc { - uint32_t packet_buffer; + uint32_t buffer_addr; uint16_t length; uint16_t flags; } QEMU_PACKED; @@ -244,20 +244,20 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, const uint8_t *buf, rx_ring_addr += s->rx_ring_index * sizeof(desc); pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); - uint32_t packet_buffer = le32_to_cpu(desc.packet_buffer); + uint32_t buffer_addr = le32_to_cpu(desc.buffer_addr); uint16_t length = le16_to_cpu(desc.length); uint16_t flags = le16_to_cpu(desc.flags); NVNET_DPRINTF("RX: Looking at ring descriptor %d (0x%" HWADDR_PRIx "): " "Buffer: 0x%x, Length: 0x%x, Flags: 0x%x\n", - s->rx_ring_index, rx_ring_addr, packet_buffer, length, flags); + s->rx_ring_index, rx_ring_addr, buffer_addr, length, flags); if (flags & NV_RX_AVAIL) { assert((length + 1) >= size); // FIXME NVNET_DPRINTF("Transferring packet, size 0x%zx, to memory at 0x%x\n", - size, packet_buffer); - pci_dma_write(d, packet_buffer, buf, size); + size, buffer_addr); + pci_dma_write(d, buffer_addr, buf, size); length = size; flags = NV_RX_BIT4 | NV_RX_DESCRIPTORVALID; @@ -302,13 +302,13 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) tx_ring_addr += s->tx_ring_index * sizeof(desc); pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); - uint32_t packet_buffer = le32_to_cpu(desc.packet_buffer); + uint32_t buffer_addr = le32_to_cpu(desc.buffer_addr); uint16_t length = le16_to_cpu(desc.length); uint16_t flags = le16_to_cpu(desc.flags); NVNET_DPRINTF("TX: Looking at ring desc %d (%" HWADDR_PRIx "): " "Buffer: 0x%x, Length: 0x%x, Flags: 0x%x\n", - s->tx_ring_index, tx_ring_addr, packet_buffer, length, + s->tx_ring_index, tx_ring_addr, buffer_addr, length, flags); if (!(flags & NV_TX_VALID)) { @@ -319,7 +319,7 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) assert((s->tx_dma_buf_offset + length + 1) <= sizeof(s->tx_dma_buf)); - pci_dma_read(d, packet_buffer, &s->tx_dma_buf[s->tx_dma_buf_offset], + pci_dma_read(d, buffer_addr, &s->tx_dma_buf[s->tx_dma_buf_offset], length + 1); s->tx_dma_buf_offset += length + 1; @@ -580,7 +580,7 @@ static void nvnet_dump_ring_descriptors(NvNetState *s) pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); NVNET_DPRINTF("TX desc %d (%" HWADDR_PRIx "): " "Buffer: 0x%x, Length: 0x%x, Flags: 0x%x\n", - i, tx_ring_addr, le32_to_cpu(desc.packet_buffer), + i, tx_ring_addr, le32_to_cpu(desc.buffer_addr), le16_to_cpu(desc.length), le16_to_cpu(desc.flags)); } @@ -593,7 +593,7 @@ static void nvnet_dump_ring_descriptors(NvNetState *s) pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); NVNET_DPRINTF("RX desc %d (%" HWADDR_PRIx "): " "Buffer: 0x%x, Length: 0x%x, Flags: 0x%x\n", - i, rx_ring_addr, le32_to_cpu(desc.packet_buffer), + i, rx_ring_addr, le32_to_cpu(desc.buffer_addr), le16_to_cpu(desc.length), le16_to_cpu(desc.flags)); } From 59d98ed3be5b7093b7199c4a7870a38b67b92880 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 19 Jun 2025 01:55:06 -0700 Subject: [PATCH 43/47] nvnet: Drop some useless debug prints --- hw/xbox/mcpx/nvnet/nvnet.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index f00fafb64b..254b7faa0a 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -325,7 +325,6 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) bool is_last_packet = flags & NV_TX_LASTPACKET; if (is_last_packet) { - NVNET_DPRINTF("Sending packet...\n"); nvnet_send_packet(s, s->tx_dma_buf, s->tx_dma_buf_offset); s->tx_dma_buf_offset = 0; packet_sent = true; @@ -347,7 +346,6 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) } if (packet_sent) { - NVNET_DPRINTF("Triggering interrupt\n"); uint32_t irq_status = nvnet_get_reg(s, NVNET_IRQ_STATUS, 4); nvnet_set_reg(s, NVNET_IRQ_STATUS, irq_status | NVNET_IRQ_STATUS_TX, 4); nvnet_update_irq(s); From d4a5e78ba77dc817aca4e62d20f1dad796f00e0a Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 19 Jun 2025 01:55:06 -0700 Subject: [PATCH 44/47] nvnet: Drop post-tx descriptor length increase --- hw/xbox/mcpx/nvnet/nvnet.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 254b7faa0a..99127c7ce5 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -333,10 +333,8 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) flags &= ~(NV_TX_VALID | NV_TX_RETRYERROR | NV_TX_DEFERRED | NV_TX_CARRIERLOST | NV_TX_LATECOLLISION | NV_TX_UNDERFLOW | NV_TX_ERROR); - length += 5; // FIXME desc.flags = cpu_to_le16(flags); - desc.length = cpu_to_le16(length); pci_dma_write(d, tx_ring_addr, &desc, sizeof(desc)); if (is_last_packet) { From e75c5f3e8fbc326459397d4d19143b484cf95241 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 19 Jun 2025 01:55:06 -0700 Subject: [PATCH 45/47] nvnet: Simplify length adjustment in nvnet_dma_packet_from_guest --- hw/xbox/mcpx/nvnet/nvnet.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 99127c7ce5..1a4d50ad83 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -303,7 +303,7 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); uint32_t buffer_addr = le32_to_cpu(desc.buffer_addr); - uint16_t length = le16_to_cpu(desc.length); + uint16_t length = le16_to_cpu(desc.length) + 1; uint16_t flags = le16_to_cpu(desc.flags); NVNET_DPRINTF("TX: Looking at ring desc %d (%" HWADDR_PRIx "): " @@ -317,11 +317,11 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) s->tx_ring_index += 1; - assert((s->tx_dma_buf_offset + length + 1) <= + assert((s->tx_dma_buf_offset + length) <= sizeof(s->tx_dma_buf)); pci_dma_read(d, buffer_addr, &s->tx_dma_buf[s->tx_dma_buf_offset], - length + 1); - s->tx_dma_buf_offset += length + 1; + length); + s->tx_dma_buf_offset += length; bool is_last_packet = flags & NV_TX_LASTPACKET; if (is_last_packet) { From 0eb0a315b8840ab4b124affa5124736037783033 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 19 Jun 2025 01:55:06 -0700 Subject: [PATCH 46/47] nvnet: Migrate ring index tracking to device registers --- hw/xbox/mcpx/nvnet/nvnet.c | 143 +++++++++++++++++++++++--------- hw/xbox/mcpx/nvnet/nvnet_regs.h | 8 +- 2 files changed, 112 insertions(+), 39 deletions(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 1a4d50ad83..0590601dc8 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -65,11 +65,13 @@ typedef struct NvNetState { uint8_t regs[MMIO_SIZE]; uint32_t phy_regs[6]; - uint8_t tx_ring_index; - uint8_t rx_ring_index; uint8_t tx_dma_buf[TX_ALLOC_BUFSIZE]; uint32_t tx_dma_buf_offset; uint8_t rx_dma_buf[RX_ALLOC_BUFSIZE]; + + /* Deprecated */ + uint8_t tx_ring_index; + uint8_t rx_ring_index; } NvNetState; struct RingDesc { @@ -110,8 +112,13 @@ static const char *nvnet_get_reg_name(hwaddr addr) R(NVNET_RING_SIZE) R(NVNET_UNKNOWN_TRANSMITTER_REG) R(NVNET_LINKSPEED) + R(NVNET_TX_RING_CURRENT_DESC_PHYS_ADDR) + R(NVNET_RX_RING_CURRENT_DESC_PHYS_ADDR) + R(NVNET_TX_CURRENT_BUFFER_PHYS_ADDR) + R(NVNET_RX_CURRENT_BUFFER_PHYS_ADDR) R(NVNET_UNKNOWN_SETUP_REG5) - R(NVNET_UNKNOWN_SETUP_REG3) + R(NVNET_TX_RING_NEXT_DESC_PHYS_ADDR) + R(NVNET_RX_RING_NEXT_DESC_PHYS_ADDR) R(NVNET_UNKNOWN_SETUP_REG8) R(NVNET_UNKNOWN_SETUP_REG7) R(NVNET_TX_RX_CONTROL) @@ -229,6 +236,19 @@ static uint16_t get_rx_ring_size(NvNetState *s) return GET_MASK(ring_size, NVNET_RING_SIZE_RX) + 1; } +static void reset_descriptor_ring_pointers(NvNetState *s) +{ + uint32_t base_desc_addr; + + base_desc_addr = nvnet_get_reg(s, NVNET_TX_RING_PHYS_ADDR, 4); + nvnet_set_reg(s, NVNET_TX_RING_CURRENT_DESC_PHYS_ADDR, base_desc_addr, 4); + nvnet_set_reg(s, NVNET_TX_RING_NEXT_DESC_PHYS_ADDR, base_desc_addr, 4); + + base_desc_addr = nvnet_get_reg(s, NVNET_RX_RING_PHYS_ADDR, 4); + nvnet_set_reg(s, NVNET_RX_RING_CURRENT_DESC_PHYS_ADDR, base_desc_addr, 4); + nvnet_set_reg(s, NVNET_RX_RING_NEXT_DESC_PHYS_ADDR, base_desc_addr, 4); +} + static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, const uint8_t *buf, size_t size) { @@ -238,19 +258,28 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, const uint8_t *buf, uint32_t ctrl = nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4); nvnet_set_reg(s, NVNET_TX_RX_CONTROL, ctrl & ~NVNET_TX_RX_CONTROL_IDLE, 4); + uint32_t base_desc_addr = nvnet_get_reg(s, NVNET_RX_RING_PHYS_ADDR, 4); + uint32_t max_desc_addr = + base_desc_addr + get_rx_ring_size(s) * sizeof(struct RingDesc); + uint32_t cur_desc_addr = + nvnet_get_reg(s, NVNET_RX_RING_NEXT_DESC_PHYS_ADDR, 4); + if ((cur_desc_addr < base_desc_addr) || + ((cur_desc_addr + sizeof(struct RingDesc)) > max_desc_addr)) { + cur_desc_addr = base_desc_addr; + } + nvnet_set_reg(s, NVNET_RX_RING_CURRENT_DESC_PHYS_ADDR, cur_desc_addr, 4); + struct RingDesc desc; - s->rx_ring_index %= get_rx_ring_size(s); - dma_addr_t rx_ring_addr = nvnet_get_reg(s, NVNET_RX_RING_PHYS_ADDR, 4); - rx_ring_addr += s->rx_ring_index * sizeof(desc); - pci_dma_read(d, rx_ring_addr, &desc, sizeof(desc)); + pci_dma_read(d, cur_desc_addr, &desc, sizeof(desc)); uint32_t buffer_addr = le32_to_cpu(desc.buffer_addr); uint16_t length = le16_to_cpu(desc.length); uint16_t flags = le16_to_cpu(desc.flags); - NVNET_DPRINTF("RX: Looking at ring descriptor %d (0x%" HWADDR_PRIx "): " + NVNET_DPRINTF("RX: Looking at ring descriptor %zd (0x%x): " "Buffer: 0x%x, Length: 0x%x, Flags: 0x%x\n", - s->rx_ring_index, rx_ring_addr, buffer_addr, length, flags); + (cur_desc_addr - base_desc_addr) / sizeof(struct RingDesc), + cur_desc_addr, buffer_addr, length, flags); if (flags & NV_RX_AVAIL) { assert((length + 1) >= size); // FIXME @@ -264,7 +293,7 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, const uint8_t *buf, desc.length = cpu_to_le16(length); desc.flags = cpu_to_le16(flags); - pci_dma_write(d, rx_ring_addr, &desc, sizeof(desc)); + pci_dma_write(d, cur_desc_addr, &desc, sizeof(desc)); NVNET_DPRINTF("Updated ring descriptor: Length: 0x%x, Flags: 0x%x\n", length, flags); @@ -274,7 +303,12 @@ static ssize_t nvnet_dma_packet_to_guest(NvNetState *s, const uint8_t *buf, nvnet_set_reg(s, NVNET_IRQ_STATUS, irq_status | NVNET_IRQ_STATUS_RX, 4); nvnet_update_irq(s); - s->rx_ring_index += 1; + uint32_t next_desc_addr = cur_desc_addr + sizeof(struct RingDesc); + if (next_desc_addr >= max_desc_addr) { + next_desc_addr = base_desc_addr; + } + nvnet_set_reg(s, NVNET_RX_RING_NEXT_DESC_PHYS_ADDR, next_desc_addr, 4); + rval = size; } else { NVNET_DPRINTF("Could not find free buffer!\n"); @@ -295,28 +329,37 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) uint32_t ctrl = nvnet_get_reg(s, NVNET_TX_RX_CONTROL, 4); nvnet_set_reg(s, NVNET_TX_RX_CONTROL, ctrl & ~NVNET_TX_RX_CONTROL_IDLE, 4); + uint32_t base_desc_addr = nvnet_get_reg(s, NVNET_TX_RING_PHYS_ADDR, 4); + uint32_t max_desc_addr = + base_desc_addr + get_tx_ring_size(s) * sizeof(struct RingDesc); + for (int i = 0; i < get_tx_ring_size(s); i++) { + uint32_t cur_desc_addr = + nvnet_get_reg(s, NVNET_TX_RING_NEXT_DESC_PHYS_ADDR, 4); + if ((cur_desc_addr < base_desc_addr) || + ((cur_desc_addr + sizeof(struct RingDesc)) > max_desc_addr)) { + cur_desc_addr = base_desc_addr; + } + nvnet_set_reg(s, NVNET_TX_RING_CURRENT_DESC_PHYS_ADDR, cur_desc_addr, + 4); + struct RingDesc desc; - s->tx_ring_index %= get_tx_ring_size(s); - dma_addr_t tx_ring_addr = nvnet_get_reg(s, NVNET_TX_RING_PHYS_ADDR, 4); - tx_ring_addr += s->tx_ring_index * sizeof(desc); - pci_dma_read(d, tx_ring_addr, &desc, sizeof(desc)); + pci_dma_read(d, cur_desc_addr, &desc, sizeof(desc)); uint32_t buffer_addr = le32_to_cpu(desc.buffer_addr); uint16_t length = le16_to_cpu(desc.length) + 1; uint16_t flags = le16_to_cpu(desc.flags); - NVNET_DPRINTF("TX: Looking at ring desc %d (%" HWADDR_PRIx "): " + NVNET_DPRINTF("TX: Looking at ring desc %zd (%x): " "Buffer: 0x%x, Length: 0x%x, Flags: 0x%x\n", - s->tx_ring_index, tx_ring_addr, buffer_addr, length, - flags); + (cur_desc_addr - base_desc_addr) / + sizeof(struct RingDesc), + cur_desc_addr, buffer_addr, length, flags); if (!(flags & NV_TX_VALID)) { break; } - s->tx_ring_index += 1; - assert((s->tx_dma_buf_offset + length) <= sizeof(s->tx_dma_buf)); pci_dma_read(d, buffer_addr, &s->tx_dma_buf[s->tx_dma_buf_offset], @@ -335,7 +378,13 @@ static ssize_t nvnet_dma_packet_from_guest(NvNetState *s) NV_TX_ERROR); desc.flags = cpu_to_le16(flags); - pci_dma_write(d, tx_ring_addr, &desc, sizeof(desc)); + pci_dma_write(d, cur_desc_addr, &desc, sizeof(desc)); + + uint32_t next_desc_addr = cur_desc_addr + sizeof(struct RingDesc); + if (next_desc_addr >= max_desc_addr) { + next_desc_addr = base_desc_addr; + } + nvnet_set_reg(s, NVNET_TX_RING_NEXT_DESC_PHYS_ADDR, next_desc_addr, 4); if (is_last_packet) { // FIXME @@ -628,8 +677,7 @@ static void nvnet_mmio_write(void *opaque, hwaddr addr, uint64_t val, } if (val & NVNET_TX_RX_CONTROL_RESET) { - s->tx_ring_index = 0; - s->rx_ring_index = 0; + reset_descriptor_ring_pointers(s); s->tx_dma_buf_offset = 0; } @@ -638,13 +686,9 @@ static void nvnet_mmio_write(void *opaque, hwaddr addr, uint64_t val, nvnet_set_reg(s, NVNET_IRQ_STATUS, 0, 4); break; } else if (val == 0) { - uint32_t temp = nvnet_get_reg(s, NVNET_UNKNOWN_SETUP_REG3, 4); - if (temp == NVNET_UNKNOWN_SETUP_REG3_VAL1) { - /* forcedeth waits for this bit to be set... */ - nvnet_set_reg(s, NVNET_UNKNOWN_SETUP_REG5, - NVNET_UNKNOWN_SETUP_REG5_BIT31, 4); - break; - } + /* forcedeth waits for this bit to be set... */ + nvnet_set_reg(s, NVNET_UNKNOWN_SETUP_REG5, + NVNET_UNKNOWN_SETUP_REG5_BIT31, 4); } break; @@ -695,9 +739,6 @@ static void nvnet_realize(PCIDevice *pci_dev, Error **errp) memset(s->regs, 0, sizeof(s->regs)); - s->rx_ring_index = 0; - s->tx_ring_index = 0; - memory_region_init_io(&s->mmio, OBJECT(dev), &nvnet_mmio_ops, s, "nvnet-mmio", MMIO_SIZE); pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio); @@ -729,11 +770,15 @@ static void nvnet_reset(void *opaque) memset(&s->regs, 0, sizeof(s->regs)); memset(&s->phy_regs, 0, sizeof(s->phy_regs)); + memset(&s->tx_dma_buf, 0, sizeof(s->tx_dma_buf)); + memset(&s->rx_dma_buf, 0, sizeof(s->rx_dma_buf)); + s->tx_dma_buf_offset = 0; + + reset_descriptor_ring_pointers(s); + + /* Deprecated */ s->tx_ring_index = 0; s->rx_ring_index = 0; - memset(&s->tx_dma_buf, 0, sizeof(s->tx_dma_buf)); - s->tx_dma_buf_offset = 0; - memset(&s->rx_dma_buf, 0, sizeof(s->rx_dma_buf)); } static void nvnet_reset_hold(Object *obj, ResetType type) @@ -742,10 +787,34 @@ static void nvnet_reset_hold(Object *obj, ResetType type) nvnet_reset(s); } +static int nvnet_post_load(void *opaque, int version_id) +{ + NvNetState *s = NVNET(opaque); + + if (version_id < 2) { + /* Migrate old snapshot tx descriptor index */ + uint32_t next_desc_addr = + nvnet_get_reg(s, NVNET_TX_RING_PHYS_ADDR, 4) + + (s->tx_ring_index % get_tx_ring_size(s)) * sizeof(struct RingDesc); + nvnet_set_reg(s, NVNET_TX_RING_NEXT_DESC_PHYS_ADDR, next_desc_addr, 4); + s->tx_ring_index = 0; + + /* Migrate old snapshot rx descriptor index */ + next_desc_addr = + nvnet_get_reg(s, NVNET_RX_RING_PHYS_ADDR, 4) + + (s->rx_ring_index % get_rx_ring_size(s)) * sizeof(struct RingDesc); + nvnet_set_reg(s, NVNET_RX_RING_NEXT_DESC_PHYS_ADDR, next_desc_addr, 4); + s->rx_ring_index = 0; + } + + return 0; +} + static const VMStateDescription vmstate_nvnet = { .name = "nvnet", - .version_id = 1, + .version_id = 2, .minimum_version_id = 1, + .post_load = nvnet_post_load, .fields = (VMStateField[]){ VMSTATE_PCI_DEVICE(parent_obj, NvNetState), VMSTATE_UINT8_ARRAY(regs, NvNetState, MMIO_SIZE), diff --git a/hw/xbox/mcpx/nvnet/nvnet_regs.h b/hw/xbox/mcpx/nvnet/nvnet_regs.h index d521c97cca..8f6d41eb6a 100644 --- a/hw/xbox/mcpx/nvnet/nvnet_regs.h +++ b/hw/xbox/mcpx/nvnet/nvnet_regs.h @@ -129,10 +129,14 @@ # define NVNET_LINKSPEED_10 10 # define NVNET_LINKSPEED_100 100 # define NVNET_LINKSPEED_1000 1000 +#define NVNET_TX_RING_CURRENT_DESC_PHYS_ADDR 0x11C +#define NVNET_RX_RING_CURRENT_DESC_PHYS_ADDR 0x120 +#define NVNET_TX_CURRENT_BUFFER_PHYS_ADDR 0x124 +#define NVNET_RX_CURRENT_BUFFER_PHYS_ADDR 0x12C #define NVNET_UNKNOWN_SETUP_REG5 0x130 # define NVNET_UNKNOWN_SETUP_REG5_BIT31 (1 << 31) -#define NVNET_UNKNOWN_SETUP_REG3 0x134 -# define NVNET_UNKNOWN_SETUP_REG3_VAL1 0x00200010 +#define NVNET_TX_RING_NEXT_DESC_PHYS_ADDR 0x134 +#define NVNET_RX_RING_NEXT_DESC_PHYS_ADDR 0x138 #define NVNET_UNKNOWN_SETUP_REG8 0x13C # define NVNET_UNKNOWN_SETUP_REG8_VAL1 0x00300010 #define NVNET_UNKNOWN_SETUP_REG7 0x140 From b22f42ff95968f63ad7f2967726d5db13feb6ff4 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 19 Jun 2025 01:55:06 -0700 Subject: [PATCH 47/47] nvnet: Move tx_dma_buf_offset field up --- hw/xbox/mcpx/nvnet/nvnet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/xbox/mcpx/nvnet/nvnet.c b/hw/xbox/mcpx/nvnet/nvnet.c index 0590601dc8..fa27b7ce33 100644 --- a/hw/xbox/mcpx/nvnet/nvnet.c +++ b/hw/xbox/mcpx/nvnet/nvnet.c @@ -65,8 +65,8 @@ typedef struct NvNetState { uint8_t regs[MMIO_SIZE]; uint32_t phy_regs[6]; - uint8_t tx_dma_buf[TX_ALLOC_BUFSIZE]; uint32_t tx_dma_buf_offset; + uint8_t tx_dma_buf[TX_ALLOC_BUFSIZE]; uint8_t rx_dma_buf[RX_ALLOC_BUFSIZE]; /* Deprecated */