qemu-sparc queue

-----BEGIN PGP SIGNATURE-----
 
 iQFSBAABCgA8FiEEzGIauY6CIA2RXMnEW8LFb64PMh8FAmJ4A6ceHG1hcmsuY2F2
 ZS1heWxhbmRAaWxhbmRlLmNvLnVrAAoJEFvCxW+uDzIf4SAH+weljMrdObceJ4vg
 MedvVXUGmr0Uzk0iSkac1FGLCwEC/9bzBMrxMxNCsGHwVWjuX7S9Vikj/4mMi15U
 6iJ56QzVbsxZknr2+gGtB4QEAWHlQSuSrvcFVFc+Vc9enCBZNZoaehF0HzUSUFxU
 nMnZQqDWrc4H9D2E+YK4OLgv3IMqOy3uKWMgIZ7JJX6YebLMXqZV1mq2G9LjKf9X
 zM3HM6V9yd+1UEzb5biHkorBcdyt5F8P/V1VtiGZYFws27UwSBxW9EEDV3XcSGYD
 kS9RpYka4qmC0saj5cBUR/AYQ/jwSbI9kEs4VsBzRQ/eX25F5TPEbyXp6bJZ75Gi
 tsOhvvg=
 =Qnnm
 -----END PGP SIGNATURE-----

Merge tag 'qemu-sparc-20220508' of https://github.com/mcayland/qemu into staging

qemu-sparc queue

# -----BEGIN PGP SIGNATURE-----
#
# iQFSBAABCgA8FiEEzGIauY6CIA2RXMnEW8LFb64PMh8FAmJ4A6ceHG1hcmsuY2F2
# ZS1heWxhbmRAaWxhbmRlLmNvLnVrAAoJEFvCxW+uDzIf4SAH+weljMrdObceJ4vg
# MedvVXUGmr0Uzk0iSkac1FGLCwEC/9bzBMrxMxNCsGHwVWjuX7S9Vikj/4mMi15U
# 6iJ56QzVbsxZknr2+gGtB4QEAWHlQSuSrvcFVFc+Vc9enCBZNZoaehF0HzUSUFxU
# nMnZQqDWrc4H9D2E+YK4OLgv3IMqOy3uKWMgIZ7JJX6YebLMXqZV1mq2G9LjKf9X
# zM3HM6V9yd+1UEzb5biHkorBcdyt5F8P/V1VtiGZYFws27UwSBxW9EEDV3XcSGYD
# kS9RpYka4qmC0saj5cBUR/AYQ/jwSbI9kEs4VsBzRQ/eX25F5TPEbyXp6bJZ75Gi
# tsOhvvg=
# =Qnnm
# -----END PGP SIGNATURE-----
# gpg: Signature made Sun 08 May 2022 12:53:43 PM CDT
# gpg:                using RSA key CC621AB98E82200D915CC9C45BC2C56FAE0F321F
# gpg:                issuer "mark.cave-ayland@ilande.co.uk"
# gpg: Good signature from "Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>" [undefined]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: CC62 1AB9 8E82 200D 915C  C9C4 5BC2 C56F AE0F 321F

* tag 'qemu-sparc-20220508' of https://github.com/mcayland/qemu: (53 commits)
  artist: only render dirty scanlines on the display surface
  artist: remove unused ROP8OFF() macro
  artist: checkpatch and newline style fixes
  hppa: simplify machine function names in machine.c
  hppa: fold machine_hppa_machine_init() into machine_hppa_machine_init_class_init()
  hppa: use MACHINE QOM macros for defining the hppa machine
  hppa: remove the empty hppa_sys.h file
  hppa: move enable_lan() define from hppa_sys.h to machine.c
  hppa: remove unused trace-events from from hw/hppa
  hppa: remove hw/hppa/pci.c
  hppa: move hppa_pci_ignore_ops from pci.c to machine.c
  lasi: move from hw/hppa to hw/misc
  hppa: move device headers from hppa_sys.h into individual .c files
  lasi: use numerical constant for iar reset value
  lasi: use constants for device register offsets
  lasi: move lasi_initfn() to machine.c
  lasi: remove address space parameter from lasi_initfn()
  lasi: move PS2 initialisation to machine.c
  lasi: move second serial port initialisation to machine.c
  lasi: move parallel port initialisation to machine.c
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2022-05-08 17:03:26 -05:00
commit 554623226f
21 changed files with 482 additions and 469 deletions

View File

