diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 66e7cba4ff..243b915631 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -213,6 +213,6 @@ obj-$(CONFIG_KVM) += ivshmem.o
obj-$(CONFIG_LINUX) += vfio_pci.o
endif
-obj-$(CONFIG_XBOX) += xbox_pci.o acpi_xbox.o amd_smbus.o nv2a.o nv2a_vsh.o mcpx_apu.o mcpx_aci.o smbus_xbox_smc.o smbus_cx25871.o smbus_adm1032.o
+obj-$(CONFIG_XBOX) += xbox_pci.o acpi_xbox.o amd_smbus.o nvnet.o nv2a.o nv2a_vsh.o mcpx_apu.o mcpx_aci.o smbus_xbox_smc.o smbus_cx25871.o smbus_adm1032.o
endif
diff --git a/hw/i386/xbox.c b/hw/i386/xbox.c
index 0cc0bff127..4f21749537 100644
--- a/hw/i386/xbox.c
+++ b/hw/i386/xbox.c
@@ -37,6 +37,7 @@
#include "exec/address-spaces.h"
#include "hw/xbox_pci.h"
+#include "hw/nvnet.h"
#include "hw/nv2a.h"
#include "hw/mcpx_apu.h"
@@ -193,13 +194,6 @@ static void xbox_init(QEMUMachineInitArgs *args)
/* does apparently have a pc speaker, though not used? */
pcspk_init(isa_bus, pit);
-
- /* TODO: ethernet */
-
- /* USB */
- pci_create_simple(host_bus, PCI_DEVFN(2, 0), "pci-ohci");
- pci_create_simple(host_bus, PCI_DEVFN(3, 0), "pci-ohci");
-
/* hdd shit
* piix3's ide be right for now, maybe
*/
@@ -263,6 +257,14 @@ static void xbox_init(QEMUMachineInitArgs *args)
smbus_cx25871_init(smbus, 0x45);
smbus_adm1032_init(smbus, 0x4c);
+
+ /* USB */
+ pci_create_simple(host_bus, PCI_DEVFN(2, 0), "pci-ohci");
+ pci_create_simple(host_bus, PCI_DEVFN(3, 0), "pci-ohci");
+
+ /* Ethernet! */
+ nvnet_init(host_bus, PCI_DEVFN(4, 0), gsi[4]);
+
/* APU! */
mcpx_apu_init(host_bus, PCI_DEVFN(5, 0), gsi[5]);
diff --git a/hw/nvnet.c b/hw/nvnet.c
new file mode 100644
index 0000000000..093be17e13
--- /dev/null
+++ b/hw/nvnet.c
@@ -0,0 +1,129 @@
+/*
+ * QEMU nForce Ethernet Controller implementation
+ *
+ * Copyright (c) 2013 espes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see .
+ */
+#include "hw.h"
+#include "pc.h"
+#include "pci/pci.h"
+
+#include "nvnet.h"
+
+
+#define IOPORT_SIZE 0x8
+#define MMIO_SIZE 0x400
+
+
+//#define DEBUG
+#ifdef DEBUG
+# define NVNET_DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
+#else
+# define NVNET_DPRINTF(format, ...) do { } while (0)
+#endif
+
+typedef struct NVNetState {
+ PCIDevice dev;
+ qemu_irq irq;
+
+ MemoryRegion mmio, io;
+} NVNetState;
+
+#define NVNET_DEVICE(obj) \
+ OBJECT_CHECK(NVNetState, (obj), "nvnet")
+
+
+static uint64_t nvnet_mmio_read(void *opaque,
+ hwaddr addr, unsigned int size)
+{
+ NVNET_DPRINTF("nvnet MMIO: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nvnet_mmio_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned int size)
+{
+ NVNET_DPRINTF("nvnet MMIO: [0x%llx] = 0x%llx\n", addr, val);
+}
+static const MemoryRegionOps nvnet_mmio_ops = {
+ .read = nvnet_mmio_read,
+ .write = nvnet_mmio_write,
+};
+
+
+static uint64_t nvnet_io_read(void *opaque,
+ hwaddr addr, unsigned int size)
+{
+ NVNET_DPRINTF("nvnet IO: read [0x%llx]\n", addr);
+ return 0;
+}
+static void nvnet_io_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned int size)
+{
+ NVNET_DPRINTF("nvnet IO: [0x%llx] = 0x%llx\n", addr, val);
+}
+static const MemoryRegionOps nvnet_io_ops = {
+ .read = nvnet_io_read,
+ .write = nvnet_io_write,
+};
+
+static int nvnet_initfn(PCIDevice *dev)
+{
+ NVNetState *d = NVNET_DEVICE(dev);
+
+ memory_region_init_io(&d->mmio, &nvnet_mmio_ops, d, "nvnet-mmio", MMIO_SIZE);
+ pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
+
+ memory_region_init_io(&d->io, &nvnet_io_ops, d, "nvnet-io", IOPORT_SIZE);
+ pci_register_bar(&d->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->io);
+
+ return 0;
+}
+
+static void nvnet_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->vendor_id = PCI_VENDOR_ID_NVIDIA;
+ k->device_id = PCI_DEVICE_ID_NVIDIA_NVENET_1;
+ k->revision = 210;
+ k->class_id = PCI_CLASS_NETWORK_ETHERNET;
+ k->init = nvnet_initfn;
+
+ dc->desc = "nForce Ethernet Controller";
+}
+
+static const TypeInfo nvnet_info = {
+ .name = "nvnet",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(NVNetState),
+ .class_init = nvnet_class_init,
+};
+
+static void nvnet_register(void)
+{
+ type_register_static(&nvnet_info);
+}
+type_init(nvnet_register);
+
+
+void nvnet_init(PCIBus *bus, int devfn, qemu_irq irq)
+{
+ PCIDevice *dev;
+ NVNetState *d;
+ dev = pci_create_simple(bus, devfn, "nvnet");
+ d = NVNET_DEVICE(dev);
+ d->irq = irq;
+}
\ No newline at end of file
diff --git a/hw/nvnet.h b/hw/nvnet.h
new file mode 100644
index 0000000000..0fcd085f79
--- /dev/null
+++ b/hw/nvnet.h
@@ -0,0 +1,27 @@
+/*
+ * QEMU nForce Ethernet Controller implementation
+ *
+ * Copyright (c) 2013 espes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see .
+ */
+
+#ifndef HW_NVNET_H
+#define HW_NVNET_H
+
+#include "pci/pci.h"
+
+void nvnet_init(PCIBus *bus, int devfn, qemu_irq irq);
+
+#endif
\ No newline at end of file
diff --git a/hw/pci/pci_ids.h b/hw/pci/pci_ids.h
index f955d21f6a..bcf09993c6 100644
--- a/hw/pci/pci_ids.h
+++ b/hw/pci/pci_ids.h
@@ -158,6 +158,7 @@
#define PCI_DEVICE_ID_NVIDIA_NFORCE_LPC 0x01b2
#define PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS 0x01b4
#define PCI_DEVICE_ID_NVIDIA_NFORCE_AGP 0x01b7
+#define PCI_DEVICE_ID_NVIDIA_NVENET_1 0x01c3
#define PCI_DEVICE_ID_NVIDIA_GEFORCE_NV2A 0x02a0
#define PCI_DEVICE_ID_NVIDIA_XBOX_PCHB 0x02a5