X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/8da3ff180974732fc4272cb4433fef85c1822961..1422e32db51ff2b1194fb24a6201c4310be5667d:/hw/stellaris_enet.c diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c index 09d92b1344..d7e1e21ff9 100644 --- a/hw/stellaris_enet.c +++ b/hw/stellaris_enet.c @@ -4,24 +4,23 @@ * Copyright (c) 2007 CodeSourcery. * Written by Paul Brook * - * This code is licenced under the GPL. + * This code is licensed under the GPL. */ -#include "hw.h" -#include "arm-misc.h" -#include "net.h" +#include "sysbus.h" +#include "net/net.h" #include //#define DEBUG_STELLARIS_ENET 1 #ifdef DEBUG_STELLARIS_ENET -#define DPRINTF(fmt, args...) \ -do { printf("stellaris_enet: " fmt , ##args); } while (0) -#define BADF(fmt, args...) \ -do { fprintf(stderr, "stellaris_enet: error: " fmt , ##args); exit(1);} while (0) +#define DPRINTF(fmt, ...) \ +do { printf("stellaris_enet: " fmt , ## __VA_ARGS__); } while (0) +#define BADF(fmt, ...) \ +do { fprintf(stderr, "stellaris_enet: error: " fmt , ## __VA_ARGS__); exit(1);} while (0) #else -#define DPRINTF(fmt, args...) do {} while(0) -#define BADF(fmt, args...) \ -do { fprintf(stderr, "stellaris_enet: error: " fmt , ##args);} while (0) +#define DPRINTF(fmt, ...) do {} while(0) +#define BADF(fmt, ...) \ +do { fprintf(stderr, "stellaris_enet: error: " fmt , ## __VA_ARGS__);} while (0) #endif #define SE_INT_RX 0x01 @@ -44,6 +43,7 @@ do { fprintf(stderr, "stellaris_enet: error: " fmt , ##args);} while (0) #define SE_TCTL_DUPLEX 0x08 typedef struct { + SysBusDevice busdev; uint32_t ris; uint32_t im; uint32_t rctl; @@ -66,9 +66,10 @@ typedef struct { uint8_t *rx_fifo; int rx_fifo_len; int next_packet; - VLANClientState *vc; + NICState *nic; + NICConf conf; qemu_irq irq; - uint8_t macaddr[6]; + MemoryRegion mmio; } stellaris_enet_state; static void stellaris_enet_update(stellaris_enet_state *s) @@ -77,18 +78,18 @@ static void stellaris_enet_update(stellaris_enet_state *s) } /* TODO: Implement MAC address filtering. */ -static void stellaris_enet_receive(void *opaque, const uint8_t *buf, int size) +static ssize_t stellaris_enet_receive(NetClientState *nc, const uint8_t *buf, size_t size) { - stellaris_enet_state *s = (stellaris_enet_state *)opaque; + stellaris_enet_state *s = DO_UPCAST(NICState, nc, nc)->opaque; int n; uint8_t *p; uint32_t crc; if ((s->rctl & SE_RCTL_RXEN) == 0) - return; + return -1; if (s->np >= 31) { DPRINTF("Packet dropped\n"); - return; + return -1; } DPRINTF("Received packet len=%d\n", size); @@ -115,11 +116,13 @@ static void stellaris_enet_receive(void *opaque, const uint8_t *buf, int size) s->ris |= SE_INT_RX; stellaris_enet_update(s); + + return size; } -static int stellaris_enet_can_receive(void *opaque) +static int stellaris_enet_can_receive(NetClientState *nc) { - stellaris_enet_state *s = (stellaris_enet_state *)opaque; + stellaris_enet_state *s = DO_UPCAST(NICState, nc, nc)->opaque; if ((s->rctl & SE_RCTL_RXEN) == 0) return 1; @@ -127,7 +130,8 @@ static int stellaris_enet_can_receive(void *opaque) return (s->np < 31); } -static uint32_t stellaris_enet_read(void *opaque, target_phys_addr_t offset) +static uint64_t stellaris_enet_read(void *opaque, hwaddr offset, + unsigned size) { stellaris_enet_state *s = (stellaris_enet_state *)opaque; uint32_t val; @@ -166,10 +170,10 @@ static uint32_t stellaris_enet_read(void *opaque, target_phys_addr_t offset) } return val; case 0x14: /* IA0 */ - return s->macaddr[0] | (s->macaddr[1] << 8) - | (s->macaddr[2] << 16) | (s->macaddr[3] << 24); + return s->conf.macaddr.a[0] | (s->conf.macaddr.a[1] << 8) + | (s->conf.macaddr.a[2] << 16) | (s->conf.macaddr.a[3] << 24); case 0x18: /* IA1 */ - return s->macaddr[4] | (s->macaddr[5] << 8); + return s->conf.macaddr.a[4] | (s->conf.macaddr.a[5] << 8); case 0x1c: /* THR */ return s->thr; case 0x20: /* MCTL */ @@ -189,14 +193,13 @@ static uint32_t stellaris_enet_read(void *opaque, target_phys_addr_t offset) case 0x3c: /* Undocuented: Timestamp? */ return 0; default: - cpu_abort (cpu_single_env, "stellaris_enet_read: Bad offset %x\n", - (int)offset); + hw_error("stellaris_enet_read: Bad offset %x\n", (int)offset); return 0; } } -static void stellaris_enet_write(void *opaque, target_phys_addr_t offset, - uint32_t value) +static void stellaris_enet_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) { stellaris_enet_state *s = (stellaris_enet_state *)opaque; @@ -256,7 +259,7 @@ static void stellaris_enet_write(void *opaque, target_phys_addr_t offset, memset(&s->tx_fifo[s->tx_frame_len], 0, 60 - s->tx_frame_len); s->tx_fifo_len = 60; } - qemu_send_packet(s->vc, s->tx_fifo, s->tx_frame_len); + qemu_send_packet(&s->nic->nc, s->tx_fifo, s->tx_frame_len); s->tx_frame_len = -1; s->ris |= SE_INT_TXEMP; stellaris_enet_update(s); @@ -265,14 +268,14 @@ static void stellaris_enet_write(void *opaque, target_phys_addr_t offset, } break; case 0x14: /* IA0 */ - s->macaddr[0] = value; - s->macaddr[1] = value >> 8; - s->macaddr[2] = value >> 16; - s->macaddr[3] = value >> 24; + s->conf.macaddr.a[0] = value; + s->conf.macaddr.a[1] = value >> 8; + s->conf.macaddr.a[2] = value >> 16; + s->conf.macaddr.a[3] = value >> 24; break; case 0x18: /* IA1 */ - s->macaddr[4] = value; - s->macaddr[5] = value >> 8; + s->conf.macaddr.a[4] = value; + s->conf.macaddr.a[5] = value >> 8; break; case 0x1c: /* THR */ s->thr = value; @@ -297,22 +300,16 @@ static void stellaris_enet_write(void *opaque, target_phys_addr_t offset, /* Ignored. */ break; default: - cpu_abort (cpu_single_env, "stellaris_enet_write: Bad offset %x\n", - (int)offset); + hw_error("stellaris_enet_write: Bad offset %x\n", (int)offset); } } -static CPUReadMemoryFunc *stellaris_enet_readfn[] = { - stellaris_enet_read, - stellaris_enet_read, - stellaris_enet_read +static const MemoryRegionOps stellaris_enet_ops = { + .read = stellaris_enet_read, + .write = stellaris_enet_write, + .endianness = DEVICE_NATIVE_ENDIAN, }; -static CPUWriteMemoryFunc *stellaris_enet_writefn[] = { - stellaris_enet_write, - stellaris_enet_write, - stellaris_enet_write -}; static void stellaris_enet_reset(stellaris_enet_state *s) { s->mdv = 0x80; @@ -384,23 +381,69 @@ static int stellaris_enet_load(QEMUFile *f, void *opaque, int version_id) return 0; } -void stellaris_enet_init(NICInfo *nd, uint32_t base, qemu_irq irq) +static void stellaris_enet_cleanup(NetClientState *nc) { - stellaris_enet_state *s; - int iomemtype; + stellaris_enet_state *s = DO_UPCAST(NICState, nc, nc)->opaque; - s = (stellaris_enet_state *)qemu_mallocz(sizeof(stellaris_enet_state)); - iomemtype = cpu_register_io_memory(0, stellaris_enet_readfn, - stellaris_enet_writefn, s); - cpu_register_physical_memory(base, 0x00001000, iomemtype); - s->irq = irq; - memcpy(s->macaddr, nd->macaddr, 6); + unregister_savevm(&s->busdev.qdev, "stellaris_enet", s); - if (nd->vlan) - s->vc = qemu_new_vlan_client(nd->vlan, stellaris_enet_receive, - stellaris_enet_can_receive, s); + memory_region_destroy(&s->mmio); + + g_free(s); +} + +static NetClientInfo net_stellaris_enet_info = { + .type = NET_CLIENT_OPTIONS_KIND_NIC, + .size = sizeof(NICState), + .can_receive = stellaris_enet_can_receive, + .receive = stellaris_enet_receive, + .cleanup = stellaris_enet_cleanup, +}; + +static int stellaris_enet_init(SysBusDevice *dev) +{ + stellaris_enet_state *s = FROM_SYSBUS(stellaris_enet_state, dev); + + memory_region_init_io(&s->mmio, &stellaris_enet_ops, s, "stellaris_enet", + 0x1000); + sysbus_init_mmio(dev, &s->mmio); + sysbus_init_irq(dev, &s->irq); + qemu_macaddr_default_if_unset(&s->conf.macaddr); + + s->nic = qemu_new_nic(&net_stellaris_enet_info, &s->conf, + object_get_typename(OBJECT(dev)), dev->qdev.id, s); + qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); stellaris_enet_reset(s); - register_savevm("stellaris_enet", -1, 1, + register_savevm(&s->busdev.qdev, "stellaris_enet", -1, 1, stellaris_enet_save, stellaris_enet_load, s); + return 0; } + +static Property stellaris_enet_properties[] = { + DEFINE_NIC_PROPERTIES(stellaris_enet_state, conf), + DEFINE_PROP_END_OF_LIST(), +}; + +static void stellaris_enet_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = stellaris_enet_init; + dc->props = stellaris_enet_properties; +} + +static TypeInfo stellaris_enet_info = { + .name = "stellaris_enet", + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(stellaris_enet_state), + .class_init = stellaris_enet_class_init, +}; + +static void stellaris_enet_register_types(void) +{ + type_register_static(&stellaris_enet_info); +} + +type_init(stellaris_enet_register_types)