@ -1113,7 +1113,11 @@ S: Odd Fixes
F: configs/devices/hppa-softmmu/default.mak
F: hw/hppa/
F: hw/net/*i82596*
F: hw/misc/lasi.c
F: hw/pci-host/dino.c
F: include/hw/misc/lasi.h
F: include/hw/net/lasi_82596.h
F: include/hw/pci-host/dino.h
F: pc-bios/hppa-firmware.img
M68K Machines

View File

@ -6,4 +6,4 @@
# Boards:
#
CONFIG_DINO=y
CONFIG_HPPA_B160L=y

View File

@ -25,12 +25,6 @@
#define TYPE_ARTIST "artist"
OBJECT_DECLARE_SIMPLE_TYPE(ARTISTState, ARTIST)
#if HOST_BIG_ENDIAN
#define ROP8OFF(_i) (3 - (_i))
#else
#define ROP8OFF
#endif
struct vram_buffer {
MemoryRegion mr;
uint8_t *data;
@ -211,8 +205,9 @@ static void artist_invalidate_lines(struct vram_buffer *buf,
int start = starty * buf->width;
int size;
if (starty + height > buf->height)
if (starty + height > buf->height) {
height = buf->height - starty;
}
size = height * buf->width;
@ -321,8 +316,9 @@ static void artist_get_cursor_pos(ARTISTState *s, int *x, int *y)
}
lx = artist_get_x(s->cursor_pos);
if (lx < offset)
if (lx < offset) {
offset = lx;
}
*x = (lx - offset) / 2;
*y = 1146 - artist_get_y(s->cursor_pos);
@ -343,6 +339,7 @@ static void artist_get_cursor_pos(ARTISTState *s, int *x, int *y)
static void artist_invalidate_cursor(ARTISTState *s)
{
int x, y;
artist_get_cursor_pos(s, &x, &y);
artist_invalidate_lines(&s->vram_buffer[ARTIST_BUFFER_AP],
y, s->cursor_height);
@ -470,10 +467,9 @@ static void draw_line(ARTISTState *s,
if ((x1 >= buf->width && x2 >= buf->width) ||
(y1 >= buf->height && y2 >= buf->height)) {
return;
return;
}
if (update_start) {
s->vram_start = (x2 << 16) | y2;
}
@ -553,15 +549,15 @@ static void draw_line(ARTISTState *s,
x++;
} while (x <= x2 && (max_pix == -1 || --max_pix > 0));
if (c1)
if (c1) {
artist_invalidate_lines(buf, x1, x2 - x1);
else
} else {
artist_invalidate_lines(buf, y1 > y2 ? y2 : y1, x2 - x1);
}
}
static void draw_line_pattern_start(ARTISTState *s)
{
int startx = artist_get_x(s->vram_start);
int starty = artist_get_y(s->vram_start);
int endx = artist_get_x(s->blockmove_size);
@ -574,7 +570,6 @@ static void draw_line_pattern_start(ARTISTState *s)
static void draw_line_pattern_next(ARTISTState *s)
{
int startx = artist_get_x(s->vram_start);
int starty = artist_get_y(s->vram_start);
int endx = artist_get_x(s->blockmove_size);
@ -589,7 +584,6 @@ static void draw_line_pattern_next(ARTISTState *s)
static void draw_line_size(ARTISTState *s, bool update_start)
{
int startx = artist_get_x(s->vram_start);
int starty = artist_get_y(s->vram_start);
int endx = artist_get_x(s->line_size);
@ -600,7 +594,6 @@ static void draw_line_size(ARTISTState *s, bool update_start)
static void draw_line_xy(ARTISTState *s, bool update_start)
{
int startx = artist_get_x(s->vram_start);
int starty = artist_get_y(s->vram_start);
int sizex = artist_get_x(s->blockmove_size);
@ -650,7 +643,6 @@ static void draw_line_xy(ARTISTState *s, bool update_start)
static void draw_line_end(ARTISTState *s, bool update_start)
{
int startx = artist_get_x(s->vram_start);
int starty = artist_get_y(s->vram_start);
int endx = artist_get_x(s->line_end);
@ -835,6 +827,7 @@ static void artist_vram_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
ARTISTState *s = opaque;
s->vram_char_y = 0;
trace_artist_vram_write(size, addr, val);
vram_bit_write(opaque, addr, 0, val, size);
@ -1244,20 +1237,22 @@ static void artist_update_display(void *opaque)
DisplaySurface *surface = qemu_console_surface(s->con);
int first = 0, last;
framebuffer_update_display(surface, &s->fbsection, s->width, s->height,
s->width, s->width * 4, 0, 0, artist_draw_line,
s, &first, &last);
artist_draw_cursor(s);
dpy_gfx_update(s->con, 0, 0, s->width, s->height);
if (first >= 0) {
dpy_gfx_update(s->con, 0, first, s->width, last - first + 1);
}
}
static void artist_invalidate(void *opaque)
{
ARTISTState *s = ARTIST(opaque);
struct vram_buffer *buf = &s->vram_buffer[ARTIST_BUFFER_AP];
memory_region_set_dirty(&buf->mr, 0, buf->size);
}

View File

@ -1,9 +1,10 @@
config DINO
config HPPA_B160L
bool
imply PCI_DEVICES
imply E1000_PCI
imply VIRTIO_VGA
select PCI
select DINO
select LASI
select SERIAL
select ISA_BUS
select I8259

View File

@ -30,11 +30,6 @@
#define PCI_HPA DINO_HPA /* PCI bus */
#define IDE_HPA 0xf9000000 /* Boot disc controller */
/* offsets to DINO HPA: */
#define DINO_PCI_ADDR 0x064
#define DINO_CONFIG_DATA 0x068
#define DINO_IO_DATA 0x06c
#define PORT_PCI_CMD (PCI_HPA + DINO_PCI_ADDR)
#define PORT_PCI_DATA (PCI_HPA + DINO_CONFIG_DATA)

View File

@ -1,24 +0,0 @@
/* HPPA cores and system support chips. */
#ifndef HW_HPPA_SYS_H
#define HW_HPPA_SYS_H
#include "hw/pci/pci.h"
#include "hw/pci/pci_host.h"
#include "hw/boards.h"
#include "hw/intc/i8259.h"
#include "hppa_hardware.h"
PCIBus *dino_init(MemoryRegion *, qemu_irq *, qemu_irq *);
DeviceState *lasi_init(MemoryRegion *);
#define enable_lasi_lan() 0
#define TYPE_DINO_PCI_HOST_BRIDGE "dino-pcihost"
/* hppa_pci.c. */
extern const MemoryRegionOps hppa_pci_ignore_ops;
extern const MemoryRegionOps hppa_pci_conf1_ops;
extern const MemoryRegionOps hppa_pci_iack_ops;
#endif

View File

