i8254xGBe.cc revision 4218
17949SAli.Saidi@ARM.com/* 27949SAli.Saidi@ARM.com * Copyright (c) 2006 The Regents of The University of Michigan 37949SAli.Saidi@ARM.com * All rights reserved. 47949SAli.Saidi@ARM.com * 57949SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 67949SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 77949SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 87949SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 97949SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 107949SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 117949SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 127949SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 137949SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 147949SAli.Saidi@ARM.com * this software without specific prior written permission. 157949SAli.Saidi@ARM.com * 167949SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177949SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187949SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197949SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207949SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217949SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227949SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237949SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247949SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257949SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267949SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277949SAli.Saidi@ARM.com * 287949SAli.Saidi@ARM.com * Authors: Ali Saidi 297949SAli.Saidi@ARM.com */ 307949SAli.Saidi@ARM.com 317949SAli.Saidi@ARM.com/* @file 327949SAli.Saidi@ARM.com * Device model for Intel's 8254x line of gigabit ethernet controllers. 337949SAli.Saidi@ARM.com * In particular an 82547 revision 2 (82547GI) MAC because it seems to have the 347949SAli.Saidi@ARM.com * fewest workarounds in the driver. It will probably work with most of the 357949SAli.Saidi@ARM.com * other MACs with slight modifications. 367949SAli.Saidi@ARM.com */ 377949SAli.Saidi@ARM.com 387949SAli.Saidi@ARM.com#include "base/inet.hh" 397949SAli.Saidi@ARM.com#include "dev/i8254xGBe.hh" 407949SAli.Saidi@ARM.com#include "mem/packet.hh" 417949SAli.Saidi@ARM.com#include "mem/packet_access.hh" 427949SAli.Saidi@ARM.com#include "sim/builder.hh" 437949SAli.Saidi@ARM.com#include "sim/stats.hh" 447949SAli.Saidi@ARM.com#include "sim/system.hh" 459330Schander.sudanthi@arm.com 469330Schander.sudanthi@arm.comusing namespace iGbReg; 477949SAli.Saidi@ARM.com 487949SAli.Saidi@ARM.comIGbE::IGbE(Params *p) 497949SAli.Saidi@ARM.com : PciDev(p), etherInt(NULL), useFlowControl(p->use_flow_control) 508229Snate@binkert.org{ 519330Schander.sudanthi@arm.com // Initialized internal registers per Intel documentation 528635Schris.emmons@arm.com regs.tctl(0); 537949SAli.Saidi@ARM.com regs.rctl(0); 547949SAli.Saidi@ARM.com regs.ctrl(0); 557949SAli.Saidi@ARM.com regs.ctrl.fd(1); 567949SAli.Saidi@ARM.com regs.ctrl.lrst(1); 578229Snate@binkert.org regs.ctrl.speed(2); 587949SAli.Saidi@ARM.com regs.ctrl.frcspd(1); 597949SAli.Saidi@ARM.com regs.sts(0); 609330Schander.sudanthi@arm.com regs.sts.speed(3); // Say we're 1000Mbps 619330Schander.sudanthi@arm.com regs.sts.fd(1); // full duplex 629330Schander.sudanthi@arm.com regs.eecd(0); 638635Schris.emmons@arm.com regs.eecd.fwe(1); 649330Schander.sudanthi@arm.com regs.eecd.ee_type(1); 657949SAli.Saidi@ARM.com regs.eerd(0); 667949SAli.Saidi@ARM.com regs.icr(0); 677949SAli.Saidi@ARM.com regs.rctl(0); 687949SAli.Saidi@ARM.com regs.tctl(0); 697949SAli.Saidi@ARM.com regs.fcrtl(0); 707949SAli.Saidi@ARM.com regs.fcrth(1); 717949SAli.Saidi@ARM.com regs.manc(0); 727949SAli.Saidi@ARM.com 737949SAli.Saidi@ARM.com regs.pba.rxa(0x30); 747949SAli.Saidi@ARM.com regs.pba.txa(0x10); 757949SAli.Saidi@ARM.com 767949SAli.Saidi@ARM.com eeOpBits = 0; 777949SAli.Saidi@ARM.com eeAddrBits = 0; 787949SAli.Saidi@ARM.com eeDataBits = 0; 797949SAli.Saidi@ARM.com eeOpcode = 0; 807949SAli.Saidi@ARM.com 817949SAli.Saidi@ARM.com // clear all 64 16 bit words of the eeprom 827949SAli.Saidi@ARM.com memset(&flash, 0, EEPROM_SIZE*2); 837949SAli.Saidi@ARM.com 847949SAli.Saidi@ARM.com //We'll need to instert the MAC address into the flash 857949SAli.Saidi@ARM.com flash[0] = 0xA4A4; 867949SAli.Saidi@ARM.com flash[1] = 0xB6B6; 877949SAli.Saidi@ARM.com flash[2] = 0xC8C8; 887949SAli.Saidi@ARM.com 897949SAli.Saidi@ARM.com uint16_t csum = 0; 907949SAli.Saidi@ARM.com for (int x = 0; x < EEPROM_SIZE; x++) 917949SAli.Saidi@ARM.com csum += flash[x]; 927949SAli.Saidi@ARM.com 937949SAli.Saidi@ARM.com // Magic happy checksum value 947949SAli.Saidi@ARM.com flash[EEPROM_SIZE-1] = htobe((uint16_t)(EEPROM_CSUM - csum)); 957949SAli.Saidi@ARM.com} 967949SAli.Saidi@ARM.com 977949SAli.Saidi@ARM.com 987949SAli.Saidi@ARM.comTick 997949SAli.Saidi@ARM.comIGbE::writeConfig(PacketPtr pkt) 1007949SAli.Saidi@ARM.com{ 1017949SAli.Saidi@ARM.com int offset = pkt->getAddr() & PCI_CONFIG_SIZE; 1027949SAli.Saidi@ARM.com if (offset < PCI_DEVICE_SPECIFIC) 1037949SAli.Saidi@ARM.com PciDev::writeConfig(pkt); 1047949SAli.Saidi@ARM.com else 1057949SAli.Saidi@ARM.com panic("Device specific PCI config space not implemented.\n"); 1067949SAli.Saidi@ARM.com 1077949SAli.Saidi@ARM.com /// 1087949SAli.Saidi@ARM.com /// Some work may need to be done here based for the pci COMMAND bits. 1097949SAli.Saidi@ARM.com /// 1107949SAli.Saidi@ARM.com 1117949SAli.Saidi@ARM.com return pioDelay; 1127949SAli.Saidi@ARM.com} 1137949SAli.Saidi@ARM.com 1147949SAli.Saidi@ARM.comTick 1157949SAli.Saidi@ARM.comIGbE::read(PacketPtr pkt) 1167949SAli.Saidi@ARM.com{ 1177949SAli.Saidi@ARM.com int bar; 1187949SAli.Saidi@ARM.com Addr daddr; 1197949SAli.Saidi@ARM.com 1207949SAli.Saidi@ARM.com if (!getBAR(pkt->getAddr(), bar, daddr)) 1217949SAli.Saidi@ARM.com panic("Invalid PCI memory access to unmapped memory.\n"); 1227949SAli.Saidi@ARM.com 1237949SAli.Saidi@ARM.com // Only Memory register BAR is allowed 1247949SAli.Saidi@ARM.com assert(bar == 0); 1257949SAli.Saidi@ARM.com 1267949SAli.Saidi@ARM.com // Only 32bit accesses allowed 1277949SAli.Saidi@ARM.com assert(pkt->getSize() == 4); 1287949SAli.Saidi@ARM.com 1297949SAli.Saidi@ARM.com //DPRINTF(Ethernet, "Read device register %#X\n", daddr); 1307949SAli.Saidi@ARM.com 1317949SAli.Saidi@ARM.com pkt->allocate(); 1327949SAli.Saidi@ARM.com 1337949SAli.Saidi@ARM.com /// 1347949SAli.Saidi@ARM.com /// Handle read of register here 1357949SAli.Saidi@ARM.com /// 1367949SAli.Saidi@ARM.com 1377949SAli.Saidi@ARM.com 1387949SAli.Saidi@ARM.com switch (daddr) { 1397949SAli.Saidi@ARM.com case REG_CTRL: 1407949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.ctrl()); 1417949SAli.Saidi@ARM.com break; 1427949SAli.Saidi@ARM.com case REG_STATUS: 1437949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.sts()); 1447949SAli.Saidi@ARM.com break; 1457949SAli.Saidi@ARM.com case REG_EECD: 1467949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.eecd()); 1477949SAli.Saidi@ARM.com break; 1487949SAli.Saidi@ARM.com case REG_EERD: 1497949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.eerd()); 1507949SAli.Saidi@ARM.com break; 1517949SAli.Saidi@ARM.com case REG_CTRL_EXT: 1527949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.ctrl_ext()); 1537949SAli.Saidi@ARM.com break; 1547949SAli.Saidi@ARM.com case REG_MDIC: 1557949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.mdic()); 1567949SAli.Saidi@ARM.com break; 1577949SAli.Saidi@ARM.com case REG_ICR: 1587949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.icr()); 1597949SAli.Saidi@ARM.com // handle auto setting mask from IAM 1607949SAli.Saidi@ARM.com break; 1617949SAli.Saidi@ARM.com case REG_ITR: 1627949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.itr()); 1637949SAli.Saidi@ARM.com break; 1647949SAli.Saidi@ARM.com case REG_RCTL: 1657949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.rctl()); 1667949SAli.Saidi@ARM.com break; 1677949SAli.Saidi@ARM.com case REG_FCTTV: 1687949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.fcttv()); 1697949SAli.Saidi@ARM.com break; 1707949SAli.Saidi@ARM.com case REG_TCTL: 1717949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.tctl()); 1727949SAli.Saidi@ARM.com break; 1737949SAli.Saidi@ARM.com case REG_PBA: 1747949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.pba()); 1757949SAli.Saidi@ARM.com break; 1767949SAli.Saidi@ARM.com case REG_WUC: 1777949SAli.Saidi@ARM.com case REG_LEDCTL: 1787949SAli.Saidi@ARM.com pkt->set<uint32_t>(0); // We don't care, so just return 0 1797949SAli.Saidi@ARM.com break; 1807949SAli.Saidi@ARM.com case REG_FCRTL: 1817949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.fcrtl()); 1827949SAli.Saidi@ARM.com break; 1837949SAli.Saidi@ARM.com case REG_FCRTH: 1847949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.fcrth()); 1857949SAli.Saidi@ARM.com break; 1867949SAli.Saidi@ARM.com case REG_RDBAL: 1877949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.rdba.rdbal()); 1887949SAli.Saidi@ARM.com break; 1897949SAli.Saidi@ARM.com case REG_RDBAH: 1907949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.rdba.rdbah()); 1917949SAli.Saidi@ARM.com break; 1927949SAli.Saidi@ARM.com case REG_RDLEN: 1937949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.rdlen()); 1947949SAli.Saidi@ARM.com break; 1957949SAli.Saidi@ARM.com case REG_RDH: 1967949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.rdh()); 1977949SAli.Saidi@ARM.com break; 1987949SAli.Saidi@ARM.com case REG_RDT: 1997949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.rdt()); 2007949SAli.Saidi@ARM.com break; 2017949SAli.Saidi@ARM.com case REG_RDTR: 2027949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.rdtr()); 2037949SAli.Saidi@ARM.com break; 2047949SAli.Saidi@ARM.com case REG_RADV: 2057949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.radv()); 2067949SAli.Saidi@ARM.com break; 2077949SAli.Saidi@ARM.com case REG_TDBAL: 2087949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.tdba.tdbal()); 2097949SAli.Saidi@ARM.com break; 2107949SAli.Saidi@ARM.com case REG_TDBAH: 2117949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.tdba.tdbah()); 2127949SAli.Saidi@ARM.com break; 2137949SAli.Saidi@ARM.com case REG_TDLEN: 2147949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.tdlen()); 2157949SAli.Saidi@ARM.com break; 2167949SAli.Saidi@ARM.com case REG_TDH: 2177949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.tdh()); 2187949SAli.Saidi@ARM.com break; 2197949SAli.Saidi@ARM.com case REG_TDT: 2207949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.tdt()); 2217949SAli.Saidi@ARM.com break; 2227949SAli.Saidi@ARM.com case REG_TIDV: 2237949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.tidv()); 2247949SAli.Saidi@ARM.com break; 2257949SAli.Saidi@ARM.com case REG_TXDCTL: 2267949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.txdctl()); 2277949SAli.Saidi@ARM.com break; 2287949SAli.Saidi@ARM.com case REG_TADV: 2297949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.tadv()); 2307949SAli.Saidi@ARM.com break; 2317949SAli.Saidi@ARM.com case REG_RXCSUM: 2327949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.rxcsum()); 2337949SAli.Saidi@ARM.com break; 2347949SAli.Saidi@ARM.com case REG_MANC: 2357949SAli.Saidi@ARM.com pkt->set<uint32_t>(regs.manc()); 2367949SAli.Saidi@ARM.com break; 2377949SAli.Saidi@ARM.com default: 2387949SAli.Saidi@ARM.com if (!(daddr >= REG_VFTA && daddr < (REG_VFTA + VLAN_FILTER_TABLE_SIZE*4)) && 2397949SAli.Saidi@ARM.com !(daddr >= REG_RAL && daddr < (REG_RAL + RCV_ADDRESS_TABLE_SIZE*8)) && 2407949SAli.Saidi@ARM.com !(daddr >= REG_MTA && daddr < (REG_MTA + MULTICAST_TABLE_SIZE*4)) && 2417949SAli.Saidi@ARM.com !(daddr >= REG_CRCERRS && daddr < (REG_CRCERRS + STATS_REGS_SIZE))) 2427949SAli.Saidi@ARM.com panic("Read request to unknown register number: %#x\n", daddr); 2437949SAli.Saidi@ARM.com else 2447949SAli.Saidi@ARM.com pkt->set<uint32_t>(0); 2457949SAli.Saidi@ARM.com }; 2467949SAli.Saidi@ARM.com 2477949SAli.Saidi@ARM.com pkt->result = Packet::Success; 2487949SAli.Saidi@ARM.com return pioDelay; 2497949SAli.Saidi@ARM.com} 2507949SAli.Saidi@ARM.com 2517949SAli.Saidi@ARM.comTick 2527949SAli.Saidi@ARM.comIGbE::write(PacketPtr pkt) 2537949SAli.Saidi@ARM.com{ 2547949SAli.Saidi@ARM.com int bar; 2557949SAli.Saidi@ARM.com Addr daddr; 2567949SAli.Saidi@ARM.com 2577949SAli.Saidi@ARM.com 2587949SAli.Saidi@ARM.com if (!getBAR(pkt->getAddr(), bar, daddr)) 2597949SAli.Saidi@ARM.com panic("Invalid PCI memory access to unmapped memory.\n"); 2607949SAli.Saidi@ARM.com 2617949SAli.Saidi@ARM.com // Only Memory register BAR is allowed 2627949SAli.Saidi@ARM.com assert(bar == 0); 2637949SAli.Saidi@ARM.com 2647949SAli.Saidi@ARM.com // Only 32bit accesses allowed 2657949SAli.Saidi@ARM.com assert(pkt->getSize() == sizeof(uint32_t)); 2667949SAli.Saidi@ARM.com 2677949SAli.Saidi@ARM.com //DPRINTF(Ethernet, "Wrote device register %#X value %#X\n", daddr, pkt->get<uint32_t>()); 2687949SAli.Saidi@ARM.com 2697949SAli.Saidi@ARM.com /// 2707949SAli.Saidi@ARM.com /// Handle write of register here 2717949SAli.Saidi@ARM.com /// 2727949SAli.Saidi@ARM.com uint32_t val = pkt->get<uint32_t>(); 2737949SAli.Saidi@ARM.com 2747949SAli.Saidi@ARM.com switch (daddr) { 2757949SAli.Saidi@ARM.com case REG_CTRL: 2767949SAli.Saidi@ARM.com regs.ctrl = val; 2777949SAli.Saidi@ARM.com if (regs.ctrl.tfce()) 2787949SAli.Saidi@ARM.com warn("TX Flow control enabled, should implement\n"); 2797949SAli.Saidi@ARM.com if (regs.ctrl.rfce()) 2807949SAli.Saidi@ARM.com warn("RX Flow control enabled, should implement\n"); 2817949SAli.Saidi@ARM.com break; 2827949SAli.Saidi@ARM.com case REG_CTRL_EXT: 2837949SAli.Saidi@ARM.com regs.ctrl_ext = val; 2847949SAli.Saidi@ARM.com break; 2857949SAli.Saidi@ARM.com case REG_STATUS: 2867949SAli.Saidi@ARM.com regs.sts = val; 2877949SAli.Saidi@ARM.com break; 2887949SAli.Saidi@ARM.com case REG_EECD: 2897949SAli.Saidi@ARM.com int oldClk; 2907949SAli.Saidi@ARM.com oldClk = regs.eecd.sk(); 2917949SAli.Saidi@ARM.com regs.eecd = val; 2927949SAli.Saidi@ARM.com // See if this is a eeprom access and emulate accordingly 2937949SAli.Saidi@ARM.com if (!oldClk && regs.eecd.sk()) { 2947949SAli.Saidi@ARM.com if (eeOpBits < 8) { 2957949SAli.Saidi@ARM.com eeOpcode = eeOpcode << 1 | regs.eecd.din(); 2967949SAli.Saidi@ARM.com eeOpBits++; 2977949SAli.Saidi@ARM.com } else if (eeAddrBits < 8 && eeOpcode == EEPROM_READ_OPCODE_SPI) { 2987949SAli.Saidi@ARM.com eeAddr = eeAddr << 1 | regs.eecd.din(); 2997949SAli.Saidi@ARM.com eeAddrBits++; 3007949SAli.Saidi@ARM.com } else if (eeDataBits < 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) { 3017949SAli.Saidi@ARM.com assert(eeAddr>>1 < EEPROM_SIZE); 3027949SAli.Saidi@ARM.com DPRINTF(EthernetEEPROM, "EEPROM bit read: %d word: %#X\n", 3037949SAli.Saidi@ARM.com flash[eeAddr>>1] >> eeDataBits & 0x1, flash[eeAddr>>1]); 3047949SAli.Saidi@ARM.com regs.eecd.dout((flash[eeAddr>>1] >> (15-eeDataBits)) & 0x1); 3057949SAli.Saidi@ARM.com eeDataBits++; 3067949SAli.Saidi@ARM.com } else if (eeDataBits < 8 && eeOpcode == EEPROM_RDSR_OPCODE_SPI) { 3077949SAli.Saidi@ARM.com regs.eecd.dout(0); 3087949SAli.Saidi@ARM.com eeDataBits++; 3097949SAli.Saidi@ARM.com } else 3107949SAli.Saidi@ARM.com panic("What's going on with eeprom interface? opcode:" 3117949SAli.Saidi@ARM.com " %#x:%d addr: %#x:%d, data: %d\n", (uint32_t)eeOpcode, 3127949SAli.Saidi@ARM.com (uint32_t)eeOpBits, (uint32_t)eeAddr, 3137949SAli.Saidi@ARM.com (uint32_t)eeAddrBits, (uint32_t)eeDataBits); 3147949SAli.Saidi@ARM.com 3157949SAli.Saidi@ARM.com // Reset everything for the next command 3167949SAli.Saidi@ARM.com if ((eeDataBits == 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) || 3179330Schander.sudanthi@arm.com (eeDataBits == 8 && eeOpcode == EEPROM_RDSR_OPCODE_SPI)) { 3187949SAli.Saidi@ARM.com eeOpBits = 0; 3197949SAli.Saidi@ARM.com eeAddrBits = 0; 3207949SAli.Saidi@ARM.com eeDataBits = 0; 3217949SAli.Saidi@ARM.com eeOpcode = 0; 3227949SAli.Saidi@ARM.com eeAddr = 0; 3237949SAli.Saidi@ARM.com } 3247949SAli.Saidi@ARM.com 3259330Schander.sudanthi@arm.com DPRINTF(EthernetEEPROM, "EEPROM: opcode: %#X:%d addr: %#X:%d\n", 3269330Schander.sudanthi@arm.com (uint32_t)eeOpcode, (uint32_t) eeOpBits, 3277949SAli.Saidi@ARM.com (uint32_t)eeAddr>>1, (uint32_t)eeAddrBits); 3287949SAli.Saidi@ARM.com if (eeOpBits == 8 && !(eeOpcode == EEPROM_READ_OPCODE_SPI || 3297949SAli.Saidi@ARM.com eeOpcode == EEPROM_RDSR_OPCODE_SPI )) 330 panic("Unknown eeprom opcode: %#X:%d\n", (uint32_t)eeOpcode, 331 (uint32_t)eeOpBits); 332 333 334 } 335 // If driver requests eeprom access, immediately give it to it 336 regs.eecd.ee_gnt(regs.eecd.ee_req()); 337 break; 338 case REG_EERD: 339 regs.eerd = val; 340 break; 341 case REG_MDIC: 342 regs.mdic = val; 343 if (regs.mdic.i()) 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()) { 350 case PHY_PSTATUS: 351 regs.mdic.data(0x796D); // link up 352 break; 353 case PHY_PID: 354 regs.mdic.data(0x02A8); 355 break; 356 case PHY_EPID: 357 regs.mdic.data(0x0380); 358 break; 359 case PHY_GSTATUS: 360 regs.mdic.data(0x7C00); 361 break; 362 case PHY_EPSTATUS: 363 regs.mdic.data(0x3000); 364 break; 365 case PHY_AGC: 366 regs.mdic.data(0x180); // some random length 367 break; 368 default: 369 regs.mdic.data(0); 370 warn("Accessing unknown phy register %d\n", regs.mdic.regadd()); 371 } 372 regs.mdic.r(1); 373 break; 374 case REG_ICR: 375 regs.icr = val; 376 // handle auto setting mask from IAM 377 break; 378 case REG_ITR: 379 regs.itr = val; 380 break; 381 case REG_ICS: 382 regs.icr = val | regs.icr(); 383 // generate an interrupt if needed here 384 break; 385 case REG_IMS: 386 regs.imr |= val; 387 // handle interrupts if needed here 388 break; 389 case REG_IMC: 390 regs.imr |= ~val; 391 // handle interrupts if needed here 392 break; 393 case REG_IAM: 394 regs.iam = val; 395 break; 396 case REG_RCTL: 397 regs.rctl = val; 398 break; 399 case REG_FCTTV: 400 regs.fcttv = val; 401 break; 402 case REG_TCTL: 403 regs.tctl = val; 404 break; 405 case REG_PBA: 406 regs.pba.rxa(val); 407 regs.pba.txa(64 - regs.pba.rxa()); 408 break; 409 case REG_WUC: 410 case REG_LEDCTL: 411 case REG_FCAL: 412 case REG_FCAH: 413 case REG_FCT: 414 case REG_VET: 415 case REG_AIFS: 416 case REG_TIPG: 417 ; // We don't care, so don't store anything 418 break; 419 case REG_FCRTL: 420 regs.fcrtl = val; 421 break; 422 case REG_FCRTH: 423 regs.fcrth = val; 424 break; 425 case REG_RDBAL: 426 regs.rdba.rdbal( val & ~mask(4)); 427 break; 428 case REG_RDBAH: 429 regs.rdba.rdbah(val); 430 break; 431 case REG_RDLEN: 432 regs.rdlen = val & ~mask(7); 433 break; 434 case REG_RDH: 435 regs.rdh = val; 436 break; 437 case REG_RDT: 438 regs.rdt = val; 439 break; 440 case REG_RDTR: 441 regs.rdtr = val; 442 break; 443 case REG_RADV: 444 regs.radv = val; 445 break; 446 case REG_TDBAL: 447 regs.tdba.tdbal( val & ~mask(4)); 448 break; 449 case REG_TDBAH: 450 regs.tdba.tdbah(val); 451 break; 452 case REG_TDLEN: 453 regs.tdlen = val & ~mask(7); 454 break; 455 case REG_TDH: 456 regs.tdh = val; 457 break; 458 case REG_TDT: 459 regs.tdt = val; 460 break; 461 case REG_TIDV: 462 regs.tidv = val; 463 break; 464 case REG_TXDCTL: 465 regs.txdctl = val; 466 break; 467 case REG_TADV: 468 regs.tadv = val; 469 break; 470 case REG_RXCSUM: 471 regs.rxcsum = val; 472 break; 473 case REG_MANC: 474 regs.manc = val; 475 break; 476 default: 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); 481 }; 482 483 pkt->result = Packet::Success; 484 return pioDelay; 485} 486 487 488bool 489IGbE::ethRxPkt(EthPacketPtr packet) 490{ 491 panic("Need to implemenet\n"); 492} 493 494 495void 496IGbE::ethTxDone() 497{ 498 panic("Need to implemenet\n"); 499} 500 501void 502IGbE::serialize(std::ostream &os) 503{ 504 panic("Need to implemenet\n"); 505} 506 507void 508IGbE::unserialize(Checkpoint *cp, const std::string §ion) 509{ 510 panic("Need to implemenet\n"); 511} 512 513 514BEGIN_DECLARE_SIM_OBJECT_PARAMS(IGbEInt) 515 516 SimObjectParam<EtherInt *> peer; 517 SimObjectParam<IGbE *> device; 518 519END_DECLARE_SIM_OBJECT_PARAMS(IGbEInt) 520 521BEGIN_INIT_SIM_OBJECT_PARAMS(IGbEInt) 522 523 INIT_PARAM_DFLT(peer, "peer interface", NULL), 524 INIT_PARAM(device, "Ethernet device of this interface") 525 526END_INIT_SIM_OBJECT_PARAMS(IGbEInt) 527 528CREATE_SIM_OBJECT(IGbEInt) 529{ 530 IGbEInt *dev_int = new IGbEInt(getInstanceName(), device); 531 532 EtherInt *p = (EtherInt *)peer; 533 if (p) { 534 dev_int->setPeer(p); 535 p->setPeer(dev_int); 536 } 537 538 return dev_int; 539} 540 541REGISTER_SIM_OBJECT("IGbEInt", IGbEInt) 542 543 544BEGIN_DECLARE_SIM_OBJECT_PARAMS(IGbE) 545 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; 554 555END_DECLARE_SIM_OBJECT_PARAMS(IGbE) 556 557BEGIN_INIT_SIM_OBJECT_PARAMS(IGbE) 558 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") 567 568END_INIT_SIM_OBJECT_PARAMS(IGbE) 569 570 571CREATE_SIM_OBJECT(IGbE) 572{ 573 IGbE::Params *params = new IGbE::Params; 574 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; 584 585 return new IGbE(params); 586} 587 588REGISTER_SIM_OBJECT("IGbE", IGbE) 589