Statistics
| Branch: | Revision:

root / hw / pci_host.c @ 2a424990

History | View | Annotate | Download (6.9 kB)

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

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

17 4f5e19e6 Isaku Yamahata
 * You should have received a copy of the GNU General Public License along
18 4f5e19e6 Isaku Yamahata
 * with this program; if not, write to the Free Software Foundation, Inc.,
19 4f5e19e6 Isaku Yamahata
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 4f5e19e6 Isaku Yamahata
 */
21 4f5e19e6 Isaku Yamahata
22 4f5e19e6 Isaku Yamahata
#include "pci.h"
23 4f5e19e6 Isaku Yamahata
#include "pci_host.h"
24 4f5e19e6 Isaku Yamahata
25 4f5e19e6 Isaku Yamahata
/* debug PCI */
26 4f5e19e6 Isaku Yamahata
//#define DEBUG_PCI
27 4f5e19e6 Isaku Yamahata
28 4f5e19e6 Isaku Yamahata
#ifdef DEBUG_PCI
29 4f5e19e6 Isaku Yamahata
#define PCI_DPRINTF(fmt, ...) \
30 4f5e19e6 Isaku Yamahata
do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
31 4f5e19e6 Isaku Yamahata
#else
32 4f5e19e6 Isaku Yamahata
#define PCI_DPRINTF(fmt, ...)
33 4f5e19e6 Isaku Yamahata
#endif
34 4f5e19e6 Isaku Yamahata
35 766347cc Isaku Yamahata
/*
36 766347cc Isaku Yamahata
 * PCI address
37 766347cc Isaku Yamahata
 * bit 16 - 24: bus number
38 766347cc Isaku Yamahata
 * bit  8 - 15: devfun number
39 766347cc Isaku Yamahata
 * bit  0 -  7: offset in configuration space of a given pci device
40 766347cc Isaku Yamahata
 */
41 766347cc Isaku Yamahata
42 766347cc Isaku Yamahata
/* the helper functio to get a PCIDeice* for a given pci address */
43 766347cc Isaku Yamahata
static inline PCIDevice *pci_addr_to_dev(PCIBus *bus, uint32_t addr)
44 766347cc Isaku Yamahata
{
45 766347cc Isaku Yamahata
    uint8_t bus_num = (addr >> 16) & 0xff;
46 766347cc Isaku Yamahata
    uint8_t devfn = (addr >> 8) & 0xff;
47 766347cc Isaku Yamahata
    return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn));
48 766347cc Isaku Yamahata
}
49 766347cc Isaku Yamahata
50 766347cc Isaku Yamahata
static inline uint32_t pci_addr_to_config(uint32_t addr)
51 766347cc Isaku Yamahata
{
52 766347cc Isaku Yamahata
    return addr & (PCI_CONFIG_SPACE_SIZE - 1);
53 766347cc Isaku Yamahata
}
54 766347cc Isaku Yamahata
55 ce195fb5 Isaku Yamahata
void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
56 766347cc Isaku Yamahata
{
57 766347cc Isaku Yamahata
    PCIDevice *pci_dev = pci_addr_to_dev(s, addr);
58 766347cc Isaku Yamahata
    uint32_t config_addr = pci_addr_to_config(addr);
59 766347cc Isaku Yamahata
60 766347cc Isaku Yamahata
    if (!pci_dev)
61 766347cc Isaku Yamahata
        return;
62 766347cc Isaku Yamahata
63 766347cc Isaku Yamahata
    PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRI32x" len=%d\n",
64 766347cc Isaku Yamahata
                __func__, pci_dev->name, config_addr, val, len);
65 766347cc Isaku Yamahata
    pci_dev->config_write(pci_dev, config_addr, val, len);
