Statistics
| Branch: | Revision:

root / hw / pci_host.c @ 0b987f19

History | View | Annotate | Download (6.7 kB)

1
/*
2
 * pci_host.c
3
 *
4
 * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
5
 *                    VA Linux Systems Japan K.K.
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version.
11

12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16

17
 * You should have received a copy of the GNU General Public License along
18
 * with this program; if not, write to the Free Software Foundation, Inc.,
19
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
 */
21

    
22
#include "pci.h"
23
#include "pci_host.h"
24

    
25
/* debug PCI */
26
//#define DEBUG_PCI
27

    
28
#ifdef DEBUG_PCI
29
#define PCI_DPRINTF(fmt, ...) \
30
do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
31
#else
32
#define PCI_DPRINTF(fmt, ...)
33
#endif
34

    
35
/*
36
 * PCI address
37
 * bit 16 - 24: bus number
38
 * bit  8 - 15: devfun number
39
 * bit  0 -  7: offset in configuration space of a given pci device
40
 */
41

    
42
/* the helper functio to get a PCIDeice* for a given pci address */
43
static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr)
44
{
45
    uint8_t bus_num = addr >> 16;
46
    uint8_t devfn = addr >> 8;
47

    
48
    return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
49
}
50

    
51
void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
52
{
53
    PCIDevice *pci_dev = pci_dev_find_by_addr(s, addr);
54
    uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1);
55

    
56
    if (!pci_dev)
57
        return;
58

    
59
    PCI_DPRINTF("%s: %s: addr=%02" PRIx32 " val=%08" PRIx32 " len=%d\n",
60
                __func__, pci_dev->name, config_addr, val, len);
61
    pci_dev->config_write(pci_dev, config_addr, val, len);
62
}
63

    
64
uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
65
{
66
    PCIDevice *pci_dev = pci_dev_find_by_addr(s, addr);
67
    uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1);
68
    uint32_t val;
69

    
70
    assert(len == 1 || len == 2 || len == 4);
71
    if (!pci_dev) {
72
        return ~0x0;
73
    }
74

    
75
    val = pci_dev->config_read(pci_dev, config_addr, len);
76
    PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
77
                __func__, pci_dev->name, config_addr, val, len);
78

    
79
    return val;
80
}
81

    
82
static void pci_host_config_writel(void *opaque, target_phys_addr_t addr,
83
                                   uint32_t val)
84
{
85
    PCIHostState *s = opaque;
86

    
87
#ifdef TARGET_WORDS_BIGENDIAN
88
    val = bswap32(val);
89
#endif
90
    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
91
                __func__, addr, val);
92
    s->config_reg = val;
93
}
94

    
95
static uint32_t pci_host_config_readl(void *opaque, target_phys_addr_t addr)
96
{
97
    PCIHostState *s = opaque;
98
    uint32_t val = s->config_reg;
99

    
100
#ifdef TARGET_WORDS_BIGENDIAN
101
    val = bswap32(val);
102
#endif
103
    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
104
                __func__, addr, val);
105
    return val;
106
}
107

    
108
static CPUWriteMemoryFunc * const pci_host_config_write[] = {
109
    &pci_host_config_writel,
110
    &pci_host_config_writel,
111
    &pci_host_config_writel,
112
};
113

    
114
static CPUReadMemoryFunc * const pci_host_config_read[] = {
115
    &pci_host_config_readl,
116
    &pci_host_config_readl,
117
    &pci_host_config_readl,
118
};
119

    
120
int pci_host_conf_register_mmio(PCIHostState *s)
121
{
122
    return cpu_register_io_memory(pci_host_config_read,
123
                                  pci_host_config_write, s);
124
}
125

    
126
static void pci_host_config_writel_noswap(void *opaque,
127
                                          target_phys_addr_t addr,
128
                                          uint32_t val)
129
{
130
    PCIHostState *s = opaque;
131

    
132
    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
133
                __func__, addr, val);
