Statistics
| Branch: | Revision:

root / hw / sh_pci.c @ 42ee76fe

History | View | Annotate | Download (5.7 kB)

1
/*
2
 * SuperH on-chip PCIC emulation.
3
 *
4
 * Copyright (c) 2008 Takashi YOSHII
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "hw.h"
25
#include "sh.h"
26
#include "pci.h"
27
#include "pci_host.h"
28
#include "sh_pci.h"
29
#include "bswap.h"
30

    
31
typedef struct {
32
    PCIBus *bus;
33
    PCIDevice *dev;
34
    uint32_t par;
35
    uint32_t mbr;
36
    uint32_t iobr;
37
} SHPCIC;
38

    
39
static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint32_t val)
40
{
41
    SHPCIC *pcic = p;
42
    switch(addr) {
43
    case 0 ... 0xfc:
44
        cpu_to_le32w((uint32_t*)(pcic->dev->config + addr), val);
45
        break;
46
    case 0x1c0:
47
        pcic->par = val;
48
        break;
49
    case 0x1c4:
50
        pcic->mbr = val;
51
        break;
52
    case 0x1c8:
53
        pcic->iobr = val;
54
        break;
55
    case 0x220:
56
        pci_data_write(pcic->bus, pcic->par, val, 4);
57
        break;
58
    }
59
}
60

    
61
static uint32_t sh_pci_reg_read (void *p, target_phys_addr_t addr)
62
{
63
    SHPCIC *pcic = p;
64
    switch(addr) {
65
    case 0 ... 0xfc:
66
        return le32_to_cpup((uint32_t*)(pcic->dev->config + addr));
67
    case 0x1c0:
68
        return pcic->par;
69
    case 0x220:
70
        return pci_data_read(pcic->bus, pcic->par, 4);
71
    }
72
    return 0;
73
}
74

    
75
static void sh_pci_data_write (SHPCIC *pcic, target_phys_addr_t addr,
76
                               uint32_t val, int size)
77
{
78
    pci_data_write(pcic->bus, addr + pcic->mbr, val, size);
79
}
80

    
81
static uint32_t sh_pci_mem_read (SHPCIC *pcic, target_phys_addr_t addr,
82
                                 int size)
83
{
84
    return pci_data_read(pcic->bus, addr + pcic->mbr, size);
85
}
86

    
87
static void sh_pci_writeb (void *p, target_phys_addr_t addr, uint32_t val)
88
{
89
    sh_pci_data_write(p, addr, val, 1);
90
}
91

    
92
static void sh_pci_writew (void *p, target_phys_addr_t addr, uint32_t val)
93
{
94
    sh_pci_data_write(p, addr, val, 2);
95
}
96

    
97
static void sh_pci_writel (void *p, target_phys_addr_t addr, uint32_t val)
98
{
99
    sh_pci_data_write(p, addr, val, 4);
100
}
101

    
102
static uint32_t sh_pci_readb (void *p, target_phys_addr_t addr)
103
{
104
    return sh_pci_mem_read(p, addr, 1);
105
}
106

    
107
static uint32_t sh_pci_readw (void *p, target_phys_addr_t addr)
108
{
109
    return sh_pci_mem_read(p, addr, 2);
110
}
111

    
112
static uint32_t sh_pci_readl (void *p, target_phys_addr_t addr)
113
{
114
    return sh_pci_mem_read(p, addr, 4);
115
}
116

    
117
static int sh_pci_addr2port(SHPCIC *pcic, target_phys_addr_t addr)
118
{
119
    return addr + pcic->iobr;
120
}
121

    
122
static void sh_pci_outb (void *p, target_phys_addr_t addr, uint32_t val)
123
{
124
    cpu_outb(sh_pci_addr2port(p, addr), val);
125
}
126

    
127
static void sh_pci_outw (void *p, target_phys_addr_t addr, uint32_t val)
128
{
129
    cpu_outw(sh_pci_addr2port(p, addr), val);
130
}
131

    
132
static void sh_pci_outl (void *p, target_phys_addr_t addr, uint32_t val)
133
{
134
    cpu_outl(sh_pci_addr2port(p, addr), val);
135
}
136

    
137
static uint32_t sh_pci_inb (void *p, target_phys_addr_t addr)
138
{
139
    return cpu_inb(sh_pci_addr2port(p, addr));
140
}
141

    
142
static uint32_t sh_pci_inw (void *p, target_phys_addr_t addr)
143
{
144
    return cpu_inw(sh_pci_addr2port(p, addr));
145
}
146

    
147
static uint32_t sh_pci_inl (void *p, target_phys_addr_t addr)
148
{
149
    return cpu_inl(sh_pci_addr2port(p, addr));
150
}
151

    
152
typedef struct {
153
    CPUReadMemoryFunc * const r[3];
154
    CPUWriteMemoryFunc * const w[3];
155
} MemOp;
156

    
157
static MemOp sh_pci_reg = {
158
    { NULL, NULL, sh_pci_reg_read },
159
    { NULL, NULL, sh_pci_reg_write },
160
};
161

    
162
static MemOp sh_pci_mem = {
163
    { sh_pci_readb, sh_pci_readw, sh_pci_readl },
164
    { sh_pci_writeb, sh_pci_writew, sh_pci_writel },
165
};
166

    
167
static MemOp sh_pci_iop = {
168
    { sh_pci_inb, sh_pci_inw, sh_pci_inl },
169
    { sh_pci_outb, sh_pci_outw, sh_pci_outl },
170
};
171

    
172
PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
173
                            void *opaque, int devfn_min, int nirq)
174
{
175
    SHPCIC *p;
176
    int mem, reg, iop;
177

    
178
    p = qemu_mallocz(sizeof(SHPCIC));
179
    p->bus = pci_register_bus(NULL, "pci",
180
                              set_irq, map_irq, opaque, devfn_min, nirq);
181

    
182
    p->dev = pci_register_device(p->bus, "SH PCIC", sizeof(PCIDevice),
183
                                 -1, NULL, NULL);
184
    reg = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w, p);
185
    iop = cpu_register_io_memory(sh_pci_iop.r, sh_pci_iop.w, p);
186
    mem = cpu_register_io_memory(sh_pci_mem.r, sh_pci_mem.w, p);
187
    cpu_register_physical_memory(0x1e200000, 0x224, reg);
188
    cpu_register_physical_memory(0x1e240000, 0x40000, iop);
189
    cpu_register_physical_memory(0x1d000000, 0x1000000, mem);
190
    cpu_register_physical_memory(0xfe200000, 0x224, reg);
191
    cpu_register_physical_memory(0xfe240000, 0x40000, iop);
192
    cpu_register_physical_memory(0xfd000000, 0x1000000, mem);
193

    
194
    pci_config_set_vendor_id(p->dev->config, PCI_VENDOR_ID_HITACHI);
195
    pci_config_set_device_id(p->dev->config, PCI_DEVICE_ID_HITACHI_SH7751R);
196
    p->dev->config[0x04] = 0x80;
197
    p->dev->config[0x05] = 0x00;
198
    p->dev->config[0x06] = 0x90;
199
    p->dev->config[0x07] = 0x02;
200

    
201
    return p->bus;
202
}