66 766347cc Isaku Yamahata
}
67 766347cc Isaku Yamahata
68 ce195fb5 Isaku Yamahata
uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
69 766347cc Isaku Yamahata
{
70 766347cc Isaku Yamahata
    PCIDevice *pci_dev = pci_addr_to_dev(s, addr);
71 766347cc Isaku Yamahata
    uint32_t config_addr = pci_addr_to_config(addr);
72 766347cc Isaku Yamahata
    uint32_t val;
73 766347cc Isaku Yamahata
74 766347cc Isaku Yamahata
    if (!pci_dev) {
75 766347cc Isaku Yamahata
        switch(len) {
76 766347cc Isaku Yamahata
        case 1:
77 766347cc Isaku Yamahata
            val = 0xff;
78 766347cc Isaku Yamahata
            break;
79 766347cc Isaku Yamahata
        case 2:
80 766347cc Isaku Yamahata
            val = 0xffff;
81 766347cc Isaku Yamahata
            break;
82 766347cc Isaku Yamahata
        default:
83 766347cc Isaku Yamahata
        case 4:
84 766347cc Isaku Yamahata
            val = 0xffffffff;
85 766347cc Isaku Yamahata
            break;
86 766347cc Isaku Yamahata
        }
87 766347cc Isaku Yamahata
    } else {
88 766347cc Isaku Yamahata
        val = pci_dev->config_read(pci_dev, config_addr, len);
89 766347cc Isaku Yamahata
        PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
90 766347cc Isaku Yamahata
                    __func__, pci_dev->name, config_addr, val, len);
91 766347cc Isaku Yamahata
    }
92 766347cc Isaku Yamahata
93 766347cc Isaku Yamahata
    return val;
94 766347cc Isaku Yamahata
}
95 766347cc Isaku Yamahata
96 a455783b Isaku Yamahata
static void pci_host_config_writel(void *opaque, target_phys_addr_t addr,
97 a455783b Isaku Yamahata
                                   uint32_t val)
98 a455783b Isaku Yamahata
{
99 a455783b Isaku Yamahata
    PCIHostState *s = opaque;
100 a455783b Isaku Yamahata
101 a455783b Isaku Yamahata
#ifdef TARGET_WORDS_BIGENDIAN
102 a455783b Isaku Yamahata
    val = bswap32(val);
103 a455783b Isaku Yamahata
#endif
104 a455783b Isaku Yamahata
    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
105 a455783b Isaku Yamahata
                __func__, addr, val);
106 a455783b Isaku Yamahata
    s->config_reg = val;
107 a455783b Isaku Yamahata
}
108 a455783b Isaku Yamahata
109 a455783b Isaku Yamahata
static uint32_t pci_host_config_readl(void *opaque, target_phys_addr_t addr)
110 a455783b Isaku Yamahata
{
111 a455783b Isaku Yamahata
    PCIHostState *s = opaque;
112 a455783b Isaku Yamahata
    uint32_t val = s->config_reg;
113 a455783b Isaku Yamahata
114 a455783b Isaku Yamahata
#ifdef TARGET_WORDS_BIGENDIAN
115 a455783b Isaku Yamahata
    val = bswap32(val);
116 a455783b Isaku Yamahata
#endif
117 a455783b Isaku Yamahata
    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
118 a455783b Isaku Yamahata
                __func__, addr, val);
119 a455783b Isaku Yamahata
    return val;
120 a455783b Isaku Yamahata
}
121 a455783b Isaku Yamahata
122 a455783b Isaku Yamahata
static CPUWriteMemoryFunc * const pci_host_config_write[] = {
123 a455783b Isaku Yamahata
    &pci_host_config_writel,
124 a455783b Isaku Yamahata
    &pci_host_config_writel,
125 a455783b Isaku Yamahata
    &pci_host_config_writel,
126 a455783b Isaku Yamahata
};
127 a455783b Isaku Yamahata
128 a455783b Isaku Yamahata
static CPUReadMemoryFunc * const pci_host_config_read[] = {
129 a455783b Isaku Yamahata
    &pci_host_config_readl,
130 a455783b Isaku Yamahata
    &pci_host_config_readl,
131 a455783b Isaku Yamahata
    &pci_host_config_readl,
132 a455783b Isaku Yamahata
};
133 a455783b Isaku Yamahata
134 a455783b Isaku Yamahata
int pci_host_config_register_io_memory(PCIHostState *s)
135 a455783b Isaku Yamahata
{
136 a455783b Isaku Yamahata
    return cpu_register_io_memory(pci_host_config_read,
137 a455783b Isaku Yamahata
                                  pci_host_config_write, s);
138 a455783b Isaku Yamahata
}
139 a455783b Isaku Yamahata
140 a455783b Isaku Yamahata
static void pci_host_config_writel_noswap(void *opaque,
141 a455783b Isaku Yamahata
                                          target_phys_addr_t addr,
142 a455783b Isaku Yamahata
                                          uint32_t val)
