提交 13144781 编写于 作者: B Blue Swirl

Merge branch 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf

* 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf:
  PPC: e500: Select MPIC v4.2 on ppce500 platform
  PPC: e500: fix mpic_iack address
  openpic: add basic support for MPIC v4.2
  openpic: fix timer address decoding
  openpic: fix remaining issues from idr-to-destmask conversion
  pseries: Adjust default VIO address allocations to play better with libvirt
  pseries: Improve handling of multiple PCI host bridges
  target-ppc: Give a meaningful error if too many threads are specified
  cuda: Move ADB bus into CUDA state
  adb: QOM'ify ADB devices
  adb: QOM'ify Apple Desktop Bus
  cuda: QOM'ify CUDA
  ide/macio: QOM'ify MacIO IDE
  mac_nvram: QOM'ify MacIO NVRAM
  mac_nvram: Mark as Big Endian
  mac_nvram: Clean up public API
  macio: Split MacIO in two
  macio: Delay qdev init until all fields are initialized
  macio: QOM'ify some more
  ppc: Move Mac machines to hw/ppc/
......@@ -380,7 +380,7 @@ New World
M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org
S: Maintained
F: hw/ppc_newworld.c
F: hw/ppc/mac_newworld.c
F: hw/unin_pci.c
F: hw/dec_pci.[hc]
......@@ -388,7 +388,7 @@ Old World
M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org
S: Maintained
F: hw/ppc_oldworld.c
F: hw/ppc/mac_oldworld.c
F: hw/grackle_pci.c
PReP
......
......@@ -48,16 +48,21 @@ do { printf("ADB: " fmt , ## __VA_ARGS__); } while (0)
#define ADB_CMD_CHANGE_ID_AND_ENABLE 0x00
/* ADB default device IDs (upper 4 bits of ADB command byte) */
#define ADB_DONGLE 1
#define ADB_KEYBOARD 2
#define ADB_MOUSE 3
#define ADB_TABLET 4
#define ADB_MODEM 5
#define ADB_MISC 7
#define ADB_DEVID_DONGLE 1
#define ADB_DEVID_KEYBOARD 2
#define ADB_DEVID_MOUSE 3
#define ADB_DEVID_TABLET 4
#define ADB_DEVID_MODEM 5
#define ADB_DEVID_MISC 7
/* error codes */
#define ADB_RET_NOTPRESENT (-2)
static void adb_device_reset(ADBDevice *d)
{
qdev_reset_all(DEVICE(d));
}
int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
{
ADBDevice *d;
......@@ -66,18 +71,17 @@ int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
cmd = buf[0] & 0xf;
if (cmd == ADB_BUSRESET) {
for(i = 0; i < s->nb_devices; i++) {
d = &s->devices[i];
if (d->devreset) {
d->devreset(d);
}
d = s->devices[i];
adb_device_reset(d);
}
return 0;
}
devaddr = buf[0] >> 4;
for(i = 0; i < s->nb_devices; i++) {
d = &s->devices[i];
d = s->devices[i];
if (d->devaddr == devaddr) {
return d->devreq(d, obuf, buf, len);
ADBDeviceClass *adc = ADB_DEVICE_GET_CLASS(d);
return adc->devreq(d, obuf, buf, len);
}
}
return ADB_RET_NOTPRESENT;
......@@ -94,7 +98,7 @@ int adb_poll(ADBBusState *s, uint8_t *obuf)
for(i = 0; i < s->nb_devices; i++) {
if (s->poll_index >= s->nb_devices)
s->poll_index = 0;
d = &s->devices[s->poll_index];
d = s->devices[s->poll_index];
buf[0] = ADB_READREG | (d->devaddr << 4);
olen = adb_request(s, obuf + 1, buf, 1);
/* if there is data, we poll again the same device */
......@@ -108,32 +112,67 @@ int adb_poll(ADBBusState *s, uint8_t *obuf)
return olen;
}
static ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
ADBDeviceRequest *devreq,
ADBDeviceReset *devreset,
void *opaque)
static const TypeInfo adb_bus_type_info = {
.name = TYPE_ADB_BUS,
.parent = TYPE_BUS,
.instance_size = sizeof(ADBBusState),
};
static void adb_device_realizefn(DeviceState *dev, Error **errp)
{
ADBDevice *d;
if (s->nb_devices >= MAX_ADB_DEVICES)
return NULL;
d = &s->devices[s->nb_devices++];
d->bus = s;
d->devaddr = devaddr;
d->devreq = devreq;
d->devreset = devreset;
d->opaque = opaque;
qemu_register_reset((QEMUResetHandler *)devreset, d);
return d;
ADBDevice *d = ADB_DEVICE(dev);
ADBBusState *bus = ADB_BUS(qdev_get_parent_bus(dev));
if (bus->nb_devices >= MAX_ADB_DEVICES) {
return;
}
bus->devices[bus->nb_devices++] = d;
}
static void adb_device_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = adb_device_realizefn;
dc->bus_type = TYPE_ADB_BUS;
}
static const TypeInfo adb_device_type_info = {
.name = TYPE_ADB_DEVICE,
.parent = TYPE_DEVICE,
.instance_size = sizeof(ADBDevice),
.abstract = true,
.class_init = adb_device_class_init,
};
/***************************************************************/
/* Keyboard ADB device */
#define ADB_KEYBOARD(obj) OBJECT_CHECK(KBDState, (obj), TYPE_ADB_KEYBOARD)
typedef struct KBDState {
/*< private >*/
ADBDevice parent_obj;
/*< public >*/
uint8_t data[128];
int rptr, wptr, count;
} KBDState;
#define ADB_KEYBOARD_CLASS(class) \
OBJECT_CLASS_CHECK(ADBKeyboardClass, (class), TYPE_ADB_KEYBOARD)
#define ADB_KEYBOARD_GET_CLASS(obj) \
OBJECT_GET_CLASS(ADBKeyboardClass, (obj), TYPE_ADB_KEYBOARD)
typedef struct ADBKeyboardClass {
/*< private >*/
ADBDeviceClass parent_class;
/*< public >*/
DeviceRealize parent_realize;
} ADBKeyboardClass;
static const uint8_t pc_to_adb_keycode[256] = {
0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54, 0, 1,
......@@ -155,8 +194,7 @@ static const uint8_t pc_to_adb_keycode[256] = {
static void adb_kbd_put_keycode(void *opaque, int keycode)
{
ADBDevice *d = opaque;
KBDState *s = d->opaque;
KBDState *s = opaque;
if (s->count < sizeof(s->data)) {
s->data[s->wptr] = keycode;
......@@ -169,7 +207,7 @@ static void adb_kbd_put_keycode(void *opaque, int keycode)
static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
{
static int ext_keycode;
KBDState *s = d->opaque;
KBDState *s = ADB_KEYBOARD(d);
int adb_keycode, keycode;
int olen;
......@@ -203,7 +241,7 @@ static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
const uint8_t *buf, int len)
{
KBDState *s = d->opaque;
KBDState *s = ADB_KEYBOARD(d);
int cmd, reg, olen;
if ((buf[0] & 0x0f) == ADB_FLUSH) {
......@@ -275,41 +313,90 @@ static const VMStateDescription vmstate_adb_kbd = {
}
};
static int adb_kbd_reset(ADBDevice *d)
static void adb_kbd_reset(DeviceState *dev)
{
KBDState *s = d->opaque;
ADBDevice *d = ADB_DEVICE(dev);
KBDState *s = ADB_KEYBOARD(dev);
d->handler = 1;
d->devaddr = ADB_KEYBOARD;
memset(s, 0, sizeof(KBDState));
return 0;
d->devaddr = ADB_DEVID_KEYBOARD;
memset(s->data, 0, sizeof(s->data));
s->rptr = 0;
s->wptr = 0;
s->count = 0;
}
void adb_kbd_init(ADBBusState *bus)
static void adb_kbd_realizefn(DeviceState *dev, Error **errp)
{
ADBDevice *d;
KBDState *s;
s = g_malloc0(sizeof(KBDState));
d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
adb_kbd_reset, s);
ADBDevice *d = ADB_DEVICE(dev);
ADBKeyboardClass *akc = ADB_KEYBOARD_GET_CLASS(dev);
akc->parent_realize(dev, errp);
qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
vmstate_register(NULL, -1, &vmstate_adb_kbd, s);
}
static void adb_kbd_initfn(Object *obj)
{
ADBDevice *d = ADB_DEVICE(obj);
d->devaddr = ADB_DEVID_KEYBOARD;
}
static void adb_kbd_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
ADBKeyboardClass *akc = ADB_KEYBOARD_CLASS(oc);
akc->parent_realize = dc->realize;
dc->realize = adb_kbd_realizefn;
adc->devreq = adb_kbd_request;
dc->reset = adb_kbd_reset;
dc->vmsd = &vmstate_adb_kbd;
}
static const TypeInfo adb_kbd_type_info = {
.name = TYPE_ADB_KEYBOARD,
.parent = TYPE_ADB_DEVICE,
.instance_size = sizeof(KBDState),
.instance_init = adb_kbd_initfn,
.class_init = adb_kbd_class_init,
.class_size = sizeof(ADBKeyboardClass),
};
/***************************************************************/
/* Mouse ADB device */
#define ADB_MOUSE(obj) OBJECT_CHECK(MouseState, (obj), TYPE_ADB_MOUSE)
typedef struct MouseState {
/*< public >*/
ADBDevice parent_obj;
/*< private >*/
int buttons_state, last_buttons_state;
int dx, dy, dz;
} MouseState;
#define ADB_MOUSE_CLASS(class) \
OBJECT_CLASS_CHECK(ADBMouseClass, (class), TYPE_ADB_MOUSE)
#define ADB_MOUSE_GET_CLASS(obj) \
OBJECT_GET_CLASS(ADBMouseClass, (obj), TYPE_ADB_MOUSE)
typedef struct ADBMouseClass {
/*< public >*/
ADBDeviceClass parent_class;
/*< private >*/
DeviceRealize parent_realize;
} ADBMouseClass;
static void adb_mouse_event(void *opaque,
int dx1, int dy1, int dz1, int buttons_state)
{
ADBDevice *d = opaque;
MouseState *s = d->opaque;
MouseState *s = opaque;
s->dx += dx1;
s->dy += dy1;
......@@ -320,7 +407,7 @@ static void adb_mouse_event(void *opaque,
static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
{
MouseState *s = d->opaque;
MouseState *s = ADB_MOUSE(d);
int dx, dy;
if (s->last_buttons_state == s->buttons_state &&
......@@ -359,7 +446,7 @@ static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
const uint8_t *buf, int len)
{
MouseState *s = d->opaque;
MouseState *s = ADB_MOUSE(d);
int cmd, reg, olen;
if ((buf[0] & 0x0f) == ADB_FLUSH) {
......@@ -416,15 +503,15 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
return olen;
}
static int adb_mouse_reset(ADBDevice *d)
static void adb_mouse_reset(DeviceState *dev)
{
MouseState *s = d->opaque;
ADBDevice *d = ADB_DEVICE(dev);
MouseState *s = ADB_MOUSE(dev);
d->handler = 2;
d->devaddr = ADB_MOUSE;
memset(s, 0, sizeof(MouseState));
return 0;
d->devaddr = ADB_DEVID_MOUSE;
s->last_buttons_state = s->buttons_state = 0;
s->dx = s->dy = s->dz = 0;
}
static const VMStateDescription vmstate_adb_mouse = {
......@@ -442,14 +529,53 @@ static const VMStateDescription vmstate_adb_mouse = {
}
};
void adb_mouse_init(ADBBusState *bus)
static void adb_mouse_realizefn(DeviceState *dev, Error **errp)
{
ADBDevice *d;
MouseState *s;
MouseState *s = ADB_MOUSE(dev);
ADBMouseClass *amc = ADB_MOUSE_GET_CLASS(dev);
amc->parent_realize(dev, errp);
qemu_add_mouse_event_handler(adb_mouse_event, s, 0, "QEMU ADB Mouse");
}
static void adb_mouse_initfn(Object *obj)
{
ADBDevice *d = ADB_DEVICE(obj);
d->devaddr = ADB_DEVID_MOUSE;
}
static void adb_mouse_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
ADBDeviceClass *adc = ADB_DEVICE_CLASS(oc);
ADBMouseClass *amc = ADB_MOUSE_CLASS(oc);
amc->parent_realize = dc->realize;
dc->realize = adb_mouse_realizefn;
s = g_malloc0(sizeof(MouseState));
d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
adb_mouse_reset, s);
qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
vmstate_register(NULL, -1, &vmstate_adb_mouse, s);
adc->devreq = adb_mouse_request;
dc->reset = adb_mouse_reset;
dc->vmsd = &vmstate_adb_mouse;
}
static const TypeInfo adb_mouse_type_info = {
.name = TYPE_ADB_MOUSE,
.parent = TYPE_ADB_DEVICE,
.instance_size = sizeof(MouseState),
.instance_init = adb_mouse_initfn,
.class_init = adb_mouse_class_init,
.class_size = sizeof(ADBMouseClass),
};
static void adb_register_types(void)
{
type_register_static(&adb_bus_type_info);
type_register_static(&adb_device_type_info);
type_register_static(&adb_kbd_type_info);
type_register_static(&adb_mouse_type_info);
}
type_init(adb_register_types)
......@@ -26,38 +26,62 @@
#if !defined(__ADB_H__)
#define __ADB_H__
#include "qdev.h"
#define MAX_ADB_DEVICES 16
#define ADB_MAX_OUT_LEN 16
typedef struct ADBBusState ADBBusState;
typedef struct ADBDevice ADBDevice;
/* buf = NULL means polling */
typedef int ADBDeviceRequest(ADBDevice *d, uint8_t *buf_out,
const uint8_t *buf, int len);
typedef int ADBDeviceReset(ADBDevice *d);
#define TYPE_ADB_DEVICE "adb-device"
#define ADB_DEVICE(obj) OBJECT_CHECK(ADBDevice, (obj), TYPE_ADB_DEVICE)
struct ADBDevice {
struct ADBBusState *bus;
/*< private >*/
DeviceState parent_obj;
/*< public >*/
int devaddr;
int handler;
ADBDeviceRequest *devreq;
ADBDeviceReset *devreset;
void *opaque;
};
typedef struct ADBBusState {
ADBDevice devices[MAX_ADB_DEVICES];
#define ADB_DEVICE_CLASS(cls) \
OBJECT_CLASS_CHECK(ADBDeviceClass, (cls), TYPE_ADB_DEVICE)
#define ADB_DEVICE_GET_CLASS(obj) \
OBJECT_GET_CLASS(ADBDeviceClass, (obj), TYPE_ADB_DEVICE)
typedef struct ADBDeviceClass {
/*< private >*/
DeviceClass parent_class;
/*< public >*/
ADBDeviceRequest *devreq;
} ADBDeviceClass;
#define TYPE_ADB_BUS "apple-desktop-bus"
#define ADB_BUS(obj) OBJECT_CHECK(ADBBusState, (obj), TYPE_ADB_BUS)
struct ADBBusState {
/*< private >*/
BusState parent_obj;
/*< public >*/
ADBDevice *devices[MAX_ADB_DEVICES];
int nb_devices;
int poll_index;
} ADBBusState;
};
int adb_request(ADBBusState *s, uint8_t *buf_out,
const uint8_t *buf, int len);
int adb_poll(ADBBusState *s, uint8_t *buf_out);
void adb_kbd_init(ADBBusState *bus);
void adb_mouse_init(ADBBusState *bus);
#define TYPE_ADB_KEYBOARD "adb-keyboard"
#define TYPE_ADB_MOUSE "adb-mouse"
extern ADBBusState adb_bus;
#endif /* !defined(__ADB_H__) */
......@@ -23,7 +23,7 @@
* THE SOFTWARE.
*/
#include "hw.h"
#include "ppc_mac.h"
#include "ppc/mac.h"
#include "adb.h"
#include "qemu/timer.h"
#include "sysemu/sysemu.h"
......@@ -108,50 +108,6 @@
/* CUDA returns time_t's offset from Jan 1, 1904, not 1970 */
#define RTC_OFFSET 2082844800
typedef struct CUDATimer {
int index;
uint16_t latch;
uint16_t counter_value; /* counter value at load time */
int64_t load_time;
int64_t next_irq_time;
QEMUTimer *timer;
} CUDATimer;
typedef struct CUDAState {
MemoryRegion mem;
/* cuda registers */
uint8_t b; /* B-side data */
uint8_t a; /* A-side data */
uint8_t dirb; /* B-side direction (1=output) */
uint8_t dira; /* A-side direction (1=output) */
uint8_t sr; /* Shift register */
uint8_t acr; /* Auxiliary control register */
uint8_t pcr; /* Peripheral control register */
uint8_t ifr; /* Interrupt flag register */
uint8_t ier; /* Interrupt enable register */
uint8_t anh; /* A-side data, no handshake */
CUDATimer timers[2];
uint32_t tick_offset;
uint8_t last_b; /* last value of B register */
uint8_t last_acr; /* last value of B register */
int data_in_size;
int data_in_index;
int data_out_index;
qemu_irq irq;
uint8_t autopoll;
uint8_t data_in[128];
uint8_t data_out[16];
QEMUTimer *adb_poll_timer;
} CUDAState;
static CUDAState cuda_state;
ADBBusState adb_bus;
static void cuda_update(CUDAState *s);
static void cuda_receive_packet_from_host(CUDAState *s,
const uint8_t *data, int len);
......@@ -501,7 +457,7 @@ static void cuda_adb_poll(void *opaque)
uint8_t obuf[ADB_MAX_OUT_LEN + 2];
int olen;
olen = adb_poll(&adb_bus, obuf + 2);
olen = adb_poll(&s->adb_bus, obuf + 2);
if (olen > 0) {
obuf[0] = ADB_PACKET;
obuf[1] = 0x40; /* polled data */
......@@ -597,7 +553,7 @@ static void cuda_receive_packet_from_host(CUDAState *s,
{
uint8_t obuf[ADB_MAX_OUT_LEN + 2];
int olen;
olen = adb_request(&adb_bus, obuf + 2, data + 1, len - 1);
olen = adb_request(&s->adb_bus, obuf + 2, data + 1, len - 1);
if (olen > 0) {
obuf[0] = ADB_PACKET;
obuf[1] = 0x00;
......@@ -701,9 +657,9 @@ static const VMStateDescription vmstate_cuda = {
}
};
static void cuda_reset(void *opaque)
static void cuda_reset(DeviceState *dev)
{
CUDAState *s = opaque;
CUDAState *s = CUDA(dev);
s->b = 0;
s->a = 0;
......@@ -728,25 +684,57 @@ static void cuda_reset(void *opaque)
set_counter(s, &s->timers[1], 0xffff);
}
void cuda_init (MemoryRegion **cuda_mem, qemu_irq irq)
static void cuda_realizefn(DeviceState *dev, Error **errp)
{
CUDAState *s = CUDA(dev);
struct tm tm;
CUDAState *s = &cuda_state;
s->irq = irq;
s->timers[0].index = 0;
s->timers[0].timer = qemu_new_timer_ns(vm_clock, cuda_timer1, s);
s->timers[1].index = 1;
qemu_get_timedate(&tm, 0);
s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
s->adb_poll_timer = qemu_new_timer_ns(vm_clock, cuda_adb_poll, s);
}
static void cuda_initfn(Object *obj)
{
SysBusDevice *d = SYS_BUS_DEVICE(obj);
CUDAState *s = CUDA(obj);
int i;
memory_region_init_io(&s->mem, &cuda_ops, s, "cuda", 0x2000);
sysbus_init_mmio(d, &s->mem);
sysbus_init_irq(d, &s->irq);
for (i = 0; i < ARRAY_SIZE(s->timers); i++) {
s->timers[i].index = i;
}
*cuda_mem = &s->mem;
vmstate_register(NULL, -1, &vmstate_cuda, s);
qemu_register_reset(cuda_reset, s);
qbus_create_inplace((BusState *)&s->adb_bus, TYPE_ADB_BUS, DEVICE(obj),
"adb.0");
}
static void cuda_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = cuda_realizefn;
dc->reset = cuda_reset;
dc->vmsd = &vmstate_cuda;
}
static const TypeInfo cuda_type_info = {
.name = TYPE_CUDA,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(CUDAState),
.instance_init = cuda_initfn,
.class_init = cuda_class_init,
};
static void cuda_register_types(void)
{
type_register_static(&cuda_type_info);
}
type_init(cuda_register_types)
......@@ -24,7 +24,7 @@
*/
#include "pci/pci_host.h"
#include "ppc_mac.h"
#include "ppc/mac.h"
#include "pci/pci.h"
/* debug Grackle */
......
......@@ -23,7 +23,7 @@
* THE SOFTWARE.
*/
#include "hw.h"
#include "ppc_mac.h"
#include "ppc/mac.h"
/* debug PIC */
//#define DEBUG_PIC
......
......@@ -19,10 +19,6 @@ PCIDevice *pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn);
PCIDevice *pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn);
void vt82c686b_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn);
/* ide-macio.c */
MemoryRegion *pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
void *dbdma, int channel, qemu_irq dma_irq);
/* ide-mmio.c */
void mmio_ide_init (hwaddr membase, hwaddr membase2,
MemoryRegion *address_space,
......
......@@ -22,9 +22,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <hw/hw.h>
#include <hw/ppc_mac.h>
#include <hw/mac_dbdma.h>
#include "hw/hw.h"
#include "hw/ppc/mac.h"
#include "hw/mac_dbdma.h"
#include "block/block.h"
#include "sysemu/dma.h"
......@@ -33,12 +33,6 @@
/***********************************************************/
/* MacIO based PowerPC IDE */
typedef struct MACIOIDEState {
MemoryRegion mem;
IDEBus bus;
BlockDriverAIOCB *aiocb;
} MACIOIDEState;
#define MACIO_PAGE_SIZE 4096
static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
......@@ -321,30 +315,70 @@ static const VMStateDescription vmstate_pmac = {
}
};
static void pmac_ide_reset(void *opaque)
static void macio_ide_reset(DeviceState *dev)
{
MACIOIDEState *d = opaque;
MACIOIDEState *d = MACIO_IDE(dev);
ide_bus_reset(&d->bus);
}
/* hd_table must contain 4 block drivers */
/* PowerMac uses memory mapped registers, not I/O. Return the memory
I/O index to access the ide. */
MemoryRegion *pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
void *dbdma, int channel, qemu_irq dma_irq)
static void macio_ide_realizefn(DeviceState *dev, Error **errp)
{
MACIOIDEState *d;
MACIOIDEState *s = MACIO_IDE(dev);
ide_init2(&s->bus, s->irq);
}
static void macio_ide_initfn(Object *obj)
{
SysBusDevice *d = SYS_BUS_DEVICE(obj);
MACIOIDEState *s = MACIO_IDE(obj);
ide_bus_new(&s->bus, DEVICE(obj), 0);
memory_region_init_io(&s->mem, &pmac_ide_ops, s, "pmac-ide", 0x1000);
sysbus_init_mmio(d, &s->mem);
sysbus_init_irq(d, &s->irq);
sysbus_init_irq(d, &s->dma_irq);
}
static void macio_ide_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = macio_ide_realizefn;
dc->reset = macio_ide_reset;
dc->vmsd = &vmstate_pmac;
}
d = g_malloc0(sizeof(MACIOIDEState));
ide_init2_with_non_qdev_drives(&d->bus, hd_table[0], hd_table[1], irq);
static const TypeInfo macio_ide_type_info = {
.name = TYPE_MACIO_IDE,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MACIOIDEState),
.instance_init = macio_ide_initfn,
.class_init = macio_ide_class_init,
};
if (dbdma)
DBDMA_register_channel(dbdma, channel, dma_irq, pmac_ide_transfer, pmac_ide_flush, d);
static void macio_ide_register_types(void)
{
type_register_static(&macio_ide_type_info);
}
memory_region_init_io(&d->mem, &pmac_ide_ops, d, "pmac-ide", 0x1000);
vmstate_register(NULL, 0, &vmstate_pmac, d);
qemu_register_reset(pmac_ide_reset, d);
/* hd_table must contain 4 block drivers */
void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table)
{
int i;
return &d->mem;
for (i = 0; i < 2; i++) {
if (hd_table[i]) {
ide_create_drive(&s->bus, i, hd_table[i]);
}
}
}
void macio_ide_register_dma(MACIOIDEState *s, void *dbdma, int channel)
{
DBDMA_register_channel(dbdma, channel, s->dma_irq,
pmac_ide_transfer, pmac_ide_flush, s);
}
type_init(macio_ide_register_types)
......@@ -25,7 +25,7 @@
#include "hw.h"
#include "firmware_abi.h"
#include "sysemu/sysemu.h"
#include "ppc_mac.h"
#include "ppc/mac.h"
/* debug NVR */
//#define DEBUG_NVR
......@@ -37,37 +37,29 @@
#define NVR_DPRINTF(fmt, ...)
#endif
struct MacIONVRAMState {
uint32_t size;
MemoryRegion mem;
unsigned int it_shift;
uint8_t *data;
};
#define DEF_SYSTEM_SIZE 0xc10
/* Direct access to NVRAM */
uint32_t macio_nvram_read (void *opaque, uint32_t addr)
uint8_t macio_nvram_read(MacIONVRAMState *s, uint32_t addr)
{
MacIONVRAMState *s = opaque;
uint32_t ret;
if (addr < s->size)
if (addr < s->size) {
ret = s->data[addr];
else
} else {
ret = -1;
NVR_DPRINTF("read addr %04x val %x\n", addr, ret);
}
NVR_DPRINTF("read addr %04" PRIx32 " val %" PRIx8 "\n", addr, ret);
return ret;
}
void macio_nvram_write (void *opaque, uint32_t addr, uint32_t val)
void macio_nvram_write(MacIONVRAMState *s, uint32_t addr, uint8_t val)
{
MacIONVRAMState *s = opaque;
NVR_DPRINTF("write addr %04x val %x\n", addr, val);
if (addr < s->size)
NVR_DPRINTF("write addr %04" PRIx32 " val %" PRIx8 "\n", addr, val);
if (addr < s->size) {
s->data[addr] = val;
}
}
/* macio style NVRAM device */
......@@ -78,7 +70,7 @@ static void macio_nvram_writeb(void *opaque, hwaddr addr,
addr = (addr >> s->it_shift) & (s->size - 1);
s->data[addr] = value;
NVR_DPRINTF("writeb addr %04x val %x\n", (int)addr, value);
NVR_DPRINTF("writeb addr %04" PHYS_PRIx " val %" PRIx64 "\n", addr, value);
}
static uint64_t macio_nvram_readb(void *opaque, hwaddr addr,
......@@ -97,7 +89,7 @@ static uint64_t macio_nvram_readb(void *opaque, hwaddr addr,
static const MemoryRegionOps macio_nvram_ops = {
.read = macio_nvram_readb,
.write = macio_nvram_writeb,
.endianness = DEVICE_NATIVE_ENDIAN,
.endianness = DEVICE_BIG_ENDIAN,
};
static const VMStateDescription vmstate_macio_nvram = {
......@@ -112,32 +104,56 @@ static const VMStateDescription vmstate_macio_nvram = {
};
static void macio_nvram_reset(void *opaque)
static void macio_nvram_reset(DeviceState *dev)
{
}
MacIONVRAMState *macio_nvram_init (hwaddr size,
unsigned int it_shift)
static void macio_nvram_realizefn(DeviceState *dev, Error **errp)
{
MacIONVRAMState *s;
SysBusDevice *d = SYS_BUS_DEVICE(dev);
MacIONVRAMState *s = MACIO_NVRAM(dev);
s = g_malloc0(sizeof(MacIONVRAMState));
s->data = g_malloc0(size);
s->size = size;
s->it_shift = it_shift;
s->data = g_malloc0(s->size);
memory_region_init_io(&s->mem, &macio_nvram_ops, s, "macio-nvram",
size << it_shift);
vmstate_register(NULL, -1, &vmstate_macio_nvram, s);
qemu_register_reset(macio_nvram_reset, s);
s->size << s->it_shift);
sysbus_init_mmio(d, &s->mem);
}
static void macio_nvram_unrealizefn(DeviceState *dev, Error **errp)
{
MacIONVRAMState *s = MACIO_NVRAM(dev);
return s;
g_free(s->data);
}
void macio_nvram_setup_bar(MacIONVRAMState *s, MemoryRegion *bar,
hwaddr mem_base)
static Property macio_nvram_properties[] = {
DEFINE_PROP_UINT32("size", MacIONVRAMState, size, 0),
DEFINE_PROP_UINT32("it_shift", MacIONVRAMState, it_shift, 0),
DEFINE_PROP_END_OF_LIST()
};
static void macio_nvram_class_init(ObjectClass *oc, void *data)
{
memory_region_add_subregion(bar, mem_base, &s->mem);
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = macio_nvram_realizefn;
dc->unrealize = macio_nvram_unrealizefn;
dc->reset = macio_nvram_reset;
dc->vmsd = &vmstate_macio_nvram;
dc->props = macio_nvram_properties;
}
static const TypeInfo macio_nvram_type_info = {
.name = TYPE_MACIO_NVRAM,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MacIONVRAMState),
.class_init = macio_nvram_class_init,
};
static void macio_nvram_register_types(void)
{
type_register_static(&macio_nvram_type_info);
}
/* Set up a system OpenBIOS NVRAM partition */
......@@ -176,3 +192,5 @@ void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len)
end = len;
OpenBIOS_finish_partition(part_header, end - start);
}
type_init(macio_nvram_register_types)
......@@ -23,118 +23,283 @@
* THE SOFTWARE.
*/
#include "hw.h"
#include "ppc_mac.h"
#include "ppc/mac.h"
#include "pci/pci.h"
#include "mac_dbdma.h"
#include "escc.h"
#define TYPE_MACIO "macio"
#define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO)
typedef struct MacIOState
{
/*< private >*/
PCIDevice parent;
int is_oldworld;
/*< public >*/
MemoryRegion bar;
CUDAState cuda;
void *dbdma;
MemoryRegion *pic_mem;
MemoryRegion *dbdma_mem;
MemoryRegion *cuda_mem;
MemoryRegion *escc_mem;
void *nvram;
int nb_ide;
MemoryRegion *ide_mem[4];
} MacIOState;
#define OLDWORLD_MACIO(obj) \
OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO)
typedef struct OldWorldMacIOState {
/*< private >*/
MacIOState parent_obj;
/*< public >*/
qemu_irq irqs[3];
MacIONVRAMState nvram;
MACIOIDEState ide;
} OldWorldMacIOState;
#define NEWWORLD_MACIO(obj) \
OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO)
typedef struct NewWorldMacIOState {
/*< private >*/
MacIOState parent_obj;
/*< public >*/
qemu_irq irqs[5];
MACIOIDEState ide[2];
} NewWorldMacIOState;
static void macio_bar_setup(MacIOState *macio_state)
{
int i;
MemoryRegion *bar = &macio_state->bar;
memory_region_init(bar, "macio", 0x80000);
if (macio_state->pic_mem) {
if (macio_state->is_oldworld) {
/* Heathrow PIC */
memory_region_add_subregion(bar, 0x00000, macio_state->pic_mem);
} else {
/* OpenPIC */
memory_region_add_subregion(bar, 0x40000, macio_state->pic_mem);
}
}
if (macio_state->dbdma_mem) {
memory_region_add_subregion(bar, 0x08000, macio_state->dbdma_mem);
}
if (macio_state->escc_mem) {
memory_region_add_subregion(bar, 0x13000, macio_state->escc_mem);
}
if (macio_state->cuda_mem) {
memory_region_add_subregion(bar, 0x16000, macio_state->cuda_mem);
}
static int macio_common_initfn(PCIDevice *d)
{
MacIOState *s = MACIO(d);
SysBusDevice *sysbus_dev;
int ret;
d->config[0x3d] = 0x01; // interrupt on pin 1
ret = qdev_init(DEVICE(&s->cuda));
if (ret < 0) {
return ret;
}
for (i = 0; i < macio_state->nb_ide; i++) {
if (macio_state->ide_mem[i]) {
memory_region_add_subregion(bar, 0x1f000 + (i * 0x1000),
macio_state->ide_mem[i]);
}
sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
memory_region_add_subregion(&s->bar, 0x16000,
sysbus_mmio_get_region(sysbus_dev, 0));
macio_bar_setup(s);
pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar);
return 0;
}
static int macio_oldworld_initfn(PCIDevice *d)
{
MacIOState *s = MACIO(d);
OldWorldMacIOState *os = OLDWORLD_MACIO(d);
SysBusDevice *sysbus_dev;
int ret = macio_common_initfn(d);
if (ret < 0) {
return ret;
}
sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
sysbus_connect_irq(sysbus_dev, 0, os->irqs[0]);
ret = qdev_init(DEVICE(&os->nvram));
if (ret < 0) {
return ret;
}
if (macio_state->nvram != NULL)
macio_nvram_setup_bar(macio_state->nvram, bar, 0x60000);
sysbus_dev = SYS_BUS_DEVICE(&os->nvram);
memory_region_add_subregion(&s->bar, 0x60000,
sysbus_mmio_get_region(sysbus_dev, 0));
pmac_format_nvram_partition(&os->nvram, os->nvram.size);
if (s->pic_mem) {
/* Heathrow PIC */
memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem);
}
sysbus_dev = SYS_BUS_DEVICE(&os->ide);
sysbus_connect_irq(sysbus_dev, 0, os->irqs[1]);
sysbus_connect_irq(sysbus_dev, 1, os->irqs[2]);
macio_ide_register_dma(&os->ide, s->dbdma, 0x16);
ret = qdev_init(DEVICE(&os->ide));
if (ret < 0) {
return ret;
}
return 0;
}
static int macio_initfn(PCIDevice *d)
static void macio_oldworld_init(Object *obj)
{
d->config[0x3d] = 0x01; // interrupt on pin 1
MacIOState *s = MACIO(obj);
OldWorldMacIOState *os = OLDWORLD_MACIO(obj);
DeviceState *dev;
qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs));
object_initialize(&os->nvram, TYPE_MACIO_NVRAM);
dev = DEVICE(&os->nvram);
qdev_prop_set_uint32(dev, "size", 0x2000);
qdev_prop_set_uint32(dev, "it_shift", 4);
object_initialize(&os->ide, TYPE_MACIO_IDE);
qdev_set_parent_bus(DEVICE(&os->ide), sysbus_get_default());
memory_region_add_subregion(&s->bar, 0x1f000 + (1 * 0x1000), &os->ide.mem);
object_property_add_child(obj, "ide", OBJECT(&os->ide), NULL);
}
static int macio_newworld_initfn(PCIDevice *d)
{
MacIOState *s = MACIO(d);
NewWorldMacIOState *ns = NEWWORLD_MACIO(d);
SysBusDevice *sysbus_dev;
int ret = macio_common_initfn(d);
if (ret < 0) {
return ret;
}
sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
sysbus_connect_irq(sysbus_dev, 0, ns->irqs[0]);
if (s->pic_mem) {
/* OpenPIC */
memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem);
}
sysbus_dev = SYS_BUS_DEVICE(&ns->ide[0]);
sysbus_connect_irq(sysbus_dev, 0, ns->irqs[1]);
sysbus_connect_irq(sysbus_dev, 1, ns->irqs[2]);
macio_ide_register_dma(&ns->ide[0], s->dbdma, 0x16);
ret = qdev_init(DEVICE(&ns->ide[0]));
if (ret < 0) {
return ret;
}
sysbus_dev = SYS_BUS_DEVICE(&ns->ide[1]);
sysbus_connect_irq(sysbus_dev, 0, ns->irqs[3]);
sysbus_connect_irq(sysbus_dev, 1, ns->irqs[4]);
macio_ide_register_dma(&ns->ide[0], s->dbdma, 0x1a);
ret = qdev_init(DEVICE(&ns->ide[1]));
if (ret < 0) {
return ret;
}
return 0;
}
static void macio_newworld_init(Object *obj)
{
MacIOState *s = MACIO(obj);
NewWorldMacIOState *ns = NEWWORLD_MACIO(obj);
int i;
gchar *name;
qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs));
for (i = 0; i < 2; i++) {
object_initialize(&ns->ide[i], TYPE_MACIO_IDE);
qdev_set_parent_bus(DEVICE(&ns->ide[i]), sysbus_get_default());
memory_region_add_subregion(&s->bar, 0x1f000 + ((i + 1) * 0x1000),
&ns->ide[i].mem);
name = g_strdup_printf("ide[%i]", i);
object_property_add_child(obj, name, OBJECT(&ns->ide[i]), NULL);
g_free(name);
}
}
static void macio_instance_init(Object *obj)
{
MacIOState *s = MACIO(obj);
MemoryRegion *dbdma_mem;
memory_region_init(&s->bar, "macio", 0x80000);
object_initialize(&s->cuda, TYPE_CUDA);
qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default());
object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL);
s->dbdma = DBDMA_init(&dbdma_mem);
memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem);
}
static void macio_oldworld_class_init(ObjectClass *oc, void *data)
{
PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
pdc->init = macio_oldworld_initfn;
pdc->device_id = PCI_DEVICE_ID_APPLE_343S1201;
}
static void macio_newworld_class_init(ObjectClass *oc, void *data)
{
PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
pdc->init = macio_newworld_initfn;
pdc->device_id = PCI_DEVICE_ID_APPLE_UNI_N_KEYL;
}
static void macio_class_init(ObjectClass *klass, void *data)
{
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->init = macio_initfn;
k->vendor_id = PCI_VENDOR_ID_APPLE;
k->class_id = PCI_CLASS_OTHERS << 8;
}
static const TypeInfo macio_info = {
.name = "macio",
static const TypeInfo macio_oldworld_type_info = {
.name = TYPE_OLDWORLD_MACIO,
.parent = TYPE_MACIO,
.instance_size = sizeof(OldWorldMacIOState),
.instance_init = macio_oldworld_init,
.class_init = macio_oldworld_class_init,
};
static const TypeInfo macio_newworld_type_info = {
.name = TYPE_NEWWORLD_MACIO,
.parent = TYPE_MACIO,
.instance_size = sizeof(NewWorldMacIOState),
.instance_init = macio_newworld_init,
.class_init = macio_newworld_class_init,
};
static const TypeInfo macio_type_info = {
.name = TYPE_MACIO,
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(MacIOState),
.instance_init = macio_instance_init,
.abstract = true,
.class_init = macio_class_init,
};
static void macio_register_types(void)
{
type_register_static(&macio_info);
type_register_static(&macio_type_info);
type_register_static(&macio_oldworld_type_info);
type_register_static(&macio_newworld_type_info);
}
type_init(macio_register_types)
void macio_init (PCIBus *bus, int device_id, int is_oldworld,
MemoryRegion *pic_mem, MemoryRegion *dbdma_mem,
MemoryRegion *cuda_mem, void *nvram,
int nb_ide, MemoryRegion **ide_mem,
MemoryRegion *escc_mem)
void macio_init(PCIDevice *d,
MemoryRegion *pic_mem,
MemoryRegion *escc_mem)
{
PCIDevice *d;
MacIOState *macio_state;
int i;
MacIOState *macio_state = MACIO(d);
d = pci_create_simple(bus, -1, "macio");
macio_state = DO_UPCAST(MacIOState, parent, d);
macio_state->is_oldworld = is_oldworld;
macio_state->pic_mem = pic_mem;
macio_state->dbdma_mem = dbdma_mem;
macio_state->cuda_mem = cuda_mem;
macio_state->escc_mem = escc_mem;
macio_state->nvram = nvram;
if (nb_ide > 4)
nb_ide = 4;
macio_state->nb_ide = nb_ide;
for (i = 0; i < nb_ide; i++)
macio_state->ide_mem[i] = ide_mem[i];
for (; i < 4; i++)
macio_state->ide_mem[i] = NULL;
/* Note: this code is strongly inspirated from the corresponding code
in PearPC */
pci_config_set_device_id(d->config, device_id);
macio_bar_setup(macio_state);
pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &macio_state->bar);
qdev_init_nofail(DEVICE(d));
}
......@@ -34,7 +34,7 @@
*
*/
#include "hw.h"
#include "ppc_mac.h"
#include "ppc/mac.h"
#include "pci/pci.h"
#include "openpic.h"
#include "sysbus.h"
......@@ -56,7 +56,7 @@ static const int debug_openpic = 0;
} \
} while (0)
#define MAX_CPU 15
#define MAX_CPU 32
#define MAX_SRC 256
#define MAX_TMR 4
#define MAX_IPI 4
......@@ -66,6 +66,7 @@ static const int debug_openpic = 0;
/* OpenPIC capability flags */
#define OPENPIC_FLAG_IDR_CRIT (1 << 0)
#define OPENPIC_FLAG_ILR (2 << 0)
/* OpenPIC address map */
#define OPENPIC_GLB_REG_START 0x0
......@@ -74,6 +75,8 @@ static const int debug_openpic = 0;
#define OPENPIC_TMR_REG_SIZE 0x220
#define OPENPIC_MSI_REG_START 0x1600
#define OPENPIC_MSI_REG_SIZE 0x200
#define OPENPIC_SUMMARY_REG_START 0x3800
#define OPENPIC_SUMMARY_REG_SIZE 0x800
#define OPENPIC_SRC_REG_START 0x10000
#define OPENPIC_SRC_REG_SIZE (MAX_SRC * 0x20)
#define OPENPIC_CPU_REG_START 0x20000
......@@ -94,33 +97,17 @@ static const int debug_openpic = 0;
/* First doorbell IRQ */
#define RAVEN_DBL_IRQ (RAVEN_IPI_IRQ + (RAVEN_MAX_CPU * RAVEN_MAX_IPI))
/* FSL_MPIC_20 */
#define FSL_MPIC_20_MAX_CPU 1
#define FSL_MPIC_20_MAX_EXT 12
#define FSL_MPIC_20_MAX_INT 64
#define FSL_MPIC_20_MAX_IRQ MAX_IRQ
typedef struct FslMpicInfo {
int max_ext;
} FslMpicInfo;
/* Interrupt definitions */
/* IRQs, accessible through the IRQ region */
#define FSL_MPIC_20_EXT_IRQ 0x00
#define FSL_MPIC_20_INT_IRQ 0x10
#define FSL_MPIC_20_MSG_IRQ 0xb0
#define FSL_MPIC_20_MSI_IRQ 0xe0
/* These are available through separate regions, but
for simplicity's sake mapped into the same number space */
#define FSL_MPIC_20_TMR_IRQ 0x100
#define FSL_MPIC_20_IPI_IRQ 0x104
static FslMpicInfo fsl_mpic_20 = {
.max_ext = 12,
};
/*
* Block Revision Register1 (BRR1): QEMU does not fully emulate
* any version on MPIC. So to start with, set the IP version to 0.
*
* NOTE: This is Freescale MPIC specific register. Keep it here till
* this code is refactored for different variants of OPENPIC and MPIC.
*/
#define FSL_BRR1_IPID (0x0040 << 16) /* 16 bit IP-block ID */
#define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */
#define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */
static FslMpicInfo fsl_mpic_42 = {
.max_ext = 12,
};
#define FRR_NIRQ_SHIFT 16
#define FRR_NCPU_SHIFT 8
......@@ -146,6 +133,49 @@ static const int debug_openpic = 0;
#define IDR_P1_SHIFT 1
#define IDR_P0_SHIFT 0
#define ILR_INTTGT_MASK 0x000000ff
#define ILR_INTTGT_INT 0x00
#define ILR_INTTGT_CINT 0x01 /* critical */
#define ILR_INTTGT_MCP 0x02 /* machine check */
/* The currently supported INTTGT values happen to be the same as QEMU's
* openpic output codes, but don't depend on this. The output codes
* could change (unlikely, but...) or support could be added for
* more INTTGT values.
*/
static const int inttgt_output[][2] = {
{ ILR_INTTGT_INT, OPENPIC_OUTPUT_INT },
{ ILR_INTTGT_CINT, OPENPIC_OUTPUT_CINT },
{ ILR_INTTGT_MCP, OPENPIC_OUTPUT_MCK },
};
static int inttgt_to_output(int inttgt)
{
int i;
for (i = 0; i < ARRAY_SIZE(inttgt_output); i++) {
if (inttgt_output[i][0] == inttgt) {
return inttgt_output[i][1];
}
}
fprintf(stderr, "%s: unsupported inttgt %d\n", __func__, inttgt);
return OPENPIC_OUTPUT_INT;
}
static int output_to_inttgt(int output)
{
int i;
for (i = 0; i < ARRAY_SIZE(inttgt_output); i++) {
if (inttgt_output[i][1] == output) {
return inttgt_output[i][0];
}
}
abort();
}
#define MSIIR_OFFSET 0x140
#define MSIIR_SRS_SHIFT 29
#define MSIIR_SRS_MASK (0x7 << MSIIR_SRS_SHIFT)
......@@ -230,6 +260,7 @@ typedef struct OpenPICState {
MemoryRegion mem;
/* Behavior control */
FslMpicInfo *fsl;
uint32_t model;
uint32_t flags;
uint32_t nb_irqs;
......@@ -243,7 +274,7 @@ typedef struct OpenPICState {
uint32_t mpic_mode_mask;
/* Sub-regions */
MemoryRegion sub_io_mem[5];
MemoryRegion sub_io_mem[6];
/* Global registers */
uint32_t frr; /* Feature reporting register */
......@@ -436,13 +467,13 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
src->ivpr &= ~IVPR_ACTIVITY_MASK;
}
if (src->idr == 0) {
if (src->destmask == 0) {
/* No target */
DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
return;
}
if (src->idr == (1 << src->last_cpu)) {
if (src->destmask == (1 << src->last_cpu)) {
/* Only one CPU is allowed to receive this IRQ */
IRQ_local_pipe(opp, src->last_cpu, n_IRQ, active, was_active);
} else if (!(src->ivpr & IVPR_MODE_MASK)) {
......@@ -558,6 +589,15 @@ static inline uint32_t read_IRQreg_idr(OpenPICState *opp, int n_IRQ)
return opp->src[n_IRQ].idr;
}
static inline uint32_t read_IRQreg_ilr(OpenPICState *opp, int n_IRQ)
{
if (opp->flags & OPENPIC_FLAG_ILR) {
return output_to_inttgt(opp->src[n_IRQ].output);
}
return 0xffffffff;
}
static inline uint32_t read_IRQreg_ivpr(OpenPICState *opp, int n_IRQ)
{
return opp->src[n_IRQ].ivpr;
......@@ -608,6 +648,19 @@ static inline void write_IRQreg_idr(OpenPICState *opp, int n_IRQ, uint32_t val)
}
}
static inline void write_IRQreg_ilr(OpenPICState *opp, int n_IRQ, uint32_t val)
{
if (opp->flags & OPENPIC_FLAG_ILR) {
IRQSource *src = &opp->src[n_IRQ];
src->output = inttgt_to_output(val & ILR_INTTGT_MASK);
DPRINTF("Set ILR %d to 0x%08x, output %d\n", n_IRQ, src->idr,
src->output);
/* TODO: on MPIC v4.0 only, set nomask for non-INT */
}
}
static inline void write_IRQreg_ivpr(OpenPICState *opp, int n_IRQ, uint32_t val)
{
uint32_t mask;
......@@ -792,19 +845,23 @@ static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
OpenPICState *opp = opaque;
int idx;
addr += 0x10f0;
DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64 "\n",
__func__, addr, val);
if (addr & 0xF) {
return;
}
idx = (addr >> 6) & 0x3;
addr = addr & 0x30;
if (addr == 0x0) {
if (addr == 0x10f0) {
/* TFRR */
opp->tfrr = val;
return;
}
idx = (addr >> 6) & 0x3;
addr = addr & 0x30;
switch (addr & 0x30) {
case 0x00: /* TCCR */
break;
......@@ -870,17 +927,20 @@ static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64 "\n",
__func__, addr, val);
if (addr & 0xF) {
return;
}
addr = addr & 0xFFF0;
addr = addr & 0xffff;
idx = addr >> 5;
if (addr & 0x10) {
/* EXDE / IFEDE / IEEDE */
write_IRQreg_idr(opp, idx, val);
} else {
/* EXVP / IFEVP / IEEVP */
switch (addr & 0x1f) {
case 0x00:
write_IRQreg_ivpr(opp, idx, val);
break;
case 0x10:
write_IRQreg_idr(opp, idx, val);
break;
case 0x18:
write_IRQreg_ilr(opp, idx, val);
break;
}
}
......@@ -892,20 +952,23 @@ static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
retval = 0xFFFFFFFF;
if (addr & 0xF) {
return retval;
}
addr = addr & 0xFFF0;
addr = addr & 0xffff;
idx = addr >> 5;
if (addr & 0x10) {
/* EXDE / IFEDE / IEEDE */
retval = read_IRQreg_idr(opp, idx);
} else {
/* EXVP / IFEVP / IEEVP */
switch (addr & 0x1f) {
case 0x00:
retval = read_IRQreg_ivpr(opp, idx);
break;
case 0x10:
retval = read_IRQreg_idr(opp, idx);
break;
case 0x18:
retval = read_IRQreg_ilr(opp, idx);
break;
}
DPRINTF("%s: => 0x%08x\n", __func__, retval);
DPRINTF("%s: => 0x%08x\n", __func__, retval);
return retval;
}
......@@ -973,6 +1036,26 @@ static uint64_t openpic_msi_read(void *opaque, hwaddr addr, unsigned size)
return r;
}
static uint64_t openpic_summary_read(void *opaque, hwaddr addr, unsigned size)
{
uint64_t r = 0;
DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr);
/* TODO: EISR/EIMR */
return r;
}
static void openpic_summary_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
DPRINTF("%s: addr %#" HWADDR_PRIx " <= 0x%08" PRIx64 "\n",
__func__, addr, val);
/* TODO: EISR/EIMR */
}
static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
uint32_t val, int idx)
{
......@@ -1000,8 +1083,7 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
case 0x70:
idx = (addr - 0x40) >> 4;
/* we use IDE as mask which CPUs to deliver the IPI to still. */
write_IRQreg_idr(opp, opp->irq_ipi0 + idx,
opp->src[opp->irq_ipi0 + idx].idr | val);
opp->src[opp->irq_ipi0 + idx].destmask |= val;
openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
break;
......@@ -1101,8 +1183,8 @@ static uint32_t openpic_iack(OpenPICState *opp, IRQDest *dst, int cpu)
}
if ((irq >= opp->irq_ipi0) && (irq < (opp->irq_ipi0 + MAX_IPI))) {
src->idr &= ~(1 << cpu);
if (src->idr && !src->level) {
src->destmask &= ~(1 << cpu);
if (src->destmask && !src->level) {
/* trigger on CPUs that didn't know about it yet */
openpic_set_irq(opp, irq, 1);
openpic_set_irq(opp, irq, 0);
......@@ -1239,19 +1321,19 @@ static const MemoryRegionOps openpic_src_ops_be = {
},
};
static const MemoryRegionOps openpic_msi_ops_le = {
static const MemoryRegionOps openpic_msi_ops_be = {
.read = openpic_msi_read,
.write = openpic_msi_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.endianness = DEVICE_BIG_ENDIAN,
.impl = {
.min_access_size = 4,
.max_access_size = 4,
},
};
static const MemoryRegionOps openpic_msi_ops_be = {
.read = openpic_msi_read,
.write = openpic_msi_write,
static const MemoryRegionOps openpic_summary_ops_be = {
.read = openpic_summary_read,
.write = openpic_summary_write,
.endianness = DEVICE_BIG_ENDIAN,
.impl = {
.min_access_size = 4,
......@@ -1307,6 +1389,7 @@ static void openpic_save(QEMUFile* f, void *opaque)
for (i = 0; i < opp->max_irq; i++) {
qemu_put_be32s(f, &opp->src[i].ivpr);
qemu_put_be32s(f, &opp->src[i].idr);
qemu_get_be32s(f, &opp->src[i].destmask);
qemu_put_sbe32s(f, &opp->src[i].last_cpu);
qemu_put_sbe32s(f, &opp->src[i].pending);
}
......@@ -1372,6 +1455,7 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
qemu_get_be32s(f, &opp->src[i].ivpr);
qemu_get_be32s(f, &opp->src[i].idr);
qemu_get_be32s(f, &opp->src[i].destmask);
qemu_get_sbe32s(f, &opp->src[i].last_cpu);
qemu_get_sbe32s(f, &opp->src[i].pending);
}
......@@ -1382,78 +1466,128 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
typedef struct MemReg {
const char *name;
MemoryRegionOps const *ops;
bool map;
hwaddr start_addr;
ram_addr_t size;
} MemReg;
static void fsl_common_init(OpenPICState *opp)
{
int i;
int virq = MAX_SRC;
opp->vid = VID_REVISION_1_2;
opp->vir = VIR_GENERIC;
opp->vector_mask = 0xFFFF;
opp->tfrr_reset = 0;
opp->ivpr_reset = IVPR_MASK_MASK;
opp->idr_reset = 1 << 0;
opp->max_irq = MAX_IRQ;
opp->irq_ipi0 = virq;
virq += MAX_IPI;
opp->irq_tim0 = virq;
virq += MAX_TMR;
assert(virq <= MAX_IRQ);
opp->irq_msi = 224;
msi_supported = true;
for (i = 0; i < opp->fsl->max_ext; i++) {
opp->src[i].level = false;
}
/* Internal interrupts, including message and MSI */
for (i = 16; i < MAX_SRC; i++) {
opp->src[i].type = IRQ_TYPE_FSLINT;
opp->src[i].level = true;
}
/* timers and IPIs */
for (i = MAX_SRC; i < virq; i++) {
opp->src[i].type = IRQ_TYPE_FSLSPECIAL;
opp->src[i].level = false;
}
}
static void map_list(OpenPICState *opp, const MemReg *list, int *count)
{
while (list->name) {
assert(*count < ARRAY_SIZE(opp->sub_io_mem));
memory_region_init_io(&opp->sub_io_mem[*count], list->ops, opp,
list->name, list->size);
memory_region_add_subregion(&opp->mem, list->start_addr,
&opp->sub_io_mem[*count]);
(*count)++;
list++;
}
}
static int openpic_init(SysBusDevice *dev)
{
OpenPICState *opp = FROM_SYSBUS(typeof (*opp), dev);
int i, j;
MemReg list_le[] = {
{"glb", &openpic_glb_ops_le, true,
int list_count = 0;
static const MemReg list_le[] = {
{"glb", &openpic_glb_ops_le,
OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
{"tmr", &openpic_tmr_ops_le, true,
{"tmr", &openpic_tmr_ops_le,
OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
{"msi", &openpic_msi_ops_le, true,
OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE},
{"src", &openpic_src_ops_le, true,
{"src", &openpic_src_ops_le,
OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
{"cpu", &openpic_cpu_ops_le, true,
{"cpu", &openpic_cpu_ops_le,
OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
{NULL}
};
MemReg list_be[] = {
{"glb", &openpic_glb_ops_be, true,
static const MemReg list_be[] = {
{"glb", &openpic_glb_ops_be,
OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
{"tmr", &openpic_tmr_ops_be, true,
{"tmr", &openpic_tmr_ops_be,
OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
{"msi", &openpic_msi_ops_be, true,
OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE},
{"src", &openpic_src_ops_be, true,
{"src", &openpic_src_ops_be,
OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
{"cpu", &openpic_cpu_ops_be, true,
{"cpu", &openpic_cpu_ops_be,
OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
{NULL}
};
static const MemReg list_fsl[] = {
{"msi", &openpic_msi_ops_be,
OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE},
{"summary", &openpic_summary_ops_be,
OPENPIC_SUMMARY_REG_START, OPENPIC_SUMMARY_REG_SIZE},
{NULL}
};
MemReg *list;
memory_region_init(&opp->mem, "openpic", 0x40000);
switch (opp->model) {
case OPENPIC_MODEL_FSL_MPIC_20:
default:
opp->fsl = &fsl_mpic_20;
opp->brr1 = 0x00400200;
opp->flags |= OPENPIC_FLAG_IDR_CRIT;
opp->nb_irqs = 80;
opp->vid = VID_REVISION_1_2;
opp->vir = VIR_GENERIC;
opp->vector_mask = 0xFFFF;
opp->tfrr_reset = 0;
opp->ivpr_reset = IVPR_MASK_MASK;
opp->idr_reset = 1 << 0;
opp->max_irq = FSL_MPIC_20_MAX_IRQ;
opp->irq_ipi0 = FSL_MPIC_20_IPI_IRQ;
opp->irq_tim0 = FSL_MPIC_20_TMR_IRQ;
opp->irq_msi = FSL_MPIC_20_MSI_IRQ;
opp->brr1 = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN;
/* XXX really only available as of MPIC 4.0 */
opp->mpic_mode_mask = GCR_MODE_PROXY;
opp->mpic_mode_mask = GCR_MODE_MIXED;
msi_supported = true;
list = list_be;
fsl_common_init(opp);
map_list(opp, list_be, &list_count);
map_list(opp, list_fsl, &list_count);
for (i = 0; i < FSL_MPIC_20_MAX_EXT; i++) {
opp->src[i].level = false;
}
break;
/* Internal interrupts, including message and MSI */
for (i = 16; i < MAX_SRC; i++) {
opp->src[i].type = IRQ_TYPE_FSLINT;
opp->src[i].level = true;
}
case OPENPIC_MODEL_FSL_MPIC_42:
opp->fsl = &fsl_mpic_42;
opp->brr1 = 0x00400402;
opp->flags |= OPENPIC_FLAG_ILR;
opp->nb_irqs = 196;
opp->mpic_mode_mask = GCR_MODE_PROXY;
/* timers and IPIs */
for (i = MAX_SRC; i < MAX_IRQ; i++) {
opp->src[i].type = IRQ_TYPE_FSLSPECIAL;
opp->src[i].level = false;
}
fsl_common_init(opp);
map_list(opp, list_be, &list_count);
map_list(opp, list_fsl, &list_count);
break;
......@@ -1470,29 +1604,14 @@ static int openpic_init(SysBusDevice *dev)
opp->irq_tim0 = RAVEN_TMR_IRQ;
opp->brr1 = -1;
opp->mpic_mode_mask = GCR_MODE_MIXED;
list = list_le;
/* Don't map MSI region */
list[2].map = false;
/* Only UP supported today */
if (opp->nb_cpus != 1) {
return -EINVAL;
}
break;
}
memory_region_init(&opp->mem, "openpic", 0x40000);
for (i = 0; i < ARRAY_SIZE(list_le); i++) {
if (!list[i].map) {
continue;
}
memory_region_init_io(&opp->sub_io_mem[i], list[i].ops, opp,
list[i].name, list[i].size);
memory_region_add_subregion(&opp->mem, list[i].start_addr,
&opp->sub_io_mem[i]);
map_list(opp, list_le, &list_count);
break;
}
for (i = 0; i < opp->nb_cpus; i++) {
......
......@@ -13,5 +13,6 @@ enum {
#define OPENPIC_MODEL_RAVEN 0
#define OPENPIC_MODEL_FSL_MPIC_20 1
#define OPENPIC_MODEL_FSL_MPIC_42 2
#endif /* __OPENPIC_H__ */
......@@ -3,10 +3,6 @@ obj-y = ppc.o ppc_booke.o
# PREP target
obj-y += mc146818rtc.o
obj-y += ppc_prep.o
# OldWorld PowerMac
obj-y += ppc_oldworld.o
# NewWorld PowerMac
obj-y += ppc_newworld.o
# IBM pSeries (sPAPR)
obj-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
obj-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
......@@ -28,4 +24,9 @@ obj-y += xilinx_ethlite.o
obj-y := $(addprefix ../,$(obj-y))
# OldWorld PowerMac
obj-y += mac_oldworld.o
# NewWorld PowerMac
obj-y += mac_newworld.o
# e500
obj-$(CONFIG_FDT) += e500.o mpc8544ds.o e500plat.o
......@@ -297,7 +297,7 @@ static int ppce500_load_device_tree(CPUPPCState *env,
snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET);
qemu_devtree_add_subnode(fdt, mpic);
qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic");
qemu_devtree_setprop_string(fdt, mpic, "compatible", "chrp,open-pic");
qemu_devtree_setprop_string(fdt, mpic, "compatible", "fsl,mpic");
qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET,
0x40000);
qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0);
......@@ -505,7 +505,7 @@ void ppce500_init(PPCE500Params *params)
irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
env->spr[SPR_BOOKE_PIR] = cs->cpu_index = i;
env->mpic_iack = MPC8544_CCSRBAR_BASE +
MPC8544_MPIC_REGS_OFFSET + 0x200A0;
MPC8544_MPIC_REGS_OFFSET + 0xa0;
ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500);
......@@ -545,7 +545,7 @@ void ppce500_init(PPCE500Params *params)
mpic = g_new(qemu_irq, 256);
dev = qdev_create(NULL, "openpic");
qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus);
qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_FSL_MPIC_20);
qdev_prop_set_uint32(dev, "model", params->mpic_version);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
......
......@@ -16,6 +16,8 @@ typedef struct PPCE500Params {
/* required -- must at least add toplevel board compatible */
void (*fixup_devtree)(struct PPCE500Params *params, void *fdt);
int mpic_version;
} PPCE500Params;
void ppce500_init(PPCE500Params *params);
......
......@@ -15,6 +15,7 @@
#include "../boards.h"
#include "sysemu/device_tree.h"
#include "hw/pci/pci.h"
#include "hw/openpic.h"
static void e500plat_fixup_devtree(PPCE500Params *params, void *fdt)
{
......@@ -44,6 +45,7 @@ static void e500plat_init(QEMUMachineInitArgs *args)
.pci_first_slot = 0x1,
.pci_nr_slots = PCI_SLOT_MAX - 1,
.fixup_devtree = e500plat_fixup_devtree,
.mpic_version = OPENPIC_MODEL_FSL_MPIC_42,
};
ppce500_init(&params);
......@@ -53,7 +55,7 @@ static QEMUMachine e500plat_machine = {
.name = "ppce500",
.desc = "generic paravirt e500 platform",
.init = e500plat_init,
.max_cpus = 15,
.max_cpus = 32,
DEFAULT_MACHINE_OPTIONS,
};
......
......@@ -26,6 +26,9 @@
#define __PPC_MAC_H__
#include "exec/memory.h"
#include "hw/sysbus.h"
#include "hw/ide/internal.h"
#include "hw/adb.h"
/* SMP is not enabled, for now */
#define MAX_CPUS 1
......@@ -42,13 +45,100 @@
#define ESCC_CLOCK 3686400
/* Cuda */
void cuda_init (MemoryRegion **cuda_mem, qemu_irq irq);
#define TYPE_CUDA "cuda"
#define CUDA(obj) OBJECT_CHECK(CUDAState, (obj), TYPE_CUDA)
/**
* CUDATimer:
* @counter_value: counter value at load time
*/
typedef struct CUDATimer {
int index;
uint16_t latch;
uint16_t counter_value;
int64_t load_time;
int64_t next_irq_time;
QEMUTimer *timer;
} CUDATimer;
/**
* CUDAState:
* @b: B-side data
* @a: A-side data
* @dirb: B-side direction (1=output)
* @dira: A-side direction (1=output)
* @sr: Shift register
* @acr: Auxiliary control register
* @pcr: Peripheral control register
* @ifr: Interrupt flag register
* @ier: Interrupt enable register
* @anh: A-side data, no handshake
* @last_b: last value of B register
* @last_acr: last value of ACR register
*/
typedef struct CUDAState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion mem;
/* cuda registers */
uint8_t b;
uint8_t a;
uint8_t dirb;
uint8_t dira;
uint8_t sr;
uint8_t acr;
uint8_t pcr;
uint8_t ifr;
uint8_t ier;
uint8_t anh;
ADBBusState adb_bus;
CUDATimer timers[2];
uint32_t tick_offset;
uint8_t last_b;
uint8_t last_acr;
int data_in_size;
int data_in_index;
int data_out_index;
qemu_irq irq;
uint8_t autopoll;
uint8_t data_in[128];
uint8_t data_out[16];
QEMUTimer *adb_poll_timer;
} CUDAState;
/* MacIO */
void macio_init (PCIBus *bus, int device_id, int is_oldworld,
MemoryRegion *pic_mem, MemoryRegion *dbdma_mem,
MemoryRegion *cuda_mem, void *nvram,
int nb_ide, MemoryRegion **ide_mem, MemoryRegion *escc_mem);
#define TYPE_OLDWORLD_MACIO "macio-oldworld"
#define TYPE_NEWWORLD_MACIO "macio-newworld"
#define TYPE_MACIO_IDE "macio-ide"
#define MACIO_IDE(obj) OBJECT_CHECK(MACIOIDEState, (obj), TYPE_MACIO_IDE)
typedef struct MACIOIDEState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
qemu_irq irq;
qemu_irq dma_irq;
MemoryRegion mem;
IDEBus bus;
BlockDriverAIOCB *aiocb;
} MACIOIDEState;
void macio_ide_init_drives(MACIOIDEState *ide, DriveInfo **hd_table);
void macio_ide_register_dma(MACIOIDEState *ide, void *dbdma, int channel);
void macio_init(PCIDevice *dev,
MemoryRegion *pic_mem,
MemoryRegion *escc_mem);
/* Heathrow PIC */
qemu_irq *heathrow_pic_init(MemoryRegion **pmem,
......@@ -69,13 +159,23 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic,
MemoryRegion *address_space_io);
/* Mac NVRAM */
typedef struct MacIONVRAMState MacIONVRAMState;
#define TYPE_MACIO_NVRAM "macio-nvram"
#define MACIO_NVRAM(obj) \
OBJECT_CHECK(MacIONVRAMState, (obj), TYPE_MACIO_NVRAM)
typedef struct MacIONVRAMState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
uint32_t size;
uint32_t it_shift;
MemoryRegion mem;
uint8_t *data;
} MacIONVRAMState;
MacIONVRAMState *macio_nvram_init (hwaddr size,
unsigned int it_shift);
void macio_nvram_setup_bar(MacIONVRAMState *s, MemoryRegion *bar,
hwaddr mem_base);
void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len);
uint32_t macio_nvram_read (void *opaque, uint32_t addr);
void macio_nvram_write (void *opaque, uint32_t addr, uint32_t val);
uint8_t macio_nvram_read(MacIONVRAMState *s, uint32_t addr);
void macio_nvram_write(MacIONVRAMState *s, uint32_t addr, uint8_t val);
#endif /* !defined(__PPC_MAC_H__) */
......@@ -46,28 +46,28 @@
* 0001:05:0c.0 IDE interface [0101]: Broadcom K2 SATA [1166:0240]
*
*/
#include "hw.h"
#include "ppc.h"
#include "ppc_mac.h"
#include "adb.h"
#include "mac_dbdma.h"
#include "nvram.h"
#include "pci/pci.h"
#include "hw/hw.h"
#include "hw/ppc.h"
#include "hw/ppc/mac.h"
#include "hw/adb.h"
#include "hw/mac_dbdma.h"
#include "hw/nvram.h"
#include "hw/pci/pci.h"
#include "net/net.h"
#include "sysemu/sysemu.h"
#include "boards.h"
#include "fw_cfg.h"
#include "escc.h"
#include "openpic.h"
#include "ide.h"
#include "loader.h"
#include "hw/boards.h"
#include "hw/fw_cfg.h"
#include "hw/escc.h"
#include "hw/openpic.h"
#include "hw/ide.h"
#include "hw/loader.h"
#include "elf.h"
#include "sysemu/kvm.h"
#include "kvm_ppc.h"
#include "hw/usb.h"
#include "sysemu/blockdev.h"
#include "exec/address-spaces.h"
#include "sysbus.h"
#include "hw/sysbus.h"
#define MAX_IDE_BUS 2
#define CFG_ADDR 0xf0000510
......@@ -147,15 +147,16 @@ static void ppc_core99_init(QEMUMachineInitArgs *args)
hwaddr kernel_base, initrd_base, cmdline_base = 0;
long kernel_size, initrd_size;
PCIBus *pci_bus;
PCIDevice *macio;
MACIOIDEState *macio_ide;
BusState *adb_bus;
MacIONVRAMState *nvr;
int bios_size;
MemoryRegion *pic_mem, *dbdma_mem, *cuda_mem, *escc_mem;
MemoryRegion *pic_mem, *escc_mem;
MemoryRegion *escc_bar = g_new(MemoryRegion, 1);
MemoryRegion *ide_mem[3];
int ppc_boot_device;
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
void *fw_cfg;
void *dbdma;
int machine_arch;
SysBusDevice *s;
DeviceState *dev;
......@@ -362,20 +363,31 @@ static void ppc_core99_init(QEMUMachineInitArgs *args)
pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
ide_drive_get(hd, MAX_IDE_BUS);
dbdma = DBDMA_init(&dbdma_mem);
/* We only emulate 2 out of 3 IDE controllers for now */
ide_mem[0] = NULL;
ide_mem[1] = pmac_ide_init(hd, pic[0x0d], dbdma, 0x16, pic[0x02]);
ide_mem[2] = pmac_ide_init(&hd[MAX_IDE_DEVS], pic[0x0e], dbdma, 0x1a, pic[0x02]);
macio = pci_create(pci_bus, -1, TYPE_NEWWORLD_MACIO);
dev = DEVICE(macio);
qdev_connect_gpio_out(dev, 0, pic[0x19]); /* CUDA */
qdev_connect_gpio_out(dev, 1, pic[0x0d]); /* IDE */
qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE DMA */
qdev_connect_gpio_out(dev, 3, pic[0x0e]); /* IDE */
qdev_connect_gpio_out(dev, 4, pic[0x02]); /* IDE DMA */
macio_init(macio, pic_mem, escc_bar);
cuda_init(&cuda_mem, pic[0x19]);
/* We only emulate 2 out of 3 IDE controllers for now */
macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio),
"ide[0]"));
macio_ide_init_drives(macio_ide, hd);
adb_kbd_init(&adb_bus);
adb_mouse_init(&adb_bus);
macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio),
"ide[1]"));
macio_ide_init_drives(macio_ide, &hd[MAX_IDE_DEVS]);
macio_init(pci_bus, PCI_DEVICE_ID_APPLE_UNI_N_KEYL, 0, pic_mem,
dbdma_mem, cuda_mem, NULL, 3, ide_mem, escc_bar);
dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda"));
adb_bus = qdev_get_child_bus(dev, "adb.0");
dev = qdev_create(adb_bus, TYPE_ADB_KEYBOARD);
qdev_init_nofail(dev);
dev = qdev_create(adb_bus, TYPE_ADB_MOUSE);
qdev_init_nofail(dev);
if (usb_enabled(machine_arch == ARCH_MAC99_U3)) {
pci_create_simple(pci_bus, -1, "pci-ohci");
......@@ -391,9 +403,13 @@ static void ppc_core99_init(QEMUMachineInitArgs *args)
graphic_depth = 15;
/* The NewWorld NVRAM is not located in the MacIO device */
nvr = macio_nvram_init(0x2000, 1);
dev = qdev_create(NULL, TYPE_MACIO_NVRAM);
qdev_prop_set_uint32(dev, "size", 0x2000);
qdev_prop_set_uint32(dev, "it_shift", 1);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xFFF04000);
nvr = MACIO_NVRAM(dev);
pmac_format_nvram_partition(nvr, 0x2000);
macio_nvram_setup_bar(nvr, get_system_memory(), 0xFFF04000);
/* No PCI init: the BIOS will do it */
fw_cfg = fw_cfg_init(0, 0, CFG_ADDR, CFG_ADDR + 2);
......
......@@ -23,21 +23,20 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "hw.h"
#include "ppc.h"
#include "ppc_mac.h"
#include "adb.h"
#include "mac_dbdma.h"
#include "nvram.h"
#include "hw/hw.h"
#include "hw/ppc.h"
#include "mac.h"
#include "hw/adb.h"
#include "hw/nvram.h"
#include "sysemu/sysemu.h"
#include "net/net.h"
#include "isa.h"
#include "pci/pci.h"
#include "boards.h"
#include "fw_cfg.h"
#include "escc.h"
#include "ide.h"
#include "loader.h"
#include "hw/isa.h"
#include "hw/pci/pci.h"
#include "hw/boards.h"
#include "hw/fw_cfg.h"
#include "hw/escc.h"
#include "hw/ide.h"
#include "hw/loader.h"
#include "elf.h"
#include "sysemu/kvm.h"
#include "kvm_ppc.h"
......@@ -90,14 +89,16 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args)
uint32_t kernel_base, initrd_base, cmdline_base = 0;
int32_t kernel_size, initrd_size;
PCIBus *pci_bus;
MacIONVRAMState *nvr;
PCIDevice *macio;
MACIOIDEState *macio_ide;
DeviceState *dev;
BusState *adb_bus;
int bios_size;
MemoryRegion *pic_mem, *dbdma_mem, *cuda_mem;
MemoryRegion *escc_mem, *escc_bar = g_new(MemoryRegion, 1), *ide_mem[2];
MemoryRegion *pic_mem;
MemoryRegion *escc_mem, *escc_bar = g_new(MemoryRegion, 1);
uint16_t ppc_boot_device;
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
void *fw_cfg;
void *dbdma;
linux_boot = (kernel_filename != NULL);
......@@ -263,10 +264,17 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args)
ide_drive_get(hd, MAX_IDE_BUS);
macio = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO);
dev = DEVICE(macio);
qdev_connect_gpio_out(dev, 0, pic[0x12]); /* CUDA */
qdev_connect_gpio_out(dev, 1, pic[0x0D]); /* IDE */
qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE DMA */
macio_init(macio, pic_mem, escc_bar);
/* First IDE channel is a MAC IDE on the MacIO bus */
dbdma = DBDMA_init(&dbdma_mem);
ide_mem[0] = NULL;
ide_mem[1] = pmac_ide_init(hd, pic[0x0D], dbdma, 0x16, pic[0x02]);
macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio),
"ide"));
macio_ide_init_drives(macio_ide, hd);
/* Second IDE channel is a CMD646 on the PCI bus */
hd[0] = hd[MAX_IDE_DEVS];
......@@ -274,17 +282,12 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args)
hd[3] = hd[2] = NULL;
pci_cmd646_ide_init(pci_bus, hd, 0);
/* cuda also initialize ADB */
cuda_init(&cuda_mem, pic[0x12]);
adb_kbd_init(&adb_bus);
adb_mouse_init(&adb_bus);
nvr = macio_nvram_init(0x2000, 4);
pmac_format_nvram_partition(nvr, 0x2000);
macio_init(pci_bus, PCI_DEVICE_ID_APPLE_343S1201, 1, pic_mem,
dbdma_mem, cuda_mem, nvr, 2, ide_mem, escc_bar);
dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda"));
adb_bus = qdev_get_child_bus(dev, "adb.0");
dev = qdev_create(adb_bus, TYPE_ADB_KEYBOARD);
qdev_init_nofail(dev);
dev = qdev_create(adb_bus, TYPE_ADB_MOUSE);
qdev_init_nofail(dev);
if (usb_enabled(false)) {
pci_create_simple(pci_bus, -1, "pci-ohci");
......
......@@ -14,6 +14,7 @@
#include "e500.h"
#include "../boards.h"
#include "sysemu/device_tree.h"
#include "hw/openpic.h"
static void mpc8544ds_fixup_devtree(PPCE500Params *params, void *fdt)
{
......@@ -43,6 +44,7 @@ static void mpc8544ds_init(QEMUMachineInitArgs *args)
.pci_first_slot = 0x11,
.pci_nr_slots = 2,
.fixup_devtree = mpc8544ds_fixup_devtree,
.mpic_version = OPENPIC_MODEL_FSL_MPIC_20,
};
ppce500_init(&params);
......
......@@ -77,12 +77,6 @@
#define MAX_CPUS 256
#define XICS_IRQS 1024
#define SPAPR_PCI_BUID 0x800000020000001ULL
#define SPAPR_PCI_MEM_WIN_ADDR (0x10000000000ULL + 0xA0000000)
#define SPAPR_PCI_MEM_WIN_SIZE 0x20000000
#define SPAPR_PCI_IO_WIN_ADDR (0x10000000000ULL + 0x80000000)
#define SPAPR_PCI_MSI_WIN_ADDR (0x10000000000ULL + 0x90000000)
#define PHANDLE_XICP 0x00001111
#define HTAB_SIZE(spapr) (1ULL << ((spapr)->htab_shift))
......@@ -857,12 +851,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
/* Set up PCI */
spapr_pci_rtas_init();
spapr_create_phb(spapr, "pci", SPAPR_PCI_BUID,
SPAPR_PCI_MEM_WIN_ADDR,
SPAPR_PCI_MEM_WIN_SIZE,
SPAPR_PCI_IO_WIN_ADDR,
SPAPR_PCI_MSI_WIN_ADDR);
phb = PCI_HOST_BRIDGE(QLIST_FIRST(&spapr->phbs));
phb = spapr_create_phb(spapr, 0, "pci");
for (i = 0; i < nb_nics; i++) {
NICInfo *nd = &nd_table[i];
......
......@@ -435,7 +435,7 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level)
*/
sPAPRPHBState *phb = opaque;
trace_spapr_pci_lsi_set(phb->busname, irq_num, phb->lsi_table[irq_num].irq);
trace_spapr_pci_lsi_set(phb->dtbusname, irq_num, phb->lsi_table[irq_num].irq);
qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level);
}
......@@ -522,7 +522,63 @@ static int spapr_phb_init(SysBusDevice *s)
int i;
PCIBus *bus;
if (sphb->index != -1) {
hwaddr windows_base;
if ((sphb->buid != -1) || (sphb->dma_liobn != -1)
|| (sphb->mem_win_addr != -1)
|| (sphb->io_win_addr != -1)
|| (sphb->msi_win_addr != -1)) {
fprintf(stderr, "Either \"index\" or other parameters must"
" be specified for PAPR PHB, not both\n");
return -1;
}
sphb->buid = SPAPR_PCI_BASE_BUID + sphb->index;
sphb->dma_liobn = SPAPR_PCI_BASE_LIOBN + sphb->index;
windows_base = SPAPR_PCI_WINDOW_BASE
+ sphb->index * SPAPR_PCI_WINDOW_SPACING;
sphb->mem_win_addr = windows_base + SPAPR_PCI_MMIO_WIN_OFF;
sphb->io_win_addr = windows_base + SPAPR_PCI_IO_WIN_OFF;
sphb->msi_win_addr = windows_base + SPAPR_PCI_MSI_WIN_OFF;
}
if (sphb->buid == -1) {
fprintf(stderr, "BUID not specified for PHB\n");
return -1;
}
if (sphb->dma_liobn == -1) {
fprintf(stderr, "LIOBN not specified for PHB\n");
return -1;
}
if (sphb->mem_win_addr == -1) {
fprintf(stderr, "Memory window address not specified for PHB\n");
return -1;
}
if (sphb->io_win_addr == -1) {
fprintf(stderr, "IO window address not specified for PHB\n");
return -1;
}
if (sphb->msi_win_addr == -1) {
fprintf(stderr, "MSI window address not specified for PHB\n");
return -1;
}
if (find_phb(spapr, sphb->buid)) {
fprintf(stderr, "PCI host bridges must have unique BUIDs\n");
return -1;
}
sphb->dtbusname = g_strdup_printf("pci@%" PRIx64, sphb->buid);
if (!sphb->busname) {
sphb->busname = sphb->dtbusname;
}
namebuf = alloca(strlen(sphb->dtbusname) + 32);
/* Initialize memory regions */
......@@ -565,17 +621,19 @@ static int spapr_phb_init(SysBusDevice *s)
&sphb->msiwindow);
}
bus = pci_register_bus(DEVICE(s),
sphb->busname ? sphb->busname : sphb->dtbusname,
bus = pci_register_bus(DEVICE(s), sphb->busname,
pci_spapr_set_irq, pci_spapr_map_irq, sphb,
&sphb->memspace, &sphb->iospace,
PCI_DEVFN(0, 0), PCI_NUM_PINS);
phb->bus = bus;
sphb->dma_liobn = SPAPR_PCI_BASE_LIOBN | (pci_find_domain(bus) << 16);
sphb->dma_window_start = 0;
sphb->dma_window_size = 0x40000000;
sphb->dma = spapr_tce_new_dma_context(sphb->dma_liobn, sphb->dma_window_size);
if (!sphb->dma) {
fprintf(stderr, "Unable to create TCE table for %s\n", sphb->dtbusname);
return -1;
}
pci_setup_iommu(bus, spapr_pci_dma_context_fn, sphb);
QLIST_INSERT_HEAD(&spapr->phbs, sphb, list);
......@@ -605,13 +663,17 @@ static void spapr_phb_reset(DeviceState *qdev)
}
static Property spapr_phb_properties[] = {
DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, 0),
DEFINE_PROP_STRING("busname", sPAPRPHBState, busname),
DEFINE_PROP_HEX64("mem_win_addr", sPAPRPHBState, mem_win_addr, 0),
DEFINE_PROP_HEX64("mem_win_size", sPAPRPHBState, mem_win_size, 0x20000000),
DEFINE_PROP_HEX64("io_win_addr", sPAPRPHBState, io_win_addr, 0),
DEFINE_PROP_HEX64("io_win_size", sPAPRPHBState, io_win_size, 0x10000),
DEFINE_PROP_HEX64("msi_win_addr", sPAPRPHBState, msi_win_addr, 0),
DEFINE_PROP_INT32("index", sPAPRPHBState, index, -1),
DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, -1),
DEFINE_PROP_HEX32("liobn", sPAPRPHBState, dma_liobn, -1),
DEFINE_PROP_HEX64("mem_win_addr", sPAPRPHBState, mem_win_addr, -1),
DEFINE_PROP_HEX64("mem_win_size", sPAPRPHBState, mem_win_size,
SPAPR_PCI_MMIO_WIN_SIZE),
DEFINE_PROP_HEX64("io_win_addr", sPAPRPHBState, io_win_addr, -1),
DEFINE_PROP_HEX64("io_win_size", sPAPRPHBState, io_win_size,
SPAPR_PCI_IO_WIN_SIZE),
DEFINE_PROP_HEX64("msi_win_addr", sPAPRPHBState, msi_win_addr, -1),
DEFINE_PROP_END_OF_LIST(),
};
......@@ -632,25 +694,17 @@ static const TypeInfo spapr_phb_info = {
.class_init = spapr_phb_class_init,
};
void spapr_create_phb(sPAPREnvironment *spapr,
const char *busname, uint64_t buid,
uint64_t mem_win_addr, uint64_t mem_win_size,
uint64_t io_win_addr, uint64_t msi_win_addr)
PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index,
const char *busname)
{
DeviceState *dev;
dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE);
if (busname) {
qdev_prop_set_string(dev, "busname", g_strdup(busname));
}
qdev_prop_set_uint64(dev, "buid", buid);
qdev_prop_set_uint64(dev, "mem_win_addr", mem_win_addr);
qdev_prop_set_uint64(dev, "mem_win_size", mem_win_size);
qdev_prop_set_uint64(dev, "io_win_addr", io_win_addr);
qdev_prop_set_uint64(dev, "msi_win_addr", msi_win_addr);
qdev_prop_set_uint32(dev, "index", index);
qdev_prop_set_string(dev, "busname", busname);
qdev_init_nofail(dev);
return PCI_HOST_BRIDGE(dev);
}
/* Macros to operate with address in OF binding to PCI */
......
......@@ -37,6 +37,7 @@
typedef struct sPAPRPHBState {
PCIHostState parent_obj;
int32_t index;
uint64_t buid;
char *busname;
char *dtbusname;
......@@ -64,18 +65,25 @@ typedef struct sPAPRPHBState {
QLIST_ENTRY(sPAPRPHBState) list;
} sPAPRPHBState;
#define SPAPR_PCI_BASE_BUID 0x800000020000000ULL
#define SPAPR_PCI_WINDOW_BASE 0x10000000000ULL
#define SPAPR_PCI_WINDOW_SPACING 0x1000000000ULL
#define SPAPR_PCI_MMIO_WIN_OFF 0xA0000000
#define SPAPR_PCI_MMIO_WIN_SIZE 0x20000000
#define SPAPR_PCI_IO_WIN_OFF 0x80000000
#define SPAPR_PCI_IO_WIN_SIZE 0x10000
#define SPAPR_PCI_MSI_WIN_OFF 0x90000000
#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL
static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin)
{
return xics_get_qirq(spapr->icp, phb->lsi_table[pin].irq);
}
#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL
#define SPAPR_PCI_IO_WIN_SIZE 0x10000
void spapr_create_phb(sPAPREnvironment *spapr,
const char *busname, uint64_t buid,
uint64_t mem_win_addr, uint64_t mem_win_size,
uint64_t io_win_addr, uint64_t msi_win_addr);
PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index,
const char *busname);
int spapr_populate_pci_dt(sPAPRPHBState *phb,
uint32_t xics_phandle,
......
......@@ -492,7 +492,7 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
qbus = qbus_create(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio");
bus = DO_UPCAST(VIOsPAPRBus, bus, qbus);
bus->next_reg = 0x1000;
bus->next_reg = 0x71000000;
/* hcall-vio */
spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);
......
......@@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
#include "hw.h"
#include "ppc_mac.h"
#include "ppc/mac.h"
#include "pci/pci.h"
#include "pci/pci_host.h"
......
......@@ -28,6 +28,7 @@
#include <sysemu/kvm.h>
#include "kvm_ppc.h"
#include "sysemu/arch_init.h"
#include "sysemu/cpus.h"
//#define PPC_DUMP_CPU
//#define PPC_DEBUG_SPR
......@@ -10036,6 +10037,17 @@ static void ppc_cpu_realize(Object *obj, Error **errp)
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
ppc_def_t *def = pcc->info;
Error *local_err = NULL;
#if !defined(CONFIG_USER_ONLY)
int max_smt = kvm_enabled() ? kvmppc_smt_threads() : 1;
#endif
#if !defined(CONFIG_USER_ONLY)
if (smp_threads > max_smt) {
fprintf(stderr, "Cannot support more than %d threads on PPC with %s\n",
max_smt, kvm_enabled() ? "KVM" : "TCG");
exit(1);
}
#endif
if (kvm_enabled()) {
if (kvmppc_fixup_cpu(cpu) != 0) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册