diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/an5206.c | 10 | ||||
-rw-r--r-- | hw/apic.c | 4 | ||||
-rw-r--r-- | hw/arm11mpcore.c | 13 | ||||
-rw-r--r-- | hw/arm_pic.c | 13 | ||||
-rw-r--r-- | hw/cris_pic_cpu.c | 6 | ||||
-rw-r--r-- | hw/etraxfs.h | 1 | ||||
-rw-r--r-- | hw/fdc.c | 34 | ||||
-rw-r--r-- | hw/g364fb.c | 4 | ||||
-rw-r--r-- | hw/gus.c | 38 | ||||
-rw-r--r-- | hw/i8259.c | 397 | ||||
-rw-r--r-- | hw/ide/core.c | 32 | ||||
-rw-r--r-- | hw/ide/internal.h | 3 | ||||
-rw-r--r-- | hw/ide/isa.c | 4 | ||||
-rw-r--r-- | hw/ide/piix.c | 7 | ||||
-rw-r--r-- | hw/ide/via.c | 7 | ||||
-rw-r--r-- | hw/ioapic.h | 7 | ||||
-rw-r--r-- | hw/isa-bus.c | 45 | ||||
-rw-r--r-- | hw/isa.h | 40 | ||||
-rw-r--r-- | hw/lan9118.c | 29 | ||||
-rw-r--r-- | hw/lm32_pic.c | 4 | ||||
-rw-r--r-- | hw/lm32_pic.h | 3 | ||||
-rw-r--r-- | hw/m48t59.c | 15 | ||||
-rw-r--r-- | hw/mc146818rtc.c | 15 | ||||
-rw-r--r-- | hw/microblaze_pic_cpu.c | 6 | ||||
-rw-r--r-- | hw/ne2000-isa.c | 5 | ||||
-rw-r--r-- | hw/opencores_eth.c | 728 | ||||
-rw-r--r-- | hw/palm.c | 53 | ||||
-rw-r--r-- | hw/parallel.c | 47 | ||||
-rw-r--r-- | hw/pc.c | 40 | ||||
-rw-r--r-- | hw/pc.h | 29 | ||||
-rw-r--r-- | hw/pc_piix.c | 30 | ||||
-rw-r--r-- | hw/petalogix_ml605_mmu.c | 15 | ||||
-rw-r--r-- | hw/petalogix_s3adsp1800_mmu.c | 18 | ||||
-rw-r--r-- | hw/ppc405_boards.c | 85 | ||||
-rw-r--r-- | hw/ppc_newworld.c | 39 | ||||
-rw-r--r-- | hw/ppc_prep.c | 2 | ||||
-rw-r--r-- | hw/qdev-properties.c | 29 | ||||
-rw-r--r-- | hw/qdev.h | 3 | ||||
-rw-r--r-- | hw/qxl.c | 2 | ||||
-rw-r--r-- | hw/realview.c | 12 | ||||
-rw-r--r-- | hw/s390-virtio.c | 11 | ||||
-rw-r--r-- | hw/sb16.c | 32 | ||||
-rw-r--r-- | hw/scsi-disk.c | 2 | ||||
-rw-r--r-- | hw/shix.c | 11 | ||||
-rw-r--r-- | hw/sun4m.c | 4 | ||||
-rw-r--r-- | hw/sun4m.h | 4 | ||||
-rw-r--r-- | hw/sun4u.c | 8 | ||||
-rw-r--r-- | hw/usb-ehci.c | 4 | ||||
-rw-r--r-- | hw/usb-hid.c | 11 | ||||
-rw-r--r-- | hw/usb-hub.c | 12 | ||||
-rw-r--r-- | hw/usb-msd.c | 5 | ||||
-rw-r--r-- | hw/usb-ohci.c | 41 | ||||
-rw-r--r-- | hw/usb-uhci.c | 2 | ||||
-rw-r--r-- | hw/usb.c | 12 | ||||
-rw-r--r-- | hw/usb.h | 1 | ||||
-rw-r--r-- | hw/versatile_pci.c | 42 | ||||
-rw-r--r-- | hw/versatilepb.c | 12 | ||||
-rw-r--r-- | hw/vga-isa.c | 17 | ||||
-rw-r--r-- | hw/vga-pci.c | 2 | ||||
-rw-r--r-- | hw/vga.c | 77 | ||||
-rw-r--r-- | hw/vga_int.h | 7 | ||||
-rw-r--r-- | hw/virtio-blk.c | 2 | ||||
-rw-r--r-- | hw/vmport.c | 16 | ||||
-rw-r--r-- | hw/vmware_vga.c | 7 | ||||
-rw-r--r-- | hw/xtensa_lx60.c | 233 | ||||
-rw-r--r-- | hw/xtensa_pic.c | 49 | ||||
-rw-r--r-- | hw/xtensa_sample.c | 107 | ||||
-rw-r--r-- | hw/xtensa_sim.c (renamed from hw/xtensa_dc232b.c) | 26 |
68 files changed, 1788 insertions, 843 deletions
diff --git a/hw/an5206.c b/hw/an5206.c index 481ae60449..3fe1f00d9b 100644 --- a/hw/an5206.c +++ b/hw/an5206.c @@ -7,7 +7,6 @@ */ #include "hw.h" -#include "pc.h" #include "mcf.h" #include "boards.h" #include "loader.h" @@ -18,15 +17,6 @@ #define AN5206_MBAR_ADDR 0x10000000 #define AN5206_RAMBAR_ADDR 0x20000000 -/* Stub functions for hardware that doesn't exist. */ -void pic_info(Monitor *mon) -{ -} - -void irq_info(Monitor *mon) -{ -} - /* Board init. */ static void an5206_init(ram_addr_t ram_size, @@ -23,6 +23,7 @@ #include "host-utils.h" #include "sysbus.h" #include "trace.h" +#include "pc.h" /* APIC Local Vector Table */ #define APIC_LVT_TIMER 0 @@ -399,6 +400,9 @@ static void apic_update_irq(APICState *s) } if (apic_irq_pending(s) > 0) { cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD); + } else if (apic_accept_pic_intr(&s->busdev.qdev) && + pic_get_output(isa_pic)) { + apic_deliver_pic_intr(&s->busdev.qdev, 1); } } diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c index 7d60ef6ba8..974a0d8262 100644 --- a/hw/arm11mpcore.c +++ b/hw/arm11mpcore.c @@ -48,17 +48,6 @@ static void mpcore_rirq_set_irq(void *opaque, int irq, int level) } } -static void mpcore_rirq_map(SysBusDevice *dev, target_phys_addr_t base) -{ - mpcore_rirq_state *s = FROM_SYSBUS(mpcore_rirq_state, dev); - sysbus_mmio_map(s->priv, 0, base); -} - -static void mpcore_rirq_unmap(SysBusDevice *dev, target_phys_addr_t base) -{ - /* nothing to do */ -} - static int realview_mpcore_init(SysBusDevice *dev) { mpcore_rirq_state *s = FROM_SYSBUS(mpcore_rirq_state, dev); @@ -84,7 +73,7 @@ static int realview_mpcore_init(SysBusDevice *dev) } } qdev_init_gpio_in(&dev->qdev, mpcore_rirq_set_irq, 64); - sysbus_init_mmio_cb2(dev, mpcore_rirq_map, mpcore_rirq_unmap); + sysbus_init_mmio_region(dev, sysbus_mmio_get_region(s->priv, 0)); return 0; } diff --git a/hw/arm_pic.c b/hw/arm_pic.c index 985148a380..a2e8a73301 100644 --- a/hw/arm_pic.c +++ b/hw/arm_pic.c @@ -8,19 +8,8 @@ */ #include "hw.h" -#include "pc.h" #include "arm-misc.h" -/* Stub functions for hardware that doesn't exist. */ -void pic_info(Monitor *mon) -{ -} - -void irq_info(Monitor *mon) -{ -} - - /* Input 0 is IRQ and input 1 is FIQ. */ static void arm_pic_cpu_handler(void *opaque, int irq, int level) { @@ -39,7 +28,7 @@ static void arm_pic_cpu_handler(void *opaque, int irq, int level) cpu_reset_interrupt(env, CPU_INTERRUPT_FIQ); break; default: - hw_error("arm_pic_cpu_handler: Bad interrput line %d\n", irq); + hw_error("arm_pic_cpu_handler: Bad interrupt line %d\n", irq); } } diff --git a/hw/cris_pic_cpu.c b/hw/cris_pic_cpu.c index 7f1e4ab855..06ae484950 100644 --- a/hw/cris_pic_cpu.c +++ b/hw/cris_pic_cpu.c @@ -24,16 +24,10 @@ #include "sysbus.h" #include "hw.h" -#include "pc.h" #include "etraxfs.h" #define D(x) -void pic_info(Monitor *mon) -{} -void irq_info(Monitor *mon) -{} - static void cris_pic_cpu_handler(void *opaque, int irq, int level) { CPUState *env = (CPUState *)opaque; diff --git a/hw/etraxfs.h b/hw/etraxfs.h index 1554b0b8e8..24e8fd880b 100644 --- a/hw/etraxfs.h +++ b/hw/etraxfs.h @@ -22,6 +22,7 @@ * THE SOFTWARE. */ +#include "net.h" #include "etraxfs_dma.h" qemu_irq *cris_pic_init_cpu(CPUState *env); @@ -424,7 +424,6 @@ typedef struct FDCtrlSysBus { typedef struct FDCtrlISABus { ISADevice busdev; - MemoryRegion io_0, io_7; struct FDCtrl state; int32_t bootindexA; int32_t bootindexB; @@ -1880,32 +1879,10 @@ static int fdctrl_init_common(FDCtrl *fdctrl) return fdctrl_connect_drives(fdctrl); } -static uint32_t fdctrl_read_port_7(void *opaque, uint32_t reg) -{ - return fdctrl_read(opaque, reg + 7); -} - -static void fdctrl_write_port_7(void *opaque, uint32_t reg, uint32_t value) -{ - fdctrl_write(opaque, reg + 7, value); -} - -static const MemoryRegionPortio fdc_portio_0[] = { +static const MemoryRegionPortio fdc_portio_list[] = { { 1, 5, 1, .read = fdctrl_read, .write = fdctrl_write }, - PORTIO_END_OF_LIST() -}; - -static const MemoryRegionPortio fdc_portio_7[] = { - { 0, 1, 1, .read = fdctrl_read_port_7, .write = fdctrl_write_port_7 }, - PORTIO_END_OF_LIST() -}; - -static const MemoryRegionOps fdc_ioport_0_ops = { - .old_portio = fdc_portio_0 -}; - -static const MemoryRegionOps fdc_ioport_7_ops = { - .old_portio = fdc_portio_7 + { 7, 1, 1, .read = fdctrl_read, .write = fdctrl_write }, + PORTIO_END_OF_LIST(), }; static int isabus_fdc_init1(ISADevice *dev) @@ -1917,10 +1894,7 @@ static int isabus_fdc_init1(ISADevice *dev) int dma_chann = 2; int ret; - memory_region_init_io(&isa->io_0, &fdc_ioport_0_ops, fdctrl, "fdc", 6); - memory_region_init_io(&isa->io_7, &fdc_ioport_7_ops, fdctrl, "fdc", 1); - isa_register_ioport(dev, &isa->io_0, iobase); - isa_register_ioport(dev, &isa->io_7, iobase + 7); + isa_register_portio_list(dev, iobase, fdc_portio_list, fdctrl, "fdc"); isa_init_irq(&isa->busdev, &fdctrl->irq, isairq); fdctrl->dma_chann = dma_chann; diff --git a/hw/g364fb.c b/hw/g364fb.c index b43341f8d7..f00ee27b17 100644 --- a/hw/g364fb.c +++ b/hw/g364fb.c @@ -245,6 +245,8 @@ static void g364fb_update_display(void *opaque) { G364State *s = opaque; + qemu_flush_coalesced_mmio_buffer(); + if (s->width == 0 || s->height == 0) return; @@ -297,6 +299,8 @@ static void g364fb_screen_dump(void *opaque, const char *filename) uint8_t *data_buffer; FILE *f; + qemu_flush_coalesced_mmio_buffer(); + if (s->depth != 8) { error_report("g364: unknown guest depth %d", s->depth); return; @@ -232,6 +232,22 @@ static const VMStateDescription vmstate_gus = { } }; +static const MemoryRegionPortio gus_portio_list1[] = { + {0x000, 1, 1, .write = gus_writeb }, + {0x000, 1, 2, .write = gus_writew }, + {0x006, 10, 1, .read = gus_readb, .write = gus_writeb }, + {0x006, 10, 2, .read = gus_readw, .write = gus_writew }, + {0x100, 8, 1, .read = gus_readb, .write = gus_writeb }, + {0x100, 8, 2, .read = gus_readw, .write = gus_writew }, + PORTIO_END_OF_LIST(), +}; + +static const MemoryRegionPortio gus_portio_list2[] = { + {0, 1, 1, .read = gus_readb }, + {0, 1, 2, .read = gus_readw }, + PORTIO_END_OF_LIST(), +}; + static int gus_initfn (ISADevice *dev) { GUSState *s = DO_UPCAST (GUSState, dev, dev); @@ -262,25 +278,9 @@ static int gus_initfn (ISADevice *dev) s->samples = AUD_get_buffer_size_out (s->voice) >> s->shift; s->mixbuf = g_malloc0 (s->samples << s->shift); - register_ioport_write (s->port, 1, 1, gus_writeb, s); - register_ioport_write (s->port, 1, 2, gus_writew, s); - isa_init_ioport_range (dev, s->port, 2); - - register_ioport_read ((s->port + 0x100) & 0xf00, 1, 1, gus_readb, s); - register_ioport_read ((s->port + 0x100) & 0xf00, 1, 2, gus_readw, s); - isa_init_ioport_range (dev, (s->port + 0x100) & 0xf00, 2); - - register_ioport_write (s->port + 6, 10, 1, gus_writeb, s); - register_ioport_write (s->port + 6, 10, 2, gus_writew, s); - register_ioport_read (s->port + 6, 10, 1, gus_readb, s); - register_ioport_read (s->port + 6, 10, 2, gus_readw, s); - isa_init_ioport_range (dev, s->port + 6, 10); - - register_ioport_write (s->port + 0x100, 8, 1, gus_writeb, s); - register_ioport_write (s->port + 0x100, 8, 2, gus_writew, s); - register_ioport_read (s->port + 0x100, 8, 1, gus_readb, s); - register_ioport_read (s->port + 0x100, 8, 2, gus_readw, s); - isa_init_ioport_range (dev, s->port + 0x100, 8); + isa_register_portio_list (dev, s->port, gus_portio_list1, s, "gus"); + isa_register_portio_list (dev, (s->port + 0x100) & 0xf00, + gus_portio_list2, s, "gus"); DMA_register_channel (s->emu.gusdma, GUS_read_DMA, s); s->emu.himemaddr = s->himem; diff --git a/hw/i8259.c b/hw/i8259.c index e5323ffa4d..ab519de5d8 100644 --- a/hw/i8259.c +++ b/hw/i8259.c @@ -40,7 +40,8 @@ //#define DEBUG_IRQ_LATENCY //#define DEBUG_IRQ_COUNT -typedef struct PicState { +struct PicState { + ISADevice dev; uint8_t last_irr; /* edge detection */ uint8_t irr; /* interrupt request register */ uint8_t imr; /* interrupt mask register */ @@ -58,63 +59,39 @@ typedef struct PicState { uint8_t single_mode; /* true if slave pic is not initialized */ uint8_t elcr; /* PIIX edge/trigger selection*/ uint8_t elcr_mask; - PicState2 *pics_state; + qemu_irq int_out[1]; + uint32_t master; /* reflects /SP input pin */ + uint32_t iobase; + uint32_t elcr_addr; MemoryRegion base_io; MemoryRegion elcr_io; -} PicState; - -struct PicState2 { - /* 0 is master pic, 1 is slave pic */ - /* XXX: better separation between the two pics */ - PicState pics[2]; - qemu_irq parent_irq; - void *irq_request_opaque; }; -#if defined(DEBUG_PIC) || defined (DEBUG_IRQ_COUNT) +#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT) static int irq_level[16]; #endif #ifdef DEBUG_IRQ_COUNT static uint64_t irq_count[16]; #endif -PicState2 *isa_pic; - -/* set irq level. If an edge is detected, then the IRR is set to 1 */ -static inline void pic_set_irq1(PicState *s, int irq, int level) -{ - int mask; - mask = 1 << irq; - if (s->elcr & mask) { - /* level triggered */ - if (level) { - s->irr |= mask; - s->last_irr |= mask; - } else { - s->irr &= ~mask; - s->last_irr &= ~mask; - } - } else { - /* edge triggered */ - if (level) { - if ((s->last_irr & mask) == 0) - s->irr |= mask; - s->last_irr |= mask; - } else { - s->last_irr &= ~mask; - } - } -} +#ifdef DEBUG_IRQ_LATENCY +static int64_t irq_time[16]; +#endif +PicState *isa_pic; +static PicState *slave_pic; /* return the highest priority found in mask (highest = smallest number). Return 8 if no irq */ -static inline int get_priority(PicState *s, int mask) +static int get_priority(PicState *s, int mask) { int priority; - if (mask == 0) + + if (mask == 0) { return 8; + } priority = 0; - while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0) + while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0) { priority++; + } return priority; } @@ -125,16 +102,19 @@ static int pic_get_irq(PicState *s) mask = s->irr & ~s->imr; priority = get_priority(s, mask); - if (priority == 8) + if (priority == 8) { return -1; + } /* compute current priority. If special fully nested mode on the master, the IRQ coming from the slave is not taken into account for the priority computation. */ mask = s->isr; - if (s->special_mask) + if (s->special_mask) { mask &= ~s->imr; - if (s->special_fully_nested_mode && s == &s->pics_state->pics[0]) + } + if (s->special_fully_nested_mode && s->master) { mask &= ~(1 << 2); + } cur_priority = get_priority(s, mask); if (priority < cur_priority) { /* higher priority found: an irq should be generated */ @@ -144,116 +124,118 @@ static int pic_get_irq(PicState *s) } } -/* raise irq to CPU if necessary. must be called every time the active - irq may change */ -/* XXX: should not export it, but it is needed for an APIC kludge */ -void pic_update_irq(PicState2 *s) +/* Update INT output. Must be called every time the output may have changed. */ +static void pic_update_irq(PicState *s) { - int irq2, irq; - - /* first look at slave pic */ - irq2 = pic_get_irq(&s->pics[1]); - if (irq2 >= 0) { - /* if irq request by slave pic, signal master PIC */ - pic_set_irq1(&s->pics[0], 2, 1); - pic_set_irq1(&s->pics[0], 2, 0); - } - /* look at requested irq */ - irq = pic_get_irq(&s->pics[0]); - if (irq >= 0) { -#if defined(DEBUG_PIC) - { - int i; - for(i = 0; i < 2; i++) { - printf("pic%d: imr=%x irr=%x padd=%d\n", - i, s->pics[i].imr, s->pics[i].irr, - s->pics[i].priority_add); + int irq; - } - } - printf("pic: cpu_interrupt\n"); -#endif - qemu_irq_raise(s->parent_irq); - } - -/* all targets should do this rather than acking the IRQ in the cpu */ -#if defined(TARGET_MIPS) || defined(TARGET_PPC) || defined(TARGET_ALPHA) - else { - qemu_irq_lower(s->parent_irq); + irq = pic_get_irq(s); + if (irq >= 0) { + DPRINTF("pic%d: imr=%x irr=%x padd=%d\n", + s->master ? 0 : 1, s->imr, s->irr, s->priority_add); + qemu_irq_raise(s->int_out[0]); + } else { + qemu_irq_lower(s->int_out[0]); } -#endif } -#ifdef DEBUG_IRQ_LATENCY -int64_t irq_time[16]; -#endif - -static void i8259_set_irq(void *opaque, int irq, int level) +/* set irq level. If an edge is detected, then the IRR is set to 1 */ +static void pic_set_irq(void *opaque, int irq, int level) { - PicState2 *s = opaque; + PicState *s = opaque; + int mask = 1 << irq; +#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT) || \ + defined(DEBUG_IRQ_LATENCY) + int irq_index = s->master ? irq : irq + 8; +#endif #if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT) - if (level != irq_level[irq]) { - DPRINTF("i8259_set_irq: irq=%d level=%d\n", irq, level); - irq_level[irq] = level; + if (level != irq_level[irq_index]) { + DPRINTF("pic_set_irq: irq=%d level=%d\n", irq_index, level); + irq_level[irq_index] = level; #ifdef DEBUG_IRQ_COUNT - if (level == 1) - irq_count[irq]++; + if (level == 1) { + irq_count[irq_index]++; + } #endif } #endif #ifdef DEBUG_IRQ_LATENCY if (level) { - irq_time[irq] = qemu_get_clock_ns(vm_clock); + irq_time[irq_index] = qemu_get_clock_ns(vm_clock); } #endif - pic_set_irq1(&s->pics[irq >> 3], irq & 7, level); + + if (s->elcr & mask) { + /* level triggered */ + if (level) { + s->irr |= mask; + s->last_irr |= mask; + } else { + s->irr &= ~mask; + s->last_irr &= ~mask; + } + } else { + /* edge triggered */ + if (level) { + if ((s->last_irr & mask) == 0) { + s->irr |= mask; + } + s->last_irr |= mask; + } else { + s->last_irr &= ~mask; + } + } pic_update_irq(s); } /* acknowledge interrupt 'irq' */ -static inline void pic_intack(PicState *s, int irq) +static void pic_intack(PicState *s, int irq) { if (s->auto_eoi) { - if (s->rotate_on_auto_eoi) + if (s->rotate_on_auto_eoi) { s->priority_add = (irq + 1) & 7; + } } else { s->isr |= (1 << irq); } /* We don't clear a level sensitive interrupt here */ - if (!(s->elcr & (1 << irq))) + if (!(s->elcr & (1 << irq))) { s->irr &= ~(1 << irq); + } + pic_update_irq(s); } -int pic_read_irq(PicState2 *s) +int pic_read_irq(PicState *s) { int irq, irq2, intno; - irq = pic_get_irq(&s->pics[0]); + irq = pic_get_irq(s); if (irq >= 0) { - pic_intack(&s->pics[0], irq); if (irq == 2) { - irq2 = pic_get_irq(&s->pics[1]); + irq2 = pic_get_irq(slave_pic); if (irq2 >= 0) { - pic_intack(&s->pics[1], irq2); + pic_intack(slave_pic, irq2); } else { /* spurious IRQ on slave controller */ irq2 = 7; } - intno = s->pics[1].irq_base + irq2; -#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_LATENCY) - irq = irq2 + 8; -#endif + intno = slave_pic->irq_base + irq2; } else { - intno = s->pics[0].irq_base + irq; + intno = s->irq_base + irq; } + pic_intack(s, irq); } else { /* spurious IRQ on host controller */ irq = 7; - intno = s->pics[0].irq_base + irq; + intno = s->irq_base + irq; } - pic_update_irq(s); +#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_LATENCY) + if (irq == 2) { + irq = irq2 + 8; + } +#endif #ifdef DEBUG_IRQ_LATENCY printf("IRQ%d latency=%0.3fus\n", irq, @@ -264,10 +246,8 @@ int pic_read_irq(PicState2 *s) return intno; } -static void pic_reset(void *opaque) +static void pic_init_reset(PicState *s) { - PicState *s = opaque; - s->last_irr = 0; s->irr = 0; s->imr = 0; @@ -284,6 +264,15 @@ static void pic_reset(void *opaque) s->init4 = 0; s->single_mode = 0; /* Note: ELCR is not reset */ + pic_update_irq(s); +} + +static void pic_reset(DeviceState *dev) +{ + PicState *s = container_of(dev, PicState, dev.qdev); + + pic_init_reset(s); + s->elcr = 0; } static void pic_ioport_write(void *opaque, target_phys_addr_t addr64, @@ -297,25 +286,26 @@ static void pic_ioport_write(void *opaque, target_phys_addr_t addr64, DPRINTF("write: addr=0x%02x val=0x%02x\n", addr, val); if (addr == 0) { if (val & 0x10) { - /* init */ - pic_reset(s); - /* deassert a pending interrupt */ - qemu_irq_lower(s->pics_state->parent_irq); + pic_init_reset(s); s->init_state = 1; s->init4 = val & 1; s->single_mode = val & 2; - if (val & 0x08) + if (val & 0x08) { hw_error("level sensitive irq not supported"); + } } else if (val & 0x08) { - if (val & 0x04) + if (val & 0x04) { s->poll = 1; - if (val & 0x02) + } + if (val & 0x02) { s->read_reg_select = val & 1; - if (val & 0x40) + } + if (val & 0x40) { s->special_mask = (val >> 5) & 1; + } } else { cmd = val >> 5; - switch(cmd) { + switch (cmd) { case 0: case 4: s->rotate_on_auto_eoi = cmd >> 2; @@ -326,25 +316,26 @@ static void pic_ioport_write(void *opaque, target_phys_addr_t addr64, if (priority != 8) { irq = (priority + s->priority_add) & 7; s->isr &= ~(1 << irq); - if (cmd == 5) + if (cmd == 5) { s->priority_add = (irq + 1) & 7; - pic_update_irq(s->pics_state); + } + pic_update_irq(s); } break; case 3: irq = val & 7; s->isr &= ~(1 << irq); - pic_update_irq(s->pics_state); + pic_update_irq(s); break; case 6: s->priority_add = (val + 1) & 7; - pic_update_irq(s->pics_state); + pic_update_irq(s); break; case 7: irq = val & 7; s->isr &= ~(1 << irq); s->priority_add = (irq + 1) & 7; - pic_update_irq(s->pics_state); + pic_update_irq(s); break; default: /* no operation */ @@ -352,11 +343,11 @@ static void pic_ioport_write(void *opaque, target_phys_addr_t addr64, } } } else { - switch(s->init_state) { + switch (s->init_state) { case 0: /* normal mode */ s->imr = val; - pic_update_irq(s->pics_state); + pic_update_irq(s); break; case 1: s->irq_base = val & 0xf8; @@ -378,46 +369,28 @@ static void pic_ioport_write(void *opaque, target_phys_addr_t addr64, } } -static uint32_t pic_poll_read(PicState *s) -{ - int ret; - - ret = pic_get_irq(s); - if (ret >= 0) { - bool slave = (s == &isa_pic->pics[1]); - - if (slave) { - s->pics_state->pics[0].isr &= ~(1 << 2); - s->pics_state->pics[0].irr &= ~(1 << 2); - } - s->irr &= ~(1 << ret); - s->isr &= ~(1 << ret); - if (slave || ret != 2) - pic_update_irq(s->pics_state); - } else { - ret = 0x07; - pic_update_irq(s->pics_state); - } - - return ret; -} - -static uint64_t pic_ioport_read(void *opaque, target_phys_addr_t addr1, +static uint64_t pic_ioport_read(void *opaque, target_phys_addr_t addr, unsigned size) { PicState *s = opaque; - unsigned int addr = addr1; int ret; if (s->poll) { - ret = pic_poll_read(s); + ret = pic_get_irq(s); + if (ret >= 0) { + pic_intack(s, ret); + ret |= 0x80; + } else { + ret = 0; + } s->poll = 0; } else { if (addr == 0) { - if (s->read_reg_select) + if (s->read_reg_select) { ret = s->isr; - else + } else { ret = s->irr; + } } else { ret = s->imr; } @@ -426,19 +399,9 @@ static uint64_t pic_ioport_read(void *opaque, target_phys_addr_t addr1, return ret; } -/* memory mapped interrupt status */ -/* XXX: may be the same than pic_read_irq() */ -uint32_t pic_intack_read(PicState2 *s) +int pic_get_output(PicState *s) { - int ret; - - ret = pic_poll_read(&s->pics[0]); - if (ret == 2) - ret = pic_poll_read(&s->pics[1]) + 8; - /* Prepare for ISR read */ - s->pics[0].read_reg_select = 1; - - return ret; + return (pic_get_irq(s) >= 0); } static void elcr_ioport_write(void *opaque, target_phys_addr_t addr, @@ -460,7 +423,7 @@ static const VMStateDescription vmstate_pic = { .version_id = 1, .minimum_version_id = 1, .minimum_version_id_old = 1, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_UINT8(last_irr, PicState), VMSTATE_UINT8(irr, PicState), VMSTATE_UINT8(imr, PicState), @@ -499,19 +462,24 @@ static const MemoryRegionOps pic_elcr_ioport_ops = { }, }; -/* XXX: add generic master/slave system */ -static void pic_init1(int io_addr, int elcr_addr, PicState *s) +static int pic_initfn(ISADevice *dev) { + PicState *s = DO_UPCAST(PicState, dev, dev); + memory_region_init_io(&s->base_io, &pic_base_ioport_ops, s, "pic", 2); memory_region_init_io(&s->elcr_io, &pic_elcr_ioport_ops, s, "elcr", 1); - isa_register_ioport(NULL, &s->base_io, io_addr); - if (elcr_addr >= 0) { - isa_register_ioport(NULL, &s->elcr_io, elcr_addr); + isa_register_ioport(NULL, &s->base_io, s->iobase); + if (s->elcr_addr != -1) { + isa_register_ioport(NULL, &s->elcr_io, s->elcr_addr); } - vmstate_register(NULL, io_addr, &vmstate_pic, s); - qemu_register_reset(pic_reset, s); + qdev_init_gpio_out(&dev->qdev, s->int_out, ARRAY_SIZE(s->int_out)); + qdev_init_gpio_in(&dev->qdev, pic_set_irq, 8); + + qdev_set_legacy_instance_id(&dev->qdev, s->iobase, 1); + + return 0; } void pic_info(Monitor *mon) @@ -519,11 +487,11 @@ void pic_info(Monitor *mon) int i; PicState *s; - if (!isa_pic) + if (!isa_pic) { return; - - for(i=0;i<2;i++) { - s = &isa_pic->pics[i]; + } + for (i = 0; i < 2; i++) { + s = i == 0 ? isa_pic : slave_pic; monitor_printf(mon, "pic%d: irr=%02x imr=%02x isr=%02x hprio=%d " "irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n", i, s->irr, s->imr, s->isr, s->priority_add, @@ -543,24 +511,69 @@ void irq_info(Monitor *mon) monitor_printf(mon, "IRQ statistics:\n"); for (i = 0; i < 16; i++) { count = irq_count[i]; - if (count > 0) + if (count > 0) { monitor_printf(mon, "%2d: %" PRId64 "\n", i, count); + } } #endif } qemu_irq *i8259_init(qemu_irq parent_irq) { - PicState2 *s; - - s = g_malloc0(sizeof(PicState2)); - pic_init1(0x20, 0x4d0, &s->pics[0]); - pic_init1(0xa0, 0x4d1, &s->pics[1]); - s->pics[0].elcr_mask = 0xf8; - s->pics[1].elcr_mask = 0xde; - s->parent_irq = parent_irq; - s->pics[0].pics_state = s; - s->pics[1].pics_state = s; - isa_pic = s; - return qemu_allocate_irqs(i8259_set_irq, s, 16); + qemu_irq *irq_set; + ISADevice *dev; + int i; + + irq_set = g_malloc(ISA_NUM_IRQS * sizeof(qemu_irq)); + + dev = isa_create("isa-i8259"); + qdev_prop_set_uint32(&dev->qdev, "iobase", 0x20); + qdev_prop_set_uint32(&dev->qdev, "elcr_addr", 0x4d0); + qdev_prop_set_uint8(&dev->qdev, "elcr_mask", 0xf8); + qdev_prop_set_bit(&dev->qdev, "master", true); + qdev_init_nofail(&dev->qdev); + + qdev_connect_gpio_out(&dev->qdev, 0, parent_irq); + for (i = 0 ; i < 8; i++) { + irq_set[i] = qdev_get_gpio_in(&dev->qdev, i); + } + + isa_pic = DO_UPCAST(PicState, dev, dev); + + dev = isa_create("isa-i8259"); + qdev_prop_set_uint32(&dev->qdev, "iobase", 0xa0); + qdev_prop_set_uint32(&dev->qdev, "elcr_addr", 0x4d1); + qdev_prop_set_uint8(&dev->qdev, "elcr_mask", 0xde); + qdev_init_nofail(&dev->qdev); + + qdev_connect_gpio_out(&dev->qdev, 0, irq_set[2]); + for (i = 0 ; i < 8; i++) { + irq_set[i + 8] = qdev_get_gpio_in(&dev->qdev, i); + } + + slave_pic = DO_UPCAST(PicState, dev, dev); + + return irq_set; +} + +static ISADeviceInfo i8259_info = { + .qdev.name = "isa-i8259", + .qdev.size = sizeof(PicState), + .qdev.vmsd = &vmstate_pic, + .qdev.reset = pic_reset, + .qdev.no_user = 1, + .init = pic_initfn, + .qdev.props = (Property[]) { + DEFINE_PROP_HEX32("iobase", PicState, iobase, -1), + DEFINE_PROP_HEX32("elcr_addr", PicState, elcr_addr, -1), + DEFINE_PROP_HEX8("elcr_mask", PicState, elcr_mask, -1), + DEFINE_PROP_BIT("master", PicState, master, 0, false), + DEFINE_PROP_END_OF_LIST(), + }, +}; + +static void pic_register(void) +{ + isa_qdev_register(&i8259_info); } +device_init(pic_register) diff --git a/hw/ide/core.c b/hw/ide/core.c index b71a356f39..280a117fe2 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -25,6 +25,7 @@ #include <hw/hw.h> #include <hw/pc.h> #include <hw/pci.h> +#include <hw/isa.h> #include "qemu-error.h" #include "qemu-timer.h" #include "sysemu.h" @@ -528,6 +529,7 @@ static int ide_handle_rw_error(IDEState *s, int error, int op) s->bus->error_status = op; bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read); vm_stop(RUN_STATE_IO_ERROR); + bdrv_iostatus_set_err(s->bs, error); } else { if (op & BM_STATUS_DMA_RETRY) { dma_buf_commit(s, 0); @@ -1872,6 +1874,7 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, } ide_reset(s); + bdrv_iostatus_enable(bs); return 0; } @@ -1969,20 +1972,27 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, bus->dma = &ide_dma_nop; } -void ide_init_ioport(IDEBus *bus, int iobase, int iobase2) +static const MemoryRegionPortio ide_portio_list[] = { + { 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write }, + { 0, 2, 2, .read = ide_data_readw, .write = ide_data_writew }, + { 0, 4, 4, .read = ide_data_readl, .write = ide_data_writel }, + PORTIO_END_OF_LIST(), +}; + +static const MemoryRegionPortio ide_portio2_list[] = { + { 0, 1, 1, .read = ide_status_read, .write = ide_cmd_write }, + PORTIO_END_OF_LIST(), +}; + +void ide_init_ioport(IDEBus *bus, ISADevice *dev, int iobase, int iobase2) { - register_ioport_write(iobase, 8, 1, ide_ioport_write, bus); - register_ioport_read(iobase, 8, 1, ide_ioport_read, bus); + /* ??? Assume only ISA and PCI configurations, and that the PCI-ISA + bridge has been setup properly to always register with ISA. */ + isa_register_portio_list(dev, iobase, ide_portio_list, bus, "ide"); + if (iobase2) { - register_ioport_read(iobase2, 1, 1, ide_status_read, bus); - register_ioport_write(iobase2, 1, 1, ide_cmd_write, bus); + isa_register_portio_list(dev, iobase2, ide_portio2_list, bus, "ide"); } - - /* data ports */ - register_ioport_write(iobase, 2, 2, ide_data_writew, bus); - register_ioport_read(iobase, 2, 2, ide_data_readw, bus); - register_ioport_write(iobase, 4, 4, ide_data_writel, bus); - register_ioport_read(iobase, 4, 4, ide_data_readl, bus); } static bool is_identify_set(void *opaque, int version_id) diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 9046e96013..c39dc058f4 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -7,6 +7,7 @@ * non-internal declarations are in hw/ide.h */ #include <hw/ide.h> +#include <hw/isa.h> #include "iorange.h" #include "dma.h" #include "sysemu.h" @@ -600,7 +601,7 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, void ide_init2(IDEBus *bus, qemu_irq irq); void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1, qemu_irq irq); -void ide_init_ioport(IDEBus *bus, int iobase, int iobase2); +void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2); void ide_exec_cmd(IDEBus *bus, uint32_t val); void ide_dma_cb(void *opaque, int ret); diff --git a/hw/ide/isa.c b/hw/ide/isa.c index 28b69d2cc3..01a9e59cb9 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -66,10 +66,8 @@ static int isa_ide_initfn(ISADevice *dev) ISAIDEState *s = DO_UPCAST(ISAIDEState, dev, dev); ide_bus_new(&s->bus, &s->dev.qdev, 0); - ide_init_ioport(&s->bus, s->iobase, s->iobase2); + ide_init_ioport(&s->bus, dev, s->iobase, s->iobase2); isa_init_irq(dev, &s->irq, s->isairq); - isa_init_ioport_range(dev, s->iobase, 8); - isa_init_ioport(dev, s->iobase2); ide_init2(&s->bus, s->irq); vmstate_register(&dev->qdev, 0, &vmstate_ide_isa, s); return 0; diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 88d318127c..08cbbe2032 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -122,8 +122,7 @@ static void piix3_reset(void *opaque) } static void pci_piix_init_ports(PCIIDEState *d) { - int i; - struct { + static const struct { int iobase; int iobase2; int isairq; @@ -131,10 +130,12 @@ static void pci_piix_init_ports(PCIIDEState *d) { {0x1f0, 0x3f6, 14}, {0x170, 0x376, 15}, }; + int i; for (i = 0; i < 2; i++) { ide_bus_new(&d->bus[i], &d->dev.qdev, i); - ide_init_ioport(&d->bus[i], port_info[i].iobase, port_info[i].iobase2); + ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase, + port_info[i].iobase2); ide_init2(&d->bus[i], isa_get_irq(port_info[i].isairq)); bmdma_init(&d->bus[i], &d->bmdma[i], d); diff --git a/hw/ide/via.c b/hw/ide/via.c index dab8a39f57..098f150bb2 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -146,8 +146,7 @@ static void via_reset(void *opaque) } static void vt82c686b_init_ports(PCIIDEState *d) { - int i; - struct { + static const struct { int iobase; int iobase2; int isairq; @@ -155,10 +154,12 @@ static void vt82c686b_init_ports(PCIIDEState *d) { {0x1f0, 0x3f6, 14}, {0x170, 0x376, 15}, }; + int i; for (i = 0; i < 2; i++) { ide_bus_new(&d->bus[i], &d->dev.qdev, i); - ide_init_ioport(&d->bus[i], port_info[i].iobase, port_info[i].iobase2); + ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase, + port_info[i].iobase2); ide_init2(&d->bus[i], isa_get_irq(port_info[i].isairq)); bmdma_init(&d->bus[i], &d->bmdma[i], d); diff --git a/hw/ioapic.h b/hw/ioapic.h index cb2642ae53..86e63dac74 100644 --- a/hw/ioapic.h +++ b/hw/ioapic.h @@ -17,4 +17,11 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ +#ifndef HW_IOAPIC_H +#define HW_IOAPIC_H + +#define IOAPIC_NUM_PINS 24 + void ioapic_eoi_broadcast(int vector); + +#endif /* !HW_IOAPIC_H */ diff --git a/hw/isa-bus.c b/hw/isa-bus.c index 6c15a31fe8..7c2c2619d0 100644 --- a/hw/isa-bus.c +++ b/hw/isa-bus.c @@ -83,39 +83,32 @@ void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq) dev->nirqs++; } -static void isa_init_ioport_one(ISADevice *dev, uint16_t ioport) +static inline void isa_init_ioport(ISADevice *dev, uint16_t ioport) { - assert(dev->nioports < ARRAY_SIZE(dev->ioports)); - dev->ioports[dev->nioports++] = ioport; + if (dev && (dev->ioport_id == 0 || ioport < dev->ioport_id)) { + dev->ioport_id = ioport; + } } -static int isa_cmp_ports(const void *p1, const void *p2) +void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start) { - return *(uint16_t*)p1 - *(uint16_t*)p2; + memory_region_add_subregion(isabus->address_space_io, start, io); + isa_init_ioport(dev, start); } -void isa_init_ioport_range(ISADevice *dev, uint16_t start, uint16_t length) +void isa_register_portio_list(ISADevice *dev, uint16_t start, + const MemoryRegionPortio *pio_start, + void *opaque, const char *name) { - int i; - for (i = start; i < start + length; i++) { - isa_init_ioport_one(dev, i); - } - qsort(dev->ioports, dev->nioports, sizeof(dev->ioports[0]), isa_cmp_ports); -} + PortioList *piolist = g_new(PortioList, 1); -void isa_init_ioport(ISADevice *dev, uint16_t ioport) -{ - isa_init_ioport_range(dev, ioport, 1); -} + /* START is how we should treat DEV, regardless of the actual + contents of the portio array. This is how the old code + actually handled e.g. the FDC device. */ + isa_init_ioport(dev, start); -void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start) -{ - memory_region_add_subregion(isabus->address_space_io, start, io); - if (dev != NULL) { - assert(dev->nio < ARRAY_SIZE(dev->io)); - dev->io[dev->nio++] = io; - isa_init_ioport_range(dev, start, memory_region_size(io)); - } + portio_list_init(piolist, pio_start, opaque, name); + portio_list_add(piolist, isabus->address_space_io, start); } static int isa_qdev_init(DeviceState *qdev, DeviceInfo *base) @@ -208,8 +201,8 @@ static char *isabus_get_fw_dev_path(DeviceState *dev) int off; off = snprintf(path, sizeof(path), "%s", qdev_fw_name(dev)); - if (d->nioports) { - snprintf(path + off, sizeof(path) - off, "@%04x", d->ioports[0]); + if (d->ioport_id) { + snprintf(path + off, sizeof(path) - off, "@%04x", d->ioport_id); } return strdup(path); @@ -7,18 +7,17 @@ #include "memory.h" #include "qdev.h" +#define ISA_NUM_IRQS 16 + typedef struct ISABus ISABus; typedef struct ISADevice ISADevice; typedef struct ISADeviceInfo ISADeviceInfo; struct ISADevice { DeviceState qdev; - MemoryRegion *io[32]; uint32_t isairq[2]; - uint16_t ioports[32]; int nirqs; - int nioports; - int nio; + int ioport_id; }; typedef int (*isa_qdev_initfn)(ISADevice *dev); @@ -31,15 +30,42 @@ ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space_io); void isa_bus_irqs(qemu_irq *irqs); qemu_irq isa_get_irq(int isairq); void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq); -void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start); -void isa_init_ioport(ISADevice *dev, uint16_t ioport); -void isa_init_ioport_range(ISADevice *dev, uint16_t start, uint16_t length); void isa_qdev_register(ISADeviceInfo *info); MemoryRegion *isa_address_space(ISADevice *dev); ISADevice *isa_create(const char *name); ISADevice *isa_try_create(const char *name); ISADevice *isa_create_simple(const char *name); +/** + * isa_register_ioport: Install an I/O port region on the ISA bus. + * + * Register an I/O port region via memory_region_add_subregion + * inside the ISA I/O address space. + * + * @dev: the ISADevice against which these are registered; may be NULL. + * @io: the #MemoryRegion being registered. + * @start: the base I/O port. + */ +void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start); + +/** + * isa_register_portio_list: Initialize a set of ISA io ports + * + * Several ISA devices have many dis-joint I/O ports. Worse, these I/O + * ports can be interleaved with I/O ports from other devices. This + * function makes it easy to create multiple MemoryRegions for a single + * device and use the legacy portio routines. + * + * @dev: the ISADevice against which these are registered; may be NULL. + * @start: the base I/O port against which the portio->offset is applied. + * @portio: the ports, sorted by offset. + * @opaque: passed into the old_portio callbacks. + * @name: passed into memory_region_init_io. + */ +void isa_register_portio_list(ISADevice *dev, uint16_t start, + const MemoryRegionPortio *portio, + void *opaque, const char *name); + extern target_phys_addr_t isa_mem_base; void isa_mmio_setup(MemoryRegion *mr, target_phys_addr_t size); diff --git a/hw/lan9118.c b/hw/lan9118.c index 73a8661ca3..634b88ee14 100644 --- a/hw/lan9118.c +++ b/hw/lan9118.c @@ -152,7 +152,7 @@ typedef struct { NICState *nic; NICConf conf; qemu_irq irq; - int mmio_index; + MemoryRegion mmio; ptimer_state *timer; uint32_t irq_cfg; @@ -895,7 +895,7 @@ static void lan9118_tick(void *opaque) } static void lan9118_writel(void *opaque, target_phys_addr_t offset, - uint32_t val) + uint64_t val, unsigned size) { lan9118_state *s = (lan9118_state *)opaque; offset &= 0xff; @@ -1022,13 +1022,14 @@ static void lan9118_writel(void *opaque, target_phys_addr_t offset, break; default: - hw_error("lan9118_write: Bad reg 0x%x = %x\n", (int)offset, val); + hw_error("lan9118_write: Bad reg 0x%x = %x\n", (int)offset, (int)val); break; } lan9118_update(s); } -static uint32_t lan9118_readl(void *opaque, target_phys_addr_t offset) +static uint64_t lan9118_readl(void *opaque, target_phys_addr_t offset, + unsigned size) { lan9118_state *s = (lan9118_state *)opaque; @@ -1101,16 +1102,10 @@ static uint32_t lan9118_readl(void *opaque, target_phys_addr_t offset) return 0; } -static CPUReadMemoryFunc * const lan9118_readfn[] = { - lan9118_readl, - lan9118_readl, - lan9118_readl -}; - -static CPUWriteMemoryFunc * const lan9118_writefn[] = { - lan9118_writel, - lan9118_writel, - lan9118_writel +static const MemoryRegionOps lan9118_mem_ops = { + .read = lan9118_readl, + .write = lan9118_writel, + .endianness = DEVICE_NATIVE_ENDIAN, }; static void lan9118_cleanup(VLANClientState *nc) @@ -1135,10 +1130,8 @@ static int lan9118_init1(SysBusDevice *dev) QEMUBH *bh; int i; - s->mmio_index = cpu_register_io_memory(lan9118_readfn, - lan9118_writefn, s, - DEVICE_NATIVE_ENDIAN); - sysbus_init_mmio(dev, 0x100, s->mmio_index); + memory_region_init_io(&s->mmio, &lan9118_mem_ops, s, "lan9118-mmio", 0x100); + sysbus_init_mmio_region(dev, &s->mmio); sysbus_init_irq(dev, &s->irq); qemu_macaddr_default_if_unset(&s->conf.macaddr); diff --git a/hw/lm32_pic.c b/hw/lm32_pic.c index 02941a7d0d..8dd005077c 100644 --- a/hw/lm32_pic.c +++ b/hw/lm32_pic.c @@ -39,7 +39,7 @@ struct LM32PicState { typedef struct LM32PicState LM32PicState; static LM32PicState *pic; -void pic_info(Monitor *mon) +void lm32_do_pic_info(Monitor *mon) { if (pic == NULL) { return; @@ -49,7 +49,7 @@ void pic_info(Monitor *mon) pic->im, pic->ip, pic->irq_state); } -void irq_info(Monitor *mon) +void lm32_irq_info(Monitor *mon) { int i; uint32_t count; diff --git a/hw/lm32_pic.h b/hw/lm32_pic.h index e6479b8f63..14456f37cb 100644 --- a/hw/lm32_pic.h +++ b/hw/lm32_pic.h @@ -8,4 +8,7 @@ uint32_t lm32_pic_get_im(DeviceState *d); void lm32_pic_set_ip(DeviceState *d, uint32_t ip); void lm32_pic_set_im(DeviceState *d, uint32_t im); +void lm32_do_pic_info(Monitor *mon); +void lm32_irq_info(Monitor *mon); + #endif /* QEMU_HW_LM32_PIC_H */ diff --git a/hw/m48t59.c b/hw/m48t59.c index 0cc361eedc..f318e67919 100644 --- a/hw/m48t59.c +++ b/hw/m48t59.c @@ -73,6 +73,7 @@ struct M48t59State { typedef struct M48t59ISAState { ISADevice busdev; M48t59State state; + MemoryRegion io; } M48t59ISAState; typedef struct M48t59SysBusState { @@ -626,6 +627,15 @@ static void m48t59_reset_sysbus(DeviceState *d) m48t59_reset_common(NVRAM); } +static const MemoryRegionPortio m48t59_portio[] = { + {0, 4, 1, .read = NVRAM_readb, .write = NVRAM_writeb }, + PORTIO_END_OF_LIST(), +}; + +static const MemoryRegionOps m48t59_io_ops = { + .old_portio = m48t59_portio, +}; + /* Initialisation routine */ M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base, uint32_t io_base, uint16_t size, int type) @@ -669,10 +679,9 @@ M48t59State *m48t59_init_isa(uint32_t io_base, uint16_t size, int type) d = DO_UPCAST(M48t59ISAState, busdev, dev); s = &d->state; + memory_region_init_io(&d->io, &m48t59_io_ops, s, "m48t59", 4); if (io_base != 0) { - register_ioport_read(io_base, 0x04, 1, NVRAM_readb, s); - register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, s); - isa_init_ioport_range(dev, io_base, 4); + isa_register_ioport(dev, &d->io, io_base); } return s; diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c index feb3b25acd..2aaca2ff41 100644 --- a/hw/mc146818rtc.c +++ b/hw/mc146818rtc.c @@ -81,6 +81,7 @@ typedef struct RTCState { ISADevice dev; + MemoryRegion io; uint8_t cmos_data[128]; uint8_t cmos_index; struct tm current_tm; @@ -604,6 +605,15 @@ static void rtc_reset(void *opaque) #endif } +static const MemoryRegionPortio cmos_portio[] = { + {0, 2, 1, .read = cmos_ioport_read, .write = cmos_ioport_write }, + PORTIO_END_OF_LIST(), +}; + +static const MemoryRegionOps cmos_ops = { + .old_portio = cmos_portio +}; + static int rtc_initfn(ISADevice *dev) { RTCState *s = DO_UPCAST(RTCState, dev, dev); @@ -632,9 +642,8 @@ static int rtc_initfn(ISADevice *dev) qemu_get_clock_ns(rtc_clock) + (get_ticks_per_sec() * 99) / 100; qemu_mod_timer(s->second_timer2, s->next_second_time); - register_ioport_write(base, 2, 1, cmos_ioport_write, s); - register_ioport_read(base, 2, 1, cmos_ioport_read, s); - isa_init_ioport_range(dev, base, 2); + memory_region_init_io(&s->io, &cmos_ops, s, "rtc", 2); + isa_register_ioport(dev, &s->io, base); qdev_set_legacy_instance_id(&dev->qdev, base, 2); qemu_register_reset(rtc_reset, s); diff --git a/hw/microblaze_pic_cpu.c b/hw/microblaze_pic_cpu.c index 9ad48b4b95..8b5623ce28 100644 --- a/hw/microblaze_pic_cpu.c +++ b/hw/microblaze_pic_cpu.c @@ -23,16 +23,10 @@ */ #include "hw.h" -#include "pc.h" #include "microblaze_pic_cpu.h" #define D(x) -void pic_info(Monitor *mon) -{} -void irq_info(Monitor *mon) -{} - static void microblaze_pic_cpu_handler(void *opaque, int irq, int level) { CPUState *env = (CPUState *)opaque; diff --git a/hw/ne2000-isa.c b/hw/ne2000-isa.c index 756ed5ca46..11ffee7d7c 100644 --- a/hw/ne2000-isa.c +++ b/hw/ne2000-isa.c @@ -68,10 +68,7 @@ static int isa_ne2000_initfn(ISADevice *dev) NE2000State *s = &isa->ne2000; ne2000_setup_io(s, 0x20); - isa_init_ioport_range(dev, isa->iobase, 16); - isa_init_ioport_range(dev, isa->iobase + 0x10, 2); - isa_init_ioport(dev, isa->iobase + 0x1f); - memory_region_add_subregion(get_system_io(), isa->iobase, &s->io); + isa_register_ioport(dev, &s->io, isa->iobase); isa_init_irq(dev, &s->irq, isa->isairq); diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c new file mode 100644 index 0000000000..64b616ec1c --- /dev/null +++ b/hw/opencores_eth.c @@ -0,0 +1,728 @@ +/* + * OpenCores Ethernet MAC 10/100 + subset of + * National Semiconductors DP83848C 10/100 PHY + * + * http://opencores.org/svnget,ethmac?file=%2Ftrunk%2F%2Fdoc%2Feth_speci.pdf + * http://cache.national.com/ds/DP/DP83848C.pdf + * + * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Open Source and Linux Lab nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "hw.h" +#include "sysbus.h" +#include "net.h" +#include "sysemu.h" +#include "trace.h" + +/* RECSMALL is not used because it breaks tap networking in linux: + * incoming ARP responses are too short + */ +#undef USE_RECSMALL + +#define GET_FIELD(v, field) (((v) & (field)) >> (field ## _LBN)) +#define GET_REGBIT(s, reg, field) ((s)->regs[reg] & (reg ## _ ## field)) +#define GET_REGFIELD(s, reg, field) \ + GET_FIELD((s)->regs[reg], reg ## _ ## field) + +#define SET_FIELD(v, field, data) \ + ((v) = (((v) & ~(field)) | (((data) << (field ## _LBN)) & (field)))) +#define SET_REGFIELD(s, reg, field, data) \ + SET_FIELD((s)->regs[reg], reg ## _ ## field, data) + +/* PHY MII registers */ +enum { + MII_BMCR, + MII_BMSR, + MII_PHYIDR1, + MII_PHYIDR2, + MII_ANAR, + MII_ANLPAR, + MII_REG_MAX = 16, +}; + +typedef struct Mii { + uint16_t regs[MII_REG_MAX]; + bool link_ok; +} Mii; + +static void mii_set_link(Mii *s, bool link_ok) +{ + if (link_ok) { + s->regs[MII_BMSR] |= 0x4; + s->regs[MII_ANLPAR] |= 0x01e1; + } else { + s->regs[MII_BMSR] &= ~0x4; + s->regs[MII_ANLPAR] &= 0x01ff; + } + s->link_ok = link_ok; +} + +static void mii_reset(Mii *s) +{ + memset(s->regs, 0, sizeof(s->regs)); + s->regs[MII_BMCR] = 0x1000; + s->regs[MII_BMSR] = 0x7848; /* no ext regs */ + s->regs[MII_PHYIDR1] = 0x2000; + s->regs[MII_PHYIDR2] = 0x5c90; + s->regs[MII_ANAR] = 0x01e1; + mii_set_link(s, s->link_ok); +} + +static void mii_ro(Mii *s, uint16_t v) +{ +} + +static void mii_write_bmcr(Mii *s, uint16_t v) +{ + if (v & 0x8000) { + mii_reset(s); + } else { + s->regs[MII_BMCR] = v; + } +} + +static void mii_write_host(Mii *s, unsigned idx, uint16_t v) +{ + static void (*reg_write[MII_REG_MAX])(Mii *s, uint16_t v) = { + [MII_BMCR] = mii_write_bmcr, + [MII_BMSR] = mii_ro, + [MII_PHYIDR1] = mii_ro, + [MII_PHYIDR2] = mii_ro, + }; + + if (idx < MII_REG_MAX) { + trace_open_eth_mii_write(idx, v); + if (reg_write[idx]) { + reg_write[idx](s, v); + } else { + s->regs[idx] = v; + } + } +} + +static uint16_t mii_read_host(Mii *s, unsigned idx) +{ + trace_open_eth_mii_read(idx, s->regs[idx]); + return s->regs[idx]; +} + +/* OpenCores Ethernet registers */ +enum { + MODER, + INT_SOURCE, + INT_MASK, + IPGT, + IPGR1, + IPGR2, + PACKETLEN, + COLLCONF, + TX_BD_NUM, + CTRLMODER, + MIIMODER, + MIICOMMAND, + MIIADDRESS, + MIITX_DATA, + MIIRX_DATA, + MIISTATUS, + MAC_ADDR0, + MAC_ADDR1, + HASH0, + HASH1, + TXCTRL, + REG_MAX, +}; + +enum { + MODER_RECSMALL = 0x10000, + MODER_PAD = 0x8000, + MODER_HUGEN = 0x4000, + MODER_RST = 0x800, + MODER_LOOPBCK = 0x80, + MODER_PRO = 0x20, + MODER_IAM = 0x10, + MODER_BRO = 0x8, + MODER_TXEN = 0x2, + MODER_RXEN = 0x1, +}; + +enum { + INT_SOURCE_RXB = 0x4, + INT_SOURCE_TXB = 0x1, +}; + +enum { + PACKETLEN_MINFL = 0xffff0000, + PACKETLEN_MINFL_LBN = 16, + PACKETLEN_MAXFL = 0xffff, + PACKETLEN_MAXFL_LBN = 0, +}; + +enum { + MIICOMMAND_WCTRLDATA = 0x4, + MIICOMMAND_RSTAT = 0x2, + MIICOMMAND_SCANSTAT = 0x1, +}; + +enum { + MIIADDRESS_RGAD = 0x1f00, + MIIADDRESS_RGAD_LBN = 8, + MIIADDRESS_FIAD = 0x1f, + MIIADDRESS_FIAD_LBN = 0, +}; + +enum { + MIITX_DATA_CTRLDATA = 0xffff, + MIITX_DATA_CTRLDATA_LBN = 0, +}; + +enum { + MIIRX_DATA_PRSD = 0xffff, + MIIRX_DATA_PRSD_LBN = 0, +}; + +enum { + MIISTATUS_LINKFAIL = 0x1, + MIISTATUS_LINKFAIL_LBN = 0, +}; + +enum { + MAC_ADDR0_BYTE2 = 0xff000000, + MAC_ADDR0_BYTE2_LBN = 24, + MAC_ADDR0_BYTE3 = 0xff0000, + MAC_ADDR0_BYTE3_LBN = 16, + MAC_ADDR0_BYTE4 = 0xff00, + MAC_ADDR0_BYTE4_LBN = 8, + MAC_ADDR0_BYTE5 = 0xff, + MAC_ADDR0_BYTE5_LBN = 0, +}; + +enum { + MAC_ADDR1_BYTE0 = 0xff00, + MAC_ADDR1_BYTE0_LBN = 8, + MAC_ADDR1_BYTE1 = 0xff, + MAC_ADDR1_BYTE1_LBN = 0, +}; + +enum { + TXD_LEN = 0xffff0000, + TXD_LEN_LBN = 16, + TXD_RD = 0x8000, + TXD_IRQ = 0x4000, + TXD_WR = 0x2000, + TXD_PAD = 0x1000, + TXD_CRC = 0x800, + TXD_UR = 0x100, + TXD_RTRY = 0xf0, + TXD_RTRY_LBN = 4, + TXD_RL = 0x8, + TXD_LC = 0x4, + TXD_DF = 0x2, + TXD_CS = 0x1, +}; + +enum { + RXD_LEN = 0xffff0000, + RXD_LEN_LBN = 16, + RXD_E = 0x8000, + RXD_IRQ = 0x4000, + RXD_WRAP = 0x2000, + RXD_CF = 0x100, + RXD_M = 0x80, + RXD_OR = 0x40, + RXD_IS = 0x20, + RXD_DN = 0x10, + RXD_TL = 0x8, + RXD_SF = 0x4, + RXD_CRC = 0x2, + RXD_LC = 0x1, +}; + +typedef struct desc { + uint32_t len_flags; + uint32_t buf_ptr; +} desc; + +#define DEFAULT_PHY 1 + +typedef struct OpenEthState { + SysBusDevice dev; + NICState *nic; + NICConf conf; + MemoryRegion reg_io; + MemoryRegion desc_io; + qemu_irq irq; + + Mii mii; + uint32_t regs[REG_MAX]; + unsigned tx_desc; + unsigned rx_desc; + desc desc[128]; +} OpenEthState; + +static desc *rx_desc(OpenEthState *s) +{ + return s->desc + s->rx_desc; +} + +static desc *tx_desc(OpenEthState *s) +{ + return s->desc + s->tx_desc; +} + +static void open_eth_update_irq(OpenEthState *s, + uint32_t old, uint32_t new) +{ + if (!old != !new) { + trace_open_eth_update_irq(new); + qemu_set_irq(s->irq, new); + } +} + +static void open_eth_int_source_write(OpenEthState *s, + uint32_t val) +{ + uint32_t old_val = s->regs[INT_SOURCE]; + + s->regs[INT_SOURCE] = val; + open_eth_update_irq(s, old_val & s->regs[INT_MASK], + s->regs[INT_SOURCE] & s->regs[INT_MASK]); +} + +static void open_eth_set_link_status(VLANClientState *nc) +{ + OpenEthState *s = DO_UPCAST(NICState, nc, nc)->opaque; + + if (GET_REGBIT(s, MIICOMMAND, SCANSTAT)) { + SET_REGFIELD(s, MIISTATUS, LINKFAIL, nc->link_down); + } + mii_set_link(&s->mii, !nc->link_down); +} + +static void open_eth_reset(void *opaque) +{ + OpenEthState *s = opaque; + + memset(s->regs, 0, sizeof(s->regs)); + s->regs[MODER] = 0xa000; + s->regs[IPGT] = 0x12; + s->regs[IPGR1] = 0xc; + s->regs[IPGR2] = 0x12; + s->regs[PACKETLEN] = 0x400600; + s->regs[COLLCONF] = 0xf003f; + s->regs[TX_BD_NUM] = 0x40; + s->regs[MIIMODER] = 0x64; + + s->tx_desc = 0; + s->rx_desc = 0x40; + + mii_reset(&s->mii); + open_eth_set_link_status(&s->nic->nc); +} + +static int open_eth_can_receive(VLANClientState *nc) +{ + OpenEthState *s = DO_UPCAST(NICState, nc, nc)->opaque; + + return GET_REGBIT(s, MODER, RXEN) && + (s->regs[TX_BD_NUM] < 0x80) && + (rx_desc(s)->len_flags & RXD_E); +} + +#define POLYNOMIAL 0x04c11db6 + +/* From FreeBSD */ +/* XXX: optimize */ +static unsigned compute_mcast_idx(const uint8_t *ep) +{ + uint32_t crc; + int carry, i, j; + uint8_t b; + + crc = 0xffffffff; + for (i = 0; i < 6; i++) { + b = *ep++; + for (j = 0; j < 8; j++) { + carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); + crc <<= 1; + b >>= 1; + if (carry) { + crc = ((crc ^ POLYNOMIAL) | carry); + } + } + } + return crc >> 26; +} + +static ssize_t open_eth_receive(VLANClientState *nc, + const uint8_t *buf, size_t size) +{ + OpenEthState *s = DO_UPCAST(NICState, nc, nc)->opaque; + size_t maxfl = GET_REGFIELD(s, PACKETLEN, MAXFL); + size_t minfl = GET_REGFIELD(s, PACKETLEN, MINFL); + bool miss = true; + + trace_open_eth_receive((unsigned)size); + + if (size >= 6) { + static const uint8_t bcast_addr[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + if (memcmp(buf, bcast_addr, sizeof(bcast_addr)) == 0) { + miss = GET_REGBIT(s, MODER, BRO); + } else if ((buf[0] & 0x1) || GET_REGBIT(s, MODER, IAM)) { + unsigned mcast_idx = compute_mcast_idx(buf); + miss = !(s->regs[HASH0 + mcast_idx / 32] & + (1 << (mcast_idx % 32))); + trace_open_eth_receive_mcast( + mcast_idx, s->regs[HASH0], s->regs[HASH1]); + } else { + miss = GET_REGFIELD(s, MAC_ADDR1, BYTE0) != buf[0] || + GET_REGFIELD(s, MAC_ADDR1, BYTE1) != buf[1] || + GET_REGFIELD(s, MAC_ADDR0, BYTE2) != buf[2] || + GET_REGFIELD(s, MAC_ADDR0, BYTE3) != buf[3] || + GET_REGFIELD(s, MAC_ADDR0, BYTE4) != buf[4] || + GET_REGFIELD(s, MAC_ADDR0, BYTE5) != buf[5]; + } + } + + if (miss && !GET_REGBIT(s, MODER, PRO)) { + trace_open_eth_receive_reject(); + return size; + } + +#ifdef USE_RECSMALL + if (GET_REGBIT(s, MODER, RECSMALL) || size >= minfl) { +#else + { +#endif + desc *desc = rx_desc(s); + size_t copy_size = GET_REGBIT(s, MODER, HUGEN) ? 65536 : maxfl; + + desc->len_flags &= ~(RXD_CF | RXD_M | RXD_OR | + RXD_IS | RXD_DN | RXD_TL | RXD_SF | RXD_CRC | RXD_LC); + + if (copy_size > size) { + copy_size = size; + } + if (miss) { + desc->len_flags |= RXD_M; + } + if (size > maxfl) { + desc->len_flags |= RXD_TL; + } +#ifdef USE_RECSMALL + if (size < minfl) { + desc->len_flags |= RXD_SF; + } +#endif + + cpu_physical_memory_write(desc->buf_ptr, buf, copy_size); + + if (GET_REGBIT(s, MODER, PAD) && copy_size < minfl) { + static const uint8_t zero[65536] = {0}; + + cpu_physical_memory_write(desc->buf_ptr + copy_size, + zero, minfl - copy_size); + copy_size = minfl; + } + + SET_FIELD(desc->len_flags, RXD_LEN, copy_size); + + if ((desc->len_flags & RXD_WRAP) || s->rx_desc == 0x7f) { + s->rx_desc = s->regs[TX_BD_NUM]; + } else { + ++s->rx_desc; + } + desc->len_flags &= ~RXD_E; + + trace_open_eth_receive_desc(desc->buf_ptr, desc->len_flags); + + if (desc->len_flags & RXD_IRQ) { + open_eth_int_source_write(s, + s->regs[INT_SOURCE] | INT_SOURCE_RXB); + } + } + return size; +} + +static void open_eth_cleanup(VLANClientState *nc) +{ +} + +static NetClientInfo net_open_eth_info = { + .type = NET_CLIENT_TYPE_NIC, + .size = sizeof(NICState), + .can_receive = open_eth_can_receive, + .receive = open_eth_receive, + .cleanup = open_eth_cleanup, + .link_status_changed = open_eth_set_link_status, +}; + +static void open_eth_start_xmit(OpenEthState *s, desc *tx) +{ + uint8_t buf[65536]; + unsigned len = GET_FIELD(tx->len_flags, TXD_LEN); + unsigned tx_len = len; + + if ((tx->len_flags & TXD_PAD) && + tx_len < GET_REGFIELD(s, PACKETLEN, MINFL)) { + tx_len = GET_REGFIELD(s, PACKETLEN, MINFL); + } + if (!GET_REGBIT(s, MODER, HUGEN) && + tx_len > GET_REGFIELD(s, PACKETLEN, MAXFL)) { + tx_len = GET_REGFIELD(s, PACKETLEN, MAXFL); + } + + trace_open_eth_start_xmit(tx->buf_ptr, len, tx_len); + + if (len > tx_len) { + len = tx_len; + } + cpu_physical_memory_read(tx->buf_ptr, buf, len); + if (tx_len > len) { + memset(buf + len, 0, tx_len - len); + } + qemu_send_packet(&s->nic->nc, buf, tx_len); + + if (tx->len_flags & TXD_WR) { + s->tx_desc = 0; + } else { + ++s->tx_desc; + if (s->tx_desc >= s->regs[TX_BD_NUM]) { + s->tx_desc = 0; + } + } + tx->len_flags &= ~(TXD_RD | TXD_UR | + TXD_RTRY | TXD_RL | TXD_LC | TXD_DF | TXD_CS); + if (tx->len_flags & TXD_IRQ) { + open_eth_int_source_write(s, s->regs[INT_SOURCE] | INT_SOURCE_TXB); + } + +} + +static void open_eth_check_start_xmit(OpenEthState *s) +{ + desc *tx = tx_desc(s); + if (GET_REGBIT(s, MODER, TXEN) && s->regs[TX_BD_NUM] > 0 && + (tx->len_flags & TXD_RD) && + GET_FIELD(tx->len_flags, TXD_LEN) > 4) { + open_eth_start_xmit(s, tx); + } +} + +static uint64_t open_eth_reg_read(void *opaque, + target_phys_addr_t addr, unsigned int size) +{ + static uint32_t (*reg_read[REG_MAX])(OpenEthState *s) = { + }; + OpenEthState *s = opaque; + unsigned idx = addr / 4; + uint64_t v = 0; + + if (idx < REG_MAX) { + if (reg_read[idx]) { + v = reg_read[idx](s); + } else { + v = s->regs[idx]; + } + } + trace_open_eth_reg_read((uint32_t)addr, (uint32_t)v); + return v; +} + +static void open_eth_ro(OpenEthState *s, uint32_t val) +{ +} + +static void open_eth_moder_host_write(OpenEthState *s, uint32_t val) +{ + uint32_t set = val & ~s->regs[MODER]; + + if (set & MODER_RST) { + open_eth_reset(s); + } + + s->regs[MODER] = val; + + if (set & MODER_RXEN) { + s->rx_desc = s->regs[TX_BD_NUM]; + } + if (set & MODER_TXEN) { + s->tx_desc = 0; + open_eth_check_start_xmit(s); + } +} + +static void open_eth_int_source_host_write(OpenEthState *s, uint32_t val) +{ + uint32_t old = s->regs[INT_SOURCE]; + + s->regs[INT_SOURCE] &= ~val; + open_eth_update_irq(s, old & s->regs[INT_MASK], + s->regs[INT_SOURCE] & s->regs[INT_MASK]); +} + +static void open_eth_int_mask_host_write(OpenEthState *s, uint32_t val) +{ + uint32_t old = s->regs[INT_MASK]; + + s->regs[INT_MASK] = val; + open_eth_update_irq(s, s->regs[INT_SOURCE] & old, + s->regs[INT_SOURCE] & s->regs[INT_MASK]); +} + +static void open_eth_mii_command_host_write(OpenEthState *s, uint32_t val) +{ + unsigned fiad = GET_REGFIELD(s, MIIADDRESS, FIAD); + unsigned rgad = GET_REGFIELD(s, MIIADDRESS, RGAD); + + if (val & MIICOMMAND_WCTRLDATA) { + if (fiad == DEFAULT_PHY) { + mii_write_host(&s->mii, rgad, + GET_REGFIELD(s, MIITX_DATA, CTRLDATA)); + } + } + if (val & MIICOMMAND_RSTAT) { + if (fiad == DEFAULT_PHY) { + SET_REGFIELD(s, MIIRX_DATA, PRSD, + mii_read_host(&s->mii, rgad)); + } else { + s->regs[MIIRX_DATA] = 0xffff; + } + SET_REGFIELD(s, MIISTATUS, LINKFAIL, s->nic->nc.link_down); + } +} + +static void open_eth_mii_tx_host_write(OpenEthState *s, uint32_t val) +{ + SET_REGFIELD(s, MIITX_DATA, CTRLDATA, val); + if (GET_REGFIELD(s, MIIADDRESS, FIAD) == DEFAULT_PHY) { + mii_write_host(&s->mii, GET_REGFIELD(s, MIIADDRESS, RGAD), + GET_REGFIELD(s, MIITX_DATA, CTRLDATA)); + } +} + +static void open_eth_reg_write(void *opaque, + target_phys_addr_t addr, uint64_t val, unsigned int size) +{ + static void (*reg_write[REG_MAX])(OpenEthState *s, uint32_t val) = { + [MODER] = open_eth_moder_host_write, + [INT_SOURCE] = open_eth_int_source_host_write, + [INT_MASK] = open_eth_int_mask_host_write, + [MIICOMMAND] = open_eth_mii_command_host_write, + [MIITX_DATA] = open_eth_mii_tx_host_write, + [MIISTATUS] = open_eth_ro, + }; + OpenEthState *s = opaque; + unsigned idx = addr / 4; + + if (idx < REG_MAX) { + trace_open_eth_reg_write((uint32_t)addr, (uint32_t)val); + if (reg_write[idx]) { + reg_write[idx](s, val); + } else { + s->regs[idx] = val; + } + } +} + +static uint64_t open_eth_desc_read(void *opaque, + target_phys_addr_t addr, unsigned int size) +{ + OpenEthState *s = opaque; + uint64_t v = 0; + + addr &= 0x3ff; + memcpy(&v, (uint8_t *)s->desc + addr, size); + trace_open_eth_desc_read((uint32_t)addr, (uint32_t)v); + return v; +} + +static void open_eth_desc_write(void *opaque, + target_phys_addr_t addr, uint64_t val, unsigned int size) +{ + OpenEthState *s = opaque; + + addr &= 0x3ff; + trace_open_eth_desc_write((uint32_t)addr, (uint32_t)val); + memcpy((uint8_t *)s->desc + addr, &val, size); + open_eth_check_start_xmit(s); +} + + +static MemoryRegionOps open_eth_reg_ops = { + .read = open_eth_reg_read, + .write = open_eth_reg_write, +}; + +static MemoryRegionOps open_eth_desc_ops = { + .read = open_eth_desc_read, + .write = open_eth_desc_write, +}; + +static int sysbus_open_eth_init(SysBusDevice *dev) +{ + OpenEthState *s = DO_UPCAST(OpenEthState, dev, dev); + + memory_region_init_io(&s->reg_io, &open_eth_reg_ops, s, + "open_eth.regs", 0x54); + sysbus_init_mmio_region(dev, &s->reg_io); + + memory_region_init_io(&s->desc_io, &open_eth_desc_ops, s, + "open_eth.desc", 0x400); + sysbus_init_mmio_region(dev, &s->desc_io); + + sysbus_init_irq(dev, &s->irq); + + s->nic = qemu_new_nic(&net_open_eth_info, &s->conf, + s->dev.qdev.info->name, s->dev.qdev.id, s); + return 0; +} + +static void qdev_open_eth_reset(DeviceState *dev) +{ + OpenEthState *d = DO_UPCAST(OpenEthState, dev.qdev, dev); + open_eth_reset(d); +} + +static SysBusDeviceInfo open_eth_info = { + .qdev.name = "open_eth", + .qdev.desc = "Opencores 10/100 Mbit Ethernet", + .qdev.size = sizeof(OpenEthState), + .qdev.reset = qdev_open_eth_reset, + .init = sysbus_open_eth_init, + .qdev.props = (Property[]) { + DEFINE_NIC_PROPERTIES(OpenEthState, conf), + DEFINE_PROP_END_OF_LIST(), + } +}; + +static void open_eth_register_devices(void) +{ + sysbus_register_withprop(&open_eth_info); +} + +device_init(open_eth_register_devices) @@ -54,16 +54,12 @@ static void static_write(void *opaque, target_phys_addr_t offset, #endif } -static CPUReadMemoryFunc * const static_readfn[] = { - static_readb, - static_readh, - static_readw, -}; - -static CPUWriteMemoryFunc * const static_writefn[] = { - static_write, - static_write, - static_write, +static const MemoryRegionOps static_ops = { + .old_mmio = { + .read = { static_readb, static_readh, static_readw, }, + .write = { static_write, static_write, static_write, }, + }, + .endianness = DEVICE_NATIVE_ENDIAN, }; /* Palm Tunsgten|E support */ @@ -203,34 +199,35 @@ static void palmte_init(ram_addr_t ram_size, struct omap_mpu_state_s *cpu; int flash_size = 0x00800000; int sdram_size = palmte_binfo.ram_size; - int io; static uint32_t cs0val = 0xffffffff; static uint32_t cs1val = 0x0000e1a0; static uint32_t cs2val = 0x0000e1a0; static uint32_t cs3val = 0xe1a0e1a0; int rom_size, rom_loaded = 0; DisplayState *ds = get_displaystate(); + MemoryRegion *flash = g_new(MemoryRegion, 1); + MemoryRegion *cs = g_new(MemoryRegion, 4); cpu = omap310_mpu_init(address_space_mem, sdram_size, cpu_model); /* External Flash (EMIFS) */ - cpu_register_physical_memory(OMAP_CS0_BASE, flash_size, - qemu_ram_alloc(NULL, "palmte.flash", - flash_size) | IO_MEM_ROM); - - io = cpu_register_io_memory(static_readfn, static_writefn, &cs0val, - DEVICE_NATIVE_ENDIAN); - cpu_register_physical_memory(OMAP_CS0_BASE + flash_size, - OMAP_CS0_SIZE - flash_size, io); - io = cpu_register_io_memory(static_readfn, static_writefn, &cs1val, - DEVICE_NATIVE_ENDIAN); - cpu_register_physical_memory(OMAP_CS1_BASE, OMAP_CS1_SIZE, io); - io = cpu_register_io_memory(static_readfn, static_writefn, &cs2val, - DEVICE_NATIVE_ENDIAN); - cpu_register_physical_memory(OMAP_CS2_BASE, OMAP_CS2_SIZE, io); - io = cpu_register_io_memory(static_readfn, static_writefn, &cs3val, - DEVICE_NATIVE_ENDIAN); - cpu_register_physical_memory(OMAP_CS3_BASE, OMAP_CS3_SIZE, io); + memory_region_init_ram(flash, NULL, "palmte.flash", flash_size); + memory_region_set_readonly(flash, true); + memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE, flash); + + memory_region_init_io(&cs[0], &static_ops, &cs0val, "palmte-cs0", + OMAP_CS0_SIZE - flash_size); + memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE + flash_size, + &cs[0]); + memory_region_init_io(&cs[1], &static_ops, &cs1val, "palmte-cs1", + OMAP_CS1_SIZE); + memory_region_add_subregion(address_space_mem, OMAP_CS1_BASE, &cs[1]); + memory_region_init_io(&cs[2], &static_ops, &cs2val, "palmte-cs2", + OMAP_CS2_SIZE); + memory_region_add_subregion(address_space_mem, OMAP_CS2_BASE, &cs[2]); + memory_region_init_io(&cs[3], &static_ops, &cs3val, "palmte-cs3", + OMAP_CS3_SIZE); + memory_region_add_subregion(address_space_mem, OMAP_CS3_BASE, &cs[3]); palmte_microwire_setup(cpu); diff --git a/hw/parallel.c b/hw/parallel.c index ecbc8c3b77..8494d94f69 100644 --- a/hw/parallel.c +++ b/hw/parallel.c @@ -448,6 +448,29 @@ static void parallel_reset(void *opaque) static const int isa_parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc }; +static const MemoryRegionPortio isa_parallel_portio_hw_list[] = { + { 0, 8, 1, + .read = parallel_ioport_read_hw, + .write = parallel_ioport_write_hw }, + { 4, 1, 2, + .read = parallel_ioport_eppdata_read_hw2, + .write = parallel_ioport_eppdata_write_hw2 }, + { 4, 1, 4, + .read = parallel_ioport_eppdata_read_hw4, + .write = parallel_ioport_eppdata_write_hw4 }, + { 0x400, 8, 1, + .read = parallel_ioport_ecp_read, + .write = parallel_ioport_ecp_write }, + PORTIO_END_OF_LIST(), +}; + +static const MemoryRegionPortio isa_parallel_portio_sw_list[] = { + { 0, 8, 1, + .read = parallel_ioport_read_sw, + .write = parallel_ioport_write_sw }, + PORTIO_END_OF_LIST(), +}; + static int parallel_isa_initfn(ISADevice *dev) { static int index; @@ -478,25 +501,11 @@ static int parallel_isa_initfn(ISADevice *dev) s->status = dummy; } - if (s->hw_driver) { - register_ioport_write(base, 8, 1, parallel_ioport_write_hw, s); - register_ioport_read(base, 8, 1, parallel_ioport_read_hw, s); - isa_init_ioport_range(dev, base, 8); - - register_ioport_write(base+4, 1, 2, parallel_ioport_eppdata_write_hw2, s); - register_ioport_read(base+4, 1, 2, parallel_ioport_eppdata_read_hw2, s); - register_ioport_write(base+4, 1, 4, parallel_ioport_eppdata_write_hw4, s); - register_ioport_read(base+4, 1, 4, parallel_ioport_eppdata_read_hw4, s); - isa_init_ioport(dev, base+4); - register_ioport_write(base+0x400, 8, 1, parallel_ioport_ecp_write, s); - register_ioport_read(base+0x400, 8, 1, parallel_ioport_ecp_read, s); - isa_init_ioport_range(dev, base+0x400, 8); - } - else { - register_ioport_write(base, 8, 1, parallel_ioport_write_sw, s); - register_ioport_read(base, 8, 1, parallel_ioport_read_sw, s); - isa_init_ioport_range(dev, base, 8); - } + isa_register_portio_list(dev, base, + (s->hw_driver + ? &isa_parallel_portio_hw_list[0] + : &isa_parallel_portio_sw_list[0]), + s, "parallel"); return 0; } @@ -88,17 +88,16 @@ struct e820_table { static struct e820_table e820_table; struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX}; -void isa_irq_handler(void *opaque, int n, int level) +void gsi_handler(void *opaque, int n, int level) { - IsaIrqState *isa = (IsaIrqState *)opaque; + GSIState *s = opaque; - DPRINTF("isa_irqs: %s irq %d\n", level? "raise" : "lower", n); - if (n < 16) { - qemu_set_irq(isa->i8259[n], level); + DPRINTF("pc: %s GSI %d\n", level ? "raising" : "lowering", n); + if (n < ISA_NUM_IRQS) { + qemu_set_irq(s->i8259_irq[n], level); } - if (isa->ioapic) - qemu_set_irq(isa->ioapic[n], level); -}; + qemu_set_irq(s->ioapic_irq[n], level); +} static void ioport80_write(void *opaque, uint32_t addr, uint32_t data) { @@ -156,9 +155,6 @@ int cpu_get_pic_interrupt(CPUState *env) intno = apic_get_interrupt(env->apic_state); if (intno >= 0) { - /* set irq request if a PIC irq is still pending */ - /* XXX: improve that */ - pic_update_irq(isa_pic); return intno; } /* read the irq from the PIC */ @@ -428,6 +424,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, /* port 92 stuff: could be split off */ typedef struct Port92State { ISADevice dev; + MemoryRegion io; uint8_t outport; qemu_irq *a20_out; } Port92State; @@ -479,13 +476,22 @@ static void port92_reset(DeviceState *d) s->outport &= ~1; } +static const MemoryRegionPortio port92_portio[] = { + { 0, 1, 1, .read = port92_read, .write = port92_write }, + PORTIO_END_OF_LIST(), +}; + +static const MemoryRegionOps port92_ops = { + .old_portio = port92_portio +}; + static int port92_initfn(ISADevice *dev) { Port92State *s = DO_UPCAST(Port92State, dev, dev); - register_ioport_read(0x92, 1, 1, port92_read, s); - register_ioport_write(0x92, 1, 1, port92_write, s); - isa_init_ioport(dev, 0x92); + memory_region_init_io(&s->io, &port92_ops, s, "port92", 1); + isa_register_ioport(dev, &s->io, 0x92); + s->outport = 0; return 0; } @@ -1116,7 +1122,7 @@ static void cpu_request_exit(void *opaque, int irq, int level) } } -void pc_basic_device_init(qemu_irq *isa_irq, +void pc_basic_device_init(qemu_irq *gsi, ISADevice **rtc_state, bool no_vmport) { @@ -1135,8 +1141,8 @@ void pc_basic_device_init(qemu_irq *isa_irq, DeviceState *hpet = sysbus_try_create_simple("hpet", HPET_BASE, NULL); if (hpet) { - for (i = 0; i < 24; i++) { - sysbus_connect_irq(sysbus_from_qdev(hpet), i, isa_irq[i]); + for (i = 0; i < GSI_NUM_PINS; i++) { + sysbus_connect_irq(sysbus_from_qdev(hpet), i, gsi[i]); } rtc_irq = qdev_get_gpio_in(hpet, 0); } @@ -8,6 +8,7 @@ #include "fdc.h" #include "net.h" #include "memory.h" +#include "ioapic.h" /* PC-style peripherals (also used by other machines). */ @@ -59,26 +60,24 @@ bool parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq, /* i8259.c */ -typedef struct PicState2 PicState2; -extern PicState2 *isa_pic; -void pic_set_irq(int irq, int level); -void pic_set_irq_new(void *opaque, int irq, int level); +typedef struct PicState PicState; +extern PicState *isa_pic; qemu_irq *i8259_init(qemu_irq parent_irq); -int pic_read_irq(PicState2 *s); -void pic_update_irq(PicState2 *s); -uint32_t pic_intack_read(PicState2 *s); +int pic_read_irq(PicState *s); +int pic_get_output(PicState *s); void pic_info(Monitor *mon); void irq_info(Monitor *mon); -/* ISA */ -#define IOAPIC_NUM_PINS 0x18 +/* Global System Interrupts */ -typedef struct isa_irq_state { - qemu_irq *i8259; - qemu_irq ioapic[IOAPIC_NUM_PINS]; -} IsaIrqState; +#define GSI_NUM_PINS IOAPIC_NUM_PINS -void isa_irq_handler(void *opaque, int n, int level); +typedef struct GSIState { + qemu_irq i8259_irq[ISA_NUM_IRQS]; + qemu_irq ioapic_irq[IOAPIC_NUM_PINS]; +} GSIState; + +void gsi_handler(void *opaque, int n, int level); /* i8254.c */ @@ -141,7 +140,7 @@ void pc_memory_init(MemoryRegion *system_memory, MemoryRegion **ram_memory); qemu_irq *pc_allocate_cpu_irq(void); void pc_vga_init(PCIBus *pci_bus); -void pc_basic_device_init(qemu_irq *isa_irq, +void pc_basic_device_init(qemu_irq *gsi, ISADevice **rtc_state, bool no_vmport); void pc_init_ne2k_isa(NICInfo *nd); diff --git a/hw/pc_piix.c b/hw/pc_piix.c index ce1c87fba9..c89042f1ce 100644 --- a/hw/pc_piix.c +++ b/hw/pc_piix.c @@ -53,7 +53,7 @@ static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 }; static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 }; static const int ide_irq[MAX_IDE_BUS] = { 14, 15 }; -static void ioapic_init(IsaIrqState *isa_irq_state) +static void ioapic_init(GSIState *gsi_state) { DeviceState *dev; SysBusDevice *d; @@ -65,7 +65,7 @@ static void ioapic_init(IsaIrqState *isa_irq_state) sysbus_mmio_map(d, 0, 0xfec00000); for (i = 0; i < IOAPIC_NUM_PINS; i++) { - isa_irq_state->ioapic[i] = qdev_get_gpio_in(dev, i); + gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i); } } @@ -87,11 +87,11 @@ static void pc_init1(MemoryRegion *system_memory, PCII440FXState *i440fx_state; int piix3_devfn = -1; qemu_irq *cpu_irq; - qemu_irq *isa_irq; + qemu_irq *gsi; qemu_irq *i8259; qemu_irq *cmos_s3; qemu_irq *smi_irq; - IsaIrqState *isa_irq_state; + GSIState *gsi_state; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; BusState *idebus[MAX_IDE_BUS]; ISADevice *rtc_state; @@ -130,11 +130,11 @@ static void pc_init1(MemoryRegion *system_memory, pci_enabled ? rom_memory : system_memory, &ram_memory); } - isa_irq_state = g_malloc0(sizeof(*isa_irq_state)); - isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24); + gsi_state = g_malloc0(sizeof(*gsi_state)); + gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS); if (pci_enabled) { - pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, + pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, gsi, system_memory, system_io, ram_size, below_4g_mem_size, 0x100000000ULL - below_4g_mem_size, @@ -149,7 +149,7 @@ static void pc_init1(MemoryRegion *system_memory, isa_bus_new(NULL, system_io); no_hpet = 1; } - isa_bus_irqs(isa_irq); + isa_bus_irqs(gsi); if (!xen_enabled()) { cpu_irq = pc_allocate_cpu_irq(); @@ -158,12 +158,14 @@ static void pc_init1(MemoryRegion *system_memory, i8259 = xen_interrupt_controller_init(); } - isa_irq_state->i8259 = i8259; + for (i = 0; i < ISA_NUM_IRQS; i++) { + gsi_state->i8259_irq[i] = i8259[i]; + } if (pci_enabled) { - ioapic_init(isa_irq_state); + ioapic_init(gsi_state); } - pc_register_ferr_irq(isa_get_irq(13)); + pc_register_ferr_irq(gsi[13]); pc_vga_init(pci_enabled? pci_bus: NULL); @@ -172,7 +174,7 @@ static void pc_init1(MemoryRegion *system_memory, } /* init basic PC hardware */ - pc_basic_device_init(isa_irq, &rtc_state, xen_enabled()); + pc_basic_device_init(gsi, &rtc_state, xen_enabled()); for(i = 0; i < nb_nics; i++) { NICInfo *nd = &nd_table[i]; @@ -202,7 +204,7 @@ static void pc_init1(MemoryRegion *system_memory, } } - audio_init(isa_irq, pci_enabled ? pci_bus : NULL); + audio_init(gsi, pci_enabled ? pci_bus : NULL); pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, idebus[0], idebus[1], rtc_state); @@ -222,7 +224,7 @@ static void pc_init1(MemoryRegion *system_memory, smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1); /* TODO: Populate SPD eeprom data. */ smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, - isa_get_irq(9), *cmos_s3, *smi_irq, + gsi[9], *cmos_s3, *smi_irq, kvm_enabled()); smbus_eeprom_init(smbus, 8, NULL, 0); } diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c index 2a0f7fd031..fb4ba29bf8 100644 --- a/hw/petalogix_ml605_mmu.c +++ b/hw/petalogix_ml605_mmu.c @@ -149,8 +149,8 @@ petalogix_ml605_init(ram_addr_t ram_size, DriveInfo *dinfo; int i; target_phys_addr_t ddr_base = MEMORY_BASEADDR; - ram_addr_t phys_lmb_bram; - ram_addr_t phys_ram; + MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1); + MemoryRegion *phys_ram = g_new(MemoryRegion, 1); qemu_irq irq[32], *cpu_irq; /* init CPUs */ @@ -162,13 +162,12 @@ petalogix_ml605_init(ram_addr_t ram_size, qemu_register_reset(main_cpu_reset, env); /* Attach emulated BRAM through the LMB. */ - phys_lmb_bram = qemu_ram_alloc(NULL, "petalogix_ml605.lmb_bram", - LMB_BRAM_SIZE); - cpu_register_physical_memory(0x00000000, LMB_BRAM_SIZE, - phys_lmb_bram | IO_MEM_RAM); + memory_region_init_ram(phys_lmb_bram, NULL, "petalogix_ml605.lmb_bram", + LMB_BRAM_SIZE); + memory_region_add_subregion(address_space_mem, 0x00000000, phys_lmb_bram); - phys_ram = qemu_ram_alloc(NULL, "petalogix_ml605.ram", ram_size); - cpu_register_physical_memory(ddr_base, ram_size, phys_ram | IO_MEM_RAM); + memory_region_init_ram(phys_ram, NULL, "petalogix_ml605.ram", ram_size); + memory_region_add_subregion(address_space_mem, ddr_base, phys_ram); dinfo = drive_get(IF_PFLASH, 0, 0); /* 5th parameter 2 means bank-width diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c index 66fb96d8eb..17da2fd87c 100644 --- a/hw/petalogix_s3adsp1800_mmu.c +++ b/hw/petalogix_s3adsp1800_mmu.c @@ -35,6 +35,7 @@ #include "loader.h" #include "elf.h" #include "blockdev.h" +#include "exec-memory.h" #include "microblaze_pic_cpu.h" @@ -125,9 +126,10 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size, DriveInfo *dinfo; int i; target_phys_addr_t ddr_base = 0x90000000; - ram_addr_t phys_lmb_bram; - ram_addr_t phys_ram; + MemoryRegion *phys_lmb_bram = g_new(MemoryRegion, 1); + MemoryRegion *phys_ram = g_new(MemoryRegion, 1); qemu_irq irq[32], *cpu_irq; + MemoryRegion *sysmem = get_system_memory(); /* init CPUs */ if (cpu_model == NULL) { @@ -139,13 +141,13 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size, qemu_register_reset(main_cpu_reset, env); /* Attach emulated BRAM through the LMB. */ - phys_lmb_bram = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.lmb_bram", - LMB_BRAM_SIZE); - cpu_register_physical_memory(0x00000000, LMB_BRAM_SIZE, - phys_lmb_bram | IO_MEM_RAM); + memory_region_init_ram(phys_lmb_bram, NULL, + "petalogix_s3adsp1800.lmb_bram", LMB_BRAM_SIZE); + memory_region_add_subregion(sysmem, 0x00000000, phys_lmb_bram); - phys_ram = qemu_ram_alloc(NULL, "petalogix_s3adsp1800.ram", ram_size); - cpu_register_physical_memory(ddr_base, ram_size, phys_ram | IO_MEM_RAM); + memory_region_init_ram(phys_ram, NULL, "petalogix_s3adsp1800.ram", + ram_size); + memory_region_add_subregion(sysmem, ddr_base, phys_ram); dinfo = drive_get(IF_PFLASH, 0, 0); pflash_cfi01_register(0xa0000000, diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c index 9136288d08..672e9347ac 100644 --- a/hw/ppc405_boards.c +++ b/hw/ppc405_boards.c @@ -137,16 +137,16 @@ static void ref405ep_fpga_writel (void *opaque, ref405ep_fpga_writeb(opaque, addr + 3, value & 0xFF); } -static CPUReadMemoryFunc * const ref405ep_fpga_read[] = { - &ref405ep_fpga_readb, - &ref405ep_fpga_readw, - &ref405ep_fpga_readl, -}; - -static CPUWriteMemoryFunc * const ref405ep_fpga_write[] = { - &ref405ep_fpga_writeb, - &ref405ep_fpga_writew, - &ref405ep_fpga_writel, +static const MemoryRegionOps ref405ep_fpga_ops = { + .old_mmio = { + .read = { + ref405ep_fpga_readb, ref405ep_fpga_readw, ref405ep_fpga_readl, + }, + .write = { + ref405ep_fpga_writeb, ref405ep_fpga_writew, ref405ep_fpga_writel, + }, + }, + .endianness = DEVICE_NATIVE_ENDIAN, }; static void ref405ep_fpga_reset (void *opaque) @@ -158,16 +158,15 @@ static void ref405ep_fpga_reset (void *opaque) fpga->reg1 = 0x0F; } -static void ref405ep_fpga_init (uint32_t base) +static void ref405ep_fpga_init (MemoryRegion *sysmem, uint32_t base) { ref405ep_fpga_t *fpga; - int fpga_memory; + MemoryRegion *fpga_memory = g_new(MemoryRegion, 1); fpga = g_malloc0(sizeof(ref405ep_fpga_t)); - fpga_memory = cpu_register_io_memory(ref405ep_fpga_read, - ref405ep_fpga_write, fpga, - DEVICE_NATIVE_ENDIAN); - cpu_register_physical_memory(base, 0x00000100, fpga_memory); + memory_region_init_io(fpga_memory, &ref405ep_fpga_ops, fpga, + "fpga", 0x00000100); + memory_region_add_subregion(sysmem, base, fpga_memory); qemu_register_reset(&ref405ep_fpga_reset, fpga); } @@ -183,7 +182,8 @@ static void ref405ep_init (ram_addr_t ram_size, CPUPPCState *env; qemu_irq *pic; MemoryRegion *bios; - ram_addr_t sram_offset, bdloc; + MemoryRegion *sram = g_new(MemoryRegion, 1); + ram_addr_t bdloc; MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories)); target_phys_addr_t ram_bases[2], ram_sizes[2]; target_ulong sram_size; @@ -195,6 +195,7 @@ static void ref405ep_init (ram_addr_t ram_size, int linux_boot; int fl_idx, fl_sectors, len; DriveInfo *dinfo; + MemoryRegion *sysmem = get_system_memory(); /* XXX: fix this */ memory_region_init_ram(&ram_memories[0], NULL, "ef405ep.ram", 0x08000000); @@ -207,17 +208,12 @@ static void ref405ep_init (ram_addr_t ram_size, #ifdef DEBUG_BOARD_INIT printf("%s: register cpu\n", __func__); #endif - env = ppc405ep_init(get_system_memory(), ram_memories, ram_bases, ram_sizes, + env = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes, 33333333, &pic, kernel_filename == NULL ? 0 : 1); /* allocate SRAM */ sram_size = 512 * 1024; - sram_offset = qemu_ram_alloc(NULL, "ef405ep.sram", sram_size); -#ifdef DEBUG_BOARD_INIT - printf("%s: register SRAM at offset " RAM_ADDR_FMT "\n", - __func__, sram_offset); -#endif - cpu_register_physical_memory(0xFFF00000, sram_size, - sram_offset | IO_MEM_RAM); + memory_region_init_ram(sram, NULL, "ef405ep.sram", sram_size); + memory_region_add_subregion(sysmem, 0xFFF00000, sram); /* allocate and load BIOS */ #ifdef DEBUG_BOARD_INIT printf("%s: register BIOS\n", __func__); @@ -264,14 +260,13 @@ static void ref405ep_init (ram_addr_t ram_size, } bios_size = (bios_size + 0xfff) & ~0xfff; memory_region_set_readonly(bios, true); - memory_region_add_subregion(get_system_memory(), - (uint32_t)(-bios_size), bios); + memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios); } /* Register FPGA */ #ifdef DEBUG_BOARD_INIT printf("%s: register FPGA\n", __func__); #endif - ref405ep_fpga_init(0xF0300000); + ref405ep_fpga_init(sysmem, 0xF0300000); /* Register NVRAM */ #ifdef DEBUG_BOARD_INIT printf("%s: register NVRAM\n", __func__); @@ -469,16 +464,12 @@ static void taihu_cpld_writel (void *opaque, taihu_cpld_writeb(opaque, addr + 3, value & 0xFF); } -static CPUReadMemoryFunc * const taihu_cpld_read[] = { - &taihu_cpld_readb, - &taihu_cpld_readw, - &taihu_cpld_readl, -}; - -static CPUWriteMemoryFunc * const taihu_cpld_write[] = { - &taihu_cpld_writeb, - &taihu_cpld_writew, - &taihu_cpld_writel, +static const MemoryRegionOps taihu_cpld_ops = { + .old_mmio = { + .read = { taihu_cpld_readb, taihu_cpld_readw, taihu_cpld_readl, }, + .write = { taihu_cpld_writeb, taihu_cpld_writew, taihu_cpld_writel, }, + }, + .endianness = DEVICE_NATIVE_ENDIAN, }; static void taihu_cpld_reset (void *opaque) @@ -490,16 +481,14 @@ static void taihu_cpld_reset (void *opaque) cpld->reg1 = 0x80; } -static void taihu_cpld_init (uint32_t base) +static void taihu_cpld_init (MemoryRegion *sysmem, uint32_t base) { taihu_cpld_t *cpld; - int cpld_memory; + MemoryRegion *cpld_memory = g_new(MemoryRegion, 1); cpld = g_malloc0(sizeof(taihu_cpld_t)); - cpld_memory = cpu_register_io_memory(taihu_cpld_read, - taihu_cpld_write, cpld, - DEVICE_NATIVE_ENDIAN); - cpu_register_physical_memory(base, 0x00000100, cpld_memory); + memory_region_init_io(cpld_memory, &taihu_cpld_ops, cpld, "cpld", 0x100); + memory_region_add_subregion(sysmem, base, cpld_memory); qemu_register_reset(&taihu_cpld_reset, cpld); } @@ -512,6 +501,7 @@ static void taihu_405ep_init(ram_addr_t ram_size, { char *filename; qemu_irq *pic; + MemoryRegion *sysmem = get_system_memory(); MemoryRegion *bios; MemoryRegion *ram_memories = g_malloc(2 * sizeof(*ram_memories)); target_phys_addr_t ram_bases[2], ram_sizes[2]; @@ -535,7 +525,7 @@ static void taihu_405ep_init(ram_addr_t ram_size, #ifdef DEBUG_BOARD_INIT printf("%s: register cpu\n", __func__); #endif - ppc405ep_init(get_system_memory(), ram_memories, ram_bases, ram_sizes, + ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes, 33333333, &pic, kernel_filename == NULL ? 0 : 1); /* allocate and load BIOS */ #ifdef DEBUG_BOARD_INIT @@ -585,8 +575,7 @@ static void taihu_405ep_init(ram_addr_t ram_size, } bios_size = (bios_size + 0xfff) & ~0xfff; memory_region_set_readonly(bios, true); - memory_region_add_subregion(get_system_memory(), (uint32_t)(-bios_size), - bios); + memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios); } /* Register Linux flash */ dinfo = drive_get(IF_PFLASH, 0, fl_idx); @@ -611,7 +600,7 @@ static void taihu_405ep_init(ram_addr_t ram_size, #ifdef DEBUG_BOARD_INIT printf("%s: register CPLD\n", __func__); #endif - taihu_cpld_init(0x50100000); + taihu_cpld_init(sysmem, 0x50100000); /* Load kernel */ linux_boot = (kernel_filename != NULL); if (linux_boot) { diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index b9a50db3fa..8c84f9e9a5 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -84,12 +84,13 @@ #endif /* UniN device */ -static void unin_writel (void *opaque, target_phys_addr_t addr, uint32_t value) +static void unin_write(void *opaque, target_phys_addr_t addr, uint64_t value, + unsigned size) { - UNIN_DPRINTF("writel addr " TARGET_FMT_plx " val %x\n", addr, value); + UNIN_DPRINTF("write addr " TARGET_FMT_plx " val %"PRIx64"\n", addr, value); } -static uint32_t unin_readl (void *opaque, target_phys_addr_t addr) +static uint64_t unin_read(void *opaque, target_phys_addr_t addr, unsigned size) { uint32_t value; @@ -99,16 +100,10 @@ static uint32_t unin_readl (void *opaque, target_phys_addr_t addr) return value; } -static CPUWriteMemoryFunc * const unin_write[] = { - &unin_writel, - &unin_writel, - &unin_writel, -}; - -static CPUReadMemoryFunc * const unin_read[] = { - &unin_readl, - &unin_readl, - &unin_readl, +static const MemoryRegionOps unin_ops = { + .read = unin_read, + .write = unin_write, + .endianness = DEVICE_NATIVE_ENDIAN, }; static int fw_cfg_boot_set(void *opaque, const char *boot_device) @@ -138,9 +133,9 @@ static void ppc_core99_init (ram_addr_t ram_size, CPUState *env = NULL; char *filename; qemu_irq *pic, **openpic_irqs; - int unin_memory; + MemoryRegion *unin_memory = g_new(MemoryRegion, 1); int linux_boot, i; - ram_addr_t ram_offset, bios_offset; + MemoryRegion *ram = g_new(MemoryRegion, 1), *bios = g_new(MemoryRegion, 1); target_phys_addr_t kernel_base, initrd_base, cmdline_base = 0; long kernel_size, initrd_size; PCIBus *pci_bus; @@ -176,15 +171,16 @@ static void ppc_core99_init (ram_addr_t ram_size, } /* allocate RAM */ - ram_offset = qemu_ram_alloc(NULL, "ppc_core99.ram", ram_size); - cpu_register_physical_memory(0, ram_size, ram_offset); + memory_region_init_ram(ram, NULL, "ppc_core99.ram", ram_size); + memory_region_add_subregion(get_system_memory(), 0, ram); /* allocate and load BIOS */ - bios_offset = qemu_ram_alloc(NULL, "ppc_core99.bios", BIOS_SIZE); + memory_region_init_ram(bios, NULL, "ppc_core99.bios", BIOS_SIZE); if (bios_name == NULL) bios_name = PROM_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - cpu_register_physical_memory(PROM_ADDR, BIOS_SIZE, bios_offset | IO_MEM_ROM); + memory_region_set_readonly(bios, true); + memory_region_add_subregion(get_system_memory(), PROM_ADDR, bios); /* Load OpenBIOS (ELF) */ if (filename) { @@ -267,9 +263,8 @@ static void ppc_core99_init (ram_addr_t ram_size, isa_mmio_init(0xf2000000, 0x00800000); /* UniN init */ - unin_memory = cpu_register_io_memory(unin_read, unin_write, NULL, - DEVICE_NATIVE_ENDIAN); - cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory); + memory_region_init_io(unin_memory, &unin_ops, NULL, "unin", 0x1000); + memory_region_add_subregion(get_system_memory(), 0xf8000000, unin_memory); openpic_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); openpic_irqs[0] = diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index d26049b1d1..6427baa562 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -130,7 +130,7 @@ static inline uint32_t _PPC_intack_read(target_phys_addr_t addr) uint32_t retval = 0; if ((addr & 0xf) == 0) - retval = pic_intack_read(isa_pic); + retval = pic_read_irq(isa_pic); #if 0 printf("%s: 0x" TARGET_FMT_plx " <= %08" PRIx32 "\n", __func__, addr, retval); diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index e0e54aa857..f0b811c806 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -93,6 +93,35 @@ PropertyInfo qdev_prop_uint8 = { .print = print_uint8, }; +/* --- 8bit hex value --- */ + +static int parse_hex8(DeviceState *dev, Property *prop, const char *str) +{ + uint8_t *ptr = qdev_get_prop_ptr(dev, prop); + char *end; + + *ptr = strtoul(str, &end, 16); + if ((*end != '\0') || (end == str)) { + return -EINVAL; + } + + return 0; +} + +static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len) +{ + uint8_t *ptr = qdev_get_prop_ptr(dev, prop); + return snprintf(dest, len, "0x%" PRIx8, *ptr); +} + +PropertyInfo qdev_prop_hex8 = { + .name = "hex8", + .type = PROP_TYPE_UINT8, + .size = sizeof(uint8_t), + .parse = parse_hex8, + .print = print_hex8, +}; + /* --- 16bit integer --- */ static int parse_uint16(DeviceState *dev, Property *prop, const char *str) @@ -224,6 +224,7 @@ extern PropertyInfo qdev_prop_uint16; extern PropertyInfo qdev_prop_uint32; extern PropertyInfo qdev_prop_int32; extern PropertyInfo qdev_prop_uint64; +extern PropertyInfo qdev_prop_hex8; extern PropertyInfo qdev_prop_hex32; extern PropertyInfo qdev_prop_hex64; extern PropertyInfo qdev_prop_string; @@ -267,6 +268,8 @@ extern PropertyInfo qdev_prop_pci_devfn; DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_int32, int32_t) #define DEFINE_PROP_UINT64(_n, _s, _f, _d) \ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t) +#define DEFINE_PROP_HEX8(_n, _s, _f, _d) \ + DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex8, uint8_t) #define DEFINE_PROP_HEX32(_n, _s, _f, _d) \ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex32, uint32_t) #define DEFINE_PROP_HEX64(_n, _s, _f, _d) \ @@ -1601,7 +1601,7 @@ static int qxl_init_primary(PCIDevice *dev) ram_size = 32 * 1024 * 1024; } vga_common_init(vga, ram_size); - vga_init(vga, pci_address_space(dev)); + vga_init(vga, pci_address_space(dev), pci_address_space_io(dev), false); register_ioport_write(0x3c0, 16, 1, qxl_vga_ioport_write, vga); register_ioport_write(0x3b4, 2, 1, qxl_vga_ioport_write, vga); register_ioport_write(0x3d4, 2, 1, qxl_vga_ioport_write, vga); diff --git a/hw/realview.c b/hw/realview.c index 549bb150c6..11ffb8a824 100644 --- a/hw/realview.c +++ b/hw/realview.c @@ -272,8 +272,16 @@ static void realview_init(ram_addr_t ram_size, sysbus_create_simple("pl031", 0x10017000, pic[10]); if (!is_pb) { - dev = sysbus_create_varargs("realview_pci", 0x60000000, - pic[48], pic[49], pic[50], pic[51], NULL); + dev = qdev_create(NULL, "realview_pci"); + busdev = sysbus_from_qdev(dev); + qdev_init_nofail(dev); + sysbus_mmio_map(busdev, 0, 0x61000000); /* PCI self-config */ + sysbus_mmio_map(busdev, 1, 0x62000000); /* PCI config */ + sysbus_mmio_map(busdev, 2, 0x63000000); /* PCI I/O */ + sysbus_connect_irq(busdev, 0, pic[48]); + sysbus_connect_irq(busdev, 1, pic[49]); + sysbus_connect_irq(busdev, 2, pic[50]); + sysbus_connect_irq(busdev, 3, pic[51]); pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci"); if (usb_enabled) { usb_ohci_init_pci(pci_bus, -1); diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index acbf02604b..778cffe39c 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -62,17 +62,6 @@ static VirtIOS390Bus *s390_bus; static CPUState **ipi_states; -void irq_info(Monitor *mon); -void pic_info(Monitor *mon); - -void irq_info(Monitor *mon) -{ -} - -void pic_info(Monitor *mon) -{ -} - CPUState *s390_cpu_addr2state(uint16_t cpu_addr) { if (cpu_addr >= smp_cpus) { @@ -1341,12 +1341,21 @@ static const VMStateDescription vmstate_sb16 = { } }; +static const MemoryRegionPortio sb16_ioport_list[] = { + { 4, 1, 1, .write = mixer_write_indexb }, + { 4, 1, 2, .write = mixer_write_indexw }, + { 5, 1, 1, .read = mixer_read, .write = mixer_write_datab }, + { 6, 1, 1, .read = dsp_read, .write = dsp_write }, + { 10, 1, 1, .read = dsp_read }, + { 12, 1, 1, .write = dsp_write }, + { 12, 4, 1, .read = dsp_read }, + PORTIO_END_OF_LIST(), +}; + + static int sb16_initfn (ISADevice *dev) { - static const uint8_t dsp_write_ports[] = {0x6, 0xc}; - static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf}; SB16State *s; - int i; s = DO_UPCAST (SB16State, dev, dev); @@ -1366,22 +1375,7 @@ static int sb16_initfn (ISADevice *dev) dolog ("warning: Could not create auxiliary timer\n"); } - for (i = 0; i < ARRAY_SIZE (dsp_write_ports); i++) { - register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s); - isa_init_ioport (dev, s->port + dsp_write_ports[i]); - } - - for (i = 0; i < ARRAY_SIZE (dsp_read_ports); i++) { - register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s); - isa_init_ioport (dev, s->port + dsp_read_ports[i]); - } - - register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s); - register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s); - isa_init_ioport (dev, s->port + 0x4); - register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s); - register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s); - isa_init_ioport (dev, s->port + 0x5); + isa_register_portio_list (dev, s->port, sb16_ioport_list, s, "sb16"); DMA_register_channel (s->hdma, SB_read_DMA, s); DMA_register_channel (s->dma, SB_read_DMA, s); diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 4f681ef092..69095780ac 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -228,6 +228,7 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, int type) bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read); vm_stop(RUN_STATE_IO_ERROR); + bdrv_iostatus_set_err(s->bs, error); } else { switch (error) { case ENOMEM: @@ -1260,6 +1261,7 @@ static int scsi_initfn(SCSIDevice *dev, uint8_t scsi_type) s->qdev.type = scsi_type; qemu_add_vm_change_state_handler(scsi_dma_restart_cb, s); + bdrv_iostatus_enable(s->bs); add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, ",0"); return 0; } @@ -28,7 +28,6 @@ More information in target-sh4/README.sh4 */ #include "hw.h" -#include "pc.h" #include "sh.h" #include "sysemu.h" #include "boards.h" @@ -37,16 +36,6 @@ #define BIOS_FILENAME "shix_bios.bin" #define BIOS_ADDRESS 0xA0000000 -void irq_info(Monitor *mon) -{ - /* XXXXX */ -} - -void pic_info(Monitor *mon) -{ - /* XXXXX */ -} - static void shix_init(ram_addr_t ram_size, const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, diff --git a/hw/sun4m.c b/hw/sun4m.c index dcaed38773..71bf648e69 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -216,13 +216,13 @@ static void nvram_init(M48t59State *nvram, uint8_t *macaddr, static DeviceState *slavio_intctl; -void pic_info(Monitor *mon) +void sun4m_pic_info(Monitor *mon) { if (slavio_intctl) slavio_pic_info(mon, slavio_intctl); } -void irq_info(Monitor *mon) +void sun4m_irq_info(Monitor *mon) { if (slavio_intctl) slavio_irq_info(mon, slavio_intctl); diff --git a/hw/sun4m.h b/hw/sun4m.h index ce97ee5a79..504c3af413 100644 --- a/hw/sun4m.h +++ b/hw/sun4m.h @@ -30,6 +30,10 @@ void slavio_irq_info(Monitor *mon, DeviceState *dev); void sun4c_pic_info(Monitor *mon, void *opaque); void sun4c_irq_info(Monitor *mon, void *opaque); +/* sun4m.c */ +void sun4m_pic_info(Monitor *mon); +void sun4m_irq_info(Monitor *mon); + /* sparc32_dma.c */ #include "sparc32_dma.h" diff --git a/hw/sun4u.c b/hw/sun4u.c index 88c633d491..96fc3d0488 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -243,14 +243,6 @@ static unsigned long sun4u_load_kernel(const char *kernel_filename, return kernel_size; } -void pic_info(Monitor *mon) -{ -} - -void irq_info(Monitor *mon) -{ -} - void cpu_check_irqs(CPUState *env) { uint32_t pil = env->pil_in | diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c index 27376a2351..bd374c1de6 100644 --- a/hw/usb-ehci.c +++ b/hw/usb-ehci.c @@ -880,6 +880,7 @@ static void ehci_reset(void *opaque) } if (devs[i] && devs[i]->attached) { usb_attach(&s->ports[i]); + usb_send_msg(devs[i], USB_MSG_RESET); } } ehci_queues_rip_all(s); @@ -978,8 +979,7 @@ static void handle_port_status_write(EHCIState *s, int port, uint32_t val) if (!(val & PORTSC_PRESET) &&(*portsc & PORTSC_PRESET)) { trace_usb_ehci_port_reset(port, 0); if (dev && dev->attached) { - usb_attach(&s->ports[port]); - usb_send_msg(dev, USB_MSG_RESET); + usb_reset(&s->ports[port]); *portsc &= ~PORTSC_CSC; } diff --git a/hw/usb-hid.c b/hw/usb-hid.c index ba79466401..a110c74dda 100644 --- a/hw/usb-hid.c +++ b/hw/usb-hid.c @@ -527,10 +527,21 @@ static int usb_keyboard_initfn(USBDevice *dev) return usb_hid_initfn(dev, HID_KEYBOARD); } +static int usb_ptr_post_load(void *opaque, int version_id) +{ + USBHIDState *s = opaque; + + if (s->dev.remote_wakeup) { + hid_pointer_activate(&s->hid); + } + return 0; +} + static const VMStateDescription vmstate_usb_ptr = { .name = "usb-ptr", .version_id = 1, .minimum_version_id = 1, + .post_load = usb_ptr_post_load, .fields = (VMStateField []) { VMSTATE_USB_DEVICE(dev, USBHIDState), VMSTATE_HID_POINTER_DEVICE(hid, USBHIDState), diff --git a/hw/usb-hub.c b/hw/usb-hub.c index 286e3ad85d..09c65160c2 100644 --- a/hw/usb-hub.c +++ b/hw/usb-hub.c @@ -207,10 +207,14 @@ static void usb_hub_complete(USBPort *port, USBPacket *packet) /* * Just pass it along upstream for now. * - * If we ever inplement usb 2.0 split transactions this will + * If we ever implement usb 2.0 split transactions this will * become a little more complicated ... + * + * Can't use usb_packet_complete() here because packet->owner is + * cleared already, go call the ->complete() callback directly + * instead. */ - usb_packet_complete(&s->dev, packet); + s->dev.port->ops->complete(s->dev.port, packet); } static void usb_hub_handle_reset(USBDevice *dev) @@ -289,7 +293,7 @@ static int usb_hub_handle_control(USBDevice *dev, USBPacket *p, port->wPortStatus |= PORT_STAT_SUSPEND; break; case PORT_RESET: - if (dev) { + if (dev && dev->attached) { usb_send_msg(dev, USB_MSG_RESET); port->wPortChange |= PORT_STAT_C_RESET; /* set enable bit */ @@ -429,7 +433,7 @@ static int usb_hub_broadcast_packet(USBHubState *s, USBPacket *p) for(i = 0; i < NUM_PORTS; i++) { port = &s->ports[i]; dev = port->port.dev; - if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) { + if (dev && dev->attached && (port->wPortStatus & PORT_STAT_ENABLE)) { ret = usb_handle_packet(dev, p); if (ret != USB_RET_NODEV) { return ret; diff --git a/hw/usb-msd.c b/hw/usb-msd.c index e92434cc94..08d2d2ac77 100644 --- a/hw/usb-msd.c +++ b/hw/usb-msd.c @@ -325,7 +325,10 @@ static int usb_msd_handle_control(USBDevice *dev, USBPacket *p, static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p) { MSDState *s = DO_UPCAST(MSDState, dev, dev); - scsi_req_cancel(s->req); + + if (s->req) { + scsi_req_cancel(s->req); + } } static int usb_msd_handle_data(USBDevice *dev, USBPacket *p) diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c index c3be65a2e9..c2981c59a4 100644 --- a/hw/usb-ohci.c +++ b/hw/usb-ohci.c @@ -150,7 +150,7 @@ static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev); #define OHCI_TD_DI_SHIFT 21 #define OHCI_TD_DI_MASK (7<<OHCI_TD_DI_SHIFT) #define OHCI_TD_T0 (1<<24) -#define OHCI_TD_T1 (1<<24) +#define OHCI_TD_T1 (1<<25) #define OHCI_TD_EC_SHIFT 26 #define OHCI_TD_EC_MASK (3<<OHCI_TD_EC_SHIFT) #define OHCI_TD_CC_SHIFT 28 @@ -449,7 +449,7 @@ static void ohci_reset(void *opaque) port = &ohci->rhport[i]; port->ctrl = 0; if (port->port.dev && port->port.dev->attached) { - usb_attach(&port->port); + usb_reset(&port->port); } } if (ohci->async_td) { @@ -872,7 +872,7 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) { int dir; - size_t len = 0; + size_t len = 0, pktlen = 0; #ifdef DEBUG_PACKET const char *str = NULL; #endif @@ -940,20 +940,30 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) len = (td.be - td.cbp) + 1; } - if (len && dir != OHCI_TD_DIR_IN && !completion) { - ohci_copy_td(ohci, &td, ohci->usb_buf, len, 0); + pktlen = len; + if (len && dir != OHCI_TD_DIR_IN) { + /* The endpoint may not allow us to transfer it all now */ + pktlen = (ed->flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT; + if (pktlen > len) { + pktlen = len; + } + if (!completion) { + ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen, 0); + } } } flag_r = (td.flags & OHCI_TD_R) != 0; #ifdef DEBUG_PACKET - DPRINTF(" TD @ 0x%.8x %" PRId64 " bytes %s r=%d cbp=0x%.8x be=0x%.8x\n", - addr, (int64_t)len, str, flag_r, td.cbp, td.be); + DPRINTF(" TD @ 0x%.8x %" PRId64 " of %" PRId64 + " bytes %s r=%d cbp=0x%.8x be=0x%.8x\n", + addr, (int64_t)pktlen, (int64_t)len, str, flag_r, td.cbp, td.be); - if (len > 0 && dir != OHCI_TD_DIR_IN) { + if (pktlen > 0 && dir != OHCI_TD_DIR_IN) { DPRINTF(" data:"); - for (i = 0; i < len; i++) + for (i = 0; i < pktlen; i++) { printf(" %.2x", ohci->usb_buf[i]); + } DPRINTF("\n"); } #endif @@ -982,7 +992,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) usb_packet_setup(&ohci->usb_packet, pid, OHCI_BM(ed->flags, ED_FA), OHCI_BM(ed->flags, ED_EN)); - usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len); + usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, pktlen); ret = usb_handle_packet(dev, &ohci->usb_packet); if (ret != USB_RET_NODEV) break; @@ -1005,12 +1015,12 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) DPRINTF("\n"); #endif } else { - ret = len; + ret = pktlen; } } /* Writeback */ - if (ret == len || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) { + if (ret == pktlen || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) { /* Transmission succeeded. */ if (ret == len) { td.cbp = 0; @@ -1026,6 +1036,12 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR); OHCI_SET_BM(td.flags, TD_EC, 0); + if ((dir != OHCI_TD_DIR_IN) && (ret != len)) { + /* Partial packet transfer: TD not ready to retire yet */ + goto exit_no_retire; + } + + /* Setting ED_C is part of the TD retirement process */ ed->head &= ~OHCI_ED_C; if (td.flags & OHCI_TD_T0) ed->head |= OHCI_ED_C; @@ -1066,6 +1082,7 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) i = OHCI_BM(td.flags, TD_DI); if (i < ohci->done_count) ohci->done_count = i; +exit_no_retire: ohci_put_td(ohci, addr, &td); return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR; } diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c index 17992cf003..171d7870b7 100644 --- a/hw/usb-uhci.c +++ b/hw/usb-uhci.c @@ -341,7 +341,7 @@ static void uhci_reset(void *opaque) port = &s->ports[i]; port->ctrl = 0x0080; if (port->port.dev && port->port.dev->attached) { - usb_attach(&port->port); + usb_reset(&port->port); } } @@ -33,6 +33,7 @@ void usb_attach(USBPort *port) assert(dev != NULL); assert(dev->attached); + assert(dev->state == USB_STATE_NOTATTACHED); port->ops->attach(port); usb_send_msg(dev, USB_MSG_ATTACH); } @@ -42,10 +43,21 @@ void usb_detach(USBPort *port) USBDevice *dev = port->dev; assert(dev != NULL); + assert(dev->state != USB_STATE_NOTATTACHED); port->ops->detach(port); usb_send_msg(dev, USB_MSG_DETACH); } +void usb_reset(USBPort *port) +{ + USBDevice *dev = port->dev; + + assert(dev != NULL); + usb_detach(port); + usb_attach(port); + usb_send_msg(dev, USB_MSG_RESET); +} + void usb_wakeup(USBDevice *dev) { if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) { @@ -306,6 +306,7 @@ void usb_cancel_packet(USBPacket * p); void usb_attach(USBPort *port); void usb_detach(USBPort *port); +void usb_reset(USBPort *port); void usb_wakeup(USBDevice *dev); int usb_generic_handle_packet(USBDevice *s, USBPacket *p); void usb_generic_async_ctrl_complete(USBDevice *s, USBPacket *p); diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c index 98e56f1610..8a88696f2c 100644 --- a/hw/versatile_pci.c +++ b/hw/versatile_pci.c @@ -58,38 +58,6 @@ static void pci_vpb_set_irq(void *opaque, int irq_num, int level) qemu_set_irq(pic[irq_num], level); } - -static void pci_vpb_map(SysBusDevice *dev, target_phys_addr_t base) -{ - PCIVPBState *s = (PCIVPBState *)dev; - /* Selfconfig area. */ - memory_region_add_subregion(get_system_memory(), base + 0x01000000, - &s->mem_config); - /* Normal config area. */ - memory_region_add_subregion(get_system_memory(), base + 0x02000000, - &s->mem_config2); - - if (s->realview) { - /* IO memory area. */ - memory_region_add_subregion(get_system_memory(), base + 0x03000000, - &s->isa); - } -} - -static void pci_vpb_unmap(SysBusDevice *dev, target_phys_addr_t base) -{ - PCIVPBState *s = (PCIVPBState *)dev; - /* Selfconfig area. */ - memory_region_del_subregion(get_system_memory(), &s->mem_config); - /* Normal config area. */ - memory_region_del_subregion(get_system_memory(), &s->mem_config2); - - if (s->realview) { - /* IO memory area. */ - memory_region_del_subregion(get_system_memory(), &s->isa); - } -} - static int pci_vpb_init(SysBusDevice *dev) { PCIVPBState *s = FROM_SYSBUS(PCIVPBState, dev); @@ -106,16 +74,22 @@ static int pci_vpb_init(SysBusDevice *dev) /* ??? Register memory space. */ + /* Our memory regions are: + * 0 : PCI self config window + * 1 : PCI config window + * 2 : PCI IO window (realview_pci only) + */ memory_region_init_io(&s->mem_config, &pci_vpb_config_ops, bus, "pci-vpb-selfconfig", 0x1000000); + sysbus_init_mmio_region(dev, &s->mem_config); memory_region_init_io(&s->mem_config2, &pci_vpb_config_ops, bus, "pci-vpb-config", 0x1000000); + sysbus_init_mmio_region(dev, &s->mem_config2); if (s->realview) { isa_mmio_setup(&s->isa, 0x0100000); + sysbus_init_mmio_region(dev, &s->isa); } - sysbus_init_mmio_cb2(dev, pci_vpb_map, pci_vpb_unmap); - pci_create_simple(bus, -1, "versatile_pci_host"); return 0; } diff --git a/hw/versatilepb.c b/hw/versatilepb.c index 49f8f5fc56..68402cc479 100644 --- a/hw/versatilepb.c +++ b/hw/versatilepb.c @@ -181,6 +181,7 @@ static void versatile_init(ram_addr_t ram_size, qemu_irq pic[32]; qemu_irq sic[32]; DeviceState *dev, *sysctl; + SysBusDevice *busdev; PCIBus *pci_bus; NICInfo *nd; int n; @@ -219,8 +220,15 @@ static void versatile_init(ram_addr_t ram_size, sysbus_create_simple("pl050_keyboard", 0x10006000, sic[3]); sysbus_create_simple("pl050_mouse", 0x10007000, sic[4]); - dev = sysbus_create_varargs("versatile_pci", 0x40000000, - sic[27], sic[28], sic[29], sic[30], NULL); + dev = qdev_create(NULL, "versatile_pci"); + busdev = sysbus_from_qdev(dev); + qdev_init_nofail(dev); + sysbus_mmio_map(busdev, 0, 0x41000000); /* PCI self-config */ + sysbus_mmio_map(busdev, 1, 0x42000000); /* PCI config */ + sysbus_connect_irq(busdev, 0, sic[27]); + sysbus_connect_irq(busdev, 1, sic[28]); + sysbus_connect_irq(busdev, 2, sic[29]); + sysbus_connect_irq(busdev, 3, sic[30]); pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci"); /* The Versatile PCI bridge does not provide access to PCI IO space, diff --git a/hw/vga-isa.c b/hw/vga-isa.c index 6b5c8ed970..4825313f67 100644 --- a/hw/vga-isa.c +++ b/hw/vga-isa.c @@ -47,24 +47,19 @@ static int vga_initfn(ISADevice *dev) ISAVGAState *d = DO_UPCAST(ISAVGAState, dev, dev); VGACommonState *s = &d->state; MemoryRegion *vga_io_memory; + const MemoryRegionPortio *vga_ports, *vbe_ports; vga_common_init(s, VGA_RAM_SIZE); s->legacy_address_space = isa_address_space(dev); - vga_io_memory = vga_init_io(s); + vga_io_memory = vga_init_io(s, &vga_ports, &vbe_ports); + isa_register_portio_list(dev, 0x3b0, vga_ports, s, "vga"); + if (vbe_ports) { + isa_register_portio_list(dev, 0x1ce, vbe_ports, s, "vbe"); + } memory_region_add_subregion_overlap(isa_address_space(dev), isa_mem_base + 0x000a0000, vga_io_memory, 1); memory_region_set_coalescing(vga_io_memory); - isa_init_ioport(dev, 0x3c0); - isa_init_ioport(dev, 0x3b4); - isa_init_ioport(dev, 0x3ba); - isa_init_ioport(dev, 0x3da); - isa_init_ioport(dev, 0x3c0); -#ifdef CONFIG_BOCHS_VBE - isa_init_ioport(dev, 0x1ce); - isa_init_ioport(dev, 0x1cf); - isa_init_ioport(dev, 0x1d0); -#endif /* CONFIG_BOCHS_VBE */ s->ds = graphic_console_init(s->update, s->invalidate, s->screen_dump, s->text_update, s); diff --git a/hw/vga-pci.c b/hw/vga-pci.c index 3c8bcb00b7..14bfadbfcf 100644 --- a/hw/vga-pci.c +++ b/hw/vga-pci.c @@ -54,7 +54,7 @@ static int pci_vga_initfn(PCIDevice *dev) // vga + console init vga_common_init(s, VGA_RAM_SIZE); - vga_init(s, pci_address_space(dev)); + vga_init(s, pci_address_space(dev), pci_address_space_io(dev), true); s->ds = graphic_console_init(s->update, s->invalidate, s->screen_dump, s->text_update, s); @@ -1838,6 +1838,8 @@ static void vga_update_display(void *opaque) VGACommonState *s = opaque; int full_update, graphic_mode; + qemu_flush_coalesced_mmio_buffer(); + if (ds_get_bits_per_pixel(s->ds) == 0) { /* nothing to do */ } else { @@ -1958,6 +1960,8 @@ static void vga_update_text(void *opaque, console_ch_t *chardata) char msg_buffer[80]; int full_update = 0; + qemu_flush_coalesced_mmio_buffer(); + if (!(s->ar_index & 0x20)) { graphic_mode = GMODE_BLANK; } else { @@ -2241,40 +2245,39 @@ void vga_common_init(VGACommonState *s, int vga_ram_size) vga_dirty_log_start(s); } -/* used by both ISA and PCI */ -MemoryRegion *vga_init_io(VGACommonState *s) -{ - MemoryRegion *vga_mem; - - register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s); - - register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s); - register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s); - register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s); - register_ioport_write(0x3da, 1, 1, vga_ioport_write, s); - - register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s); - - register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s); - register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s); - register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s); - register_ioport_read(0x3da, 1, 1, vga_ioport_read, s); +static const MemoryRegionPortio vga_portio_list[] = { + { 0x04, 2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3b4 */ + { 0x0a, 1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3ba */ + { 0x10, 16, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3c0 */ + { 0x24, 2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3d4 */ + { 0x2a, 1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3da */ + PORTIO_END_OF_LIST(), +}; #ifdef CONFIG_BOCHS_VBE -#if defined (TARGET_I386) - register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s); - register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s); +static const MemoryRegionPortio vbe_portio_list[] = { + { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index }, +# ifdef TARGET_I386 + { 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data }, +# else + { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data }, +# endif + PORTIO_END_OF_LIST(), +}; +#endif /* CONFIG_BOCHS_VBE */ - register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s); - register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s); -#else - register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s); - register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s); +/* Used by both ISA and PCI */ +MemoryRegion *vga_init_io(VGACommonState *s, + const MemoryRegionPortio **vga_ports, + const MemoryRegionPortio **vbe_ports) +{ + MemoryRegion *vga_mem; - register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s); - register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s); + *vga_ports = vga_portio_list; + *vbe_ports = NULL; +#ifdef CONFIG_BOCHS_VBE + *vbe_ports = vbe_portio_list; #endif -#endif /* CONFIG_BOCHS_VBE */ vga_mem = g_malloc(sizeof(*vga_mem)); memory_region_init_io(vga_mem, &vga_mem_ops, s, @@ -2283,9 +2286,13 @@ MemoryRegion *vga_init_io(VGACommonState *s) return vga_mem; } -void vga_init(VGACommonState *s, MemoryRegion *address_space) +void vga_init(VGACommonState *s, MemoryRegion *address_space, + MemoryRegion *address_space_io, bool init_vga_ports) { MemoryRegion *vga_io_memory; + const MemoryRegionPortio *vga_ports, *vbe_ports; + PortioList *vga_port_list = g_new(PortioList, 1); + PortioList *vbe_port_list = g_new(PortioList, 1); qemu_register_reset(vga_reset, s); @@ -2293,12 +2300,20 @@ void vga_init(VGACommonState *s, MemoryRegion *address_space) s->legacy_address_space = address_space; - vga_io_memory = vga_init_io(s); + vga_io_memory = vga_init_io(s, &vga_ports, &vbe_ports); memory_region_add_subregion_overlap(address_space, isa_mem_base + 0x000a0000, vga_io_memory, 1); memory_region_set_coalescing(vga_io_memory); + if (init_vga_ports) { + portio_list_init(vga_port_list, vga_ports, s, "vga"); + portio_list_add(vga_port_list, address_space_io, 0x3b0); + } + if (vbe_ports) { + portio_list_init(vbe_port_list, vbe_ports, s, "vbe"); + portio_list_add(vbe_port_list, address_space_io, 0x1ce); + } } void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory) diff --git a/hw/vga_int.h b/hw/vga_int.h index 99287dde9b..c1e700fa0b 100644 --- a/hw/vga_int.h +++ b/hw/vga_int.h @@ -187,8 +187,11 @@ static inline int c6_to_8(int v) } void vga_common_init(VGACommonState *s, int vga_ram_size); -void vga_init(VGACommonState *s, MemoryRegion *address_space); -MemoryRegion *vga_init_io(VGACommonState *s); +void vga_init(VGACommonState *s, MemoryRegion *address_space, + MemoryRegion *address_space_io, bool init_vga_ports); +MemoryRegion *vga_init_io(VGACommonState *s, + const MemoryRegionPortio **vga_ports, + const MemoryRegionPortio **vbe_ports); void vga_common_reset(VGACommonState *s); void vga_dirty_log_start(VGACommonState *s); diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 03878bfc5e..2a5d1a92b3 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -78,6 +78,7 @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error, s->rq = req; bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read); vm_stop(RUN_STATE_IO_ERROR); + bdrv_iostatus_set_err(s->bs, error); } else { virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR); bdrv_acct_done(s->bs, &req->acct); @@ -603,6 +604,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf, bdrv_set_dev_ops(s->bs, &virtio_block_ops, s); bdrv_set_buffer_alignment(s->bs, conf->logical_block_size); + bdrv_iostatus_enable(s->bs); add_boot_device_path(conf->bootindex, dev, "/disk@0,0"); return &s->vdev; diff --git a/hw/vmport.c b/hw/vmport.c index c8aefaabb8..b5c6fa19cd 100644 --- a/hw/vmport.c +++ b/hw/vmport.c @@ -38,6 +38,7 @@ typedef struct _VMPortState { ISADevice dev; + MemoryRegion io; IOPortReadFunc *func[VMPORT_ENTRIES]; void *opaque[VMPORT_ENTRIES]; } VMPortState; @@ -120,13 +121,22 @@ void vmmouse_set_data(const uint32_t *data) env->regs[R_ESI] = data[4]; env->regs[R_EDI] = data[5]; } +static const MemoryRegionPortio vmport_portio[] = { + {0, 1, 4, .read = vmport_ioport_read, .write = vmport_ioport_write }, + PORTIO_END_OF_LIST(), +}; + +static const MemoryRegionOps vmport_ops = { + .old_portio = vmport_portio +}; + static int vmport_initfn(ISADevice *dev) { VMPortState *s = DO_UPCAST(VMPortState, dev, dev); - register_ioport_read(0x5658, 1, 4, vmport_ioport_read, s); - register_ioport_write(0x5658, 1, 4, vmport_ioport_write, s); - isa_init_ioport(dev, 0x5658); + memory_region_init_io(&s->io, &vmport_ops, s, "vmport", 1); + isa_register_ioport(dev, &s->io, 0x5658); + port_state = s; /* Register some generic port commands */ vmport_register(VMPORT_CMD_GETVERSION, vmport_cmd_get_version, NULL); diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index aa682376ad..af70bdee09 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -1079,7 +1079,7 @@ static const VMStateDescription vmstate_vmware_vga = { }; static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size, - MemoryRegion *address_space) + MemoryRegion *address_space, MemoryRegion *io) { s->scratch_size = SVGA_SCRATCH_SIZE; s->scratch = g_malloc(s->scratch_size * 4); @@ -1095,7 +1095,7 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size, s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram); vga_common_init(&s->vga, vga_ram_size); - vga_init(&s->vga, address_space); + vga_init(&s->vga, address_space, io, true); vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga); s->depth = ds_get_bits_per_pixel(s->vga.ds); @@ -1183,7 +1183,8 @@ static int pci_vmsvga_initfn(PCIDevice *dev) "vmsvga-io", 0x10); pci_register_bar(&s->card, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar); - vmsvga_init(&s->chip, VGA_RAM_SIZE, pci_address_space(dev)); + vmsvga_init(&s->chip, VGA_RAM_SIZE, pci_address_space(dev), + pci_address_space_io(dev)); pci_register_bar(&s->card, 1, PCI_BASE_ADDRESS_MEM_PREFETCH, iomem); pci_register_bar(&s->card, 2, PCI_BASE_ADDRESS_MEM_PREFETCH, diff --git a/hw/xtensa_lx60.c b/hw/xtensa_lx60.c new file mode 100644 index 0000000000..3cebca1cfc --- /dev/null +++ b/hw/xtensa_lx60.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Open Source and Linux Lab nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sysemu.h" +#include "boards.h" +#include "loader.h" +#include "elf.h" +#include "memory.h" +#include "exec-memory.h" +#include "pc.h" +#include "sysbus.h" + +typedef struct Lx60FpgaState { + MemoryRegion iomem; + uint32_t leds; + uint32_t switches; +} Lx60FpgaState; + +static void lx60_fpga_reset(void *opaque) +{ + Lx60FpgaState *s = opaque; + + s->leds = 0; + s->switches = 0; +} + +static uint64_t lx60_fpga_read(void *opaque, target_phys_addr_t addr, + unsigned size) +{ + Lx60FpgaState *s = opaque; + + switch (addr) { + case 0x0: /*build date code*/ + return 0x27092011; + + case 0x4: /*processor clock frequency, Hz*/ + return 10000000; + + case 0x8: /*LEDs (off = 0, on = 1)*/ + return s->leds; + + case 0xc: /*DIP switches (off = 0, on = 1)*/ + return s->switches; + } + return 0; +} + +static void lx60_fpga_write(void *opaque, target_phys_addr_t addr, + uint64_t val, unsigned size) +{ + Lx60FpgaState *s = opaque; + + switch (addr) { + case 0x8: /*LEDs (off = 0, on = 1)*/ + s->leds = val; + break; + + case 0x10: /*board reset*/ + if (val == 0xdead) { + qemu_system_reset_request(); + } + break; + } +} + +static const MemoryRegionOps lx60_fpga_ops = { + .read = lx60_fpga_read, + .write = lx60_fpga_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static Lx60FpgaState *lx60_fpga_init(MemoryRegion *address_space, + target_phys_addr_t base) +{ + Lx60FpgaState *s = g_malloc(sizeof(Lx60FpgaState)); + + memory_region_init_io(&s->iomem, &lx60_fpga_ops, s, + "lx60-fpga", 0x10000); + memory_region_add_subregion(address_space, base, &s->iomem); + lx60_fpga_reset(s); + qemu_register_reset(lx60_fpga_reset, s); + return s; +} + +static void lx60_net_init(MemoryRegion *address_space, + target_phys_addr_t base, + target_phys_addr_t descriptors, + target_phys_addr_t buffers, + qemu_irq irq, NICInfo *nd) +{ + DeviceState *dev; + SysBusDevice *s; + MemoryRegion *ram; + + dev = qdev_create(NULL, "open_eth"); + qdev_set_nic_properties(dev, nd); + qdev_init_nofail(dev); + + s = sysbus_from_qdev(dev); + sysbus_connect_irq(s, 0, irq); + memory_region_add_subregion(address_space, base, + sysbus_mmio_get_region(s, 0)); + memory_region_add_subregion(address_space, descriptors, + sysbus_mmio_get_region(s, 1)); + + ram = g_malloc(sizeof(*ram)); + memory_region_init_ram(ram, NULL, "open_eth.ram", 16384); + memory_region_add_subregion(address_space, buffers, ram); +} + +static uint64_t translate_phys_addr(void *env, uint64_t addr) +{ + return cpu_get_phys_page_debug(env, addr); +} + +static void lx60_reset(void *env) +{ + cpu_reset(env); +} + +static void lx60_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ +#ifdef TARGET_WORDS_BIGENDIAN + int be = 1; +#else + int be = 0; +#endif + MemoryRegion *system_memory = get_system_memory(); + CPUState *env = NULL; + MemoryRegion *ram, *rom, *system_io; + int n; + + for (n = 0; n < smp_cpus; n++) { + env = cpu_init(cpu_model); + if (!env) { + fprintf(stderr, "Unable to find CPU definition\n"); + exit(1); + } + env->sregs[PRID] = n; + qemu_register_reset(lx60_reset, env); + /* Need MMU initialized prior to ELF loading, + * so that ELF gets loaded into virtual addresses + */ + cpu_reset(env); + } + + ram = g_malloc(sizeof(*ram)); + memory_region_init_ram(ram, NULL, "xtensa.sram", ram_size); + memory_region_add_subregion(system_memory, 0, ram); + + rom = g_malloc(sizeof(*rom)); + memory_region_init_ram(rom, NULL, "xtensa.rom", 0x1000); + memory_region_add_subregion(system_memory, 0xfe000000, rom); + + system_io = g_malloc(sizeof(*system_io)); + memory_region_init(system_io, "system.io", 224 * 1024 * 1024); + memory_region_add_subregion(system_memory, 0xf0000000, system_io); + lx60_fpga_init(system_io, 0x0d020000); + if (nd_table[0].vlan) { + lx60_net_init(system_io, 0x0d030000, 0x0d030400, 0x0d800000, + xtensa_get_extint(env, 1), nd_table); + } + + if (!serial_hds[0]) { + serial_hds[0] = qemu_chr_new("serial0", "null", NULL); + } + + serial_mm_init(system_io, 0x0d050020, 2, xtensa_get_extint(env, 0), + 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN); + + if (kernel_filename) { + uint64_t elf_entry; + uint64_t elf_lowaddr; + int success = load_elf(kernel_filename, translate_phys_addr, env, + &elf_entry, &elf_lowaddr, NULL, be, ELF_MACHINE, 0); + if (success > 0) { + env->pc = elf_entry; + } + } +} + +static void xtensa_lx60_init(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, const char *cpu_model) +{ + if (!cpu_model) { + cpu_model = "dc232b"; + } + lx60_init(ram_size, boot_device, kernel_filename, kernel_cmdline, + initrd_filename, cpu_model); +} + +static QEMUMachine xtensa_lx60_machine = { + .name = "lx60", + .desc = "lx60 EVB (dc232b)", + .init = xtensa_lx60_init, + .max_cpus = 4, +}; + +static void xtensa_lx60_machine_init(void) +{ + qemu_register_machine(&xtensa_lx60_machine); +} + +machine_init(xtensa_lx60_machine_init); diff --git a/hw/xtensa_pic.c b/hw/xtensa_pic.c index 3033ae214a..71d5fc89d4 100644 --- a/hw/xtensa_pic.c +++ b/hw/xtensa_pic.c @@ -26,19 +26,9 @@ */ #include "hw.h" -#include "pc.h" #include "qemu-log.h" #include "qemu-timer.h" -/* Stub functions for hardware that doesn't exist. */ -void pic_info(Monitor *mon) -{ -} - -void irq_info(Monitor *mon) -{ -} - void xtensa_advance_ccount(CPUState *env, uint32_t d) { uint32_t old_ccount = env->sregs[CCOUNT]; @@ -116,10 +106,35 @@ void xtensa_timer_irq(CPUState *env, uint32_t id, uint32_t active) qemu_set_irq(env->irq_inputs[env->config->timerint[id]], active); } +void xtensa_rearm_ccompare_timer(CPUState *env) +{ + int i; + uint32_t wake_ccount = env->sregs[CCOUNT] - 1; + + for (i = 0; i < env->config->nccompare; ++i) { + if (env->sregs[CCOMPARE + i] - env->sregs[CCOUNT] < + wake_ccount - env->sregs[CCOUNT]) { + wake_ccount = env->sregs[CCOMPARE + i]; + } + } + env->wake_ccount = wake_ccount; + qemu_mod_timer(env->ccompare_timer, env->halt_clock + + muldiv64(wake_ccount - env->sregs[CCOUNT], + 1000000, env->config->clock_freq_khz)); +} + static void xtensa_ccompare_cb(void *opaque) { CPUState *env = opaque; - xtensa_advance_ccount(env, env->wake_ccount - env->sregs[CCOUNT]); + + if (env->halted) { + env->halt_clock = qemu_get_clock_ns(vm_clock); + xtensa_advance_ccount(env, env->wake_ccount - env->sregs[CCOUNT]); + if (!cpu_has_work(env)) { + env->sregs[CCOUNT] = env->wake_ccount + 1; + xtensa_rearm_ccompare_timer(env); + } + } } void xtensa_irq_init(CPUState *env) @@ -132,3 +147,15 @@ void xtensa_irq_init(CPUState *env) qemu_new_timer_ns(vm_clock, &xtensa_ccompare_cb, env); } } + +void *xtensa_get_extint(CPUState *env, unsigned extint) +{ + if (extint < env->config->nextint) { + unsigned irq = env->config->extint[extint]; + return env->irq_inputs[irq]; + } else { + qemu_log("%s: trying to acquire invalid external interrupt %d\n", + __func__, extint); + return NULL; + } +} diff --git a/hw/xtensa_sample.c b/hw/xtensa_sample.c deleted file mode 100644 index 31a6f70825..0000000000 --- a/hw/xtensa_sample.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the Open Source and Linux Lab nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "sysemu.h" -#include "boards.h" -#include "loader.h" -#include "elf.h" -#include "memory.h" -#include "exec-memory.h" - -static void xtensa_sample_reset(void *env) -{ - cpu_reset(env); -} - -static void xtensa_init(ram_addr_t ram_size, - const char *boot_device, - const char *kernel_filename, const char *kernel_cmdline, - const char *initrd_filename, const char *cpu_model) -{ - CPUState *env = NULL; - MemoryRegion *ram; - const size_t dram_size = 0x10000; - const size_t iram_size = 0x20000; - int n; - - for (n = 0; n < smp_cpus; n++) { - env = cpu_init(cpu_model); - if (!env) { - fprintf(stderr, "Unable to find CPU definition\n"); - exit(1); - } - qemu_register_reset(xtensa_sample_reset, env); - env->sregs[PRID] = n; - } - - ram = g_malloc(sizeof(*ram)); - memory_region_init_ram(ram, NULL, "xtensa.ram", - dram_size + iram_size + ram_size); - memory_region_add_subregion(get_system_memory(), - 0x60000000 - dram_size - iram_size, ram); - - if (kernel_filename) { - uint64_t elf_entry; - uint64_t elf_lowaddr; -#ifdef TARGET_WORDS_BIGENDIAN - int success = load_elf(kernel_filename, NULL, NULL, &elf_entry, - &elf_lowaddr, NULL, 1, ELF_MACHINE, 0); -#else - int success = load_elf(kernel_filename, NULL, NULL, &elf_entry, - &elf_lowaddr, NULL, 0, ELF_MACHINE, 0); -#endif - if (success > 0) { - env->pc = elf_entry; - } - } -} - -static void xtensa_sample_init(ram_addr_t ram_size, - const char *boot_device, - const char *kernel_filename, const char *kernel_cmdline, - const char *initrd_filename, const char *cpu_model) -{ - if (!cpu_model) { - cpu_model = "sample-xtensa-core"; - } - xtensa_init(ram_size, boot_device, kernel_filename, kernel_cmdline, - initrd_filename, cpu_model); -} - -static QEMUMachine xtensa_sample_machine = { - .name = "sample-xtensa-machine", - .desc = "Sample Xtensa machine (sample Xtensa core)", - .init = xtensa_sample_init, - .max_cpus = 4, -}; - -static void xtensa_sample_machine_init(void) -{ - qemu_register_machine(&xtensa_sample_machine); -} - -machine_init(xtensa_sample_machine_init); diff --git a/hw/xtensa_dc232b.c b/hw/xtensa_sim.c index 015d6aaa6b..a94e4e561e 100644 --- a/hw/xtensa_dc232b.c +++ b/hw/xtensa_sim.c @@ -37,12 +37,12 @@ static uint64_t translate_phys_addr(void *env, uint64_t addr) return cpu_get_phys_page_debug(env, addr); } -static void dc232b_reset(void *env) +static void sim_reset(void *env) { cpu_reset(env); } -static void dc232b_init(ram_addr_t ram_size, +static void sim_init(ram_addr_t ram_size, const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) @@ -58,11 +58,11 @@ static void dc232b_init(ram_addr_t ram_size, exit(1); } env->sregs[PRID] = n; - qemu_register_reset(dc232b_reset, env); + qemu_register_reset(sim_reset, env); /* Need MMU initialized prior to ELF loading, * so that ELF gets loaded into virtual addresses */ - dc232b_reset(env); + sim_reset(env); } ram = g_malloc(sizeof(*ram)); @@ -89,7 +89,7 @@ static void dc232b_init(ram_addr_t ram_size, } } -static void xtensa_dc232b_init(ram_addr_t ram_size, +static void xtensa_sim_init(ram_addr_t ram_size, const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) @@ -97,20 +97,20 @@ static void xtensa_dc232b_init(ram_addr_t ram_size, if (!cpu_model) { cpu_model = "dc232b"; } - dc232b_init(ram_size, boot_device, kernel_filename, kernel_cmdline, + sim_init(ram_size, boot_device, kernel_filename, kernel_cmdline, initrd_filename, cpu_model); } -static QEMUMachine xtensa_dc232b_machine = { - .name = "dc232b", - .desc = "Diamond 232L Standard Core Rev.B (LE) (dc232b)", - .init = xtensa_dc232b_init, +static QEMUMachine xtensa_sim_machine = { + .name = "sim", + .desc = "sim machine (dc232b)", + .init = xtensa_sim_init, .max_cpus = 4, }; -static void xtensa_dc232b_machine_init(void) +static void xtensa_sim_machine_init(void) { - qemu_register_machine(&xtensa_dc232b_machine); + qemu_register_machine(&xtensa_sim_machine); } -machine_init(xtensa_dc232b_machine_init); +machine_init(xtensa_sim_machine_init); |