Statistics
| Branch: | Revision:

root / hw / pxa2xx_pcmcia.c @ 4beeaa71

History | View | Annotate | Download (5.3 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

    
15
struct PXA2xxPCMCIAState {
16
    PCMCIASocket slot;
17
    PCMCIACardState *card;
18
    MemoryRegion common_iomem;
19
    MemoryRegion attr_iomem;
20

    
21
    qemu_irq irq;
22
    qemu_irq cd_irq;
23
};
24

    
25
static uint64_t pxa2xx_pcmcia_common_read(void *opaque,
26
                target_phys_addr_t offset, unsigned size)
27
{
28
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
29

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

    
34
    return 0;
35
}
36

    
37
static void pxa2xx_pcmcia_common_write(void *opaque, target_phys_addr_t offset,
38
                                       uint64_t value, unsigned size)
39
{
40
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
41

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

    
47
static uint64_t pxa2xx_pcmcia_attr_read(void *opaque,
48
                target_phys_addr_t offset, unsigned size)
49
{
50
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
51

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

    
56
    return 0;
57
}
58

    
59
static void pxa2xx_pcmcia_attr_write(void *opaque, target_phys_addr_t offset,
60
                                     uint64_t value, unsigned size)
61
{
62
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
63

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

    
69
static uint32_t pxa2xx_pcmcia_io_read(void *opaque,
70
                target_phys_addr_t offset)
71
{
72
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
73

    
74
    if (s->slot.attached) {
75
        return s->card->io_read(s->card->state, offset);
76
    }
77

    
78
    return 0;
79
}
80

    
81
static void pxa2xx_pcmcia_io_write(void *opaque,
82
                target_phys_addr_t offset, uint32_t value)
83
{
84
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
85

    
86
    if (s->slot.attached) {
87
        s->card->io_write(s->card->state, offset, value);
88
    }
89
}
90

    
91
static const MemoryRegionOps pxa2xx_pcmcia_common_ops = {
92
    .read = pxa2xx_pcmcia_common_read,
93
    .write = pxa2xx_pcmcia_common_write,
94
    .endianness = DEVICE_NATIVE_ENDIAN
95
};
96

    
97
static const MemoryRegionOps pxa2xx_pcmcia_attr_ops = {
98
    .read = pxa2xx_pcmcia_attr_read,
99
    .write = pxa2xx_pcmcia_attr_write,
100
    .endianness = DEVICE_NATIVE_ENDIAN
101
};
102

    
103
static CPUReadMemoryFunc * const pxa2xx_pcmcia_io_readfn[] = {
104
    pxa2xx_pcmcia_io_read,
105
    pxa2xx_pcmcia_io_read,
106
    pxa2xx_pcmcia_io_read,
107
};
108

    
109
static CPUWriteMemoryFunc * const pxa2xx_pcmcia_io_writefn[] = {
110
    pxa2xx_pcmcia_io_write,
111
    pxa2xx_pcmcia_io_write,
112
    pxa2xx_pcmcia_io_write,
113
};
114

    
115
static void pxa2xx_pcmcia_set_irq(void *opaque, int line, int level)
116
{
117
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
118
    if (!s->irq)
119
        return;
120

    
121
    qemu_set_irq(s->irq, level);
122
}
123

    
124
PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem,
125
                                      target_phys_addr_t base)
126
{
127
    int iomemtype;
128
    PXA2xxPCMCIAState *s;
129

    
130
    s = (PXA2xxPCMCIAState *)
131
            g_malloc0(sizeof(PXA2xxPCMCIAState));
132

    
133
    /* Socket I/O Memory Space */
134
    iomemtype = cpu_register_io_memory(pxa2xx_pcmcia_io_readfn,
135
                    pxa2xx_pcmcia_io_writefn, s, DEVICE_NATIVE_ENDIAN);
136
    cpu_register_physical_memory(base | 0x00000000, 0x04000000, iomemtype);
137

    
138
    /* Then next 64 MB is reserved */
139

    
140
    /* Socket Attribute Memory Space */
141
    memory_region_init_io(&s->attr_iomem, &pxa2xx_pcmcia_attr_ops, s,
142
                          "pxa2xx-pcmcia-attribute", 0x04000000);
143
    memory_region_add_subregion(sysmem, base | 0x08000000,
144
                                &s->attr_iomem);
145

    
146
    /* Socket Common Memory Space */
147
    memory_region_init_io(&s->common_iomem, &pxa2xx_pcmcia_common_ops, s,
148
                          "pxa2xx-pcmcia-common", 0x04000000);
149
    memory_region_add_subregion(sysmem, base | 0x0c000000,
150
                                &s->common_iomem);
151

    
152
    if (base == 0x30000000)
153
        s->slot.slot_string = "PXA PC Card Socket 1";
154
    else
155
        s->slot.slot_string = "PXA PC Card Socket 0";
156
    s->slot.irq = qemu_allocate_irqs(pxa2xx_pcmcia_set_irq, s, 1)[0];
157
    pcmcia_socket_register(&s->slot);
158

    
159
    return s;
160
}
161

    
162
/* Insert a new card into a slot */
163
int pxa2xx_pcmcia_attach(void *opaque, PCMCIACardState *card)
164
{
165
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
166
    if (s->slot.attached)
167
        return -EEXIST;
168

    
169
    if (s->cd_irq) {
170
        qemu_irq_raise(s->cd_irq);
171
    }
172

    
173
    s->card = card;
174

    
175
    s->slot.attached = 1;
176
    s->card->slot = &s->slot;
177
    s->card->attach(s->card->state);
178

    
179
    return 0;
180
}
181

    
182
/* Eject card from the slot */
183
int pxa2xx_pcmcia_dettach(void *opaque)
184
{
185
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
186
    if (!s->slot.attached)
187
        return -ENOENT;
188

    
189
    s->card->detach(s->card->state);
190
    s->card->slot = NULL;
191
    s->card = NULL;
192

    
193
    s->slot.attached = 0;
194

    
195
    if (s->irq)
196
        qemu_irq_lower(s->irq);
197
    if (s->cd_irq)
198
        qemu_irq_lower(s->cd_irq);
199

    
200
    return 0;
201
}
202

    
203
/* Who to notify on card events */
204
void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq)
205
{
206
    PXA2xxPCMCIAState *s = (PXA2xxPCMCIAState *) opaque;
207
    s->irq = irq;
208
    s->cd_irq = cd_irq;
209
}