kvm: qemu: propagate errors on failed migration.
[kvm-userspace.git] / qemu / hw / pxa2xx_pcmcia.c
blobb26c59753d8c85f4f415daefca79c8ae0a6434e4
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"
14 struct pxa2xx_pcmcia_s {
15 struct pcmcia_socket_s slot;
16 struct pcmcia_card_s *card;
18 qemu_irq irq;
19 qemu_irq cd_irq;
22 static uint32_t pxa2xx_pcmcia_common_read(void *opaque,
23 target_phys_addr_t offset)
25 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
27 if (s->slot.attached) {
28 return s->card->common_read(s->card->state, offset);
31 return 0;
34 static void pxa2xx_pcmcia_common_write(void *opaque,
35 target_phys_addr_t offset, uint32_t value)
37 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
39 if (s->slot.attached) {
40 s->card->common_write(s->card->state, offset, value);
44 static uint32_t pxa2xx_pcmcia_attr_read(void *opaque,
45 target_phys_addr_t offset)
47 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
49 if (s->slot.attached) {
50 return s->card->attr_read(s->card->state, offset);
53 return 0;
56 static void pxa2xx_pcmcia_attr_write(void *opaque,
57 target_phys_addr_t offset, uint32_t value)
59 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
61 if (s->slot.attached) {
62 s->card->attr_write(s->card->state, offset, value);
66 static uint32_t pxa2xx_pcmcia_io_read(void *opaque,
67 target_phys_addr_t offset)
69 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
71 if (s->slot.attached) {
72 return s->card->io_read(s->card->state, offset);
75 return 0;
78 static void pxa2xx_pcmcia_io_write(void *opaque,
79 target_phys_addr_t offset, uint32_t value)
81 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
83 if (s->slot.attached) {
84 s->card->io_write(s->card->state, offset, value);
88 static CPUReadMemoryFunc *pxa2xx_pcmcia_common_readfn[] = {
89 pxa2xx_pcmcia_common_read,
90 pxa2xx_pcmcia_common_read,
91 pxa2xx_pcmcia_common_read,
94 static CPUWriteMemoryFunc *pxa2xx_pcmcia_common_writefn[] = {
95 pxa2xx_pcmcia_common_write,
96 pxa2xx_pcmcia_common_write,
97 pxa2xx_pcmcia_common_write,
100 static CPUReadMemoryFunc *pxa2xx_pcmcia_attr_readfn[] = {
101 pxa2xx_pcmcia_attr_read,
102 pxa2xx_pcmcia_attr_read,
103 pxa2xx_pcmcia_attr_read,
106 static CPUWriteMemoryFunc *pxa2xx_pcmcia_attr_writefn[] = {
107 pxa2xx_pcmcia_attr_write,
108 pxa2xx_pcmcia_attr_write,
109 pxa2xx_pcmcia_attr_write,
112 static CPUReadMemoryFunc *pxa2xx_pcmcia_io_readfn[] = {
113 pxa2xx_pcmcia_io_read,
114 pxa2xx_pcmcia_io_read,
115 pxa2xx_pcmcia_io_read,
118 static CPUWriteMemoryFunc *pxa2xx_pcmcia_io_writefn[] = {
119 pxa2xx_pcmcia_io_write,
120 pxa2xx_pcmcia_io_write,
121 pxa2xx_pcmcia_io_write,
124 static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
126 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
127 if (!s->irq)
128 return;
130 qemu_set_irq(s->irq, level);
133 struct pxa2xx_pcmcia_s *pxa2xx_pcmcia_init(target_phys_addr_t base)
135 int iomemtype;
136 struct pxa2xx_pcmcia_s *s;
138 s = (struct pxa2xx_pcmcia_s *)
139 qemu_mallocz(sizeof(struct pxa2xx_pcmcia_s));
141 /* Socket I/O Memory Space */
142 iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_io_readfn,
143 pxa2xx_pcmcia_io_writefn, s);
144 cpu_register_physical_memory(base | 0x00000000, 0x04000000, iomemtype);
146 /* Then next 64 MB is reserved */
148 /* Socket Attribute Memory Space */
149 iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_attr_readfn,
150 pxa2xx_pcmcia_attr_writefn, s);
151 cpu_register_physical_memory(base | 0x08000000, 0x04000000, iomemtype);
153 /* Socket Common Memory Space */
154 iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_common_readfn,
155 pxa2xx_pcmcia_common_writefn, s);
156 cpu_register_physical_memory(base | 0x0c000000, 0x04000000, iomemtype);
158 if (base == 0x30000000)
159 s->slot.slot_string = "PXA PC Card Socket 1";
160 else
161 s->slot.slot_string = "PXA PC Card Socket 0";
162 s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
163 pcmcia_socket_register(&s->slot);
165 return s;
168 /* Insert a new card into a slot */
169 int pxa2xx_pcmcia_attach(void *opaque, struct pcmcia_card_s *card)
171 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
172 if (s->slot.attached)
173 return -EEXIST;
175 if (s->cd_irq) {
176 qemu_irq_raise(s->cd_irq);
179 s->card = card;
181 s->slot.attached = 1;
182 s->card->slot = &s->slot;
183 s->card->attach(s->card->state);
185 return 0;
188 /* Eject card from the slot */
189 int pxa2xx_pcmcia_dettach(void *opaque)
191 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
192 if (!s->slot.attached)
193 return -ENOENT;
195 s->card->detach(s->card->state);
196 s->card->slot = 0;
197 s->card = 0;
199 s->slot.attached = 0;
201 if (s->irq)
202 qemu_irq_lower(s->irq);
203 if (s->cd_irq)
204 qemu_irq_lower(s->cd_irq);
206 return 0;
209 /* Who to notify on card events */
210 void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
212 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
213 s->irq = irq;
214 s->cd_irq = cd_irq;