7fc68f4e7abcb2674a306cc0fb5fc380376f09e7
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 "mem/packet_access.hh"
42 #include "sim/builder.hh"
43 #include "sim/stats.hh"
44 #include "sim/system.hh"
46 using namespace iGbReg
;
49 : PciDev(p
), etherInt(NULL
)
51 // Initialized internal registers per Intel documentation
62 regs
.eecd
.ee_type
= 1;
78 // clear all 64 16 bit words of the eeprom
79 memset(&flash
, 0, EEPROM_SIZE
*2);
81 // Magic happy checksum value
87 IGbE::writeConfig(PacketPtr pkt
)
89 int offset
= pkt
->getAddr() & PCI_CONFIG_SIZE
;
90 if (offset
< PCI_DEVICE_SPECIFIC
)
91 PciDev::writeConfig(pkt
);
93 panic("Device specific PCI config space not implemented.\n");
96 /// Some work may need to be done here based for the pci COMMAND bits.
103 IGbE::read(PacketPtr pkt
)
108 if (!getBAR(pkt
->getAddr(), bar
, daddr
))
109 panic("Invalid PCI memory access to unmapped memory.\n");
111 // Only Memory register BAR is allowed
114 // Only 32bit accesses allowed
115 assert(pkt
->getSize() == 4);
117 //DPRINTF(Ethernet, "Read device register %#X\n", daddr);
122 /// Handle read of register here
128 pkt
->set
<uint32_t>(regs
.ctrl
.reg
);
131 pkt
->set
<uint32_t>(regs
.sts
.reg
);
134 pkt
->set
<uint32_t>(regs
.eecd
.reg
);
137 pkt
->set
<uint32_t>(regs
.eerd
.reg
);
140 pkt
->set
<uint32_t>(regs
.icd
.reg
);
143 pkt
->set
<uint32_t>(regs
.imc
.reg
);
146 pkt
->set
<uint32_t>(regs
.rctl
.reg
);
149 pkt
->set
<uint32_t>(regs
.tctl
.reg
);
152 pkt
->set
<uint32_t>(regs
.pba
.reg
);
156 pkt
->set
<uint32_t>(0); // We don't care, so just return 0
159 pkt
->set
<uint32_t>(regs
.manc
.reg
);
162 if (!(daddr
>= VFTA
&& daddr
< (VFTA
+ VLAN_FILTER_TABLE_SIZE
)*4) &&
163 !(daddr
>= RAL
&& daddr
< (RAL
+ RCV_ADDRESS_TABLE_SIZE
)*4) &&
164 !(daddr
>= MTA
&& daddr
< (MTA
+ MULTICAST_TABLE_SIZE
)*4))
165 pkt
->set
<uint32_t>(0);
167 panic("Read request to unknown register number: %#x\n", daddr
);
170 pkt
->result
= Packet::Success
;
175 IGbE::write(PacketPtr pkt
)
181 if (!getBAR(pkt
->getAddr(), bar
, daddr
))
182 panic("Invalid PCI memory access to unmapped memory.\n");
184 // Only Memory register BAR is allowed
187 // Only 32bit accesses allowed
188 assert(pkt
->getSize() == sizeof(uint32_t));
190 //DPRINTF(Ethernet, "Wrote device register %#X value %#X\n", daddr, pkt->get<uint32_t>());
193 /// Handle write of register here
195 uint32_t val
= pkt
->get
<uint32_t>();
206 oldClk
= regs
.eecd
.sk
;
208 // See if this is a eeprom access and emulate accordingly
209 if (!oldClk
&& regs
.eecd
.sk
) {
211 eeOpcode
= eeOpcode
<< 1 | regs
.eecd
.din
;
213 } else if (eeAddrBits
< 8 && eeOpcode
== EEPROM_READ_OPCODE_SPI
) {
214 eeAddr
= eeAddr
<< 1 | regs
.eecd
.din
;
216 } else if (eeDataBits
< 16 && eeOpcode
== EEPROM_READ_OPCODE_SPI
) {
217 assert(eeAddr
>>1 < EEPROM_SIZE
);
218 DPRINTF(EthernetEEPROM
, "EEPROM bit read: %d word: %#X\n",
219 flash
[eeAddr
>>1] >> eeDataBits
& 0x1, flash
[eeAddr
>>1]);
220 regs
.eecd
.dout
= (flash
[eeAddr
>>1] >> (15-eeDataBits
)) & 0x1;
222 } else if (eeDataBits
< 8 && eeOpcode
== EEPROM_RDSR_OPCODE_SPI
) {
226 panic("What's going on with eeprom interface? opcode:"
227 " %#x:%d addr: %#x:%d, data: %d\n", (uint32_t)eeOpcode
,
228 (uint32_t)eeOpBits
, (uint32_t)eeAddr
,
229 (uint32_t)eeAddrBits
, (uint32_t)eeDataBits
);
231 // Reset everything for the next command
232 if ((eeDataBits
== 16 && eeOpcode
== EEPROM_READ_OPCODE_SPI
) ||
233 (eeDataBits
== 8 && eeOpcode
== EEPROM_RDSR_OPCODE_SPI
)) {
241 DPRINTF(EthernetEEPROM
, "EEPROM: opcode: %#X:%d addr: %#X:%d\n",
242 (uint32_t)eeOpcode
, (uint32_t) eeOpBits
,
243 (uint32_t)eeAddr
>>1, (uint32_t)eeAddrBits
);
244 if (eeOpBits
== 8 && !(eeOpcode
== EEPROM_READ_OPCODE_SPI
||
245 eeOpcode
== EEPROM_RDSR_OPCODE_SPI
))
246 panic("Unknown eeprom opcode: %#X:%d\n", (uint32_t)eeOpcode
,
251 // If driver requests eeprom access, immediately give it to it
252 regs
.eecd
.ee_gnt
= regs
.eecd
.ee_req
;
271 regs
.pba
.txa
= 64 - regs
.pba
.rxa
;
275 ; // We don't care, so don't store anything
281 if (!(daddr
>= VFTA
&& daddr
< (VFTA
+ VLAN_FILTER_TABLE_SIZE
)*4) &&
282 !(daddr
>= RAL
&& daddr
< (RAL
+ RCV_ADDRESS_TABLE_SIZE
)*4) &&
283 !(daddr
>= MTA
&& daddr
< (MTA
+ MULTICAST_TABLE_SIZE
)*4))
284 panic("Write request to unknown register number: %#x\n", daddr
);
287 pkt
->result
= Packet::Success
;
293 IGbE::ethRxPkt(EthPacketPtr packet
)
295 panic("Need to implemenet\n");
302 panic("Need to implemenet\n");
306 IGbE::serialize(std::ostream
&os
)
308 panic("Need to implemenet\n");
312 IGbE::unserialize(Checkpoint
*cp
, const std::string
§ion
)
314 panic("Need to implemenet\n");
318 BEGIN_DECLARE_SIM_OBJECT_PARAMS(IGbEInt
)
320 SimObjectParam
<EtherInt
*> peer
;
321 SimObjectParam
<IGbE
*> device
;
323 END_DECLARE_SIM_OBJECT_PARAMS(IGbEInt
)
325 BEGIN_INIT_SIM_OBJECT_PARAMS(IGbEInt
)
327 INIT_PARAM_DFLT(peer
, "peer interface", NULL
),
328 INIT_PARAM(device
, "Ethernet device of this interface")
330 END_INIT_SIM_OBJECT_PARAMS(IGbEInt
)
332 CREATE_SIM_OBJECT(IGbEInt
)
334 IGbEInt
*dev_int
= new IGbEInt(getInstanceName(), device
);
336 EtherInt
*p
= (EtherInt
*)peer
;
345 REGISTER_SIM_OBJECT("IGbEInt", IGbEInt
)
348 BEGIN_DECLARE_SIM_OBJECT_PARAMS(IGbE
)
350 SimObjectParam
<System
*> system
;
351 SimObjectParam
<Platform
*> platform
;
352 SimObjectParam
<PciConfigData
*> configdata
;
353 Param
<uint32_t> pci_bus
;
354 Param
<uint32_t> pci_dev
;
355 Param
<uint32_t> pci_func
;
356 Param
<Tick
> pio_latency
;
357 Param
<Tick
> config_latency
;
359 END_DECLARE_SIM_OBJECT_PARAMS(IGbE
)
361 BEGIN_INIT_SIM_OBJECT_PARAMS(IGbE
)
363 INIT_PARAM(system
, "System pointer"),
364 INIT_PARAM(platform
, "Platform pointer"),
365 INIT_PARAM(configdata
, "PCI Config data"),
366 INIT_PARAM(pci_bus
, "PCI bus ID"),
367 INIT_PARAM(pci_dev
, "PCI device number"),
368 INIT_PARAM(pci_func
, "PCI function code"),
369 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency in bus cycles", 1),
370 INIT_PARAM(config_latency
, "Number of cycles for a config read or write")
372 END_INIT_SIM_OBJECT_PARAMS(IGbE
)
375 CREATE_SIM_OBJECT(IGbE
)
377 IGbE::Params
*params
= new IGbE::Params
;
379 params
->name
= getInstanceName();
380 params
->platform
= platform
;
381 params
->system
= system
;
382 params
->configData
= configdata
;
383 params
->busNum
= pci_bus
;
384 params
->deviceNum
= pci_dev
;
385 params
->functionNum
= pci_func
;
386 params
->pio_delay
= pio_latency
;
387 params
->config_delay
= config_latency
;
389 return new IGbE(params
);
392 REGISTER_SIM_OBJECT("IGbE", IGbE
)