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.
28 * Authors: Andrew Schultz
33 * PCI Configspace implementation
41 #include "base/trace.hh"
42 #include "dev/pciconfigall.hh"
43 #include "dev/pcidev.hh"
44 #include "dev/pcireg.h"
45 #include "dev/platform.hh"
46 #include "mem/packet.hh"
47 #include "sim/builder.hh"
48 #include "sim/system.hh"
52 PciConfigAll::PciConfigAll(Params
*p
)
57 // Set backpointer for pci config. Really the config stuff should be able to
58 // automagically do this
59 p
->platform
->pciconfig
= this;
61 // Make all the pointers to devices null
62 for(int x
=0; x
< MAX_PCI_DEV
; x
++)
63 for(int y
=0; y
< MAX_PCI_FUNC
; y
++)
67 // If two interrupts share the same line largely bad things will happen.
68 // Since we don't track how many times an interrupt was set and correspondingly
69 // cleared two devices on the same interrupt line and assert and deassert each
70 // others interrupt "line". Interrupts will not work correctly.
72 PciConfigAll::startup()
78 for (int x
= 0; x
< MAX_PCI_DEV
; x
++) {
79 for (int y
= 0; y
< MAX_PCI_FUNC
; y
++) {
80 if (devices
[x
][y
] != NULL
) {
81 tempDev
= devices
[x
][y
];
82 intline
= tempDev
->interruptLine();
83 if (intLines
.test(intline
))
84 warn("Interrupt line %#X is used multiple times"
85 "(You probably want to fix this).\n", (uint32_t)intline
);
87 intLines
.set(intline
);
95 PciConfigAll::read(Packet
*pkt
)
97 assert(pkt
->result
== Packet::Unknown
);
98 assert(pkt
->getAddr() >= pioAddr
&& pkt
->getAddr() < pioAddr
+ pioSize
);
100 Addr daddr
= pkt
->getAddr() - pioAddr
;
101 int device
= (daddr
>> 11) & 0x1F;
102 int func
= (daddr
>> 8) & 0x7;
103 int reg
= daddr
& 0xFF;
107 DPRINTF(PciConfigAll
, "read va=%#x da=%#x size=%d\n", pkt
->getAddr(), daddr
,
110 switch (pkt
->getSize()) {
111 case sizeof(uint32_t):
112 if (devices
[device
][func
] == NULL
)
113 pkt
->set
<uint32_t>(0xFFFFFFFF);
115 devices
[device
][func
]->readConfig(reg
, pkt
->getPtr
<uint32_t>());
117 case sizeof(uint16_t):
118 if (devices
[device
][func
] == NULL
)
119 pkt
->set
<uint16_t>(0xFFFF);
121 devices
[device
][func
]->readConfig(reg
, pkt
->getPtr
<uint16_t>());
123 case sizeof(uint8_t):
124 if (devices
[device
][func
] == NULL
)
125 pkt
->set
<uint8_t>(0xFF);
127 devices
[device
][func
]->readConfig(reg
, pkt
->getPtr
<uint8_t>());
130 panic("invalid access size(?) for PCI configspace!\n");
132 pkt
->result
= Packet::Success
;
137 PciConfigAll::write(Packet
*pkt
)
139 assert(pkt
->result
== Packet::Unknown
);
140 assert(pkt
->getAddr() >= pioAddr
&& pkt
->getAddr() < pioAddr
+ pioSize
);
141 assert(pkt
->getSize() == sizeof(uint8_t) || pkt
->getSize() == sizeof(uint16_t) ||
142 pkt
->getSize() == sizeof(uint32_t));
143 Addr daddr
= pkt
->getAddr() - pioAddr
;
145 int device
= (daddr
>> 11) & 0x1F;
146 int func
= (daddr
>> 8) & 0x7;
147 int reg
= daddr
& 0xFF;
149 if (devices
[device
][func
] == NULL
)
150 panic("Attempting to write to config space on non-existant device\n");
152 DPRINTF(PciConfigAll
, "write - va=%#x size=%d data=%#x\n",
153 pkt
->getAddr(), pkt
->getSize(), pkt
->get
<uint32_t>());
155 switch (pkt
->getSize()) {
156 case sizeof(uint8_t):
157 devices
[device
][func
]->writeConfig(reg
, pkt
->get
<uint8_t>());
159 case sizeof(uint16_t):
160 devices
[device
][func
]->writeConfig(reg
, pkt
->get
<uint16_t>());
162 case sizeof(uint32_t):
163 devices
[device
][func
]->writeConfig(reg
, pkt
->get
<uint32_t>());
166 panic("invalid pci config write size\n");
168 pkt
->result
= Packet::Success
;
173 PciConfigAll::serialize(std::ostream
&os
)
176 * There is no state associated with this object that requires
177 * serialization. The only real state are the device pointers
178 * which are all setup by the constructor of the PciDev class
183 PciConfigAll::unserialize(Checkpoint
*cp
, const std::string
§ion
)
186 * There is no state associated with this object that requires
187 * serialization. The only real state are the device pointers
188 * which are all setup by the constructor of the PciDev class
192 #ifndef DOXYGEN_SHOULD_SKIP_THIS
194 BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll
)
196 Param
<Addr
> pio_addr
;
197 Param
<Tick
> pio_latency
;
198 SimObjectParam
<Platform
*> platform
;
199 SimObjectParam
<System
*> system
;
201 END_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll
)
203 BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigAll
)
205 INIT_PARAM(pio_addr
, "Device Address"),
206 INIT_PARAM(pio_latency
, "Programmed IO latency"),
207 INIT_PARAM(platform
, "platform"),
208 INIT_PARAM(system
, "system object")
210 END_INIT_SIM_OBJECT_PARAMS(PciConfigAll
)
212 CREATE_SIM_OBJECT(PciConfigAll
)
214 BasicPioDevice::Params
*p
= new BasicPioDevice::Params
;
215 p
->pio_addr
= pio_addr
;
216 p
->pio_delay
= pio_latency
;
217 p
->platform
= platform
;
219 return new PciConfigAll(p
);
222 REGISTER_SIM_OBJECT("PciConfigAll", PciConfigAll
)
224 #endif // DOXYGEN_SHOULD_SKIP_THIS