@ -15,9 +15,15 @@
#include "hw/rtc/mc146818rtc.h"
#include "hw/timer/i8254.h"
#include "hw/char/serial.h"
#include "hw/char/parallel.h"
#include "hw/intc/i8259.h"
#include "hw/input/lasips2.h"
#include "hw/net/lasi_82596.h"
#include "hw/nmi.h"
#include "hppa_sys.h"
#include "hw/pci/pci.h"
#include "hw/pci-host/dino.h"
#include "hw/misc/lasi.h"
#include "hppa_hardware.h"
#include "qemu/units.h"
#include "qapi/error.h"
#include "net/net.h"
@ -30,6 +36,9 @@
#define HPA_POWER_BUTTON (FIRMWARE_END - 0x10)
#define enable_lasi_lan() 0
static void hppa_powerdown_req(Notifier *n, void *opaque)
{
hwaddr soft_power_reg = HPA_POWER_BUTTON;
@ -51,6 +60,29 @@ static Notifier hppa_system_powerdown_notifier = {
.notify = hppa_powerdown_req
};
/* Fallback for unassigned PCI I/O operations. Avoids MCHK. */
static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size)
{
return 0;
}
static void ignore_write(void *opaque, hwaddr addr, uint64_t v, unsigned size)
{
}
static const MemoryRegionOps hppa_pci_ignore_ops = {
.read = ignore_read,
.write = ignore_write,
.endianness = DEVICE_BIG_ENDIAN,
.valid = {
.min_access_size = 1,
.max_access_size = 8,
},
.impl = {
.min_access_size = 1,
.max_access_size = 8,
},
};
static ISABus *hppa_isa_bus(void)
{
@ -121,15 +153,36 @@ static FWCfgState *create_fw_cfg(MachineState *ms)
return fw_cfg;
}
static LasiState *lasi_init(void)
{
DeviceState *dev;
dev = qdev_new(TYPE_LASI_CHIP);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
return LASI_CHIP(dev);
}
static DinoState *dino_init(MemoryRegion *addr_space)
{
DeviceState *dev;
dev = qdev_new(TYPE_DINO_PCI_HOST_BRIDGE);
object_property_set_link(OBJECT(dev), "memory-as", OBJECT(addr_space),
&error_fatal);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
return DINO_PCI_HOST_BRIDGE(dev);
}
static void machine_hppa_init(MachineState *machine)
{
const char *kernel_filename = machine->kernel_filename;
const char *kernel_cmdline = machine->kernel_cmdline;
const char *initrd_filename = machine->initrd_filename;
DeviceState *dev;
DeviceState *dev, *dino_dev, *lasi_dev;
PCIBus *pci_bus;
ISABus *isa_bus;
qemu_irq rtc_irq, serial_irq;
char *firmware_filename;
uint64_t firmware_low, firmware_high;
long size;
@ -163,10 +216,17 @@ static void machine_hppa_init(MachineState *machine)
/* Init Lasi chip */
lasi_init(addr_space);
lasi_dev = DEVICE(lasi_init());
memory_region_add_subregion(addr_space, LASI_HPA,
sysbus_mmio_get_region(
SYS_BUS_DEVICE(lasi_dev), 0));
/* Init Dino (PCI host bus chip). */
pci_bus = dino_init(addr_space, &rtc_irq, &serial_irq);
dino_dev = DEVICE(dino_init(addr_space));
memory_region_add_subregion(addr_space, DINO_HPA,
sysbus_mmio_get_region(
SYS_BUS_DEVICE(dino_dev), 0));
pci_bus = PCI_BUS(qdev_get_child_bus(dino_dev, "pci"));
assert(pci_bus);
/* Create ISA bus. */
@ -174,15 +234,28 @@ static void machine_hppa_init(MachineState *machine)
assert(isa_bus);
/* Realtime clock, used by firmware for PDC_TOD call. */
mc146818_rtc_init(isa_bus, 2000, rtc_irq);
mc146818_rtc_init(isa_bus, 2000, NULL);
/* Serial code setup. */
if (serial_hd(0)) {
uint32_t addr = DINO_UART_HPA + 0x800;
serial_mm_init(addr_space, addr, 0, serial_irq,
serial_mm_init(addr_space, addr, 0,
qdev_get_gpio_in(dino_dev, DINO_IRQ_RS232INT),
115200, serial_hd(0), DEVICE_BIG_ENDIAN);
}
if (serial_hd(1)) {
/* Serial port */
serial_mm_init(addr_space, LASI_UART_HPA + 0x800, 0,
qdev_get_gpio_in(lasi_dev, LASI_IRQ_UART_HPA), 8000000 / 16,
serial_hd(1), DEVICE_BIG_ENDIAN);
}
/* Parallel port */
parallel_mm_init(addr_space, LASI_LPT_HPA + 0x800, 0,
qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
parallel_hds[0]);
/* fw_cfg configuration interface */
create_fw_cfg(machine);
@ -200,12 +273,21 @@ static void machine_hppa_init(MachineState *machine)
}
/* Network setup. */
if (enable_lasi_lan()) {
lasi_82596_init(addr_space, LASI_LAN_HPA,
qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA));
}
for (i = 0; i < nb_nics; i++) {
if (!enable_lasi_lan()) {
pci_nic_init_nofail(&nd_table[i], pci_bus, "tulip", NULL);
}
}
/* PS/2 Keyboard/Mouse */
lasips2_init(addr_space, LASI_PS2KBD_HPA,
qdev_get_gpio_in(lasi_dev, LASI_IRQ_PS2KBD_HPA));
/* register power switch emulation */
qemu_register_powerdown_notifier(&hppa_system_powerdown_notifier);
@ -364,9 +446,12 @@ static void hppa_nmi(NMIState *n, int cpu_index, Error **errp)
}
}
static void machine_hppa_machine_init(MachineClass *mc)
static void hppa_machine_init_class_init(ObjectClass *oc, void *data)
{
mc->desc = "HPPA generic machine";
MachineClass *mc = MACHINE_CLASS(oc);
NMIClass *nc = NMI_CLASS(oc);
mc->desc = "HPPA B160L machine";
mc->default_cpu_type = TYPE_HPPA_CPU;
mc->init = machine_hppa_init;
mc->reset = hppa_machine_reset;
@ -377,30 +462,23 @@ static void machine_hppa_machine_init(MachineClass *mc)
mc->default_ram_size = 512 * MiB;
mc->default_boot_order = "cd";
mc->default_ram_id = "ram";
}
static void machine_hppa_machine_init_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
machine_hppa_machine_init(mc);
NMIClass *nc = NMI_CLASS(oc);
nc->nmi_monitor_handler = hppa_nmi;
}
static const TypeInfo machine_hppa_machine_init_typeinfo = {
.name = ("hppa" "-machine"),
.parent = "machine",
.class_init = machine_hppa_machine_init_class_init,
static const TypeInfo hppa_machine_init_typeinfo = {
.name = MACHINE_TYPE_NAME("hppa"),
.parent = TYPE_MACHINE,
.class_init = hppa_machine_init_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_NMI },
{ }
},
};
static void machine_hppa_machine_init_register_types(void)
static void hppa_machine_init_register_types(void)
{
type_register_static(&machine_hppa_machine_init_typeinfo);
type_register_static(&hppa_machine_init_typeinfo);
}
type_init(machine_hppa_machine_init_register_types)
type_init(hppa_machine_init_register_types)

View File

@ -1,4 +1,4 @@
hppa_ss = ss.source_set()
hppa_ss.add(when: 'CONFIG_DINO', if_true: files('pci.c', 'machine.c', 'dino.c', 'lasi.c'))
hppa_ss.add(when: 'CONFIG_HPPA_B160L', if_true: files('machine.c'))
hw_arch += {'hppa': hppa_ss}

View File

@ -1,88 +0,0 @@
/*
* QEMU HP-PARISC PCI support functions.
*
*/
#include "qemu/osdep.h"
#include "hppa_sys.h"
#include "qemu/log.h"
#include "trace.h"
/* Fallback for unassigned PCI I/O operations. Avoids MCHK. */
static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size)
{
return 0;
}
static void ignore_write(void *opaque, hwaddr addr, uint64_t v, unsigned size)
{
}
const MemoryRegionOps hppa_pci_ignore_ops = {
.read = ignore_read,
.write = ignore_write,
.endianness = DEVICE_BIG_ENDIAN,
.valid = {
.min_access_size = 1,
.max_access_size = 8,
},
.impl = {
.min_access_size = 1,
.max_access_size = 8,
},
};
/* PCI config space reads/writes, to byte-word addressable memory. */
static uint64_t bw_conf1_read(void *opaque, hwaddr addr,
unsigned size)
{
PCIBus *b = opaque;
return pci_data_read(b, addr, size);
}
static void bw_conf1_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
PCIBus *b = opaque;
pci_data_write(b, addr, val, size);
}
const MemoryRegionOps hppa_pci_conf1_ops = {
.read = bw_conf1_read,
.write = bw_conf1_write,
.endianness = DEVICE_BIG_ENDIAN,
.impl = {
.min_access_size = 1,
.max_access_size = 4,
},
};
/* PCI/EISA Interrupt Acknowledge Cycle. */
static uint64_t iack_read(void *opaque, hwaddr addr, unsigned size)
{
return pic_read_irq(isa_pic);
}
static void special_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
trace_hppa_pci_iack_write();
}
const MemoryRegionOps hppa_pci_iack_ops = {
.read = iack_read,
.write = special_write,
.endianness = DEVICE_BIG_ENDIAN,
.valid = {
.min_access_size = 4,
.max_access_size = 4,
},
.impl = {
.min_access_size = 4,
.max_access_size = 4,
},
};

View File

