Statistics
| Branch: | Revision:

root / hw / pxa2xx_pcmcia.c @ 3f582262

History | View | Annotate | Download (5.7 kB)

1
/*
2
 * Intel XScale PXA255/270 PC Card and CompactFlash Interface.
3
 *
4
 * Copyright (c) 2006 Openedhand Ltd.
5
 * Written by Andrzej Zaborowski <balrog@zabor.org>
6
 *
7
 * This code is licensed under the GPLv2.
8
 */
9

    
10
#include "vl.h"
11

    
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;
18

    
19
    qemu_irq irq;
20
    qemu_irq cd_irq;
21
};
22

    
23
static uint32_t pxa2xx_pcmcia_common_read(void *opaque,
24
                target_phys_addr_t offset)
25
{
26
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
27

    
28
    if (s->slot.attached) {
29
        offset -= s->common_base;
30
        return s->card->common_read(s->card->state, offset);
31
    }
32

    
33
    return 0;
34
}
35

    
36
static void pxa2xx_pcmcia_common_write(void *opaque,
37
                target_phys_addr_t offset, uint32_t value)
38
{
39
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
40

    
41
    if (s->slot.attached) {
42
        offset -= s->common_base;
43
        s->card->common_write(s->card->state, offset, value);
44
    }
45
}
46

    
47
static uint32_t pxa2xx_pcmcia_attr_read(void *opaque,
48
                target_phys_addr_t offset)
49
{
50
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
51

    
52
    if (s->slot.attached) {
53
        offset -= s->attr_base;
54
        return s->card->attr_read(s->card->state, offset);
55
    }
56

    
57
    return 0;
58
}
59

    
60
static void pxa2xx_pcmcia_attr_write(void *opaque,
61
                target_phys_addr_t offset, uint32_t value)
62
{
63
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
64

    
65
    if (s->slot.attached) {
66
        offset -= s->attr_base;
67
        s->card->attr_write(s->card->state, offset, value);
68
    }
69
}
70

    
71
static uint32_t pxa2xx_pcmcia_io_read(void *opaque,
72
                target_phys_addr_t offset)
73
{
74
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
75

    
76
    if (s->slot.attached) {
77
        offset -= s->io_base;
78
        return s->card->io_read(s->card->state, offset);
79
    }
80

    
81
    return 0;
82
}
83

    
84
static void pxa2xx_pcmcia_io_write(void *opaque,
85
                target_phys_addr_t offset, uint32_t value)
86
{
87
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
88

    
89
    if (s->slot.attached) {
90
        offset -= s->io_base;
91
        s->card->io_write(s->card->state, offset, value);
92
    }
93
}
94

    
95
static CPUReadMemoryFunc *pxa2xx_pcmcia_common_readfn[] = {
96
    pxa2xx_pcmcia_common_read,
97
    pxa2xx_pcmcia_common_read,
98
    pxa2xx_pcmcia_common_read,
99
};
100

    
101
static CPUWriteMemoryFunc *pxa2xx_pcmcia_common_writefn[] = {
102
    pxa2xx_pcmcia_common_write,
103
    pxa2xx_pcmcia_common_write,
104
    pxa2xx_pcmcia_common_write,
105
};
106

    
107
static CPUReadMemoryFunc *pxa2xx_pcmcia_attr_readfn[] = {
108
    pxa2xx_pcmcia_attr_read,
109
    pxa2xx_pcmcia_attr_read,
110
    pxa2xx_pcmcia_attr_read,
111
};
112

    
113
static CPUWriteMemoryFunc *pxa2xx_pcmcia_attr_writefn[] = {
114
    pxa2xx_pcmcia_attr_write,
115
    pxa2xx_pcmcia_attr_write,
116
    pxa2xx_pcmcia_attr_write,
117
};
118

    
119
static CPUReadMemoryFunc *pxa2xx_pcmcia_io_readfn[] = {
120
    pxa2xx_pcmcia_io_read,
121
    pxa2xx_pcmcia_io_read,
122
    pxa2xx_pcmcia_io_read,
123
};
124

    
125
static CPUWriteMemoryFunc *pxa2xx_pcmcia_io_writefn[] = {
126
    pxa2xx_pcmcia_io_write,
127
    pxa2xx_pcmcia_io_write,
128
    pxa2xx_pcmcia_io_write,
129
};
130

    
131
static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
132
{
133
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
134
    if (!s->irq)
135
        return;
136

    
137
    qemu_set_irq(s->irq, level);
138
}
139

    
140
struct pxa2xx_pcmcia_s *pxa2xx_pcmcia_init(target_phys_addr_t base)
141
{
142
    int iomemtype;
143
    struct pxa2xx_pcmcia_s *s;
144

    
145
    s = (struct pxa2xx_pcmcia_s *)
146
            qemu_mallocz(sizeof(struct pxa2xx_pcmcia_s));
147

    
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);
153

    
154
    /* Then next 64 MB is reserved */
155

    
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);
161

    
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);
167

    
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

    
175
    return s;
176
}
177

    
178
/* Insert a new card into a slot */
179
int pxa2xx_pcmcia_attach(void *opaque, struct pcmcia_card_s *card)
180
{
181
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
182
    if (s->slot.attached)
183
        return -EEXIST;
184

    
185
    if (s->cd_irq) {
186
        qemu_irq_raise(s->cd_irq);
187
    }
188

    
189
    s->card = card;
190

    
191
    s->slot.attached = 1;
192
    s->card->slot = &s->slot;
193
    s->card->attach(s->card->state);
194

    
195
    return 0;
196
}
197

    
198
/* Eject card from the slot */
199
int pxa2xx_pcmcia_dettach(void *opaque)
200
{
201
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
202
    if (!s->slot.attached)
203
        return -ENOENT;
204

    
205
    s->card->detach(s->card->state);
206
    s->card->slot = 0;
207
    s->card = 0;
208

    
209
    s->slot.attached = 0;
210

    
211
    if (s->irq)
212
        qemu_irq_lower(s->irq);
213
    if (s->cd_irq)
214
        qemu_irq_lower(s->cd_irq);
215

    
216
    return 0;
217
}
218

    
219
/* Who to notify on card events */
220
void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
221
{
222
    struct pxa2xx_pcmcia_s *s = (struct pxa2xx_pcmcia_s *) opaque;
223
    s->irq = irq;
224
    s->cd_irq = cd_irq;
225
}