143 a455783b Isaku Yamahata
{
144 a455783b Isaku Yamahata
    PCIHostState *s = opaque;
145 a455783b Isaku Yamahata
146 a455783b Isaku Yamahata
    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
147 a455783b Isaku Yamahata
                __func__, addr, val);
148 a455783b Isaku Yamahata
    s->config_reg = val;
149 a455783b Isaku Yamahata
}
150 a455783b Isaku Yamahata
151 a455783b Isaku Yamahata
static uint32_t pci_host_config_readl_noswap(void *opaque,
152 a455783b Isaku Yamahata
                                             target_phys_addr_t addr)
153 a455783b Isaku Yamahata
{
154 a455783b Isaku Yamahata
    PCIHostState *s = opaque;
155 a455783b Isaku Yamahata
    uint32_t val = s->config_reg;
156 a455783b Isaku Yamahata
157 a455783b Isaku Yamahata
    PCI_DPRINTF("%s addr " TARGET_FMT_plx " val %"PRIx32"\n",
158 a455783b Isaku Yamahata
                __func__, addr, val);
159 a455783b Isaku Yamahata
    return val;
160 a455783b Isaku Yamahata
}
161 a455783b Isaku Yamahata
162 a455783b Isaku Yamahata
static CPUWriteMemoryFunc * const pci_host_config_write_noswap[] = {
163 a455783b Isaku Yamahata
    &pci_host_config_writel_noswap,
164 a455783b Isaku Yamahata
    &pci_host_config_writel_noswap,
165 a455783b Isaku Yamahata
    &pci_host_config_writel_noswap,
166 a455783b Isaku Yamahata
};
167 a455783b Isaku Yamahata
168 a455783b Isaku Yamahata
static CPUReadMemoryFunc * const pci_host_config_read_noswap[] = {
169 a455783b Isaku Yamahata
    &pci_host_config_readl_noswap,
170 a455783b Isaku Yamahata
    &pci_host_config_readl_noswap,
171 a455783b Isaku Yamahata
    &pci_host_config_readl_noswap,
172 a455783b Isaku Yamahata
};
173 a455783b Isaku Yamahata
174 a455783b Isaku Yamahata
int pci_host_config_register_io_memory_noswap(PCIHostState *s)
175 a455783b Isaku Yamahata
{
176 a455783b Isaku Yamahata
    return cpu_register_io_memory(pci_host_config_read_noswap,
177 a455783b Isaku Yamahata
                                  pci_host_config_write_noswap, s);
178 a455783b Isaku Yamahata
}
179 a455783b Isaku Yamahata
180 a455783b Isaku Yamahata
static void pci_host_config_writel_ioport(void *opaque,
181 a455783b Isaku Yamahata
                                          uint32_t addr, uint32_t val)
