2 * Copyright (c) 2006 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.
32 * Device model for Intel's 8254x line of gigabit ethernet controllers.
33 * In particular an 82547 revision 2 (82547GI) MAC because it seems to have the
34 * fewest workarounds in the driver. It will probably work with most of the
35 * other MACs with slight modifications.
38 #include "base/inet.hh"
39 #include "dev/i8254xGBe.hh"
40 #include "mem/packet.hh"
41 #include "sim/builder.hh"
42 #include "sim/stats.hh"
43 #include "sim/system.hh"
45 using namespace iGbReg
;
48 : PciDev(p
), etherInt(NULL
)
50 // Initialized internal registers per Intel documentation
61 regs
.eecd
.ee_type
= 1;
74 memset(&flash
, 0, EEPROM_SIZE
);
75 // Magic happy checksum value
81 IGbE::writeConfig(Packet
*pkt
)
83 int offset
= pkt
->getAddr() & PCI_CONFIG_SIZE
;
84 if (offset
< PCI_DEVICE_SPECIFIC
)
85 PciDev::writeConfig(pkt
);
87 panic("Device specific PCI config space not implemented.\n");
90 /// Some work may need to be done here based for the pci COMMAND bits.
97 IGbE::read(Packet
*pkt
)
102 if (!getBAR(pkt
->getAddr(), bar
, daddr
))
103 panic("Invalid PCI memory access to unmapped memory.\n");
105 // Only Memory register BAR is allowed
108 // Only 32bit accesses allowed
109 assert(pkt
->getSize() == 4);
111 DPRINTF(Ethernet
, "Read device register %#X\n", daddr
);
116 /// Handle read of register here
121 pkt
->set
<uint32_t>(regs
.ctrl
.reg
);
124 pkt
->set
<uint32_t>(regs
.sts
.reg
);
127 pkt
->set
<uint32_t>(regs
.eecd
.reg
);
130 pkt
->set
<uint32_t>(regs
.eerd
.reg
);
133 pkt
->set
<uint32_t>(regs
.icd
.reg
);
136 pkt
->set
<uint32_t>(regs
.imc
.reg
);
139 pkt
->set
<uint32_t>(regs
.rctl
.reg
);
142 pkt
->set
<uint32_t>(regs
.tctl
.reg
);
145 pkt
->set
<uint32_t>(regs
.manc
.reg
);
148 panic("Read request to unknown register number: %#x\n", daddr
);
151 pkt
->result
= Packet::Success
;
156 IGbE::write(Packet
*pkt
)
162 if (!getBAR(pkt
->getAddr(), bar
, daddr
))
163 panic("Invalid PCI memory access to unmapped memory.\n");
165 // Only Memory register BAR is allowed
168 // Only 32bit accesses allowed
169 assert(pkt
->getSize() == sizeof(uint32_t));
171 DPRINTF(Ethernet
, "Wrote device register %#X value %#X\n", daddr
, pkt
->get
<uint32_t>());
174 /// Handle write of register here
176 uint32_t val
= pkt
->get
<uint32_t>();
187 oldClk
= regs
.eecd
.sk
;
189 // See if this is a eeprom access and emulate accordingly
190 if (!oldClk
&& regs
.eecd
.sk
) {
192 eeOpcode
= eeOpcode
<< 1 | regs
.eecd
.din
;
194 } else if (eeAddrBits
< 8 && eeOpcode
== EEPROM_READ_OPCODE_SPI
) {
195 eeAddr
= eeAddr
<< 1 | regs
.eecd
.din
;
197 } else if (eeDataBits
< 16 && eeOpcode
== EEPROM_READ_OPCODE_SPI
) {
198 assert(eeAddr
< EEPROM_SIZE
);
199 DPRINTF(Ethernet
, "EEPROM bit read: %d word: %#X\n",
200 flash
[eeAddr
] >> eeDataBits
& 0x1, flash
[eeAddr
]);
201 regs
.eecd
.dout
= (flash
[eeAddr
] >> eeDataBits
) & 0x1;
203 } else if (eeDataBits
< 8 && eeOpcode
== EEPROM_RDSR_OPCODE_SPI
) {
207 panic("What's going on with eeprom interface? opcode:"
208 " %#x:%d addr: %#x:%d, data: %d\n", (uint32_t)eeOpcode
,
209 (uint32_t)eeOpBits
, (uint32_t)eeAddr
,
210 (uint32_t)eeAddrBits
, (uint32_t)eeDataBits
);
212 // Reset everything for the next command
213 if ((eeDataBits
== 16 && eeOpcode
== EEPROM_READ_OPCODE_SPI
) ||
214 (eeDataBits
== 8 && eeOpcode
== EEPROM_RDSR_OPCODE_SPI
)) {
222 DPRINTF(Ethernet
, "EEPROM: opcode: %#X:%d\n",
223 (uint32_t)eeOpcode
, (uint32_t) eeOpBits
);
224 if (eeOpBits
== 8 && !(eeOpcode
== EEPROM_READ_OPCODE_SPI
||
225 eeOpcode
== EEPROM_RDSR_OPCODE_SPI
))
226 panic("Unknown eeprom opcode: %#X:%d\n", (uint32_t)eeOpcode
,
231 // If driver requests eeprom access, immediately give it to it
232 regs
.eecd
.ee_gnt
= regs
.eecd
.ee_req
;
253 panic("Write request to unknown register number: %#x\n", daddr
);
256 pkt
->result
= Packet::Success
;
262 IGbE::ethRxPkt(EthPacketPtr packet
)
264 panic("Need to implemenet\n");
271 panic("Need to implemenet\n");
275 IGbE::serialize(std::ostream
&os
)
277 panic("Need to implemenet\n");
281 IGbE::unserialize(Checkpoint
*cp
, const std::string
§ion
)
283 panic("Need to implemenet\n");
287 BEGIN_DECLARE_SIM_OBJECT_PARAMS(IGbEInt
)
289 SimObjectParam
<EtherInt
*> peer
;
290 SimObjectParam
<IGbE
*> device
;
292 END_DECLARE_SIM_OBJECT_PARAMS(IGbEInt
)
294 BEGIN_INIT_SIM_OBJECT_PARAMS(IGbEInt
)
296 INIT_PARAM_DFLT(peer
, "peer interface", NULL
),
297 INIT_PARAM(device
, "Ethernet device of this interface")
299 END_INIT_SIM_OBJECT_PARAMS(IGbEInt
)
301 CREATE_SIM_OBJECT(IGbEInt
)
303 IGbEInt
*dev_int
= new IGbEInt(getInstanceName(), device
);
305 EtherInt
*p
= (EtherInt
*)peer
;
314 REGISTER_SIM_OBJECT("IGbEInt", IGbEInt
)
317 BEGIN_DECLARE_SIM_OBJECT_PARAMS(IGbE
)
319 SimObjectParam
<System
*> system
;
320 SimObjectParam
<Platform
*> platform
;
321 SimObjectParam
<PciConfigData
*> configdata
;
322 Param
<uint32_t> pci_bus
;
323 Param
<uint32_t> pci_dev
;
324 Param
<uint32_t> pci_func
;
325 Param
<Tick
> pio_latency
;
326 Param
<Tick
> config_latency
;
328 END_DECLARE_SIM_OBJECT_PARAMS(IGbE
)
330 BEGIN_INIT_SIM_OBJECT_PARAMS(IGbE
)
332 INIT_PARAM(system
, "System pointer"),
333 INIT_PARAM(platform
, "Platform pointer"),
334 INIT_PARAM(configdata
, "PCI Config data"),
335 INIT_PARAM(pci_bus
, "PCI bus ID"),
336 INIT_PARAM(pci_dev
, "PCI device number"),
337 INIT_PARAM(pci_func
, "PCI function code"),
338 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency in bus cycles", 1),
339 INIT_PARAM(config_latency
, "Number of cycles for a config read or write")
341 END_INIT_SIM_OBJECT_PARAMS(IGbE
)
344 CREATE_SIM_OBJECT(IGbE
)
346 IGbE::Params
*params
= new IGbE::Params
;
348 params
->name
= getInstanceName();
349 params
->platform
= platform
;
350 params
->system
= system
;
351 params
->configData
= configdata
;
352 params
->busNum
= pci_bus
;
353 params
->deviceNum
= pci_dev
;
354 params
->functionNum
= pci_func
;
355 params
->pio_delay
= pio_latency
;
356 params
->config_delay
= config_latency
;
358 return new IGbE(params
);
361 REGISTER_SIM_OBJECT("IGbE", IGbE
)