2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * PCI Configspace implementation
38 #include "base/trace.hh"
39 #include "dev/pciconfigall.hh"
40 #include "dev/pcidev.hh"
41 #include "dev/pcireg.h"
42 #include "dev/platform.hh"
43 #include "mem/packet.hh"
44 #include "sim/builder.hh"
45 #include "sim/system.hh"
49 PciConfigAll::PciConfigAll(Params
*p
)
54 // Set backpointer for pci config. Really the config stuff should be able to
55 // automagically do this
56 p
->platform
->pciconfig
= this;
58 // Make all the pointers to devices null
59 for(int x
=0; x
< MAX_PCI_DEV
; x
++)
60 for(int y
=0; y
< MAX_PCI_FUNC
; y
++)
64 // If two interrupts share the same line largely bad things will happen.
65 // Since we don't track how many times an interrupt was set and correspondingly
66 // cleared two devices on the same interrupt line and assert and deassert each
67 // others interrupt "line". Interrupts will not work correctly.
69 PciConfigAll::startup()
75 for (int x
= 0; x
< MAX_PCI_DEV
; x
++) {
76 for (int y
= 0; y
< MAX_PCI_FUNC
; y
++) {
77 if (devices
[x
][y
] != NULL
) {
78 tempDev
= devices
[x
][y
];
79 intline
= tempDev
->interruptLine();
80 if (intLines
.test(intline
))
81 warn("Interrupt line %#X is used multiple times"
82 "(You probably want to fix this).\n", (uint32_t)intline
);
84 intLines
.set(intline
);
92 PciConfigAll::read(Packet
*pkt
)
94 assert(pkt
->result
== Packet::Unknown
);
95 assert(pkt
->getAddr() >= pioAddr
&& pkt
->getAddr() < pioAddr
+ pioSize
);
97 Addr daddr
= pkt
->getAddr() - pioAddr
;
98 int device
= (daddr
>> 11) & 0x1F;
99 int func
= (daddr
>> 8) & 0x7;
100 int reg
= daddr
& 0xFF;
104 DPRINTF(PciConfigAll
, "read va=%#x da=%#x size=%d\n", pkt
->getAddr(), daddr
,
107 switch (pkt
->getSize()) {
108 case sizeof(uint32_t):
109 if (devices
[device
][func
] == NULL
)
110 pkt
->set
<uint32_t>(0xFFFFFFFF);
112 devices
[device
][func
]->readConfig(reg
, pkt
->getPtr
<uint32_t>());
114 case sizeof(uint16_t):
115 if (devices
[device
][func
] == NULL
)
116 pkt
->set
<uint16_t>(0xFFFF);
118 devices
[device
][func
]->readConfig(reg
, pkt
->getPtr
<uint16_t>());
120 case sizeof(uint8_t):
121 if (devices
[device
][func
] == NULL
)
122 pkt
->set
<uint8_t>(0xFF);
124 devices
[device
][func
]->readConfig(reg
, pkt
->getPtr
<uint8_t>());
127 panic("invalid access size(?) for PCI configspace!\n");
129 pkt
->result
= Packet::Success
;
134 PciConfigAll::write(Packet
*pkt
)
136 assert(pkt
->result
== Packet::Unknown
);
137 assert(pkt
->getAddr() >= pioAddr
&& pkt
->getAddr() < pioAddr
+ pioSize
);
138 assert(pkt
->getSize() == sizeof(uint8_t) || pkt
->getSize() == sizeof(uint16_t) ||
139 pkt
->getSize() == sizeof(uint32_t));
140 Addr daddr
= pkt
->getAddr() - pioAddr
;
142 int device
= (daddr
>> 11) & 0x1F;
143 int func
= (daddr
>> 8) & 0x7;
144 int reg
= daddr
& 0xFF;
146 if (devices
[device
][func
] == NULL
)
147 panic("Attempting to write to config space on non-existant device\n");
149 DPRINTF(PciConfigAll
, "write - va=%#x size=%d data=%#x\n",
150 pkt
->getAddr(), pkt
->getSize(), pkt
->get
<uint32_t>());
152 switch (pkt
->getSize()) {
153 case sizeof(uint8_t):
154 devices
[device
][func
]->writeConfig(reg
, pkt
->get
<uint8_t>());
156 case sizeof(uint16_t):
157 devices
[device
][func
]->writeConfig(reg
, pkt
->get
<uint16_t>());
159 case sizeof(uint32_t):
160 devices
[device
][func
]->writeConfig(reg
, pkt
->get
<uint32_t>());
163 panic("invalid pci config write size\n");
165 pkt
->result
= Packet::Success
;
170 PciConfigAll::serialize(std::ostream
&os
)
173 * There is no state associated with this object that requires
174 * serialization. The only real state are the device pointers
175 * which are all setup by the constructor of the PciDev class
180 PciConfigAll::unserialize(Checkpoint
*cp
, const std::string
§ion
)
183 * There is no state associated with this object that requires
184 * serialization. The only real state are the device pointers
185 * which are all setup by the constructor of the PciDev class
189 #ifndef DOXYGEN_SHOULD_SKIP_THIS
191 BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll
)
193 Param
<Addr
> pio_addr
;
194 Param
<Tick
> pio_latency
;
195 SimObjectParam
<Platform
*> platform
;
196 SimObjectParam
<System
*> system
;
198 END_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll
)
200 BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigAll
)
202 INIT_PARAM(pio_addr
, "Device Address"),
203 INIT_PARAM(pio_latency
, "Programmed IO latency"),
204 INIT_PARAM(platform
, "platform"),
205 INIT_PARAM(system
, "system object")
207 END_INIT_SIM_OBJECT_PARAMS(PciConfigAll
)
209 CREATE_SIM_OBJECT(PciConfigAll
)
211 BasicPioDevice::Params
*p
= new BasicPioDevice::Params
;
212 p
->pio_addr
= pio_addr
;
213 p
->pio_delay
= pio_latency
;
214 p
->platform
= platform
;
216 return new PciConfigAll(p
);
219 REGISTER_SIM_OBJECT("PciConfigAll", PciConfigAll
)
221 #endif // DOXYGEN_SHOULD_SKIP_THIS