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()
71 /* bitset<256> intLines;
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
== Unknown
);
95 assert(pkt
.addr
>= pioAddr
&& pkt
.addr
< pioAddr
+ pioSize
);
97 Addr daddr
= pkt
.addr
- pioAddr
;
98 int device
= (daddr
>> 11) & 0x1F;
99 int func
= (daddr
>> 8) & 0x7;
100 //int reg = daddr & 0xFF;
102 pkt
.time
= curTick
+ pioDelay
;
104 DPRINTF(PciConfigAll
, "read va=%#x da=%#x size=%d\n", pkt
.addr
, daddr
,
112 /* case sizeof(uint64_t):
114 data64 = new uint64_t;
115 pkt.data = (uint8_t*)data64;
117 data64 = (uint64_t*)pkt.data;
119 if (devices[device][func] == NULL)
120 *data64 = 0xFFFFFFFFFFFFFFFFULL;
122 devices[device][func]->readConfig(reg, req.size, data64);
124 case sizeof(uint32_t):
126 data32
= new uint32_t;
127 pkt
.data
= (uint8_t*)data32
;
129 data32
= (uint32_t*)pkt
.data
;
131 if (devices
[device
][func
] == NULL
)
132 *data32
= 0xFFFFFFFF;
134 ;//devices[device][func]->readConfig(reg, req.size, data32);
136 case sizeof(uint16_t):
138 data16
= new uint16_t;
139 pkt
.data
= (uint8_t*)data16
;
141 data16
= (uint16_t*)pkt
.data
;
143 if (devices
[device
][func
] == NULL
)
146 ;//devices[device][func]->readConfig(reg, req.size, data16);
148 case sizeof(uint8_t):
153 data8
= (uint8_t*)pkt
.data
;
155 if (devices
[device
][func
] == NULL
)
158 ;//devices[device][func]->readConfig(reg, req.size, data8);
161 panic("invalid access size(?) for PCI configspace!\n");
163 pkt
.result
= Success
;
168 PciConfigAll::write(Packet
&pkt
)
170 pkt
.time
= curTick
+ pioDelay
;
172 assert(pkt
.result
== Unknown
);
173 assert(pkt
.addr
>= pioAddr
&& pkt
.addr
< pioAddr
+ pioSize
);
174 assert(pkt
.size
== sizeof(uint8_t) || pkt
.size
== sizeof(uint16_t) ||
175 pkt
.size
== sizeof(uint32_t));
176 Addr daddr
= pkt
.addr
- pioAddr
;
178 int device
= (daddr
>> 11) & 0x1F;
179 int func
= (daddr
>> 8) & 0x7;
180 // int reg = daddr & 0xFF;
182 if (devices
[device
][func
] == NULL
)
183 panic("Attempting to write to config space on non-existant device\n");
185 DPRINTF(PciConfigAll
, "write - va=%#x size=%d data=%#x\n",
186 pkt
.addr
, pkt
.size
, *(uint32_t*)pkt
.data
);
188 // devices[device][func]->writeConfig(reg, req->size, data);
194 PciConfigAll::serialize(std::ostream
&os
)
197 * There is no state associated with this object that requires
198 * serialization. The only real state are the device pointers
199 * which are all setup by the constructor of the PciDev class
204 PciConfigAll::unserialize(Checkpoint
*cp
, const std::string
§ion
)
207 * There is no state associated with this object that requires
208 * serialization. The only real state are the device pointers
209 * which are all setup by the constructor of the PciDev class
213 #ifndef DOXYGEN_SHOULD_SKIP_THIS
215 BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll
)
217 Param
<Addr
> pio_addr
;
218 Param
<Tick
> pio_latency
;
219 SimObjectParam
<Platform
*> platform
;
220 SimObjectParam
<System
*> system
;
222 END_DECLARE_SIM_OBJECT_PARAMS(PciConfigAll
)
224 BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigAll
)
226 INIT_PARAM(pio_addr
, "Device Address"),
227 INIT_PARAM(pio_latency
, "Programmed IO latency"),
228 INIT_PARAM(platform
, "platform"),
229 INIT_PARAM(system
, "system object")
231 END_INIT_SIM_OBJECT_PARAMS(PciConfigAll
)
233 CREATE_SIM_OBJECT(PciConfigAll
)
235 BasicPioDevice::Params
*p
= new BasicPioDevice::Params
;
236 p
->pio_addr
= pio_addr
;
237 p
->pio_delay
= pio_latency
;
238 p
->platform
= platform
;
240 return new PciConfigAll(p
);
243 REGISTER_SIM_OBJECT("PciConfigAll", PciConfigAll
)
245 #endif // DOXYGEN_SHOULD_SKIP_THIS