134
    s->config_reg = val;
135
}
136

    
137
static uint32_t pci_host_config_readl_noswap(void *opaque,
138
                                             target_phys_addr_t addr)
139
{
140
    PCIHostState *s = opaque;
141
    uint32_t val = s->config_reg;
142

    
143
    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
144
                __func__, addr, val);
145
    return val;
146
}
147

    
148
static CPUWriteMemoryFunc * const pci_host_config_write_noswap[] = {
149
    &pci_host_config_writel_noswap,
150
    &pci_host_config_writel_noswap,
151
    &pci_host_config_writel_noswap,
152
};
153

    
154
static CPUReadMemoryFunc * const pci_host_config_read_noswap[] = {
155
    &pci_host_config_readl_noswap,
156
    &pci_host_config_readl_noswap,
157
    &pci_host_config_readl_noswap,
158
};
159

    
160
int pci_host_conf_register_mmio_noswap(PCIHostState *s)
161
{
162
    return cpu_register_io_memory(pci_host_config_read_noswap,
163
                                  pci_host_config_write_noswap, s);
164
}
165

    
166
static void pci_host_config_writel_ioport(void *opaque,
167
                                          uint32_t addr, uint32_t val)
168
{
169
    PCIHostState *s = opaque;
170

    
171
    PCI_DPRINTF("%s addr %"PRIx32 " val %"PRIx32"\n", __func__, addr, val);
172
    s->config_reg = val;
173
}
174

    
175
static uint32_t pci_host_config_readl_ioport(void *opaque, uint32_t addr)
176
{
177
    PCIHostState *s = opaque;
178
    uint32_t val = s->config_reg;
179

    
180
    PCI_DPRINTF("%s addr %"PRIx32" val %"PRIx32"\n", __func__, addr, val);
181
    return val;
182
}
183

    
184
void pci_host_conf_register_ioport(pio_addr_t ioport, PCIHostState *s)
185
{
186
    register_ioport_write(ioport, 4, 4, pci_host_config_writel_ioport, s);
187
    register_ioport_read(ioport, 4, 4, pci_host_config_readl_ioport, s);
188
}
189

    
190
#define PCI_ADDR_T      target_phys_addr_t
191
#define PCI_HOST_SUFFIX _mmio
192

    
193
#include "pci_host_template.h"
194

    
195
static CPUWriteMemoryFunc * const pci_host_data_write_mmio[] = {
196
    pci_host_data_writeb_mmio,
197
    pci_host_data_writew_mmio,
198
    pci_host_data_writel_mmio,
199
};
200

    
201
static CPUReadMemoryFunc * const pci_host_data_read_mmio[] = {
202
    pci_host_data_readb_mmio,
203
    pci_host_data_readw_mmio,
204
    pci_host_data_readl_mmio,
205
};
206

    
207
int pci_host_data_register_mmio(PCIHostState *s)
208
{
209
    return cpu_register_io_memory(pci_host_data_read_mmio,
210
                                  pci_host_data_write_mmio,
211
                                  s);
212
}
213

    
214
#undef PCI_ADDR_T
215
#undef PCI_HOST_SUFFIX
216

    
217
#define PCI_ADDR_T      uint32_t
218
#define PCI_HOST_SUFFIX _ioport
219

    
220
#include "pci_host_template.h"
221

    
222
void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s)
223
{
224
    register_ioport_write(ioport, 4, 1, pci_host_data_writeb_ioport, s);
225
    register_ioport_write(ioport, 4, 2, pci_host_data_writew_ioport, s);
226
    register_ioport_write(ioport, 4, 4, pci_host_data_writel_ioport, s);
227
    register_ioport_read(ioport, 4, 1, pci_host_data_readb_ioport, s);
228
    register_ioport_read(ioport, 4, 2, pci_host_data_readw_ioport, s);
229
    register_ioport_read(ioport, 4, 4, pci_host_data_readl_ioport, s);
230
}