5476ef9eba41ab808eb91ca939e1812c79c620f9
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
), useFlowControl(p
->use_flow_control
)
51 // Initialized internal registers per Intel documentation
60 regs
.sts
.speed(3); // Say we're 1000Mbps
61 regs
.sts
.fd(1); // full duplex
81 // clear all 64 16 bit words of the eeprom
82 memset(&flash
, 0, EEPROM_SIZE
*2);
84 //We'll need to instert the MAC address into the flash
90 for (int x
= 0; x
< EEPROM_SIZE
; x
++)
93 // Magic happy checksum value
94 flash
[EEPROM_SIZE
-1] = htobe((uint16_t)(EEPROM_CSUM
- csum
));
99 IGbE::writeConfig(PacketPtr pkt
)
101 int offset
= pkt
->getAddr() & PCI_CONFIG_SIZE
;
102 if (offset
< PCI_DEVICE_SPECIFIC
)
103 PciDev::writeConfig(pkt
);
105 panic("Device specific PCI config space not implemented.\n");
108 /// Some work may need to be done here based for the pci COMMAND bits.
115 IGbE::read(PacketPtr pkt
)
120 if (!getBAR(pkt
->getAddr(), bar
, daddr
))
121 panic("Invalid PCI memory access to unmapped memory.\n");
123 // Only Memory register BAR is allowed
126 // Only 32bit accesses allowed
127 assert(pkt
->getSize() == 4);
129 //DPRINTF(Ethernet, "Read device register %#X\n", daddr);
134 /// Handle read of register here
140 pkt
->set
<uint32_t>(regs
.ctrl());
143 pkt
->set
<uint32_t>(regs
.sts());
146 pkt
->set
<uint32_t>(regs
.eecd());
149 pkt
->set
<uint32_t>(regs
.eerd());
152 pkt
->set
<uint32_t>(regs
.ctrl_ext());
155 pkt
->set
<uint32_t>(regs
.mdic());
158 pkt
->set
<uint32_t>(regs
.icr());
159 // handle auto setting mask from IAM
162 pkt
->set
<uint32_t>(regs
.itr());
165 pkt
->set
<uint32_t>(regs
.rctl());
168 pkt
->set
<uint32_t>(regs
.fcttv());
171 pkt
->set
<uint32_t>(regs
.tctl());
174 pkt
->set
<uint32_t>(regs
.pba());
178 pkt
->set
<uint32_t>(0); // We don't care, so just return 0
181 pkt
->set
<uint32_t>(regs
.fcrtl());
184 pkt
->set
<uint32_t>(regs
.fcrth());
187 pkt
->set
<uint32_t>(regs
.rdba
.rdbal());
190 pkt
->set
<uint32_t>(regs
.rdba
.rdbah());
193 pkt
->set
<uint32_t>(regs
.rdlen());
196 pkt
->set
<uint32_t>(regs
.rdh());
199 pkt
->set
<uint32_t>(regs
.rdt());
202 pkt
->set
<uint32_t>(regs
.rdtr());
205 pkt
->set
<uint32_t>(regs
.radv());
208 pkt
->set
<uint32_t>(regs
.tdba
.tdbal());
211 pkt
->set
<uint32_t>(regs
.tdba
.tdbah());
214 pkt
->set
<uint32_t>(regs
.tdlen());
217 pkt
->set
<uint32_t>(regs
.tdh());
220 pkt
->set
<uint32_t>(regs
.tdt());
223 pkt
->set
<uint32_t>(regs
.tidv());
226 pkt
->set
<uint32_t>(regs
.txdctl());
229 pkt
->set
<uint32_t>(regs
.tadv());
232 pkt
->set
<uint32_t>(regs
.rxcsum());
235 pkt
->set
<uint32_t>(regs
.manc());
238 if (!(daddr
>= REG_VFTA
&& daddr
< (REG_VFTA
+ VLAN_FILTER_TABLE_SIZE
*4)) &&
239 !(daddr
>= REG_RAL
&& daddr
< (REG_RAL
+ RCV_ADDRESS_TABLE_SIZE
*8)) &&
240 !(daddr
>= REG_MTA
&& daddr
< (REG_MTA
+ MULTICAST_TABLE_SIZE
*4)) &&
241 !(daddr
>= REG_CRCERRS
&& daddr
< (REG_CRCERRS
+ STATS_REGS_SIZE
)))
242 panic("Read request to unknown register number: %#x\n", daddr
);
244 pkt
->set
<uint32_t>(0);
247 pkt
->result
= Packet::Success
;
252 IGbE::write(PacketPtr pkt
)
258 if (!getBAR(pkt
->getAddr(), bar
, daddr
))
259 panic("Invalid PCI memory access to unmapped memory.\n");
261 // Only Memory register BAR is allowed
264 // Only 32bit accesses allowed
265 assert(pkt
->getSize() == sizeof(uint32_t));
267 //DPRINTF(Ethernet, "Wrote device register %#X value %#X\n", daddr, pkt->get<uint32_t>());
270 /// Handle write of register here
272 uint32_t val
= pkt
->get
<uint32_t>();
277 if (regs
.ctrl
.tfce())
278 warn("TX Flow control enabled, should implement\n");
279 if (regs
.ctrl
.rfce())
280 warn("RX Flow control enabled, should implement\n");
290 oldClk
= regs
.eecd
.sk();
292 // See if this is a eeprom access and emulate accordingly
293 if (!oldClk
&& regs
.eecd
.sk()) {
295 eeOpcode
= eeOpcode
<< 1 | regs
.eecd
.din();
297 } else if (eeAddrBits
< 8 && eeOpcode
== EEPROM_READ_OPCODE_SPI
) {
298 eeAddr
= eeAddr
<< 1 | regs
.eecd
.din();
300 } else if (eeDataBits
< 16 && eeOpcode
== EEPROM_READ_OPCODE_SPI
) {
301 assert(eeAddr
>>1 < EEPROM_SIZE
);
302 DPRINTF(EthernetEEPROM
, "EEPROM bit read: %d word: %#X\n",
303 flash
[eeAddr
>>1] >> eeDataBits
& 0x1, flash
[eeAddr
>>1]);
304 regs
.eecd
.dout((flash
[eeAddr
>>1] >> (15-eeDataBits
)) & 0x1);
306 } else if (eeDataBits
< 8 && eeOpcode
== EEPROM_RDSR_OPCODE_SPI
) {
310 panic("What's going on with eeprom interface? opcode:"
311 " %#x:%d addr: %#x:%d, data: %d\n", (uint32_t)eeOpcode
,
312 (uint32_t)eeOpBits
, (uint32_t)eeAddr
,
313 (uint32_t)eeAddrBits
, (uint32_t)eeDataBits
);
315 // Reset everything for the next command
316 if ((eeDataBits
== 16 && eeOpcode
== EEPROM_READ_OPCODE_SPI
) ||
317 (eeDataBits
== 8 && eeOpcode
== EEPROM_RDSR_OPCODE_SPI
)) {
325 DPRINTF(EthernetEEPROM
, "EEPROM: opcode: %#X:%d addr: %#X:%d\n",
326 (uint32_t)eeOpcode
, (uint32_t) eeOpBits
,
327 (uint32_t)eeAddr
>>1, (uint32_t)eeAddrBits
);
328 if (eeOpBits
== 8 && !(eeOpcode
== EEPROM_READ_OPCODE_SPI
||
329 eeOpcode
== EEPROM_RDSR_OPCODE_SPI
))
330 panic("Unknown eeprom opcode: %#X:%d\n", (uint32_t)eeOpcode
,
335 // If driver requests eeprom access, immediately give it to it
336 regs
.eecd
.ee_gnt(regs
.eecd
.ee_req());
344 panic("No support for interrupt on mdic complete\n");
345 if (regs
.mdic
.phyadd() != 1)
346 panic("No support for reading anything but phy\n");
347 DPRINTF(Ethernet
, "%s phy address %x\n", regs
.mdic
.op() == 1 ? "Writing"
348 : "Reading", regs
.mdic
.regadd());
349 switch (regs
.mdic
.regadd()) {
351 regs
.mdic
.data(0x796D); // link up
354 regs
.mdic
.data(0x02A8);
357 regs
.mdic
.data(0x0380);
360 regs
.mdic
.data(0x7C00);
363 regs
.mdic
.data(0x3000);
366 regs
.mdic
.data(0x180); // some random length
370 warn("Accessing unknown phy register %d\n", regs
.mdic
.regadd());
376 // handle auto setting mask from IAM
382 regs
.icr
= val
| regs
.icr();
383 // generate an interrupt if needed here
387 // handle interrupts if needed here
391 // handle interrupts if needed here
407 regs
.pba
.txa(64 - regs
.pba
.rxa());
417 ; // We don't care, so don't store anything
426 regs
.rdba
.rdbal( val
& ~mask(4));
429 regs
.rdba
.rdbah(val
);
432 regs
.rdlen
= val
& ~mask(7);
447 regs
.tdba
.tdbal( val
& ~mask(4));
450 regs
.tdba
.tdbah(val
);
453 regs
.tdlen
= val
& ~mask(7);
477 if (!(daddr
>= REG_VFTA
&& daddr
< (REG_VFTA
+ VLAN_FILTER_TABLE_SIZE
*4)) &&
478 !(daddr
>= REG_RAL
&& daddr
< (REG_RAL
+ RCV_ADDRESS_TABLE_SIZE
*8)) &&
479 !(daddr
>= REG_MTA
&& daddr
< (REG_MTA
+ MULTICAST_TABLE_SIZE
*4)))
480 panic("Write request to unknown register number: %#x\n", daddr
);
483 pkt
->result
= Packet::Success
;
489 IGbE::ethRxPkt(EthPacketPtr packet
)
491 panic("Need to implemenet\n");
498 panic("Need to implemenet\n");
502 IGbE::serialize(std::ostream
&os
)
504 panic("Need to implemenet\n");
508 IGbE::unserialize(Checkpoint
*cp
, const std::string
§ion
)
510 panic("Need to implemenet\n");
514 BEGIN_DECLARE_SIM_OBJECT_PARAMS(IGbEInt
)
516 SimObjectParam
<EtherInt
*> peer
;
517 SimObjectParam
<IGbE
*> device
;
519 END_DECLARE_SIM_OBJECT_PARAMS(IGbEInt
)
521 BEGIN_INIT_SIM_OBJECT_PARAMS(IGbEInt
)
523 INIT_PARAM_DFLT(peer
, "peer interface", NULL
),
524 INIT_PARAM(device
, "Ethernet device of this interface")
526 END_INIT_SIM_OBJECT_PARAMS(IGbEInt
)
528 CREATE_SIM_OBJECT(IGbEInt
)
530 IGbEInt
*dev_int
= new IGbEInt(getInstanceName(), device
);
532 EtherInt
*p
= (EtherInt
*)peer
;
541 REGISTER_SIM_OBJECT("IGbEInt", IGbEInt
)
544 BEGIN_DECLARE_SIM_OBJECT_PARAMS(IGbE
)
546 SimObjectParam
<System
*> system
;
547 SimObjectParam
<Platform
*> platform
;
548 SimObjectParam
<PciConfigData
*> configdata
;
549 Param
<uint32_t> pci_bus
;
550 Param
<uint32_t> pci_dev
;
551 Param
<uint32_t> pci_func
;
552 Param
<Tick
> pio_latency
;
553 Param
<Tick
> config_latency
;
555 END_DECLARE_SIM_OBJECT_PARAMS(IGbE
)
557 BEGIN_INIT_SIM_OBJECT_PARAMS(IGbE
)
559 INIT_PARAM(system
, "System pointer"),
560 INIT_PARAM(platform
, "Platform pointer"),
561 INIT_PARAM(configdata
, "PCI Config data"),
562 INIT_PARAM(pci_bus
, "PCI bus ID"),
563 INIT_PARAM(pci_dev
, "PCI device number"),
564 INIT_PARAM(pci_func
, "PCI function code"),
565 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency in bus cycles", 1),
566 INIT_PARAM(config_latency
, "Number of cycles for a config read or write")
568 END_INIT_SIM_OBJECT_PARAMS(IGbE
)
571 CREATE_SIM_OBJECT(IGbE
)
573 IGbE::Params
*params
= new IGbE::Params
;
575 params
->name
= getInstanceName();
576 params
->platform
= platform
;
577 params
->system
= system
;
578 params
->configData
= configdata
;
579 params
->busNum
= pci_bus
;
580 params
->deviceNum
= pci_dev
;
581 params
->functionNum
= pci_func
;
582 params
->pio_delay
= pio_latency
;
583 params
->config_delay
= config_latency
;
585 return new IGbE(params
);
588 REGISTER_SIM_OBJECT("IGbE", IGbE
)