Statistics
| Branch: | Revision:

root / hw / pxa2xx_pcmcia.c @ 1eed09cb

History | View | Annotate | Download (5.2 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 "hw.h"
11
#include "pcmcia.h"
12
#include "pxa.h"
13

    
14
struct PXA2xxPCMCIAState {
15
    PCMCIASocket slot;
16
    PCMCIACardState *card;
17

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

    
22
static uint32_t pxa2xx_pcmcia_common_read(void *opaque,
23
                target_phys_addr_t offset)
24
{
25
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
26

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

    
31
    return 0;
32
}
33

    
34
static void pxa2xx_pcmcia_common_write(void *opaque,
35
                target_phys_addr_t offset, uint32_t value)
36
{
37
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
38

    
39
    if (s->slot.attached) {
40
        s->card->common_write(s->card->state, offset, value);
41
    }
42
}
43

    
44
static uint32_t pxa2xx_pcmcia_attr_read(void *opaque,
45
                target_phys_addr_t offset)
46
{
47
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
48

    
49
    if (s->slot.attached) {
50
        return s->card->attr_read(s->card->state, offset);
51
    }
52

    
53
    return 0;
54
}
55

    
56
static void pxa2xx_pcmcia_attr_write(void *opaque,
57
                target_phys_addr_t offset, uint32_t value)
58
{
59
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
60

    
61
    if (s->slot.attached) {
62
        s->card->attr_write(s->card->state, offset, value);
63
    }
64
}
65

    
66
static uint32_t pxa2xx_pcmcia_io_read(void *opaque,
67
                target_phys_addr_t offset)
68
{
69
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
70

    
71
    if (s->slot.attached) {
72
        return s->card->io_read(s->card->state, offset);
73
    }
74

    
75
    return 0;
76
}
77

    
78
static void pxa2xx_pcmcia_io_write(void *opaque,
79
                target_phys_addr_t offset, uint32_t value)
80
{
81
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
82

    
83
    if (s->slot.attached) {
84
        s->card->io_write(s->card->state, offset, value);
85
    }
86
}
87

    
88
static CPUReadMemoryFunc *pxa2xx_pcmcia_common_readfn[] = {
89
    pxa2xx_pcmcia_common_read,
90
    pxa2xx_pcmcia_common_read,
91
    pxa2xx_pcmcia_common_read,
92
};
93

    
94
static CPUWriteMemoryFunc *pxa2xx_pcmcia_common_writefn[] = {
95
    pxa2xx_pcmcia_common_write,
96
    pxa2xx_pcmcia_common_write,
97
    pxa2xx_pcmcia_common_write,
98
};
99

    
100
static CPUReadMemoryFunc *pxa2xx_pcmcia_attr_readfn[] = {
101
    pxa2xx_pcmcia_attr_read,
102
    pxa2xx_pcmcia_attr_read,
103
    pxa2xx_pcmcia_attr_read,
104
};
105

    
106
static CPUWriteMemoryFunc *pxa2xx_pcmcia_attr_writefn[] = {
107
    pxa2xx_pcmcia_attr_write,
108
    pxa2xx_pcmcia_attr_write,
109
    pxa2xx_pcmcia_attr_write,
110
};
111

    
112
static CPUReadMemoryFunc *pxa2xx_pcmcia_io_readfn[] = {
113
    pxa2xx_pcmcia_io_read,
114
    pxa2xx_pcmcia_io_read,
115
    pxa2xx_pcmcia_io_read,
116
};
117

    
118
static CPUWriteMemoryFunc *pxa2xx_pcmcia_io_writefn[] = {
119
    pxa2xx_pcmcia_io_write,
120
    pxa2xx_pcmcia_io_write,
121
    pxa2xx_pcmcia_io_write,
122
};
123

    
124
static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
125
{
126
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
127
    if (!s->irq)
128
        return;
129

    
130
    qemu_set_irq(s->irq, level);
131
}
132

    
133
PXA2xxPCMCIAState *pxa2xx_pcmcia_init(target_phys_addr_t base)
134
{
135
    int iomemtype;
136
    PXA2xxPCMCIAState *s;
137

    
138
    s = (PXA2xxPCMCIAState *)
139
            qemu_mallocz(sizeof(PXA2xxPCMCIAState));
140

    
141
    /* Socket I/O Memory Space */
142
    iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_io_readfn,
143
                    pxa2xx_pcmcia_io_writefn, s);
144
    cpu_register_physical_memory(base | 0x00000000, 0x04000000, iomemtype);
145

    
146
    /* Then next 64 MB is reserved */
147

    
148
    /* Socket Attribute Memory Space */
149
    iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_attr_readfn,
150
                    pxa2xx_pcmcia_attr_writefn, s);
151
    cpu_register_physical_memory(base | 0x08000000, 0x04000000, iomemtype);
152

    
153
    /* Socket Common Memory Space */
154
    iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_common_readfn,
155
                    pxa2xx_pcmcia_common_writefn, s);
156
    cpu_register_physical_memory(base | 0x0c000000, 0x04000000, iomemtype);
157

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

    
165
    return s;
166
}
167

    
168
/* Insert a new card into a slot */
169
int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card)
170
{
171
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
172
    if (s->slot.attached)
173
        return -EEXIST;
174

    
175
    if (s->cd_irq) {
176
        qemu_irq_raise(s->cd_irq);
177
    }
178

    
179
    s->card = card;
180

    
181
    s->slot.attached = 1;
182
    s->card->slot = &s->slot;
183
    s->card->attach(s->card->state);
184

    
185
    return 0;
186
}
187

    
188
/* Eject card from the slot */
189
int pxa2xx_pcmcia_dettach(void *opaque)
190
{
191
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
192
    if (!s->slot.attached)
193
        return -ENOENT;
194

    
195
    s->card->detach(s->card->state);
196
    s->card->slot = 0;
197
    s->card = 0;
198

    
199
    s->slot.attached = 0;
200

    
201
    if (s->irq)
202
        qemu_irq_lower(s->irq);
203
    if (s->cd_irq)
204
        qemu_irq_lower(s->cd_irq);
205

    
206
    return 0;
207
}
208

    
209
/* Who to notify on card events */
210
void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
211
{
212
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
213
    s->irq = irq;
214
    s->cd_irq = cd_irq;
215
}