qemu/hw/pxa2xx_pcmcia.c
Alexander Graf 2507c12ab0 Add endianness as io mem parameter
As stated before, devices can be little, big or native endian. The
target endianness is not of their concern, so we need to push things
down a level.

This patch adds a parameter to cpu_register_io_memory that allows a
device to choose its endianness. For now, all devices simply choose
native endian, because that's the same behavior as before.

Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
2010-12-11 15:24:25 +00:00

216 lines
5.3 KiB
C

/*
* Intel XScale PXA255/270 PC Card and CompactFlash Interface.
*
* Copyright (c) 2006 Openedhand Ltd.
* Written by Andrzej Zaborowski <balrog@zabor.org>
*
* This code is licensed under the GPLv2.
*/
#include "hw.h"
#include "pcmcia.h"
#include "pxa.h"
struct PXA2xxPCMCIAState {
PCMCIASocket slot;
PCMCIACardState *card;
qemu_irq irq;
qemu_irq cd_irq;
};
static uint32_t pxa2xx_pcmcia_common_read(void *opaque,
target_phys_addr_t offset)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
if (s->slot.attached) {
return s->card->common_read(s->card->state, offset);
}
return 0;
}
static void pxa2xx_pcmcia_common_write(void *opaque,
target_phys_addr_t offset, uint32_t value)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
if (s->slot.attached) {
s->card->common_write(s->card->state, offset, value);
}
}
static uint32_t pxa2xx_pcmcia_attr_read(void *opaque,
target_phys_addr_t offset)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
if (s->slot.attached) {
return s->card->attr_read(s->card->state, offset);
}
return 0;
}
static void pxa2xx_pcmcia_attr_write(void *opaque,
target_phys_addr_t offset, uint32_t value)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
if (s->slot.attached) {
s->card->attr_write(s->card->state, offset, value);
}
}
static uint32_t pxa2xx_pcmcia_io_read(void *opaque,
target_phys_addr_t offset)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
if (s->slot.attached) {
return s->card->io_read(s->card->state, offset);
}
return 0;
}
static void pxa2xx_pcmcia_io_write(void *opaque,
target_phys_addr_t offset, uint32_t value)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
if (s->slot.attached) {
s->card->io_write(s->card->state, offset, value);
}
}
static CPUReadMemoryFunc * const pxa2xx_pcmcia_common_readfn[] = {
pxa2xx_pcmcia_common_read,
pxa2xx_pcmcia_common_read,
pxa2xx_pcmcia_common_read,
};
static CPUWriteMemoryFunc * const pxa2xx_pcmcia_common_writefn[] = {
pxa2xx_pcmcia_common_write,
pxa2xx_pcmcia_common_write,
pxa2xx_pcmcia_common_write,
};
static CPUReadMemoryFunc * const pxa2xx_pcmcia_attr_readfn[] = {
pxa2xx_pcmcia_attr_read,
pxa2xx_pcmcia_attr_read,
pxa2xx_pcmcia_attr_read,
};
static CPUWriteMemoryFunc * const pxa2xx_pcmcia_attr_writefn[] = {
pxa2xx_pcmcia_attr_write,
pxa2xx_pcmcia_attr_write,
pxa2xx_pcmcia_attr_write,
};
static CPUReadMemoryFunc * const pxa2xx_pcmcia_io_readfn[] = {
pxa2xx_pcmcia_io_read,
pxa2xx_pcmcia_io_read,
pxa2xx_pcmcia_io_read,
};
static CPUWriteMemoryFunc * const pxa2xx_pcmcia_io_writefn[] = {
pxa2xx_pcmcia_io_write,
pxa2xx_pcmcia_io_write,
pxa2xx_pcmcia_io_write,
};
static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
if (!s->irq)
return;
qemu_set_irq(s->irq, level);
}
PXA2xxPCMCIAState *pxa2xx_pcmcia_init(target_phys_addr_t base)
{
int iomemtype;
PXA2xxPCMCIAState *s;
s = (PXA2xxPCMCIAState *)
qemu_mallocz(sizeof(PXA2xxPCMCIAState));
/* Socket I/O Memory Space */
iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_io_readfn,
pxa2xx_pcmcia_io_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(base | 0x00000000, 0x04000000, iomemtype);
/* Then next 64 MB is reserved */
/* Socket Attribute Memory Space */
iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_attr_readfn,
pxa2xx_pcmcia_attr_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(base | 0x08000000, 0x04000000, iomemtype);
/* Socket Common Memory Space */
iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_common_readfn,
pxa2xx_pcmcia_common_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(base | 0x0c000000, 0x04000000, iomemtype);
if (base == 0x30000000)
s->slot.slot_string = "PXA PC Card Socket 1";
else
s->slot.slot_string = "PXA PC Card Socket 0";
s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
pcmcia_socket_register(&s->slot);
return s;
}
/* Insert a new card into a slot */
int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
if (s->slot.attached)
return -EEXIST;
if (s->cd_irq) {
qemu_irq_raise(s->cd_irq);
}
s->card = card;
s->slot.attached = 1;
s->card->slot = &s->slot;
s->card->attach(s->card->state);
return 0;
}
/* Eject card from the slot */
int pxa2xx_pcmcia_dettach(void *opaque)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
if (!s->slot.attached)
return -ENOENT;
s->card->detach(s->card->state);
s->card->slot = NULL;
s->card = NULL;
s->slot.attached = 0;
if (s->irq)
qemu_irq_lower(s->irq);
if (s->cd_irq)
qemu_irq_lower(s->cd_irq);
return 0;
}
/* Who to notify on card events */
void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
{
PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
s->irq = irq;
s->cd_irq = cd_irq;
}