182 a455783b Isaku Yamahata
{
183 a455783b Isaku Yamahata
    PCIHostState *s = opaque;
184 a455783b Isaku Yamahata
185 a455783b Isaku Yamahata
    PCI_DPRINTF("%s addr %"PRIx32 " val %"PRIx32"\n", __func__, addr, val);
186 a455783b Isaku Yamahata
    s->config_reg = val;
187 a455783b Isaku Yamahata
}
188 a455783b Isaku Yamahata
189 a455783b Isaku Yamahata
static uint32_t pci_host_config_readl_ioport(void *opaque, uint32_t addr)
190 a455783b Isaku Yamahata
{
191 a455783b Isaku Yamahata
    PCIHostState *s = opaque;
192 a455783b Isaku Yamahata
    uint32_t val = s->config_reg;
193 a455783b Isaku Yamahata
194 a455783b Isaku Yamahata
    PCI_DPRINTF("%s addr %"PRIx32" val %"PRIx32"\n", __func__, addr, val);
195 a455783b Isaku Yamahata
    return val;
196 a455783b Isaku Yamahata
}
197 a455783b Isaku Yamahata
198 a455783b Isaku Yamahata
void pci_host_config_register_ioport(pio_addr_t ioport, PCIHostState *s)
199 a455783b Isaku Yamahata
{
200 a455783b Isaku Yamahata
    register_ioport_write(ioport, 4, 4, pci_host_config_writel_ioport, s);
201 a455783b Isaku Yamahata
    register_ioport_read(ioport, 4, 4, pci_host_config_readl_ioport, s);
202 a455783b Isaku Yamahata
}
203 a455783b Isaku Yamahata
204 4f5e19e6 Isaku Yamahata
#define PCI_ADDR_T      target_phys_addr_t
205 4f5e19e6 Isaku Yamahata
#define PCI_HOST_SUFFIX _mmio
206 4f5e19e6 Isaku Yamahata
207 4f5e19e6 Isaku Yamahata
#include "pci_host_template.h"
208 4f5e19e6 Isaku Yamahata
209 4f5e19e6 Isaku Yamahata
static CPUWriteMemoryFunc * const pci_host_data_write_mmio[] = {
210 4f5e19e6 Isaku Yamahata
    pci_host_data_writeb_mmio,
211 4f5e19e6 Isaku Yamahata
    pci_host_data_writew_mmio,
212 4f5e19e6 Isaku Yamahata
    pci_host_data_writel_mmio,
213 4f5e19e6 Isaku Yamahata
};
214 4f5e19e6 Isaku Yamahata
215 4f5e19e6 Isaku Yamahata
static CPUReadMemoryFunc * const pci_host_data_read_mmio[] = {
216 4f5e19e6 Isaku Yamahata
    pci_host_data_readb_mmio,
217 4f5e19e6 Isaku Yamahata
    pci_host_data_readw_mmio,
218 4f5e19e6 Isaku Yamahata
    pci_host_data_readl_mmio,
219 4f5e19e6 Isaku Yamahata
};
220 4f5e19e6 Isaku Yamahata
221 4f5e19e6 Isaku Yamahata
int pci_host_data_register_io_memory(PCIHostState *s)
222 4f5e19e6 Isaku Yamahata
{
223 4f5e19e6 Isaku Yamahata
    return cpu_register_io_memory(pci_host_data_read_mmio,
224 4f5e19e6 Isaku Yamahata
                                  pci_host_data_write_mmio,
225 4f5e19e6 Isaku Yamahata
                                  s);
226 4f5e19e6 Isaku Yamahata
}
227 4f5e19e6 Isaku Yamahata
228 4f5e19e6 Isaku Yamahata
#undef PCI_ADDR_T
229 4f5e19e6 Isaku Yamahata
#undef PCI_HOST_SUFFIX
230 4f5e19e6 Isaku Yamahata
231 4f5e19e6 Isaku Yamahata
#define PCI_ADDR_T      uint32_t
232 4f5e19e6 Isaku Yamahata
#define PCI_HOST_SUFFIX _ioport
233 4f5e19e6 Isaku Yamahata
234 4f5e19e6 Isaku Yamahata
#include "pci_host_template.h"
235 4f5e19e6 Isaku Yamahata
236 4f5e19e6 Isaku Yamahata
void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s)
237 4f5e19e6 Isaku Yamahata
{
238 4f5e19e6 Isaku Yamahata
    register_ioport_write(ioport, 4, 1, pci_host_data_writeb_ioport, s);
239 4f5e19e6 Isaku Yamahata
    register_ioport_write(ioport, 4, 2, pci_host_data_writew_ioport, s);
240 4f5e19e6 Isaku Yamahata
    register_ioport_write(ioport, 4, 4, pci_host_data_writel_ioport, s);
241 4f5e19e6 Isaku Yamahata
    register_ioport_read(ioport, 4, 1, pci_host_data_readb_ioport, s);
242 4f5e19e6 Isaku Yamahata
    register_ioport_read(ioport, 4, 2, pci_host_data_readw_ioport, s);
243 4f5e19e6 Isaku Yamahata
    register_ioport_read(ioport, 4, 4, pci_host_data_readl_ioport, s);
244 4f5e19e6 Isaku Yamahata
}