Signed-off-by: Laurent Vivier <laur...@vivier.eu> --- hw/mips/mips_jazz.c | 2 +- hw/net/dp8393x.c | 182 +++++++++++++++++++++++++++++++---------------- include/hw/net/dp8393x.h | 1 - 3 files changed, 121 insertions(+), 64 deletions(-)
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c index 4d556ab..8eca5a2 100644 --- a/hw/mips/mips_jazz.c +++ b/hw/mips/mips_jazz.c @@ -268,7 +268,7 @@ static void mips_jazz_init(MemoryRegion *address_space, if (!nd->model) nd->model = g_strdup("dp83932"); if (strcmp(nd->model, "dp83932") == 0) { - dp83932_init(nd, 0x80001000, 0, 2, 0, get_system_memory(), + dp83932_init(nd, 0x80001000, 0, 2, 0, rc4030[4], rc4030_opaque, rc4030_dma_memory_rw); break; } else if (is_help_option(nd->model)) { diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index bd97851..b81e68c 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -17,9 +17,10 @@ * with this program; if not, see <http://www.gnu.org/licenses/>. */ -#include "hw/hw.h" -#include "qemu/timer.h" +#include "hw/sysbus.h" #include "net/net.h" +#include "hw/devices.h" +#include "qemu/timer.h" #include "hw/net/dp8393x.h" //#define DEBUG_SONIC @@ -147,10 +148,15 @@ do { printf("sonic ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0) #define SONIC_ISR_PINT 0x0800 #define SONIC_ISR_LCD 0x1000 +#define TYPE_DP8393X "dp8393x" +#define DP8393X(obj) OBJECT_CHECK(dp8393xState, (obj), TYPE_DP8393X) + typedef struct dp8393xState { + SysBusDevice parent_obj; + /* Hardware */ - int it_shift; - int regs_offset; + int32_t it_shift; + int32_t regs_offset; qemu_irq irq; #ifdef DEBUG_SONIC int irq_level; @@ -172,10 +178,13 @@ typedef struct dp8393xState { int loopback_packet; /* Memory access */ - void (*memory_rw)(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write); - void* mem_opaque; + void *memory_rw; + void *mem_opaque; } dp8393xState; +#define MEMORY_RW(func) void (*func)(void *opaque, hwaddr addr, \ + uint8_t *buf, int len, int is_write) = s->memory_rw + static void dp8393x_update_irq(dp8393xState *s) { int level = (s->regs[SONIC_IMR] & s->regs[SONIC_ISR]) ? 1 : 0; @@ -199,13 +208,14 @@ static void do_load_cam(dp8393xState *s) uint16_t data[8]; int width, size; uint16_t index = 0; + MEMORY_RW(memory_rw); width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1; size = sizeof(uint16_t) * 4 * width; while (s->regs[SONIC_CDC] & 0x1f) { /* Fill current entry */ - s->memory_rw(s->mem_opaque, + memory_rw(s->mem_opaque, (s->regs[SONIC_URRA] << 16) | s->regs[SONIC_CDP], (uint8_t *)data, size, 0); s->cam[index][0] = data[1 * width] & 0xff; @@ -224,7 +234,7 @@ static void do_load_cam(dp8393xState *s) } /* Read CAM enable */ - s->memory_rw(s->mem_opaque, + memory_rw(s->mem_opaque, (s->regs[SONIC_URRA] << 16) | s->regs[SONIC_CDP], (uint8_t *)data, size, 0); s->regs[SONIC_CE] = data[0 * width]; @@ -240,11 +250,14 @@ static void do_read_rra(dp8393xState *s) { uint16_t data[8]; int width, size; + MEMORY_RW(memory_rw); /* Read memory */ width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1; size = sizeof(uint16_t) * 4 * width; - s->memory_rw(s->mem_opaque, + DPRINTF("READ from %08x\n", + (s->regs[SONIC_URRA] << 16) | s->regs[SONIC_RRP]); + memory_rw(s->mem_opaque, (s->regs[SONIC_URRA] << 16) | s->regs[SONIC_RRP], (uint8_t *)data, size, 0); @@ -348,6 +361,7 @@ static void do_transmit_packets(dp8393xState *s) int width, size; int tx_len, len; uint16_t i; + MEMORY_RW(memory_rw); width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1; @@ -357,7 +371,7 @@ static void do_transmit_packets(dp8393xState *s) (s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_CTDA]); size = sizeof(uint16_t) * 6 * width; s->regs[SONIC_TTDA] = s->regs[SONIC_CTDA]; - s->memory_rw(s->mem_opaque, + memory_rw(s->mem_opaque, ((s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA]) + sizeof(uint16_t) * width, (uint8_t *)data, size, 0); tx_len = 0; @@ -383,7 +397,7 @@ static void do_transmit_packets(dp8393xState *s) if (tx_len + len > sizeof(s->tx_buffer)) { len = sizeof(s->tx_buffer) - tx_len; } - s->memory_rw(s->mem_opaque, + memory_rw(s->mem_opaque, (s->regs[SONIC_TSA1] << 16) | s->regs[SONIC_TSA0], &s->tx_buffer[tx_len], len, 0); tx_len += len; @@ -392,7 +406,7 @@ static void do_transmit_packets(dp8393xState *s) if (i != s->regs[SONIC_TFC]) { /* Read next fragment details */ size = sizeof(uint16_t) * 3 * width; - s->memory_rw(s->mem_opaque, + memory_rw(s->mem_opaque, ((s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA]) + sizeof(uint16_t) * (4 + 3 * i) * width, (uint8_t *)data, size, 0); s->regs[SONIC_TSA0] = data[0 * width]; @@ -426,14 +440,14 @@ static void do_transmit_packets(dp8393xState *s) /* Write status */ data[0 * width] = s->regs[SONIC_TCR] & 0x0fff; /* status */ size = sizeof(uint16_t) * width; - s->memory_rw(s->mem_opaque, + memory_rw(s->mem_opaque, (s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA], (uint8_t *)data, size, 1); if (!(s->regs[SONIC_CR] & SONIC_CR_HTX)) { /* Read footer of packet */ size = sizeof(uint16_t) * width; - s->memory_rw(s->mem_opaque, + memory_rw(s->mem_opaque, ((s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA]) + sizeof(uint16_t) * (4 + 3 * s->regs[SONIC_TFC]) * width, (uint8_t *)data, size, 0); s->regs[SONIC_CTDA] = data[0 * width] & ~0x1; @@ -680,7 +694,7 @@ static const MemoryRegionOps dp8393x_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static int nic_can_receive(NetClientState *nc) +static int dp8393x_can_receive(NetClientState *nc) { dp8393xState *s = qemu_get_nic_opaque(nc); @@ -729,7 +743,8 @@ static int receive_filter(dp8393xState *s, const uint8_t * buf, int size) return -1; } -static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size) +static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf, + size_t size) { dp8393xState *s = qemu_get_nic_opaque(nc); uint16_t data[10]; @@ -737,6 +752,7 @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size) uint32_t available, address; int width, rx_len = size; uint32_t checksum; + MEMORY_RW(memory_rw); width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1; @@ -755,8 +771,9 @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size) if (s->regs[SONIC_LLFA] & 0x1) { /* Are we still in resource exhaustion? */ size = sizeof(uint16_t) * 1 * width; - address = ((s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA]) + sizeof(uint16_t) * 5 * width; - s->memory_rw(s->mem_opaque, address, (uint8_t*)data, size, 0); + address = ((s->regs[SONIC_URDA] << 16) | + s->regs[SONIC_CRDA]) + sizeof(uint16_t) * 5 * width; + memory_rw(s->mem_opaque, address, (uint8_t *)data, size, 0); if (data[0 * width] & 0x1) { /* Still EOL ; stop reception */ return -1; @@ -779,9 +796,9 @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size) /* Put packet into RBA */ DPRINTF("Receive packet at %08x\n", (s->regs[SONIC_CRBA1] << 16) | s->regs[SONIC_CRBA0]); address = (s->regs[SONIC_CRBA1] << 16) | s->regs[SONIC_CRBA0]; - s->memory_rw(s->mem_opaque, address, (uint8_t*)buf, rx_len, 1); + memory_rw(s->mem_opaque, address, (uint8_t *)buf, rx_len, 1); address += rx_len; - s->memory_rw(s->mem_opaque, address, (uint8_t*)&checksum, 4, 1); + memory_rw(s->mem_opaque, address, (uint8_t *)&checksum, 4, 1); rx_len += 4; s->regs[SONIC_CRBA1] = address >> 16; s->regs[SONIC_CRBA0] = address & 0xffff; @@ -809,11 +826,12 @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size) data[3 * width] = s->regs[SONIC_TRBA1]; /* pkt_ptr1 */ data[4 * width] = s->regs[SONIC_RSC]; /* seq_no */ size = sizeof(uint16_t) * 5 * width; - s->memory_rw(s->mem_opaque, (s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA], (uint8_t *)data, size, 1); + memory_rw(s->mem_opaque, (s->regs[SONIC_URDA] << 16) | + s->regs[SONIC_CRDA], (uint8_t *)data, size, 1); /* Move to next descriptor */ size = sizeof(uint16_t) * width; - s->memory_rw(s->mem_opaque, + memory_rw(s->mem_opaque, ((s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA]) + sizeof(uint16_t) * 5 * width, (uint8_t *)data, size, 0); s->regs[SONIC_LLFA] = data[0 * width]; @@ -822,7 +840,7 @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size) s->regs[SONIC_ISR] |= SONIC_ISR_RDE; } else { data[0 * width] = 0; /* in_use */ - s->memory_rw(s->mem_opaque, + memory_rw(s->mem_opaque, ((s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA]) + sizeof(uint16_t) * 6 * width, (uint8_t *)data, size, 1); s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA]; @@ -841,9 +859,9 @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size) return size; } -static void nic_reset(void *opaque) +static void dp8393x_reset(DeviceState *d) { - dp8393xState *s = opaque; + dp8393xState *s = DP8393X(d); timer_del(s->watchdog); s->regs[SONIC_CR] = SONIC_CR_RST | SONIC_CR_STP | SONIC_CR_RXDIS; @@ -865,7 +883,7 @@ static void nic_reset(void *opaque) dp8393x_update_irq(s); } -static void nic_cleanup(NetClientState *nc) +static void dp8393x_cleanup(NetClientState *nc) { dp8393xState *s = qemu_get_nic_opaque(nc); @@ -878,54 +896,94 @@ static void nic_cleanup(NetClientState *nc) static NetClientInfo net_dp83932_info = { .type = NET_CLIENT_OPTIONS_KIND_NIC, .size = sizeof(NICState), - .can_receive = nic_can_receive, - .receive = nic_receive, - .cleanup = nic_cleanup, + .can_receive = dp8393x_can_receive, + .receive = dp8393x_receive, + .cleanup = dp8393x_cleanup, }; -void dp83932_init(NICInfo *nd, hwaddr base, hwaddr prombase, - int it_shift, int regs_offset, - MemoryRegion *address_space, - qemu_irq irq, void* mem_opaque, - void (*memory_rw)(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write)) +static int dp8393x_init1(SysBusDevice *sbd) { - dp8393xState *s; + DeviceState *dev = DEVICE(sbd); + dp8393xState *s = DP8393X(dev); int i; uint8_t *prom; - qemu_check_nic_model(nd, "dp83932"); + memory_region_init_io(&s->mmio, NULL, &dp8393x_ops, s, + "dp8393x", 0x40 << s->it_shift); + sysbus_init_mmio(sbd, &s->mmio); + sysbus_init_irq(sbd, &s->irq); - s = g_malloc0(sizeof(dp8393xState)); + s->nic = qemu_new_nic(&net_dp83932_info, &s->conf, + object_get_typename(OBJECT(dev)), dev->id, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); - s->address_space = address_space; - s->mem_opaque = mem_opaque; - s->memory_rw = memory_rw; - s->it_shift = it_shift; - s->regs_offset = regs_offset; - s->irq = irq; s->watchdog = timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s); s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */ - s->conf.macaddr = nd->macaddr; - s->conf.peers.ncs[0] = nd->netdev; + memory_region_init_rom_device(&s->prom, NULL, NULL, NULL, + "dp8393x-prom", SONIC_PROM_SIZE, NULL); + prom = memory_region_get_ram_ptr(&s->prom); + for (i = 0; i < 6; i++) { + prom[i] = s->conf.macaddr.a[i]; + } + sysbus_init_mmio(sbd, &s->prom); - s->nic = qemu_new_nic(&net_dp83932_info, &s->conf, nd->model, nd->name, s); + return 0; +} - qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); - qemu_register_reset(nic_reset, s); - nic_reset(s); +static Property dp8393x_properties[] = { + DEFINE_NIC_PROPERTIES(dp8393xState, conf), + DEFINE_PROP_PTR("memory_rw", dp8393xState, memory_rw), + DEFINE_PROP_PTR("mem_opaque", dp8393xState, mem_opaque), + DEFINE_PROP_INT32("it_shift", dp8393xState, it_shift, 0), + DEFINE_PROP_INT32("regs_offset", dp8393xState, regs_offset, 0), + DEFINE_PROP_END_OF_LIST(), +}; - memory_region_init_io(&s->mmio, NULL, &dp8393x_ops, s, - "dp8393x", 0x40 << it_shift); - memory_region_add_subregion(address_space, base, &s->mmio); - - if (prombase) { - memory_region_init_rom_device(&s->prom, NULL, NULL, NULL, - "dp8393x-prom", SONIC_PROM_SIZE, NULL); - prom = memory_region_get_ram_ptr(&s->prom); - for (i = 0; i < 6; i++) { - prom[i] = s->conf.macaddr.a[i]; - } - memory_region_add_subregion(address_space, prombase, &s->prom); - } +static void dp8393x_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = dp8393x_init1; + dc->reset = dp8393x_reset; + dc->props = dp8393x_properties; } + +static const TypeInfo dp8393x_info = { + .name = TYPE_DP8393X, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(dp8393xState), + .class_init = dp8393x_class_init, +}; + +static void dp8393x_register_types(void) +{ + type_register_static(&dp8393x_info); +} + +void dp83932_init(NICInfo *nd, hwaddr base, hwaddr prombase, + int it_shift, int regs_offset, + qemu_irq irq, void *mem_opaque, + void (*memory_rw)(void *opaque, hwaddr addr, uint8_t *buf, + int len, int is_write)) +{ + DeviceState *dev; + SysBusDevice *s; + + qemu_check_nic_model(nd, "dp83932"); + + dev = qdev_create(NULL, TYPE_DP8393X); + qdev_set_nic_properties(dev, nd); + qdev_prop_set_int32(dev, "it_shift", it_shift); + qdev_prop_set_int32(dev, "regs_offset", regs_offset); + qdev_prop_set_ptr(dev, "mem_opaque", mem_opaque); + qdev_prop_set_ptr(dev, "memory_rw", memory_rw); + qdev_init_nofail(dev); + s = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(s, 0, base); + sysbus_mmio_map(s, 1, prombase); + sysbus_connect_irq(s, 0, irq); +} + +type_init(dp8393x_register_types) diff --git a/include/hw/net/dp8393x.h b/include/hw/net/dp8393x.h index 47eb187..178ff5c 100644 --- a/include/hw/net/dp8393x.h +++ b/include/hw/net/dp8393x.h @@ -1,6 +1,5 @@ void dp83932_init(NICInfo *nd, hwaddr base, hwaddr rombase, int it_shift, int regs_offset, - MemoryRegion *address_space, qemu_irq irq, void *mem_opaque, void (*memory_rw)(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write)); -- 1.9.1