Merge branch 'master' of git://git.qemu.org/qemu
[qemu.git] / hw / pxa2xx_pcmcia.c
blobdc522dcf4384797d6f4a614411f3edaee446e028
1 /*
2 * Intel XScale PXA255/270 PC Card and CompactFlash Interface.
4 * Copyright (c) 2006 Openedhand Ltd.
5 * Written by Andrzej Zaborowski <balrog@zabor.org>
7 * This code is licensed under the GPLv2.
8 */
10 #include "hw.h"
11 #include "pcmcia.h"
12 #include "pxa.h"
15 struct PXA2xxPCMCIAState {
16 PCMCIASocket slot;
17 PCMCIACardState *card;
18 MemoryRegion common_iomem;
19 MemoryRegion attr_iomem;
20 MemoryRegion iomem;
22 qemu_irq irq;
23 qemu_irq cd_irq;
26 static uint64_t pxa2xx_pcmcia_common_read(void *opaque,
27 target_phys_addr_t offset, unsigned size)
29 PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
31 if (s->slot.attached) {
32 return s->card->common_read(s->card->state, offset);
35 return 0;
38 static void pxa2xx_pcmcia_common_write(void *opaque, target_phys_addr_t offset,
39 uint64_t value, unsigned size)
41 PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
43 if (s->slot.attached) {
44 s->card->common_write(s->card->state, offset, value);
48 static uint64_t pxa2xx_pcmcia_attr_read(void *opaque,
49 target_phys_addr_t offset, unsigned size)
51 PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
53 if (s->slot.attached) {
54 return s->card->attr_read(s->card->state, offset);
57 return 0;
60 static void pxa2xx_pcmcia_attr_write(void *opaque, target_phys_addr_t offset,
61 uint64_t value, unsigned size)
63 PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
65 if (s->slot.attached) {
66 s->card->attr_write(s->card->state, offset, value);
70 static uint64_t pxa2xx_pcmcia_io_read(void *opaque,
71 target_phys_addr_t offset, unsigned size)
73 PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
75 if (s->slot.attached) {
76 return s->card->io_read(s->card->state, offset);
79 return 0;
82 static void pxa2xx_pcmcia_io_write(void *opaque, target_phys_addr_t offset,
83 uint64_t value, unsigned size)
85 PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
87 if (s->slot.attached) {
88 s->card->io_write(s->card->state, offset, value);
92 static const MemoryRegionOps pxa2xx_pcmcia_common_ops = {
93 .read = pxa2xx_pcmcia_common_read,
94 .write = pxa2xx_pcmcia_common_write,
95 .endianness = DEVICE_NATIVE_ENDIAN
98 static const MemoryRegionOps pxa2xx_pcmcia_attr_ops = {
99 .read = pxa2xx_pcmcia_attr_read,
100 .write = pxa2xx_pcmcia_attr_write,
101 .endianness = DEVICE_NATIVE_ENDIAN
104 static const MemoryRegionOps pxa2xx_pcmcia_io_ops = {
105 .read = pxa2xx_pcmcia_io_read,
106 .write = pxa2xx_pcmcia_io_write,
107 .endianness = DEVICE_NATIVE_ENDIAN
110 static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
112 PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
113 if (!s->irq)
114 return;
116 qemu_set_irq(s->irq, level);
119 PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
120 target_phys_addr_t base)
122 PXA2xxPCMCIAState *s;
124 s = (PXA2xxPCMCIAState *)
125 g_malloc0(sizeof(PXA2xxPCMCIAState));
127 /* Socket I/O Memory Space */
128 memory_region_init_io(&s->iomem, &pxa2xx_pcmcia_io_ops, s,
129 "pxa2xx-pcmcia-io", 0x04000000);
130 memory_region_add_subregion(sysmem, base | 0x00000000,
131 &s->iomem);
133 /* Then next 64 MB is reserved */
135 /* Socket Attribute Memory Space */
136 memory_region_init_io(&s->attr_iomem, &pxa2xx_pcmcia_attr_ops, s,
137 "pxa2xx-pcmcia-attribute", 0x04000000);
138 memory_region_add_subregion(sysmem, base | 0x08000000,
139 &s->attr_iomem);
141 /* Socket Common Memory Space */
142 memory_region_init_io(&s->common_iomem, &pxa2xx_pcmcia_common_ops, s,
143 "pxa2xx-pcmcia-common", 0x04000000);
144 memory_region_add_subregion(sysmem, base | 0x0c000000,
145 &s->common_iomem);
147 if (base == 0x30000000)
148 s->slot.slot_string = "PXA PC Card Socket 1";
149 else
150 s->slot.slot_string = "PXA PC Card Socket 0";
151 s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
152 pcmcia_socket_register(&s->slot);
154 return s;
157 /* Insert a new card into a slot */
158 int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card)
160 PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
161 if (s->slot.attached)
162 return -EEXIST;
164 if (s->cd_irq) {
165 qemu_irq_raise(s->cd_irq);
168 s->card = card;
170 s->slot.attached = 1;
171 s->card->slot = &s->slot;
172 s->card->attach(s->card->state);
174 return 0;
177 /* Eject card from the slot */
178 int pxa2xx_pcmcia_dettach(void *opaque)
180 PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
181 if (!s->slot.attached)
182 return -ENOENT;
184 s->card->detach(s->card->state);
185 s->card->slot = NULL;
186 s->card = NULL;
188 s->slot.attached = 0;
190 if (s->irq)
191 qemu_irq_lower(s->irq);
192 if (s->cd_irq)
193 qemu_irq_lower(s->cd_irq);
195 return 0;
198 /* Who to notify on card events */
199 void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
201 PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
202 s->irq = irq;
203 s->cd_irq = cd_irq;