blob: 48862b5083571bd2b220736d90b4c657f5720d75 [file] [log] [blame]
pbrook502a5392006-05-13 16:11:23 +00001/*
2 * QEMU Common PCI Host bridge configuration data space access routines.
3 *
4 * Copyright (c) 2006 Fabrice Bellard
ths5fafdf22007-09-16 21:08:06 +00005 *
pbrook502a5392006-05-13 16:11:23 +00006 * 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
25/* Worker routines for a PCI host controller that uses an {address,data}
26 register pair to access PCI configuration space. */
27
blueswir180260372009-01-08 18:52:52 +000028/* debug PCI */
29//#define DEBUG_PCI
30
Gerd Hoffmann8a14daa2009-07-22 15:17:01 +020031#include "sysbus.h"
32
blueswir180260372009-01-08 18:52:52 +000033#ifdef DEBUG_PCI
Blue Swirl001faf32009-05-13 17:53:17 +000034#define PCI_DPRINTF(fmt, ...) \
35do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0)
blueswir180260372009-01-08 18:52:52 +000036#else
Blue Swirl001faf32009-05-13 17:53:17 +000037#define PCI_DPRINTF(fmt, ...)
blueswir180260372009-01-08 18:52:52 +000038#endif
39
pbrook502a5392006-05-13 16:11:23 +000040typedef struct {
Gerd Hoffmann8a14daa2009-07-22 15:17:01 +020041 SysBusDevice busdev;
pbrook502a5392006-05-13 16:11:23 +000042 uint32_t config_reg;
43 PCIBus *bus;
44} PCIHostState;
45
Anthony Liguoric227f092009-10-01 16:12:16 -050046static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
pbrook502a5392006-05-13 16:11:23 +000047{
48 PCIHostState *s = opaque;
blueswir180260372009-01-08 18:52:52 +000049
50 PCI_DPRINTF("writeb addr " TARGET_FMT_plx " val %x\n",
Anthony Liguoric227f092009-10-01 16:12:16 -050051 (target_phys_addr_t)addr, val);
pbrook502a5392006-05-13 16:11:23 +000052 if (s->config_reg & (1u << 31))
53 pci_data_write(s->bus, s->config_reg | (addr & 3), val, 1);
54}
55
Anthony Liguoric227f092009-10-01 16:12:16 -050056static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val)
pbrook502a5392006-05-13 16:11:23 +000057{
58 PCIHostState *s = opaque;
59#ifdef TARGET_WORDS_BIGENDIAN
60 val = bswap16(val);
61#endif
blueswir180260372009-01-08 18:52:52 +000062 PCI_DPRINTF("writew addr " TARGET_FMT_plx " val %x\n",
Anthony Liguoric227f092009-10-01 16:12:16 -050063 (target_phys_addr_t)addr, val);
pbrook502a5392006-05-13 16:11:23 +000064 if (s->config_reg & (1u << 31))
65 pci_data_write(s->bus, s->config_reg | (addr & 3), val, 2);
66}
67
Anthony Liguoric227f092009-10-01 16:12:16 -050068static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
pbrook502a5392006-05-13 16:11:23 +000069{
70 PCIHostState *s = opaque;
71#ifdef TARGET_WORDS_BIGENDIAN
72 val = bswap32(val);
73#endif
blueswir180260372009-01-08 18:52:52 +000074 PCI_DPRINTF("writel addr " TARGET_FMT_plx " val %x\n",
Anthony Liguoric227f092009-10-01 16:12:16 -050075 (target_phys_addr_t)addr, val);
pbrook502a5392006-05-13 16:11:23 +000076 if (s->config_reg & (1u << 31))
77 pci_data_write(s->bus, s->config_reg, val, 4);
78}
79
Anthony Liguoric227f092009-10-01 16:12:16 -050080static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr)
pbrook502a5392006-05-13 16:11:23 +000081{
82 PCIHostState *s = opaque;
blueswir180260372009-01-08 18:52:52 +000083 uint32_t val;
84
pbrook502a5392006-05-13 16:11:23 +000085 if (!(s->config_reg & (1 << 31)))
86 return 0xff;
blueswir180260372009-01-08 18:52:52 +000087 val = pci_data_read(s->bus, s->config_reg | (addr & 3), 1);
88 PCI_DPRINTF("readb addr " TARGET_FMT_plx " val %x\n",
Anthony Liguoric227f092009-10-01 16:12:16 -050089 (target_phys_addr_t)addr, val);
blueswir180260372009-01-08 18:52:52 +000090 return val;
pbrook502a5392006-05-13 16:11:23 +000091}
92
Anthony Liguoric227f092009-10-01 16:12:16 -050093static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
pbrook502a5392006-05-13 16:11:23 +000094{
95 PCIHostState *s = opaque;
96 uint32_t val;
97 if (!(s->config_reg & (1 << 31)))
98 return 0xffff;
99 val = pci_data_read(s->bus, s->config_reg | (addr & 3), 2);
blueswir180260372009-01-08 18:52:52 +0000100 PCI_DPRINTF("readw addr " TARGET_FMT_plx " val %x\n",
Anthony Liguoric227f092009-10-01 16:12:16 -0500101 (target_phys_addr_t)addr, val);
pbrook502a5392006-05-13 16:11:23 +0000102#ifdef TARGET_WORDS_BIGENDIAN
103 val = bswap16(val);
104#endif
105 return val;
106}
107
Anthony Liguoric227f092009-10-01 16:12:16 -0500108static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr)
pbrook502a5392006-05-13 16:11:23 +0000109{
110 PCIHostState *s = opaque;
111 uint32_t val;
112 if (!(s->config_reg & (1 << 31)))
113 return 0xffffffff;
114 val = pci_data_read(s->bus, s->config_reg | (addr & 3), 4);
blueswir180260372009-01-08 18:52:52 +0000115 PCI_DPRINTF("readl addr " TARGET_FMT_plx " val %x\n",
Anthony Liguoric227f092009-10-01 16:12:16 -0500116 (target_phys_addr_t)addr, val);
pbrook502a5392006-05-13 16:11:23 +0000117#ifdef TARGET_WORDS_BIGENDIAN
118 val = bswap32(val);
119#endif
120 return val;
121}