@ -1,14 +0,0 @@
# See docs/devel/tracing.rst for syntax documentation.
# pci.c
hppa_pci_iack_write(void) ""
# dino.c
dino_chip_mem_valid(uint64_t addr, uint32_t val) "access to addr 0x%"PRIx64" is %d"
dino_chip_read(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"
dino_chip_write(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"
# lasi.c
lasi_chip_mem_valid(uint64_t addr, uint32_t val) "access to addr 0x%"PRIx64" is %d"
lasi_chip_read(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"
lasi_chip_write(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"

View File

@ -171,4 +171,7 @@ config SIFIVE_U_PRCI
config VIRT_CTRL
bool
config LASI
bool
source macio/Kconfig

View File

@ -17,57 +17,10 @@
#include "hw/irq.h"
#include "sysemu/sysemu.h"
#include "sysemu/runstate.h"
#include "hppa_sys.h"
#include "hw/net/lasi_82596.h"
#include "hw/char/parallel.h"
#include "hw/char/serial.h"
#include "hw/input/lasips2.h"
#include "migration/vmstate.h"
#include "qom/object.h"
#include "hw/misc/lasi.h"
#define TYPE_LASI_CHIP "lasi-chip"
#define LASI_IRR 0x00 /* RO */
#define LASI_IMR 0x04
#define LASI_IPR 0x08
#define LASI_ICR 0x0c
#define LASI_IAR 0x10
#define LASI_PCR 0x0C000 /* LASI Power Control register */
#define LASI_ERRLOG 0x0C004 /* LASI Error Logging register */
#define LASI_VER 0x0C008 /* LASI Version Control register */
#define LASI_IORESET 0x0C00C /* LASI I/O Reset register */
#define LASI_AMR 0x0C010 /* LASI Arbitration Mask register */
#define LASI_IO_CONF 0x7FFFE /* LASI primary configuration register */
#define LASI_IO_CONF2 0x7FFFF /* LASI secondary configuration register */
#define LASI_BIT(x) (1ul << (x))
#define LASI_IRQ_BITS (LASI_BIT(5) | LASI_BIT(7) | LASI_BIT(8) | LASI_BIT(9) \
| LASI_BIT(13) | LASI_BIT(14) | LASI_BIT(16) | LASI_BIT(17) \
| LASI_BIT(18) | LASI_BIT(19) | LASI_BIT(20) | LASI_BIT(21) \
| LASI_BIT(26))
#define ICR_BUS_ERROR_BIT LASI_BIT(8) /* bit 8 in ICR */
#define ICR_TOC_BIT LASI_BIT(1) /* bit 1 in ICR */
OBJECT_DECLARE_SIMPLE_TYPE(LasiState, LASI_CHIP)
struct LasiState {
PCIHostState parent_obj;
uint32_t irr;
uint32_t imr;
uint32_t ipr;
uint32_t icr;
uint32_t iar;
uint32_t errlog;
uint32_t amr;
uint32_t rtc;
time_t rtc_ref;
MemoryRegion this_mem;
};
static bool lasi_chip_mem_valid(void *opaque, hwaddr addr,
unsigned size, bool is_write,
@ -82,10 +35,10 @@ static bool lasi_chip_mem_valid(void *opaque, hwaddr addr,
case LASI_ICR:
case LASI_IAR:
case (LASI_LAN_HPA - LASI_HPA):
case (LASI_LPT_HPA - LASI_HPA):
case (LASI_UART_HPA - LASI_HPA):
case (LASI_RTC_HPA - LASI_HPA):
case LASI_LPT:
case LASI_UART:
case LASI_LAN:
case LASI_RTC:
case LASI_PCR ... LASI_AMR:
ret = true;
@ -122,12 +75,12 @@ static MemTxResult lasi_chip_read_with_attrs(void *opaque, hwaddr addr,
val = s->iar;
break;
case (LASI_LAN_HPA - LASI_HPA):
case (LASI_LPT_HPA - LASI_HPA):
case (LASI_UART_HPA - LASI_HPA):
case LASI_LPT:
case LASI_UART:
case LASI_LAN:
val = 0;
break;
case (LASI_RTC_HPA - LASI_HPA):
case LASI_RTC:
val = time(NULL);
val += s->rtc_ref;
break;
@ -169,10 +122,11 @@ static MemTxResult lasi_chip_write_with_attrs(void *opaque, hwaddr addr,
break;
case LASI_IMR:
s->imr = val;
if (((val & LASI_IRQ_BITS) != val) && (val != 0xffffffff))
if (((val & LASI_IRQ_BITS) != val) && (val != 0xffffffff)) {
qemu_log_mask(LOG_GUEST_ERROR,
"LASI: tried to set invalid %lx IMR value.\n",
(unsigned long) val);
}
break;
case LASI_IPR:
/* Any write to IPR clears the register. */
@ -186,22 +140,23 @@ static MemTxResult lasi_chip_write_with_attrs(void *opaque, hwaddr addr,
s->iar = val;
break;
case (LASI_LAN_HPA - LASI_HPA):
/* XXX: reset LAN card */
break;
case (LASI_LPT_HPA - LASI_HPA):
case LASI_LPT:
/* XXX: reset parallel port */
break;
case (LASI_UART_HPA - LASI_HPA):
case LASI_UART:
/* XXX: reset serial port */
break;
case (LASI_RTC_HPA - LASI_HPA):
case LASI_LAN:
/* XXX: reset LAN card */
break;
case LASI_RTC:
s->rtc_ref = val - time(NULL);
break;
case LASI_PCR:
if (val == 0x02) /* immediately power off */
if (val == 0x02) { /* immediately power off */
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
}
break;
case LASI_ERRLOG:
s->errlog = val;
@ -271,90 +226,42 @@ static void lasi_set_irq(void *opaque, int irq, int level)
}
}
static int lasi_get_irq(unsigned long hpa)
static void lasi_reset(DeviceState *dev)
{
switch (hpa) {
case LASI_HPA:
return 14;
case LASI_UART_HPA:
return 5;
case LASI_LPT_HPA:
return 7;
case LASI_LAN_HPA:
return 8;
case LASI_SCSI_HPA:
return 9;
case LASI_AUDIO_HPA:
return 13;
case LASI_PS2KBD_HPA:
case LASI_PS2MOU_HPA:
return 26;
default:
g_assert_not_reached();
}
}
LasiState *s = LASI_CHIP(dev);
DeviceState *lasi_init(MemoryRegion *address_space)
{
DeviceState *dev;
LasiState *s;
dev = qdev_new(TYPE_LASI_CHIP);
s = LASI_CHIP(dev);
s->iar = CPU_HPA + 3;
/* Lasi access from main memory. */
memory_region_init_io(&s->this_mem, OBJECT(s), &lasi_chip_ops,
s, "lasi", 0x100000);
memory_region_add_subregion(address_space, LASI_HPA, &s->this_mem);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
/* LAN */
if (enable_lasi_lan()) {
qemu_irq lan_irq = qemu_allocate_irq(lasi_set_irq, s,
lasi_get_irq(LASI_LAN_HPA));
lasi_82596_init(address_space, LASI_LAN_HPA, lan_irq);
}
/* Parallel port */
qemu_irq lpt_irq = qemu_allocate_irq(lasi_set_irq, s,
lasi_get_irq(LASI_LPT_HPA));
parallel_mm_init(address_space, LASI_LPT_HPA + 0x800, 0,
lpt_irq, parallel_hds[0]);
s->iar = 0xFFFB0000 + 3; /* CPU_HPA + 3 */
/* Real time clock (RTC), it's only one 32-bit counter @9000 */
s->rtc = time(NULL);
s->rtc_ref = 0;
}
if (serial_hd(1)) {
/* Serial port */
qemu_irq serial_irq = qemu_allocate_irq(lasi_set_irq, s,
lasi_get_irq(LASI_UART_HPA));
serial_mm_init(address_space, LASI_UART_HPA + 0x800, 0,
serial_irq, 8000000 / 16,
serial_hd(0), DEVICE_NATIVE_ENDIAN);
}
static void lasi_init(Object *obj)
{
LasiState *s = LASI_CHIP(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
/* PS/2 Keyboard/Mouse */
qemu_irq ps2kbd_irq = qemu_allocate_irq(lasi_set_irq, s,
lasi_get_irq(LASI_PS2KBD_HPA));
lasips2_init(address_space, LASI_PS2KBD_HPA, ps2kbd_irq);
memory_region_init_io(&s->this_mem, OBJECT(s), &lasi_chip_ops,
s, "lasi", 0x100000);
return dev;
sysbus_init_mmio(sbd, &s->this_mem);
qdev_init_gpio_in(DEVICE(obj), lasi_set_irq, LASI_IRQS);
}
static void lasi_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->reset = lasi_reset;
dc->vmsd = &vmstate_lasi;
}
static const TypeInfo lasi_pcihost_info = {
.name = TYPE_LASI_CHIP,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_init = lasi_init,
.instance_size = sizeof(LasiState),
.class_init = lasi_class_init,
};

View File

@ -134,3 +134,6 @@ specific_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_cmgcr.c', 'mips_cp
specific_ss.add(when: 'CONFIG_MIPS_ITU', if_true: files('mips_itu.c'))
specific_ss.add(when: 'CONFIG_SBSA_REF', if_true: files('sbsa_ec.c'))
# HPPA devices
softmmu_ss.add(when: 'CONFIG_LASI', if_true: files('lasi.c'))

View File

@ -263,3 +263,8 @@ virt_ctrl_write(void *dev, unsigned int addr, unsigned int size, uint64_t value)
virt_ctrl_reset(void *dev) "ctrl: %p"
virt_ctrl_realize(void *dev) "ctrl: %p"
virt_ctrl_instance_init(void *dev) "ctrl: %p"
# lasi.c
lasi_chip_mem_valid(uint64_t addr, uint32_t val) "access to addr 0x%"PRIx64" is %d"
lasi_chip_read(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"
lasi_chip_write(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"

View File

@ -77,3 +77,7 @@ config MV64361
bool
select PCI
select I8259
config DINO
bool
select PCI

View File

@ -17,118 +17,13 @@
#include "hw/irq.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_bus.h"
#include "hw/qdev-properties.h"
#include "hw/pci-host/dino.h"
#include "migration/vmstate.h"
#include "hppa_sys.h"
#include "trace.h"
#include "qom/object.h"
#define TYPE_DINO_PCI_HOST_BRIDGE "dino-pcihost"
#define DINO_IAR0 0x004
#define DINO_IODC 0x008
#define DINO_IRR0 0x00C /* RO */
#define DINO_IAR1 0x010
#define DINO_IRR1 0x014 /* RO */
#define DINO_IMR 0x018
#define DINO_IPR 0x01C
#define DINO_TOC_ADDR 0x020
#define DINO_ICR 0x024
#define DINO_ILR 0x028 /* RO */
#define DINO_IO_COMMAND 0x030 /* WO */
#define DINO_IO_STATUS 0x034 /* RO */
#define DINO_IO_CONTROL 0x038
#define DINO_IO_GSC_ERR_RESP 0x040 /* RO */
#define DINO_IO_ERR_INFO 0x044 /* RO */
#define DINO_IO_PCI_ERR_RESP 0x048 /* RO */
#define DINO_IO_FBB_EN 0x05c
#define DINO_IO_ADDR_EN 0x060
#define DINO_PCI_CONFIG_ADDR 0x064
#define DINO_PCI_CONFIG_DATA 0x068
#define DINO_PCI_IO_DATA 0x06c
#define DINO_PCI_MEM_DATA 0x070 /* Dino 3.x only */
#define DINO_GSC2X_CONFIG 0x7b4 /* RO */
#define DINO_GMASK 0x800
#define DINO_PAMR 0x804
#define DINO_PAPR 0x808
#define DINO_DAMODE 0x80c
#define DINO_PCICMD 0x810
#define DINO_PCISTS 0x814 /* R/WC */
#define DINO_MLTIM 0x81c
#define DINO_BRDG_FEAT 0x820
#define DINO_PCIROR 0x824
#define DINO_PCIWOR 0x828
#define DINO_TLTIM 0x830
#define DINO_IRQS 11 /* bits 0-10 are architected */
#define DINO_IRR_MASK 0x5ff /* only 10 bits are implemented */
#define DINO_LOCAL_IRQS (DINO_IRQS + 1)
#define DINO_MASK_IRQ(x) (1 << (x))
#define PCIINTA 0x001
#define PCIINTB 0x002
#define PCIINTC 0x004
#define PCIINTD 0x008
#define PCIINTE 0x010
#define PCIINTF 0x020
#define GSCEXTINT 0x040
/* #define xxx 0x080 - bit 7 is "default" */
/* #define xxx 0x100 - bit 8 not used */
/* #define xxx 0x200 - bit 9 not used */
#define RS232INT 0x400
#define DINO_MEM_CHUNK_SIZE (8 * MiB)
OBJECT_DECLARE_SIMPLE_TYPE(DinoState, DINO_PCI_HOST_BRIDGE)
#define DINO800_REGS (1 + (DINO_TLTIM - DINO_GMASK) / 4)
static const uint32_t reg800_keep_bits[DINO800_REGS] = {
MAKE_64BIT_MASK(0, 1), /* GMASK */
MAKE_64BIT_MASK(0, 7), /* PAMR */
MAKE_64BIT_MASK(0, 7), /* PAPR */
MAKE_64BIT_MASK(0, 8), /* DAMODE */
MAKE_64BIT_MASK(0, 7), /* PCICMD */
MAKE_64BIT_MASK(0, 9), /* PCISTS */
MAKE_64BIT_MASK(0, 32), /* Undefined */
MAKE_64BIT_MASK(0, 8), /* MLTIM */
MAKE_64BIT_MASK(0, 30), /* BRDG_FEAT */
MAKE_64BIT_MASK(0, 24), /* PCIROR */
MAKE_64BIT_MASK(0, 22), /* PCIWOR */
MAKE_64BIT_MASK(0, 32), /* Undocumented */
MAKE_64BIT_MASK(0, 9), /* TLTIM */
};
struct DinoState {
PCIHostState parent_obj;
/* PCI_CONFIG_ADDR is parent_obj.config_reg, via pci_host_conf_be_ops,
so that we can map PCI_CONFIG_DATA to pci_host_data_be_ops. */
uint32_t config_reg_dino; /* keep original copy, including 2 lowest bits */
uint32_t iar0;
uint32_t iar1;
uint32_t imr;
uint32_t ipr;
uint32_t icr;
uint32_t ilr;
uint32_t io_fbb_en;
uint32_t io_addr_en;
uint32_t io_control;
uint32_t toc_addr;
uint32_t reg800[DINO800_REGS];
MemoryRegion this_mem;
MemoryRegion pci_mem;
MemoryRegion pci_mem_alias[32];
AddressSpace bm_as;
MemoryRegion bm;
MemoryRegion bm_ram_alias;
MemoryRegion bm_pci_alias;
MemoryRegion bm_cpu_alias;
};
/*
* Dino can forward memory accesses from the CPU in the range between
* 0xf0800000 and 0xff000000 to the PCI bus.
@ -200,6 +95,7 @@ static MemTxResult dino_chip_read_with_attrs(void *opaque, hwaddr addr,
MemTxAttrs attrs)
{
DinoState *s = opaque;
PCIHostState *phb = PCI_HOST_BRIDGE(s);
MemTxResult ret = MEMTX_OK;
AddressSpace *io;
uint16_t ioaddr;
@ -209,7 +105,7 @@ static MemTxResult dino_chip_read_with_attrs(void *opaque, hwaddr addr,
case DINO_PCI_IO_DATA ... DINO_PCI_IO_DATA + 3:
/* Read from PCI IO space. */
io = &address_space_io;
ioaddr = s->parent_obj.config_reg + (addr & 3);
ioaddr = phb->config_reg + (addr & 3);
switch (size) {
case 1:
val = address_space_ldub(io, ioaddr, attrs, &ret);
@ -292,6 +188,7 @@ static MemTxResult dino_chip_write_with_attrs(void *opaque, hwaddr addr,
MemTxAttrs attrs)
{
DinoState *s = opaque;
PCIHostState *phb = PCI_HOST_BRIDGE(s);
AddressSpace *io;
MemTxResult ret;
uint16_t ioaddr;
@ -303,7 +200,7 @@ static MemTxResult dino_chip_write_with_attrs(void *opaque, hwaddr addr,
case DINO_IO_DATA ... DINO_PCI_IO_DATA + 3:
/* Write into PCI IO space. */
io = &address_space_io;
ioaddr = s->parent_obj.config_reg + (addr & 3);
ioaddr = phb->config_reg + (addr & 3);
switch (size) {
case 1:
address_space_stb(io, ioaddr, val, attrs, &ret);
@ -501,52 +398,78 @@ static int dino_pci_map_irq(PCIDevice *d, int irq_num)
return slot & 0x03;
}
static void dino_set_timer_irq(void *opaque, int irq, int level)
static void dino_pcihost_reset(DeviceState *dev)
{
/* ??? Not connected. */
}
DinoState *s = DINO_PCI_HOST_BRIDGE(dev);
static void dino_set_serial_irq(void *opaque, int irq, int level)
{
dino_set_irq(opaque, 10, level);
}
PCIBus *dino_init(MemoryRegion *addr_space,
qemu_irq *p_rtc_irq, qemu_irq *p_ser_irq)
{
DeviceState *dev;
DinoState *s;
PCIBus *b;
int i;
dev = qdev_new(TYPE_DINO_PCI_HOST_BRIDGE);
s = DINO_PCI_HOST_BRIDGE(dev);
s->iar0 = s->iar1 = CPU_HPA + 3;
s->iar0 = s->iar1 = 0xFFFB0000 + 3; /* CPU_HPA + 3 */
s->toc_addr = 0xFFFA0030; /* IO_COMMAND of CPU */
}
static void dino_pcihost_realize(DeviceState *dev, Error **errp)
{
DinoState *s = DINO_PCI_HOST_BRIDGE(dev);
/* Set up PCI view of memory: Bus master address space. */
memory_region_init(&s->bm, OBJECT(s), "bm-dino", 4 * GiB);
memory_region_init_alias(&s->bm_ram_alias, OBJECT(s),
"bm-system", s->memory_as, 0,
0xf0000000 + DINO_MEM_CHUNK_SIZE);
memory_region_init_alias(&s->bm_pci_alias, OBJECT(s),
"bm-pci", &s->pci_mem,
0xf0000000 + DINO_MEM_CHUNK_SIZE,
30 * DINO_MEM_CHUNK_SIZE);
memory_region_init_alias(&s->bm_cpu_alias, OBJECT(s),
"bm-cpu", s->memory_as, 0xfff00000,
0xfffff);
memory_region_add_subregion(&s->bm, 0,
&s->bm_ram_alias);
memory_region_add_subregion(&s->bm,
0xf0000000 + DINO_MEM_CHUNK_SIZE,
&s->bm_pci_alias);
memory_region_add_subregion(&s->bm, 0xfff00000,
&s->bm_cpu_alias);
address_space_init(&s->bm_as, &s->bm, "pci-bm");
}
static void dino_pcihost_unrealize(DeviceState *dev)
{
DinoState *s = DINO_PCI_HOST_BRIDGE(dev);
address_space_destroy(&s->bm_as);
}
static void dino_pcihost_init(Object *obj)
{
DinoState *s = DINO_PCI_HOST_BRIDGE(obj);
PCIHostState *phb = PCI_HOST_BRIDGE(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
int i;
/* Dino PCI access from main memory. */
memory_region_init_io(&s->this_mem, OBJECT(s), &dino_chip_ops,
s, "dino", 4096);
memory_region_add_subregion(addr_space, DINO_HPA, &s->this_mem);
/* Dino PCI config. */
memory_region_init_io(&s->parent_obj.conf_mem, OBJECT(&s->parent_obj),
&dino_config_addr_ops, dev, "pci-conf-idx", 4);
memory_region_init_io(&s->parent_obj.data_mem, OBJECT(&s->parent_obj),
&dino_config_data_ops, dev, "pci-conf-data", 4);
memory_region_init_io(&phb->conf_mem, OBJECT(phb),
&dino_config_addr_ops, DEVICE(s),
"pci-conf-idx", 4);
memory_region_init_io(&phb->data_mem, OBJECT(phb),
&dino_config_data_ops, DEVICE(s),
"pci-conf-data", 4);
memory_region_add_subregion(&s->this_mem, DINO_PCI_CONFIG_ADDR,
&s->parent_obj.conf_mem);
&phb->conf_mem);
memory_region_add_subregion(&s->this_mem, DINO_CONFIG_DATA,
&s->parent_obj.data_mem);
&phb->data_mem);
/* Dino PCI bus memory. */
memory_region_init(&s->pci_mem, OBJECT(s), "pci-memory", 4 * GiB);
b = pci_register_root_bus(dev, "pci", dino_set_irq, dino_pci_map_irq, s,
&s->pci_mem, get_system_io(),
PCI_DEVFN(0, 0), 32, TYPE_PCI_BUS);
s->parent_obj.bus = b;
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
phb->bus = pci_register_root_bus(DEVICE(s), "pci",
dino_set_irq, dino_pci_map_irq, s,
&s->pci_mem, get_system_io(),
PCI_DEVFN(0, 0), 32, TYPE_PCI_BUS);
/* Set up windows into PCI bus memory. */
for (i = 1; i < 31; i++) {
@ -558,44 +481,34 @@ PCIBus *dino_init(MemoryRegion *addr_space,
g_free(name);
}
/* Set up PCI view of memory: Bus master address space. */
memory_region_init(&s->bm, OBJECT(s), "bm-dino", 4 * GiB);
memory_region_init_alias(&s->bm_ram_alias, OBJECT(s),
"bm-system", addr_space, 0,
0xf0000000 + DINO_MEM_CHUNK_SIZE);
memory_region_init_alias(&s->bm_pci_alias, OBJECT(s),
"bm-pci", &s->pci_mem,
0xf0000000 + DINO_MEM_CHUNK_SIZE,
30 * DINO_MEM_CHUNK_SIZE);
memory_region_init_alias(&s->bm_cpu_alias, OBJECT(s),
"bm-cpu", addr_space, 0xfff00000,
0xfffff);
memory_region_add_subregion(&s->bm, 0,
&s->bm_ram_alias);
memory_region_add_subregion(&s->bm,
0xf0000000 + DINO_MEM_CHUNK_SIZE,
&s->bm_pci_alias);
memory_region_add_subregion(&s->bm, 0xfff00000,
&s->bm_cpu_alias);
address_space_init(&s->bm_as, &s->bm, "pci-bm");
pci_setup_iommu(b, dino_pcihost_set_iommu, s);
pci_setup_iommu(phb->bus, dino_pcihost_set_iommu, s);
*p_rtc_irq = qemu_allocate_irq(dino_set_timer_irq, s, 0);
*p_ser_irq = qemu_allocate_irq(dino_set_serial_irq, s, 0);
sysbus_init_mmio(sbd, &s->this_mem);
return b;
qdev_init_gpio_in(DEVICE(obj), dino_set_irq, DINO_IRQS);
}
static Property dino_pcihost_properties[] = {
DEFINE_PROP_LINK("memory-as", DinoState, memory_as, TYPE_MEMORY_REGION,
MemoryRegion *),
DEFINE_PROP_END_OF_LIST(),
};
static void dino_pcihost_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->reset = dino_pcihost_reset;
dc->realize = dino_pcihost_realize;
dc->unrealize = dino_pcihost_unrealize;
device_class_set_props(dc, dino_pcihost_properties);
dc->vmsd = &vmstate_dino;
}
static const TypeInfo dino_pcihost_info = {
.name = TYPE_DINO_PCI_HOST_BRIDGE,
.parent = TYPE_PCI_HOST_BRIDGE,
.instance_init = dino_pcihost_init,
.instance_size = sizeof(DinoState),
.class_init = dino_pcihost_class_init,
};

View File

@ -25,6 +25,9 @@ pci_ss.add(when: 'CONFIG_MV64361', if_true: files('mv64361.c'))
# ARM devices
pci_ss.add(when: 'CONFIG_VERSATILE_PCI', if_true: files('versatile.c'))
# HPPA devices
pci_ss.add(when: 'CONFIG_DINO', if_true: files('dino.c'))
softmmu_ss.add_all(when: 'CONFIG_PCI', if_true: pci_ss)
specific_ss.add(when: 'CONFIG_PCI_POWERNV', if_true: files(

View File

@ -34,3 +34,8 @@ unin_read(uint64_t addr, uint64_t value) "addr=0x%" PRIx64 " val=0x%"PRIx64
pnv_phb4_xive_notify(uint64_t notif_port, uint64_t data) "notif=@0x%"PRIx64" data=0x%"PRIx64
pnv_phb4_xive_notify_ic(uint64_t addr, uint64_t data) "addr=@0x%"PRIx64" data=0x%"PRIx64
pnv_phb4_xive_notify_abt(uint64_t notif_port, uint64_t data) "notif=@0x%"PRIx64" data=0x%"PRIx64
# dino.c
dino_chip_mem_valid(uint64_t addr, uint32_t val) "access to addr 0x%"PRIx64" is %d"
dino_chip_read(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"
dino_chip_write(uint64_t addr, uint32_t val) "addr 0x%"PRIx64" val 0x%08x"

78
include/hw/misc/lasi.h Normal file
View File

@ -0,0 +1,78 @@
/*
* HP-PARISC Lasi chipset emulation.
*
* (C) 2019 by Helge Deller <deller@gmx.de>
*
* This work is licensed under the GNU GPL license version 2 or later.
*
* Documentation available at:
* https://parisc.wiki.kernel.org/images-parisc/7/79/Lasi_ers.pdf
*/
#ifndef LASI_H
#define LASI_H
#include "exec/address-spaces.h"
#include "hw/pci/pci_host.h"
#include "hw/boards.h"
#define TYPE_LASI_CHIP "lasi-chip"
OBJECT_DECLARE_SIMPLE_TYPE(LasiState, LASI_CHIP)
#define LASI_IRR 0x00 /* RO */
#define LASI_IMR 0x04
#define LASI_IPR 0x08
#define LASI_ICR 0x0c
#define LASI_IAR 0x10
#define LASI_LPT 0x02000
#define LASI_UART 0x05000
#define LASI_LAN 0x07000
#define LASI_RTC 0x09000
#define LASI_PCR 0x0C000 /* LASI Power Control register */
#define LASI_ERRLOG 0x0C004 /* LASI Error Logging register */
#define LASI_VER 0x0C008 /* LASI Version Control register */
#define LASI_IORESET 0x0C00C /* LASI I/O Reset register */
#define LASI_AMR 0x0C010 /* LASI Arbitration Mask register */
#define LASI_IO_CONF 0x7FFFE /* LASI primary configuration register */
#define LASI_IO_CONF2 0x7FFFF /* LASI secondary configuration register */
#define LASI_BIT(x) (1ul << (x))
#define LASI_IRQ_BITS (LASI_BIT(5) | LASI_BIT(7) | LASI_BIT(8) | LASI_BIT(9) \
| LASI_BIT(13) | LASI_BIT(14) | LASI_BIT(16) | LASI_BIT(17) \
| LASI_BIT(18) | LASI_BIT(19) | LASI_BIT(20) | LASI_BIT(21) \
| LASI_BIT(26))
#define ICR_BUS_ERROR_BIT LASI_BIT(8) /* bit 8 in ICR */
#define ICR_TOC_BIT LASI_BIT(1) /* bit 1 in ICR */
#define LASI_IRQS 27
#define LASI_IRQ_HPA 14
#define LASI_IRQ_UART_HPA 5
#define LASI_IRQ_LPT_HPA 7
#define LASI_IRQ_LAN_HPA 8
#define LASI_IRQ_SCSI_HPA 9
#define LASI_IRQ_AUDIO_HPA 13
#define LASI_IRQ_PS2KBD_HPA 26
#define LASI_IRQ_PS2MOU_HPA 26
struct LasiState {
PCIHostState parent_obj;
uint32_t irr;
uint32_t imr;
uint32_t ipr;
uint32_t icr;
uint32_t iar;
uint32_t errlog;
uint32_t amr;
uint32_t rtc;
time_t rtc_ref;
MemoryRegion this_mem;
};
#endif

146
include/hw/pci-host/dino.h Normal file
View File

@ -0,0 +1,146 @@
/*
* HP-PARISC Dino PCI chipset emulation, as in B160L and similiar machines
*
* (C) 2017-2019 by Helge Deller <deller@gmx.de>
*
* This work is licensed under the GNU GPL license version 2 or later.
*
* Documentation available at:
* https://parisc.wiki.kernel.org/images-parisc/9/91/Dino_ers.pdf
* https://parisc.wiki.kernel.org/images-parisc/7/70/Dino_3_1_Errata.pdf
*/
#ifndef DINO_H
#define DINO_H
#include "hw/pci/pci_host.h"
#define TYPE_DINO_PCI_HOST_BRIDGE "dino-pcihost"
OBJECT_DECLARE_SIMPLE_TYPE(DinoState, DINO_PCI_HOST_BRIDGE)
#define DINO_IAR0 0x004
#define DINO_IODC 0x008
#define DINO_IRR0 0x00C /* RO */
#define DINO_IAR1 0x010
#define DINO_IRR1 0x014 /* RO */
#define DINO_IMR 0x018
#define DINO_IPR 0x01C
#define DINO_TOC_ADDR 0x020
#define DINO_ICR 0x024
#define DINO_ILR 0x028 /* RO */
#define DINO_IO_COMMAND 0x030 /* WO */
#define DINO_IO_STATUS 0x034 /* RO */
#define DINO_IO_CONTROL 0x038
#define DINO_IO_GSC_ERR_RESP 0x040 /* RO */
#define DINO_IO_ERR_INFO 0x044 /* RO */
#define DINO_IO_PCI_ERR_RESP 0x048 /* RO */
#define DINO_IO_FBB_EN 0x05c
#define DINO_IO_ADDR_EN 0x060
#define DINO_PCI_CONFIG_ADDR 0x064
#define DINO_PCI_CONFIG_DATA 0x068
#define DINO_PCI_IO_DATA 0x06c
#define DINO_PCI_MEM_DATA 0x070 /* Dino 3.x only */
#define DINO_GSC2X_CONFIG 0x7b4 /* RO */
#define DINO_GMASK 0x800
#define DINO_PAMR 0x804
#define DINO_PAPR 0x808
#define DINO_DAMODE 0x80c
#define DINO_PCICMD 0x810
#define DINO_PCISTS 0x814 /* R/WC */
#define DINO_MLTIM 0x81c
#define DINO_BRDG_FEAT 0x820
#define DINO_PCIROR 0x824
#define DINO_PCIWOR 0x828
#define DINO_TLTIM 0x830
#define DINO_IRQS 11 /* bits 0-10 are architected */
#define DINO_IRR_MASK 0x5ff /* only 10 bits are implemented */
#define DINO_LOCAL_IRQS (DINO_IRQS + 1)
#define DINO_MASK_IRQ(x) (1 << (x))
#define DINO_IRQ_PCIINTA 0
#define DINO_IRQ_PCIINTB 1
#define DINO_IRQ_PCIINTC 2
#define DINO_IRQ_PCIINTD 3
#define DINO_IRQ_PCIINTE 4
#define DINO_IRQ_PCIINTF 5
#define DINO_IRQ_GSCEXTINT 6
#define DINO_IRQ_BUSERRINT 7
#define DINO_IRQ_PS2INT 8
#define DINO_IRQ_UNUSED 9
#define DINO_IRQ_RS232INT 10
#define PCIINTA 0x001
#define PCIINTB 0x002
#define PCIINTC 0x004
#define PCIINTD 0x008
#define PCIINTE 0x010
#define PCIINTF 0x020
#define GSCEXTINT 0x040
/* #define xxx 0x080 - bit 7 is "default" */
/* #define xxx 0x100 - bit 8 not used */
/* #define xxx 0x200 - bit 9 not used */
#define RS232INT 0x400
#define DINO_MEM_CHUNK_SIZE (8 * MiB)
#define DINO800_REGS (1 + (DINO_TLTIM - DINO_GMASK) / 4)
static const uint32_t reg800_keep_bits[DINO800_REGS] = {
MAKE_64BIT_MASK(0, 1), /* GMASK */
MAKE_64BIT_MASK(0, 7), /* PAMR */
MAKE_64BIT_MASK(0, 7), /* PAPR */
MAKE_64BIT_MASK(0, 8), /* DAMODE */
MAKE_64BIT_MASK(0, 7), /* PCICMD */
MAKE_64BIT_MASK(0, 9), /* PCISTS */
MAKE_64BIT_MASK(0, 32), /* Undefined */
MAKE_64BIT_MASK(0, 8), /* MLTIM */
MAKE_64BIT_MASK(0, 30), /* BRDG_FEAT */
MAKE_64BIT_MASK(0, 24), /* PCIROR */
MAKE_64BIT_MASK(0, 22), /* PCIWOR */
MAKE_64BIT_MASK(0, 32), /* Undocumented */
MAKE_64BIT_MASK(0, 9), /* TLTIM */
};
/* offsets to DINO HPA: */
#define DINO_PCI_ADDR 0x064
#define DINO_CONFIG_DATA 0x068
#define DINO_IO_DATA 0x06c
struct DinoState {
PCIHostState parent_obj;
/*
* PCI_CONFIG_ADDR is parent_obj.config_reg, via pci_host_conf_be_ops,
* so that we can map PCI_CONFIG_DATA to pci_host_data_be_ops.
*/
uint32_t config_reg_dino; /* keep original copy, including 2 lowest bits */
uint32_t iar0;
uint32_t iar1;
uint32_t imr;
uint32_t ipr;
uint32_t icr;
uint32_t ilr;
uint32_t io_fbb_en;
uint32_t io_addr_en;
uint32_t io_control;
uint32_t toc_addr;
uint32_t reg800[DINO800_REGS];
MemoryRegion this_mem;
MemoryRegion pci_mem;
MemoryRegion pci_mem_alias[32];
MemoryRegion *memory_as;
AddressSpace bm_as;
MemoryRegion bm;
MemoryRegion bm_ram_alias;
MemoryRegion bm_pci_alias;
MemoryRegion bm_cpu_alias;
qemu_irq irqs[DINO_IRQS];
};
#endif

View File

@ -2944,7 +2944,6 @@ if have_system
'hw/char',
'hw/display',
'hw/dma',
'hw/hppa',
'hw/hyperv',
'hw/i2c',
'hw/i386',