Clear BD slot on next exception if appropriate.
[qemu/dscho.git] / hw / pxa2xx_pcmcia.c
blob171d902796fab70bcdbea7c07f15c964890c60a5
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 "vl.h"
12 struct pxa2xx_pcmcia_s {
13 struct pcmcia_socket_s slot;
14 struct pcmcia_card_s *card;
15 target_phys_addr_t common_base;
16 target_phys_addr_t attr_base;
17 target_phys_addr_t io_base;
19 qemu_irq irq;
20 qemu_irq cd_irq;
23 static uint32_t pxa2xx_pcmcia_common_read(void *opaque,
24 target_phys_addr_t offset)
26 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
28 if (s->slot.attached) {
29 offset -= s->common_base;
30 return s->card->common_read(s->card->state, offset);
33 return 0;
36 static void pxa2xx_pcmcia_common_write(void *opaque,
37 target_phys_addr_t offset, uint32_t value)
39 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
41 if (s->slot.attached) {
42 offset -= s->common_base;
43 s->card->common_write(s->card->state, offset, value);
47 static uint32_t pxa2xx_pcmcia_attr_read(void *opaque,
48 target_phys_addr_t offset)
50 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
52 if (s->slot.attached) {
53 offset -= s->attr_base;
54 return s->card->attr_read(s->card->state, offset);
57 return 0;
60 static void pxa2xx_pcmcia_attr_write(void *opaque,
61 target_phys_addr_t offset, uint32_t value)
63 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
65 if (s->slot.attached) {
66 offset -= s->attr_base;
67 s->card->attr_write(s->card->state, offset, value);
71 static uint32_t pxa2xx_pcmcia_io_read(void *opaque,
72 target_phys_addr_t offset)
74 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
76 if (s->slot.attached) {
77 offset -= s->io_base;
78 return s->card->io_read(s->card->state, offset);
81 return 0;
84 static void pxa2xx_pcmcia_io_write(void *opaque,
85 target_phys_addr_t offset, uint32_t value)
87 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
89 if (s->slot.attached) {
90 offset -= s->io_base;
91 s->card->io_write(s->card->state, offset, value);
95 static CPUReadMemoryFunc *pxa2xx_pcmcia_common_readfn[] = {
96 pxa2xx_pcmcia_common_read,
97 pxa2xx_pcmcia_common_read,
98 pxa2xx_pcmcia_common_read,
101 static CPUWriteMemoryFunc *pxa2xx_pcmcia_common_writefn[] = {
102 pxa2xx_pcmcia_common_write,
103 pxa2xx_pcmcia_common_write,
104 pxa2xx_pcmcia_common_write,
107 static CPUReadMemoryFunc *pxa2xx_pcmcia_attr_readfn[] = {
108 pxa2xx_pcmcia_attr_read,
109 pxa2xx_pcmcia_attr_read,
110 pxa2xx_pcmcia_attr_read,
113 static CPUWriteMemoryFunc *pxa2xx_pcmcia_attr_writefn[] = {
114 pxa2xx_pcmcia_attr_write,
115 pxa2xx_pcmcia_attr_write,
116 pxa2xx_pcmcia_attr_write,
119 static CPUReadMemoryFunc *pxa2xx_pcmcia_io_readfn[] = {
120 pxa2xx_pcmcia_io_read,
121 pxa2xx_pcmcia_io_read,
122 pxa2xx_pcmcia_io_read,
125 static CPUWriteMemoryFunc *pxa2xx_pcmcia_io_writefn[] = {
126 pxa2xx_pcmcia_io_write,
127 pxa2xx_pcmcia_io_write,
128 pxa2xx_pcmcia_io_write,
131 static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
133 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
134 if (!s->irq)
135 return;
137 qemu_set_irq(s->irq, level);
140 struct pxa2xx_pcmcia_s *pxa2xx_pcmcia_init(target_phys_addr_t base)
142 int iomemtype;
143 struct pxa2xx_pcmcia_s *s;
145 s = (struct pxa2xx_pcmcia_s *)
146 qemu_mallocz(sizeof(struct pxa2xx_pcmcia_s));
148 /* Socket I/O Memory Space */
149 s->io_base = base | 0x00000000;
150 iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_io_readfn,
151 pxa2xx_pcmcia_io_writefn, s);
152 cpu_register_physical_memory(s->io_base, 0x03ffffff, iomemtype);
154 /* Then next 64 MB is reserved */
156 /* Socket Attribute Memory Space */
157 s->attr_base = base | 0x08000000;
158 iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_attr_readfn,
159 pxa2xx_pcmcia_attr_writefn, s);
160 cpu_register_physical_memory(s->attr_base, 0x03ffffff, iomemtype);
162 /* Socket Common Memory Space */
163 s->common_base = base | 0x0c000000;
164 iomemtype = cpu_register_io_memory(0, pxa2xx_pcmcia_common_readfn,
165 pxa2xx_pcmcia_common_writefn, s);
166 cpu_register_physical_memory(s->common_base, 0x03ffffff, iomemtype);
168 if (base == 0x30000000)
169 s->slot.slot_string = "PXA PC Card Socket 1";
170 else
171 s->slot.slot_string = "PXA PC Card Socket 0";
172 s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
173 pcmcia_socket_register(&s->slot);
174 return s;
177 /* Insert a new card into a slot */
178 int pxa2xx_pcmcia_attach(void *opaque, struct pcmcia_card_s *card)
180 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
181 if (s->slot.attached)
182 return -EEXIST;
184 if (s->cd_irq) {
185 qemu_irq_raise(s->cd_irq);
188 s->card = card;
190 s->slot.attached = 1;
191 s->card->slot = &s->slot;
192 s->card->attach(s->card->state);
194 return 0;
197 /* Eject card from the slot */
198 int pxa2xx_pcmcia_dettach(void *opaque)
200 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
201 if (!s->slot.attached)
202 return -ENOENT;
204 s->card->detach(s->card->state);
205 s->card->slot = 0;
206 s->card = 0;
208 s->slot.attached = 0;
210 if (s->irq)
211 qemu_irq_lower(s->irq);
212 if (s->cd_irq)
213 qemu_irq_lower(s->cd_irq);
215 return 0;
218 /* Who to notify on card events */
219 void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
221 struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
222 s->irq = irq;
223 s->cd_irq = cd_irq;