ns_gige.cc revision 12087
1837SN/A/*
21762SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
3837SN/A * All rights reserved.
4837SN/A *
5837SN/A * Redistribution and use in source and binary forms, with or without
6837SN/A * modification, are permitted provided that the following conditions are
7837SN/A * met: redistributions of source code must retain the above copyright
8837SN/A * notice, this list of conditions and the following disclaimer;
9837SN/A * redistributions in binary form must reproduce the above copyright
10837SN/A * notice, this list of conditions and the following disclaimer in the
11837SN/A * documentation and/or other materials provided with the distribution;
12837SN/A * neither the name of the copyright holders nor the names of its
13837SN/A * contributors may be used to endorse or promote products derived from
14837SN/A * this software without specific prior written permission.
15837SN/A *
16837SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17837SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18837SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19837SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20837SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21837SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22837SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23837SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24837SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25837SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26837SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665SN/A *
282760SN/A * Authors: Nathan Binkert
292760SN/A *          Lisa Hsu
30837SN/A */
31837SN/A
321730SN/A/** @file
33837SN/A * Device module for modelling the National Semiconductor
34837SN/A * DP83820 ethernet controller.  Does not support priority queueing
35837SN/A */
3611263Sandreas.sandberg@arm.com
3711263Sandreas.sandberg@arm.com#include "dev/net/ns_gige.hh"
3811263Sandreas.sandberg@arm.com
39837SN/A#include <deque>
4010469SN/A#include <memory>
41837SN/A#include <string>
42837SN/A
435882SN/A#include "base/debug.hh"
44837SN/A#include "base/inet.hh"
456216SN/A#include "base/types.hh"
466658SN/A#include "config/the_isa.hh"
478232SN/A#include "debug/EthernetAll.hh"
4811263Sandreas.sandberg@arm.com#include "dev/net/etherlink.hh"
492566SN/A#include "mem/packet.hh"
503348SN/A#include "mem/packet_access.hh"
514762SN/A#include "params/NSGigE.hh"
522566SN/A#include "sim/system.hh"
53854SN/A
548737SN/A// clang complains about std::set being overloaded with Packet::set if
558737SN/A// we open up the entire namespace std
5610469SN/Ausing std::make_shared;
578737SN/Ausing std::min;
588737SN/Ausing std::ostream;
598737SN/Ausing std::string;
608737SN/A
61854SN/Aconst char *NsRxStateStrings[] =
62854SN/A{
63854SN/A    "rxIdle",
64854SN/A    "rxDescRefr",
65854SN/A    "rxDescRead",
66854SN/A    "rxFifoBlock",
67854SN/A    "rxFragWrite",
68854SN/A    "rxDescWrite",
69854SN/A    "rxAdvance"
70854SN/A};
71854SN/A
72854SN/Aconst char *NsTxStateStrings[] =
73854SN/A{
74854SN/A    "txIdle",
75854SN/A    "txDescRefr",
76854SN/A    "txDescRead",
77854SN/A    "txFifoBlock",
78854SN/A    "txFragRead",
79854SN/A    "txDescWrite",
80854SN/A    "txAdvance"
81854SN/A};
82854SN/A
83854SN/Aconst char *NsDmaState[] =
84854SN/A{
85854SN/A    "dmaIdle",
86854SN/A    "dmaReading",
87854SN/A    "dmaWriting",
88854SN/A    "dmaReadWaiting",
89854SN/A    "dmaWriteWaiting"
90854SN/A};
91837SN/A
921114SN/Ausing namespace Net;
932107SN/Ausing namespace TheISA;
94927SN/A
95837SN/A///////////////////////////////////////////////////////////////////////
96837SN/A//
97879SN/A// NSGigE PCI Device
98837SN/A//
991149SN/ANSGigE::NSGigE(Params *p)
1009339SN/A    : EtherDevBase(p), ioEnable(false),
1011149SN/A      txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size),
102915SN/A      txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
1034093SN/A      txXferLen(0), rxXferLen(0), rxDmaFree(false), txDmaFree(false),
1044093SN/A      txState(txIdle), txEnable(false), CTDD(false), txHalt(false),
105854SN/A      txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
1064093SN/A      rxEnable(false), CRDD(false), rxPktBytes(0), rxHalt(false),
107854SN/A      rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false),
1084093SN/A      eepromState(eepromStart), eepromClk(false), eepromBitsToRx(0),
1094093SN/A      eepromOpcode(0), eepromAddress(0), eepromData(0),
1104093SN/A      dmaReadDelay(p->dma_read_delay), dmaWriteDelay(p->dma_write_delay),
1114093SN/A      dmaReadFactor(p->dma_read_factor), dmaWriteFactor(p->dma_write_factor),
1124093SN/A      rxDmaData(NULL), rxDmaAddr(0), rxDmaLen(0),
1134093SN/A      txDmaData(NULL), txDmaAddr(0), txDmaLen(0),
11412087Sspwilson2@wisc.edu      rxDmaReadEvent([this]{ rxDmaReadDone(); }, name()),
11512087Sspwilson2@wisc.edu      rxDmaWriteEvent([this]{ rxDmaWriteDone(); }, name()),
11612087Sspwilson2@wisc.edu      txDmaReadEvent([this]{ txDmaReadDone(); }, name()),
11712087Sspwilson2@wisc.edu      txDmaWriteEvent([this]{ txDmaWriteDone(); }, name()),
1181149SN/A      dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free),
1191149SN/A      txDelay(p->tx_delay), rxDelay(p->rx_delay),
12012087Sspwilson2@wisc.edu      rxKickTick(0),
12112087Sspwilson2@wisc.edu      rxKickEvent([this]{ rxKick(); }, name()),
12212087Sspwilson2@wisc.edu      txKickTick(0),
12312087Sspwilson2@wisc.edu      txKickEvent([this]{ txKick(); }, name()),
12412087Sspwilson2@wisc.edu      txEvent([this]{ txEventTransmit(); }, name()),
12512087Sspwilson2@wisc.edu      rxFilterEnable(p->rx_filter),
1264093SN/A      acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false),
1271843SN/A      acceptPerfect(false), acceptArp(false), multicastHashEnable(false),
1284093SN/A      intrDelay(p->intr_delay), intrTick(0), cpuPendingIntr(false),
129995SN/A      intrEvent(0), interface(0)
130837SN/A{
131854SN/A
132854SN/A
1334981SN/A    interface = new NSGigEInt(name() + ".int0", this);
1344981SN/A
135837SN/A    regsReset();
1364762SN/A    memcpy(&rom.perfectMatch, p->hardware_address.bytes(), ETH_ADDR_LEN);
1371909SN/A
1381909SN/A    memset(&rxDesc32, 0, sizeof(rxDesc32));
1391909SN/A    memset(&txDesc32, 0, sizeof(txDesc32));
1401909SN/A    memset(&rxDesc64, 0, sizeof(rxDesc64));
1411909SN/A    memset(&txDesc64, 0, sizeof(txDesc64));
142837SN/A}
143837SN/A
144879SN/ANSGigE::~NSGigE()
1459086SN/A{
1469086SN/A    delete interface;
1479086SN/A}
148837SN/A
149855SN/A/**
150855SN/A * This is to write to the PCI general configuration registers
151855SN/A */
1522846SN/ATick
1533349SN/ANSGigE::writeConfig(PacketPtr pkt)
154837SN/A{
1552846SN/A    int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
156837SN/A    if (offset < PCI_DEVICE_SPECIFIC)
1579807SN/A        PciDevice::writeConfig(pkt);
158837SN/A    else
159897SN/A        panic("Device specific PCI config space not implemented!\n");
160897SN/A
161897SN/A    switch (offset) {
1621027SN/A        // seems to work fine without all these PCI settings, but i
1631027SN/A        // put in the IO to double check, an assertion will fail if we
1641027SN/A        // need to properly implement it
165917SN/A      case PCI_COMMAND:
166917SN/A        if (config.data[offset] & PCI_CMD_IOSE)
167927SN/A            ioEnable = true;
168917SN/A        else
169927SN/A            ioEnable = false;
170897SN/A        break;
171897SN/A    }
1724875SN/A
1732846SN/A    return configDelay;
174837SN/A}
175837SN/A
1764981SN/AEtherInt*
1774981SN/ANSGigE::getEthPort(const std::string &if_name, int idx)
1784981SN/A{
1794981SN/A    if (if_name == "interface") {
1804981SN/A       if (interface->getPeer())
1814981SN/A           panic("interface already connected to\n");
1824981SN/A       return interface;
1834981SN/A    }
1844981SN/A    return NULL;
1854981SN/A}
1864981SN/A
187855SN/A/**
188855SN/A * This reads the device registers, which are detailed in the NS83820
189855SN/A * spec sheet
190855SN/A */
1912566SN/ATick
1923349SN/ANSGigE::read(PacketPtr pkt)
193837SN/A{
194927SN/A    assert(ioEnable);
195917SN/A
196855SN/A    //The mask is to give you only the offset into the device register file
1972641SN/A    Addr daddr = pkt->getAddr() & 0xfff;
1982566SN/A    DPRINTF(EthernetPIO, "read  da=%#x pa=%#x size=%d\n",
1992641SN/A            daddr, pkt->getAddr(), pkt->getSize());
200837SN/A
201855SN/A
2021027SN/A    // there are some reserved registers, you can see ns_gige_reg.h and
2031027SN/A    // the spec sheet for details
204854SN/A    if (daddr > LAST && daddr <=  RESERVED) {
205837SN/A        panic("Accessing reserved register");
206854SN/A    } else if (daddr > RESERVED && daddr <= 0x3FC) {
2072846SN/A        return readConfig(pkt);
208854SN/A    } else if (daddr >= MIB_START && daddr <= MIB_END) {
209854SN/A        // don't implement all the MIB's.  hopefully the kernel
210854SN/A        // doesn't actually DEPEND upon their values
211855SN/A        // MIB are just hardware stats keepers
2122630SN/A        pkt->set<uint32_t>(0);
2134870SN/A        pkt->makeAtomicResponse();
2142566SN/A        return pioDelay;
215854SN/A    } else if (daddr > 0x3FC)
216854SN/A        panic("Something is messed up!\n");
217837SN/A
2182641SN/A    assert(pkt->getSize() == sizeof(uint32_t));
2192630SN/A        uint32_t &reg = *pkt->getPtr<uint32_t>();
2202566SN/A        uint16_t rfaddr;
2212566SN/A
2222566SN/A        switch (daddr) {
2232566SN/A          case CR:
2242566SN/A            reg = regs.command;
2252566SN/A            //these are supposed to be cleared on a read
2262566SN/A            reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR);
2272566SN/A            break;
2282566SN/A
2292566SN/A          case CFGR:
2302566SN/A            reg = regs.config;
2312566SN/A            break;
2322566SN/A
2332566SN/A          case MEAR:
2342566SN/A            reg = regs.mear;
2352566SN/A            break;
2362566SN/A
2372566SN/A          case PTSCR:
2382566SN/A            reg = regs.ptscr;
2392566SN/A            break;
2402566SN/A
2412566SN/A          case ISR:
2422566SN/A            reg = regs.isr;
2432566SN/A            devIntrClear(ISR_ALL);
2442566SN/A            break;
2452566SN/A
2462566SN/A          case IMR:
2472566SN/A            reg = regs.imr;
2482566SN/A            break;
2492566SN/A
2502566SN/A          case IER:
2512566SN/A            reg = regs.ier;
2522566SN/A            break;
2532566SN/A
2542566SN/A          case IHR:
2552566SN/A            reg = regs.ihr;
2562566SN/A            break;
2572566SN/A
2582566SN/A          case TXDP:
2592566SN/A            reg = regs.txdp;
2602566SN/A            break;
2612566SN/A
2622566SN/A          case TXDP_HI:
2632566SN/A            reg = regs.txdp_hi;
2642566SN/A            break;
2652566SN/A
2662566SN/A          case TX_CFG:
2672566SN/A            reg = regs.txcfg;
2682566SN/A            break;
2692566SN/A
2702566SN/A          case GPIOR:
2712566SN/A            reg = regs.gpior;
2722566SN/A            break;
2732566SN/A
2742566SN/A          case RXDP:
2752566SN/A            reg = regs.rxdp;
2762566SN/A            break;
2772566SN/A
2782566SN/A          case RXDP_HI:
2792566SN/A            reg = regs.rxdp_hi;
2802566SN/A            break;
2812566SN/A
2822566SN/A          case RX_CFG:
2832566SN/A            reg = regs.rxcfg;
2842566SN/A            break;
2852566SN/A
2862566SN/A          case PQCR:
2872566SN/A            reg = regs.pqcr;
2882566SN/A            break;
2892566SN/A
2902566SN/A          case WCSR:
2912566SN/A            reg = regs.wcsr;
2922566SN/A            break;
2932566SN/A
2942566SN/A          case PCR:
2952566SN/A            reg = regs.pcr;
2962566SN/A            break;
2972566SN/A
2982566SN/A            // see the spec sheet for how RFCR and RFDR work
2992566SN/A            // basically, you write to RFCR to tell the machine
3002566SN/A            // what you want to do next, then you act upon RFDR,
3012566SN/A            // and the device will be prepared b/c of what you
3022566SN/A            // wrote to RFCR
3032566SN/A          case RFCR:
3042566SN/A            reg = regs.rfcr;
3052566SN/A            break;
3062566SN/A
3072566SN/A          case RFDR:
3082566SN/A            rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
3092566SN/A            switch (rfaddr) {
3102566SN/A              // Read from perfect match ROM octets
3112566SN/A              case 0x000:
3122566SN/A                reg = rom.perfectMatch[1];
3132566SN/A                reg = reg << 8;
3142566SN/A                reg += rom.perfectMatch[0];
315837SN/A                break;
3162566SN/A              case 0x002:
3172566SN/A                reg = rom.perfectMatch[3] << 8;
3182566SN/A                reg += rom.perfectMatch[2];
319837SN/A                break;
3202566SN/A              case 0x004:
3212566SN/A                reg = rom.perfectMatch[5] << 8;
3222566SN/A                reg += rom.perfectMatch[4];
323837SN/A                break;
3242566SN/A              default:
3252566SN/A                // Read filter hash table
3262566SN/A                if (rfaddr >= FHASH_ADDR &&
3272566SN/A                    rfaddr < FHASH_ADDR + FHASH_SIZE) {
3282566SN/A
3292566SN/A                    // Only word-aligned reads supported
3302566SN/A                    if (rfaddr % 2)
3312566SN/A                        panic("unaligned read from filter hash table!");
3322566SN/A
3332566SN/A                    reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8;
3342566SN/A                    reg += rom.filterHash[rfaddr - FHASH_ADDR];
335837SN/A                    break;
336837SN/A                }
3372566SN/A
3382566SN/A                panic("reading RFDR for something other than pattern"
3392566SN/A                      " matching or hashing! %#x\n", rfaddr);
340837SN/A            }
3412566SN/A            break;
3422566SN/A
3432566SN/A          case SRR:
3442566SN/A            reg = regs.srr;
3452566SN/A            break;
3462566SN/A
3472566SN/A          case MIBC:
3482566SN/A            reg = regs.mibc;
3492566SN/A            reg &= ~(MIBC_MIBS | MIBC_ACLR);
3502566SN/A            break;
3512566SN/A
3522566SN/A          case VRCR:
3532566SN/A            reg = regs.vrcr;
3542566SN/A            break;
3552566SN/A
3562566SN/A          case VTCR:
3572566SN/A            reg = regs.vtcr;
3582566SN/A            break;
3592566SN/A
3602566SN/A          case VDR:
3612566SN/A            reg = regs.vdr;
3622566SN/A            break;
3632566SN/A
3642566SN/A          case CCSR:
3652566SN/A            reg = regs.ccsr;
3662566SN/A            break;
3672566SN/A
3682566SN/A          case TBICR:
3692566SN/A            reg = regs.tbicr;
3702566SN/A            break;
3712566SN/A
3722566SN/A          case TBISR:
3732566SN/A            reg = regs.tbisr;
3742566SN/A            break;
3752566SN/A
3762566SN/A          case TANAR:
3772566SN/A            reg = regs.tanar;
3782566SN/A            break;
3792566SN/A
3802566SN/A          case TANLPAR:
3812566SN/A            reg = regs.tanlpar;
3822566SN/A            break;
3832566SN/A
3842566SN/A          case TANER:
3852566SN/A            reg = regs.taner;
3862566SN/A            break;
3872566SN/A
3882566SN/A          case TESR:
3892566SN/A            reg = regs.tesr;
3902566SN/A            break;
3912566SN/A
3922566SN/A          case M5REG:
3932566SN/A            reg = 0;
3942566SN/A            if (params()->rx_thread)
3952566SN/A                reg |= M5REG_RX_THREAD;
3962566SN/A            if (params()->tx_thread)
3972566SN/A                reg |= M5REG_TX_THREAD;
3982566SN/A            if (params()->rss)
3992566SN/A                reg |= M5REG_RSS;
4002566SN/A            break;
4012566SN/A
4022566SN/A          default:
4032566SN/A            panic("reading unimplemented register: addr=%#x", daddr);
404837SN/A        }
4052566SN/A
4062566SN/A        DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
4072566SN/A                daddr, reg, reg);
4082566SN/A
4094870SN/A    pkt->makeAtomicResponse();
4102566SN/A    return pioDelay;
411837SN/A}
412837SN/A
4132566SN/ATick
4143349SN/ANSGigE::write(PacketPtr pkt)
415837SN/A{
416927SN/A    assert(ioEnable);
417917SN/A
4182641SN/A    Addr daddr = pkt->getAddr() & 0xfff;
4192566SN/A    DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n",
4202641SN/A            daddr, pkt->getAddr(), pkt->getSize());
4212630SN/A
422854SN/A    if (daddr > LAST && daddr <=  RESERVED) {
423837SN/A        panic("Accessing reserved register");
424854SN/A    } else if (daddr > RESERVED && daddr <= 0x3FC) {
4252846SN/A        return writeConfig(pkt);
426854SN/A    } else if (daddr > 0x3FC)
427854SN/A        panic("Something is messed up!\n");
428837SN/A
4292641SN/A    if (pkt->getSize() == sizeof(uint32_t)) {
4302630SN/A        uint32_t reg = pkt->get<uint32_t>();
4311848SN/A        uint16_t rfaddr;
4321848SN/A
433854SN/A        DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg);
434837SN/A
435837SN/A        switch (daddr) {
436837SN/A          case CR:
437837SN/A            regs.command = reg;
4381035SN/A            if (reg & CR_TXD) {
4391035SN/A                txEnable = false;
440837SN/A            } else if (reg & CR_TXE) {
4412126SN/A                txEnable = true;
4422126SN/A
4432126SN/A                // the kernel is enabling the transmit machine
4442126SN/A                if (txState == txIdle)
4452126SN/A                    txKick();
446837SN/A            }
447837SN/A
4481035SN/A            if (reg & CR_RXD) {
4491035SN/A                rxEnable = false;
450837SN/A            } else if (reg & CR_RXE) {
4512126SN/A                rxEnable = true;
4522126SN/A
4532126SN/A                if (rxState == rxIdle)
4542126SN/A                    rxKick();
455837SN/A            }
456837SN/A
457837SN/A            if (reg & CR_TXR)
458837SN/A                txReset();
459837SN/A
460837SN/A            if (reg & CR_RXR)
461837SN/A                rxReset();
462837SN/A
463837SN/A            if (reg & CR_SWI)
464837SN/A                devIntrPost(ISR_SWI);
465837SN/A
466837SN/A            if (reg & CR_RST) {
467837SN/A                txReset();
468837SN/A                rxReset();
469854SN/A
470837SN/A                regsReset();
471837SN/A            }
472837SN/A            break;
473837SN/A
4741690SN/A          case CFGR:
4751690SN/A            if (reg & CFGR_LNKSTS ||
4761690SN/A                reg & CFGR_SPDSTS ||
4771690SN/A                reg & CFGR_DUPSTS ||
4781690SN/A                reg & CFGR_RESERVED ||
4791690SN/A                reg & CFGR_T64ADDR ||
4808726SN/A                reg & CFGR_PCI64_DET) {
4818726SN/A                // First clear all writable bits
4828726SN/A                regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
4838726SN/A                    CFGR_RESERVED | CFGR_T64ADDR |
4848726SN/A                    CFGR_PCI64_DET;
4858726SN/A                // Now set the appropriate writable bits
4868726SN/A                regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
4878726SN/A                                       CFGR_RESERVED | CFGR_T64ADDR |
4888726SN/A                                       CFGR_PCI64_DET);
4898726SN/A            }
4901027SN/A
4911027SN/A// all these #if 0's are because i don't THINK the kernel needs to
4921027SN/A// have these implemented. if there is a problem relating to one of
4931027SN/A// these, you may need to add functionality in.
4948737SN/A
4958737SN/A// grouped together and #if 0'ed to avoid empty if body and make clang happy
4968737SN/A#if 0
4971690SN/A            if (reg & CFGR_TBI_EN) ;
4981690SN/A            if (reg & CFGR_MODE_1000) ;
499837SN/A
5001690SN/A            if (reg & CFGR_PINT_DUPSTS ||
5011690SN/A                reg & CFGR_PINT_LNKSTS ||
5021690SN/A                reg & CFGR_PINT_SPDSTS)
5031027SN/A                ;
5041027SN/A
5051690SN/A            if (reg & CFGR_TMRTEST) ;
5061690SN/A            if (reg & CFGR_MRM_DIS) ;
5071690SN/A            if (reg & CFGR_MWI_DIS) ;
5081690SN/A
5091690SN/A            if (reg & CFGR_DATA64_EN) ;
5101690SN/A            if (reg & CFGR_M64ADDR) ;
5111690SN/A            if (reg & CFGR_PHY_RST) ;
5121690SN/A            if (reg & CFGR_PHY_DIS) ;
513837SN/A
5141909SN/A            if (reg & CFGR_REQALG) ;
5151909SN/A            if (reg & CFGR_SB) ;
5161909SN/A            if (reg & CFGR_POW) ;
5171909SN/A            if (reg & CFGR_EXD) ;
5181909SN/A            if (reg & CFGR_PESEL) ;
5191909SN/A            if (reg & CFGR_BROM_DIS) ;
5201909SN/A            if (reg & CFGR_EXT_125) ;
5211909SN/A            if (reg & CFGR_BEM) ;
5228737SN/A
5238737SN/A            if (reg & CFGR_T64ADDR) ;
5248737SN/A            // panic("CFGR_T64ADDR is read only register!\n");
5258737SN/A#endif
5268737SN/A            if (reg & CFGR_AUTO_1000)
5278737SN/A                panic("CFGR_AUTO_1000 not implemented!\n");
5288737SN/A
5298737SN/A            if (reg & CFGR_PCI64_DET)
5308737SN/A                panic("CFGR_PCI64_DET is read only register!\n");
5318737SN/A
5328737SN/A            if (reg & CFGR_EXTSTS_EN)
5338737SN/A                extstsEnable = true;
5348737SN/A            else
5358737SN/A                extstsEnable = false;
536837SN/A            break;
537837SN/A
538837SN/A          case MEAR:
5391843SN/A            // Clear writable bits
5401843SN/A            regs.mear &= MEAR_EEDO;
5411843SN/A            // Set appropriate writable bits
5421843SN/A            regs.mear |= reg & ~MEAR_EEDO;
5431843SN/A
5441843SN/A            // FreeBSD uses the EEPROM to read PMATCH (for the MAC address)
5451843SN/A            // even though it could get it through RFDR
5461843SN/A            if (reg & MEAR_EESEL) {
5471843SN/A                // Rising edge of clock
5481843SN/A                if (reg & MEAR_EECLK && !eepromClk)
5491843SN/A                    eepromKick();
5501843SN/A            }
5511843SN/A            else {
5521843SN/A                eepromState = eepromStart;
5531843SN/A                regs.mear &= ~MEAR_EEDI;
5541843SN/A            }
5551843SN/A
5561843SN/A            eepromClk = reg & MEAR_EECLK;
5571843SN/A
5581027SN/A            // since phy is completely faked, MEAR_MD* don't matter
5598737SN/A
5608737SN/A// grouped together and #if 0'ed to avoid empty if body and make clang happy
5618737SN/A#if 0
562837SN/A            if (reg & MEAR_MDIO) ;
563837SN/A            if (reg & MEAR_MDDIR) ;
564837SN/A            if (reg & MEAR_MDC) ;
5658737SN/A#endif
566837SN/A            break;
567837SN/A
568837SN/A          case PTSCR:
569854SN/A            regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY);
5701027SN/A            // these control BISTs for various parts of chip - we
5711027SN/A            // don't care or do just fake that the BIST is done
572854SN/A            if (reg & PTSCR_RBIST_EN)
573854SN/A                regs.ptscr |= PTSCR_RBIST_DONE;
574854SN/A            if (reg & PTSCR_EEBIST_EN)
575854SN/A                regs.ptscr &= ~PTSCR_EEBIST_EN;
576854SN/A            if (reg & PTSCR_EELOAD_EN)
577854SN/A                regs.ptscr &= ~PTSCR_EELOAD_EN;
578837SN/A            break;
579837SN/A
580837SN/A          case ISR: /* writing to the ISR has no effect */
581837SN/A            panic("ISR is a read only register!\n");
582837SN/A
583837SN/A          case IMR:
584837SN/A            regs.imr = reg;
585837SN/A            devIntrChangeMask();
586837SN/A            break;
587837SN/A
588837SN/A          case IER:
589837SN/A            regs.ier = reg;
590837SN/A            break;
591837SN/A
592837SN/A          case IHR:
593837SN/A            regs.ihr = reg;
594837SN/A            /* not going to implement real interrupt holdoff */
595837SN/A            break;
596837SN/A
597837SN/A          case TXDP:
598837SN/A            regs.txdp = (reg & 0xFFFFFFFC);
599837SN/A            assert(txState == txIdle);
600837SN/A            CTDD = false;
601837SN/A            break;
602837SN/A
603837SN/A          case TXDP_HI:
604837SN/A            regs.txdp_hi = reg;
605837SN/A            break;
606837SN/A
6071690SN/A          case TX_CFG:
608837SN/A            regs.txcfg = reg;
609837SN/A#if 0
6101690SN/A            if (reg & TX_CFG_CSI) ;
6111690SN/A            if (reg & TX_CFG_HBI) ;
6121690SN/A            if (reg & TX_CFG_MLB) ;
6131690SN/A            if (reg & TX_CFG_ATP) ;
6141690SN/A            if (reg & TX_CFG_ECRETRY) {
6151027SN/A                /*
6161027SN/A                 * this could easily be implemented, but considering
6171027SN/A                 * the network is just a fake pipe, wouldn't make
6181027SN/A                 * sense to do this
6191027SN/A                 */
6201027SN/A            }
621837SN/A
6221690SN/A            if (reg & TX_CFG_BRST_DIS) ;
623837SN/A#endif
624837SN/A
6251027SN/A#if 0
626854SN/A            /* we handle our own DMA, ignore the kernel's exhortations */
6271690SN/A            if (reg & TX_CFG_MXDMA) ;
6281027SN/A#endif
6291027SN/A
6301027SN/A            // also, we currently don't care about fill/drain
6311027SN/A            // thresholds though this may change in the future with
6321027SN/A            // more realistic networks or a driver which changes it
6331027SN/A            // according to feedback
634837SN/A
635837SN/A            break;
636837SN/A
637837SN/A          case GPIOR:
6381843SN/A            // Only write writable bits
6391843SN/A            regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
6401843SN/A                        | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN;
6411843SN/A            regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
6421843SN/A                                | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN);
643837SN/A            /* these just control general purpose i/o pins, don't matter */
644837SN/A            break;
645837SN/A
646854SN/A          case RXDP:
647854SN/A            regs.rxdp = reg;
6481035SN/A            CRDD = false;
649854SN/A            break;
650854SN/A
651854SN/A          case RXDP_HI:
652854SN/A            regs.rxdp_hi = reg;
653854SN/A            break;
654854SN/A
6551690SN/A          case RX_CFG:
656837SN/A            regs.rxcfg = reg;
657837SN/A#if 0
6581690SN/A            if (reg & RX_CFG_AEP) ;
6591690SN/A            if (reg & RX_CFG_ARP) ;
6601690SN/A            if (reg & RX_CFG_STRIPCRC) ;
6611690SN/A            if (reg & RX_CFG_RX_RD) ;
6621690SN/A            if (reg & RX_CFG_ALP) ;
6631690SN/A            if (reg & RX_CFG_AIRL) ;
664837SN/A
665854SN/A            /* we handle our own DMA, ignore what kernel says about it */
6661690SN/A            if (reg & RX_CFG_MXDMA) ;
6671027SN/A
668927SN/A            //also, we currently don't care about fill/drain thresholds
669927SN/A            //though this may change in the future with more realistic
670927SN/A            //networks or a driver which changes it according to feedback
6711690SN/A            if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ;
672837SN/A#endif
673837SN/A            break;
674837SN/A
675837SN/A          case PQCR:
676837SN/A            /* there is no priority queueing used in the linux 2.6 driver */
677837SN/A            regs.pqcr = reg;
678837SN/A            break;
679837SN/A
680837SN/A          case WCSR:
681837SN/A            /* not going to implement wake on LAN */
682837SN/A            regs.wcsr = reg;
683837SN/A            break;
684837SN/A
685837SN/A          case PCR:
686837SN/A            /* not going to implement pause control */
687837SN/A            regs.pcr = reg;
688837SN/A            break;
689837SN/A
690837SN/A          case RFCR:
691837SN/A            regs.rfcr = reg;
692854SN/A
693837SN/A            rxFilterEnable = (reg & RFCR_RFEN) ? true : false;
694837SN/A            acceptBroadcast = (reg & RFCR_AAB) ? true : false;
695837SN/A            acceptMulticast = (reg & RFCR_AAM) ? true : false;
696837SN/A            acceptUnicast = (reg & RFCR_AAU) ? true : false;
697837SN/A            acceptPerfect = (reg & RFCR_APM) ? true : false;
698837SN/A            acceptArp = (reg & RFCR_AARP) ? true : false;
6991843SN/A            multicastHashEnable = (reg & RFCR_MHEN) ? true : false;
700837SN/A
7011027SN/A#if 0
7021027SN/A            if (reg & RFCR_APAT)
7031027SN/A                panic("RFCR_APAT not implemented!\n");
7041027SN/A#endif
7051843SN/A            if (reg & RFCR_UHEN)
7061843SN/A                panic("Unicast hash filtering not used by drivers!\n");
707837SN/A
708837SN/A            if (reg & RFCR_ULM)
709837SN/A                panic("RFCR_ULM not implemented!\n");
710837SN/A
711837SN/A            break;
712837SN/A
713837SN/A          case RFDR:
7141848SN/A            rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
7151843SN/A            switch (rfaddr) {
7161843SN/A              case 0x000:
7171843SN/A                rom.perfectMatch[0] = (uint8_t)reg;
7181843SN/A                rom.perfectMatch[1] = (uint8_t)(reg >> 8);
7191843SN/A                break;
7201843SN/A              case 0x002:
7211843SN/A                rom.perfectMatch[2] = (uint8_t)reg;
7221843SN/A                rom.perfectMatch[3] = (uint8_t)(reg >> 8);
7231843SN/A                break;
7241843SN/A              case 0x004:
7251843SN/A                rom.perfectMatch[4] = (uint8_t)reg;
7261843SN/A                rom.perfectMatch[5] = (uint8_t)(reg >> 8);
7271843SN/A                break;
7281843SN/A              default:
7291843SN/A
7301843SN/A                if (rfaddr >= FHASH_ADDR &&
7311843SN/A                    rfaddr < FHASH_ADDR + FHASH_SIZE) {
7321843SN/A
7331843SN/A                    // Only word-aligned writes supported
7341843SN/A                    if (rfaddr % 2)
7351843SN/A                        panic("unaligned write to filter hash table!");
7361843SN/A
7371843SN/A                    rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg;
7381843SN/A                    rom.filterHash[rfaddr - FHASH_ADDR + 1]
7391843SN/A                        = (uint8_t)(reg >> 8);
7401843SN/A                    break;
7411843SN/A                }
74210367SN/A                panic("writing RFDR for something other than pattern matching "
74310367SN/A                    "or hashing! %#x\n", rfaddr);
7441843SN/A            }
745837SN/A
746837SN/A          case BRAR:
7471843SN/A            regs.brar = reg;
7481843SN/A            break;
749837SN/A
750837SN/A          case BRDR:
751837SN/A            panic("the driver never uses BRDR, something is wrong!\n");
752837SN/A
753837SN/A          case SRR:
754837SN/A            panic("SRR is read only register!\n");
755837SN/A
756837SN/A          case MIBC:
757837SN/A            panic("the driver never uses MIBC, something is wrong!\n");
758837SN/A
759837SN/A          case VRCR:
760837SN/A            regs.vrcr = reg;
761837SN/A            break;
762837SN/A
763837SN/A          case VTCR:
764837SN/A            regs.vtcr = reg;
765837SN/A            break;
766837SN/A
767837SN/A          case VDR:
768837SN/A            panic("the driver never uses VDR, something is wrong!\n");
769837SN/A
770837SN/A          case CCSR:
771837SN/A            /* not going to implement clockrun stuff */
772837SN/A            regs.ccsr = reg;
773837SN/A            break;
774837SN/A
775837SN/A          case TBICR:
776837SN/A            regs.tbicr = reg;
777837SN/A            if (reg & TBICR_MR_LOOPBACK)
778837SN/A                panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
779837SN/A
780837SN/A            if (reg & TBICR_MR_AN_ENABLE) {
781837SN/A                regs.tanlpar = regs.tanar;
782837SN/A                regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS);
783837SN/A            }
784837SN/A
785837SN/A#if 0
786837SN/A            if (reg & TBICR_MR_RESTART_AN) ;
787837SN/A#endif
788837SN/A
789837SN/A            break;
790837SN/A
791837SN/A          case TBISR:
792837SN/A            panic("TBISR is read only register!\n");
793837SN/A
794837SN/A          case TANAR:
7951843SN/A            // Only write the writable bits
7961843SN/A            regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED;
7971843SN/A            regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED);
7981843SN/A
7991843SN/A            // Pause capability unimplemented
8001843SN/A#if 0
8011843SN/A            if (reg & TANAR_PS2) ;
8021843SN/A            if (reg & TANAR_PS1) ;
8031843SN/A#endif
8041843SN/A
805837SN/A            break;
806837SN/A
807837SN/A          case TANLPAR:
808837SN/A            panic("this should only be written to by the fake phy!\n");
809837SN/A
810837SN/A          case TANER:
811837SN/A            panic("TANER is read only register!\n");
812837SN/A
813837SN/A          case TESR:
814837SN/A            regs.tesr = reg;
815837SN/A            break;
816837SN/A
817837SN/A          default:
8181027SN/A            panic("invalid register access daddr=%#x", daddr);
819837SN/A        }
8201027SN/A    } else {
821837SN/A        panic("Invalid Request Size");
8221027SN/A    }
8234870SN/A    pkt->makeAtomicResponse();
8242566SN/A    return pioDelay;
825837SN/A}
826837SN/A
827837SN/Avoid
828879SN/ANSGigE::devIntrPost(uint32_t interrupts)
829837SN/A{
830854SN/A    if (interrupts & ISR_RESERVE)
831854SN/A        panic("Cannot set a reserved interrupt");
832837SN/A
8331057SN/A    if (interrupts & ISR_NOIMPL)
8341057SN/A        warn("interrupt not implemented %#x\n", interrupts);
8351057SN/A
8361883SN/A    interrupts &= ISR_IMPL;
8371057SN/A    regs.isr |= interrupts;
8381057SN/A
8391263SN/A    if (interrupts & regs.imr) {
8401263SN/A        if (interrupts & ISR_SWI) {
8411263SN/A            totalSwi++;
8421263SN/A        }
8431263SN/A        if (interrupts & ISR_RXIDLE) {
8441263SN/A            totalRxIdle++;
8451263SN/A        }
8461263SN/A        if (interrupts & ISR_RXOK) {
8471263SN/A            totalRxOk++;
8481263SN/A        }
8491263SN/A        if (interrupts & ISR_RXDESC) {
8501263SN/A            totalRxDesc++;
8511263SN/A        }
8521263SN/A        if (interrupts & ISR_TXOK) {
8531263SN/A            totalTxOk++;
8541263SN/A        }
8551263SN/A        if (interrupts & ISR_TXIDLE) {
8561263SN/A            totalTxIdle++;
8571263SN/A        }
8581263SN/A        if (interrupts & ISR_TXDESC) {
8591263SN/A            totalTxDesc++;
8601263SN/A        }
8611263SN/A        if (interrupts & ISR_RXORN) {
8621263SN/A            totalRxOrn++;
8631263SN/A        }
8641263SN/A    }
8651263SN/A
8661057SN/A    DPRINTF(EthernetIntr,
8671057SN/A            "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
8681057SN/A            interrupts, regs.isr, regs.imr);
869837SN/A
870854SN/A    if ((regs.isr & regs.imr)) {
8717823SN/A        Tick when = curTick();
8721883SN/A        if ((regs.isr & regs.imr & ISR_NODELAY) == 0)
873854SN/A            when += intrDelay;
8745485SN/A        postedInterrupts++;
875854SN/A        cpuIntrPost(when);
876854SN/A    }
877837SN/A}
878837SN/A
8791263SN/A/* writing this interrupt counting stats inside this means that this function
8801263SN/A   is now limited to being used to clear all interrupts upon the kernel
8811263SN/A   reading isr and servicing.  just telling you in case you were thinking
8821263SN/A   of expanding use.
8831263SN/A*/
884837SN/Avoid
885879SN/ANSGigE::devIntrClear(uint32_t interrupts)
886837SN/A{
887837SN/A    if (interrupts & ISR_RESERVE)
888837SN/A        panic("Cannot clear a reserved interrupt");
889837SN/A
8901263SN/A    if (regs.isr & regs.imr & ISR_SWI) {
8911263SN/A        postedSwi++;
8921263SN/A    }
8931263SN/A    if (regs.isr & regs.imr & ISR_RXIDLE) {
8941263SN/A        postedRxIdle++;
8951263SN/A    }
8961263SN/A    if (regs.isr & regs.imr & ISR_RXOK) {
8971263SN/A        postedRxOk++;
8981263SN/A    }
8991263SN/A    if (regs.isr & regs.imr & ISR_RXDESC) {
9001263SN/A            postedRxDesc++;
9011263SN/A    }
9021263SN/A    if (regs.isr & regs.imr & ISR_TXOK) {
9031263SN/A        postedTxOk++;
9041263SN/A    }
9051263SN/A    if (regs.isr & regs.imr & ISR_TXIDLE) {
9061263SN/A        postedTxIdle++;
9071263SN/A    }
9081263SN/A    if (regs.isr & regs.imr & ISR_TXDESC) {
9091263SN/A        postedTxDesc++;
9101263SN/A    }
9111263SN/A    if (regs.isr & regs.imr & ISR_RXORN) {
9121263SN/A        postedRxOrn++;
9131263SN/A    }
9141263SN/A
9151057SN/A    interrupts &= ~ISR_NOIMPL;
9161057SN/A    regs.isr &= ~interrupts;
917837SN/A
9181027SN/A    DPRINTF(EthernetIntr,
9191027SN/A            "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",
920881SN/A            interrupts, regs.isr, regs.imr);
9211036SN/A
9221036SN/A    if (!(regs.isr & regs.imr))
9231036SN/A        cpuIntrClear();
924837SN/A}
925837SN/A
926837SN/Avoid
927879SN/ANSGigE::devIntrChangeMask()
928837SN/A{
9291036SN/A    DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n",
9301036SN/A            regs.isr, regs.imr, regs.isr & regs.imr);
931837SN/A
932837SN/A    if (regs.isr & regs.imr)
9337823SN/A        cpuIntrPost(curTick());
934837SN/A    else
935837SN/A        cpuIntrClear();
936837SN/A}
937837SN/A
938837SN/Avoid
939879SN/ANSGigE::cpuIntrPost(Tick when)
940837SN/A{
9411027SN/A    // If the interrupt you want to post is later than an interrupt
9421027SN/A    // already scheduled, just let it post in the coming one and don't
9431027SN/A    // schedule another.
9441027SN/A    // HOWEVER, must be sure that the scheduled intrTick is in the
9451027SN/A    // future (this was formerly the source of a bug)
9461035SN/A    /**
9471035SN/A     * @todo this warning should be removed and the intrTick code should
9481035SN/A     * be fixed.
9491035SN/A     */
9507823SN/A    assert(when >= curTick());
9517823SN/A    assert(intrTick >= curTick() || intrTick == 0);
9521072SN/A    if (when > intrTick && intrTick != 0) {
9531072SN/A        DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
9541072SN/A                intrTick);
9551072SN/A        return;
9561035SN/A    }
957854SN/A
958854SN/A    intrTick = when;
9597823SN/A    if (intrTick < curTick()) {
9607823SN/A        intrTick = curTick();
9611072SN/A    }
9621072SN/A
9631072SN/A    DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
9641072SN/A            intrTick);
9651072SN/A
9661072SN/A    if (intrEvent)
967854SN/A        intrEvent->squash();
96812087Sspwilson2@wisc.edu
96912087Sspwilson2@wisc.edu    intrEvent = new EventFunctionWrapper([this]{ cpuInterrupt(); },
97012087Sspwilson2@wisc.edu                                         name(), true);
9715606SN/A    schedule(intrEvent, intrTick);
972854SN/A}
973854SN/A
974854SN/Avoid
975879SN/ANSGigE::cpuInterrupt()
976854SN/A{
9777823SN/A    assert(intrTick == curTick());
9781072SN/A
9791072SN/A    // Whether or not there's a pending interrupt, we don't care about
9801072SN/A    // it anymore
9811072SN/A    intrEvent = 0;
9821072SN/A    intrTick = 0;
9831072SN/A
984854SN/A    // Don't send an interrupt if there's already one
985927SN/A    if (cpuPendingIntr) {
986927SN/A        DPRINTF(EthernetIntr,
987927SN/A                "would send an interrupt now, but there's already pending\n");
9881072SN/A    } else {
9891072SN/A        // Send interrupt
9901072SN/A        cpuPendingIntr = true;
9911072SN/A
9921149SN/A        DPRINTF(EthernetIntr, "posting interrupt\n");
9931149SN/A        intrPost();
994927SN/A    }
995837SN/A}
996837SN/A
997837SN/Avoid
998879SN/ANSGigE::cpuIntrClear()
999837SN/A{
10001027SN/A    if (!cpuPendingIntr)
10011027SN/A        return;
10021027SN/A
10031072SN/A    if (intrEvent) {
10041072SN/A        intrEvent->squash();
10051072SN/A        intrEvent = 0;
10061072SN/A    }
10071072SN/A
10081072SN/A    intrTick = 0;
10091072SN/A
10101027SN/A    cpuPendingIntr = false;
10111057SN/A
10121149SN/A    DPRINTF(EthernetIntr, "clearing interrupt\n");
10131149SN/A    intrClear();
1014837SN/A}
1015837SN/A
1016837SN/Abool
1017879SN/ANSGigE::cpuIntrPending() const
1018837SN/A{ return cpuPendingIntr; }
1019837SN/A
1020837SN/Avoid
1021879SN/ANSGigE::txReset()
1022837SN/A{
1023837SN/A
1024837SN/A    DPRINTF(Ethernet, "transmit reset\n");
1025837SN/A
1026837SN/A    CTDD = false;
10271035SN/A    txEnable = false;;
1028854SN/A    txFragPtr = 0;
1029854SN/A    assert(txDescCnt == 0);
1030837SN/A    txFifo.clear();
1031837SN/A    txState = txIdle;
1032854SN/A    assert(txDmaState == dmaIdle);
1033837SN/A}
1034837SN/A
1035837SN/Avoid
1036879SN/ANSGigE::rxReset()
1037837SN/A{
1038837SN/A    DPRINTF(Ethernet, "receive reset\n");
1039837SN/A
1040837SN/A    CRDD = false;
1041854SN/A    assert(rxPktBytes == 0);
10421035SN/A    rxEnable = false;
1043854SN/A    rxFragPtr = 0;
1044854SN/A    assert(rxDescCnt == 0);
1045854SN/A    assert(rxDmaState == dmaIdle);
1046837SN/A    rxFifo.clear();
1047837SN/A    rxState = rxIdle;
1048837SN/A}
1049837SN/A
10501036SN/Avoid
10511036SN/ANSGigE::regsReset()
1052915SN/A{
1053915SN/A    memset(&regs, 0, sizeof(regs));
10541817SN/A    regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000);
10551843SN/A    regs.mear = 0x12;
10561057SN/A    regs.txcfg = 0x120; // set drain threshold to 1024 bytes and
10571057SN/A                        // fill threshold to 32 bytes
10581057SN/A    regs.rxcfg = 0x4;   // set drain threshold to 16 bytes
10591057SN/A    regs.srr = 0x0103;  // set the silicon revision to rev B or 0x103
10601057SN/A    regs.mibc = MIBC_FRZ;
10611057SN/A    regs.vdr = 0x81;    // set the vlan tag type to 802.1q
10621057SN/A    regs.tesr = 0xc000; // TBI capable of both full and half duplex
10631843SN/A    regs.brar = 0xffffffff;
1064927SN/A
1065927SN/A    extstsEnable = false;
1066927SN/A    acceptBroadcast = false;
1067927SN/A    acceptMulticast = false;
1068927SN/A    acceptUnicast = false;
1069927SN/A    acceptPerfect = false;
1070927SN/A    acceptArp = false;
1071915SN/A}
1072915SN/A
1073854SN/Abool
1074879SN/ANSGigE::doRxDmaRead()
1075854SN/A{
1076854SN/A    assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
1077854SN/A    rxDmaState = dmaReading;
1078854SN/A
107910913SN/A    if (dmaPending() || drainState() != DrainState::Running)
10802566SN/A        rxDmaState = dmaReadWaiting;
10812566SN/A    else
10822566SN/A        dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData);
10832566SN/A
1084854SN/A    return true;
1085854SN/A}
1086854SN/A
1087854SN/Avoid
1088879SN/ANSGigE::rxDmaReadDone()
1089854SN/A{
1090854SN/A    assert(rxDmaState == dmaReading);
10912566SN/A    rxDmaState = dmaIdle;
10922566SN/A
10932566SN/A    DPRINTF(EthernetDMA, "rx dma read  paddr=%#x len=%d\n",
10942566SN/A            rxDmaAddr, rxDmaLen);
10952566SN/A    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1096854SN/A
1097854SN/A    // If the transmit state machine has a pending DMA, let it go first
1098854SN/A    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1099854SN/A        txKick();
1100854SN/A
1101854SN/A    rxKick();
1102854SN/A}
1103854SN/A
1104854SN/Abool
1105879SN/ANSGigE::doRxDmaWrite()
1106854SN/A{
1107854SN/A    assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
1108854SN/A    rxDmaState = dmaWriting;
1109854SN/A
111010913SN/A    if (dmaPending() || drainState() != DrainState::Running)
11112566SN/A        rxDmaState = dmaWriteWaiting;
11122566SN/A    else
11132566SN/A        dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData);
1114854SN/A    return true;
1115854SN/A}
1116854SN/A
1117854SN/Avoid
1118879SN/ANSGigE::rxDmaWriteDone()
1119854SN/A{
1120854SN/A    assert(rxDmaState == dmaWriting);
11212566SN/A    rxDmaState = dmaIdle;
11222566SN/A
11232566SN/A    DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
11242566SN/A            rxDmaAddr, rxDmaLen);
11252566SN/A    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1126854SN/A
1127854SN/A    // If the transmit state machine has a pending DMA, let it go first
1128854SN/A    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1129854SN/A        txKick();
1130854SN/A
1131854SN/A    rxKick();
1132837SN/A}
1133837SN/A
1134837SN/Avoid
1135879SN/ANSGigE::rxKick()
1136837SN/A{
11371909SN/A    bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
11381909SN/A
11391909SN/A    DPRINTF(EthernetSM,
11401909SN/A            "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n",
11411909SN/A            NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32);
11421909SN/A
11431909SN/A    Addr link, bufptr;
11441909SN/A    uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts;
11451909SN/A    uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts;
1146837SN/A
11471801SN/A  next:
11489417SN/A    if (rxKickTick > curTick()) {
11499417SN/A        DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
11509417SN/A                rxKickTick);
11511801SN/A
11529417SN/A        goto exit;
11539417SN/A    }
11541801SN/A
11559417SN/A    // Go to the next state machine clock tick.
11569417SN/A    rxKickTick = clockEdge(Cycles(1));
1157837SN/A
1158854SN/A    switch(rxDmaState) {
1159854SN/A      case dmaReadWaiting:
1160854SN/A        if (doRxDmaRead())
1161854SN/A            goto exit;
1162854SN/A        break;
1163854SN/A      case dmaWriteWaiting:
1164854SN/A        if (doRxDmaWrite())
1165854SN/A            goto exit;
1166854SN/A        break;
1167854SN/A      default:
1168854SN/A        break;
1169854SN/A    }
1170837SN/A
11711909SN/A    link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link;
11721909SN/A    bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr;
11731909SN/A
1174855SN/A    // see state machine from spec for details
11751027SN/A    // the way this works is, if you finish work on one state and can
11761027SN/A    // go directly to another, you do that through jumping to the
11771027SN/A    // label "next".  however, if you have intermediate work, like DMA
11781027SN/A    // so that you can't go to the next state yet, you go to exit and
11791027SN/A    // exit the loop.  however, when the DMA is done it will trigger
11801027SN/A    // an event and come back to this loop.
1181854SN/A    switch (rxState) {
1182854SN/A      case rxIdle:
11831035SN/A        if (!rxEnable) {
1184927SN/A            DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");
1185854SN/A            goto exit;
1186854SN/A        }
1187837SN/A
1188854SN/A        if (CRDD) {
1189854SN/A            rxState = rxDescRefr;
1190837SN/A
1191854SN/A            rxDmaAddr = regs.rxdp & 0x3fffffff;
11921909SN/A            rxDmaData =
11931909SN/A                is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link;
11941909SN/A            rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link);
1195854SN/A            rxDmaFree = dmaDescFree;
1196854SN/A
1197961SN/A            descDmaReads++;
1198961SN/A            descDmaRdBytes += rxDmaLen;
1199961SN/A
1200854SN/A            if (doRxDmaRead())
1201854SN/A                goto exit;
1202837SN/A        } else {
1203837SN/A            rxState = rxDescRead;
1204854SN/A
1205854SN/A            rxDmaAddr = regs.rxdp & 0x3fffffff;
12061909SN/A            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
12071909SN/A            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1208854SN/A            rxDmaFree = dmaDescFree;
1209854SN/A
1210961SN/A            descDmaReads++;
1211961SN/A            descDmaRdBytes += rxDmaLen;
1212961SN/A
1213854SN/A            if (doRxDmaRead())
1214854SN/A                goto exit;
1215837SN/A        }
1216854SN/A        break;
1217854SN/A
1218854SN/A      case rxDescRefr:
1219854SN/A        if (rxDmaState != dmaIdle)
1220854SN/A            goto exit;
1221854SN/A
1222854SN/A        rxState = rxAdvance;
1223854SN/A        break;
1224854SN/A
1225854SN/A     case rxDescRead:
1226854SN/A        if (rxDmaState != dmaIdle)
1227854SN/A            goto exit;
1228854SN/A
12291909SN/A        DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n",
12301036SN/A                regs.rxdp & 0x3fffffff);
12311036SN/A        DPRINTF(EthernetDesc,
12321909SN/A                "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
12331909SN/A                link, bufptr, cmdsts, extsts);
12341909SN/A
12351909SN/A        if (cmdsts & CMDSTS_OWN) {
12361035SN/A            devIntrPost(ISR_RXIDLE);
1237837SN/A            rxState = rxIdle;
12381035SN/A            goto exit;
1239837SN/A        } else {
1240837SN/A            rxState = rxFifoBlock;
12411909SN/A            rxFragPtr = bufptr;
12421909SN/A            rxDescCnt = cmdsts & CMDSTS_LEN_MASK;
1243854SN/A        }
1244854SN/A        break;
1245837SN/A
1246854SN/A      case rxFifoBlock:
1247854SN/A        if (!rxPacket) {
1248854SN/A            /**
1249854SN/A             * @todo in reality, we should be able to start processing
1250854SN/A             * the packet as it arrives, and not have to wait for the
1251854SN/A             * full packet ot be in the receive fifo.
1252854SN/A             */
1253854SN/A            if (rxFifo.empty())
1254854SN/A                goto exit;
1255854SN/A
12561036SN/A            DPRINTF(EthernetSM, "****processing receive of new packet****\n");
1257927SN/A
1258854SN/A            // If we don't have a packet, grab a new one from the fifo.
1259854SN/A            rxPacket = rxFifo.front();
1260854SN/A            rxPktBytes = rxPacket->length;
1261854SN/A            rxPacketBufPtr = rxPacket->data;
1262854SN/A
12631011SN/A#if TRACING_ON
1264927SN/A            if (DTRACE(Ethernet)) {
12651114SN/A                IpPtr ip(rxPacket);
12661078SN/A                if (ip) {
12671078SN/A                    DPRINTF(Ethernet, "ID is %d\n", ip->id());
12681114SN/A                    TcpPtr tcp(ip);
12691078SN/A                    if (tcp) {
12701561SN/A                        DPRINTF(Ethernet,
12711561SN/A                                "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
12721561SN/A                                tcp->sport(), tcp->dport(), tcp->seq(),
12731561SN/A                                tcp->ack());
1274927SN/A                    }
1275927SN/A                }
1276927SN/A            }
12771011SN/A#endif
1278927SN/A
1279854SN/A            // sanity check - i think the driver behaves like this
1280854SN/A            assert(rxDescCnt >= rxPktBytes);
12811154SN/A            rxFifo.pop();
1282837SN/A        }
1283837SN/A
1284837SN/A
12851027SN/A        // dont' need the && rxDescCnt > 0 if driver sanity check
12861027SN/A        // above holds
1287854SN/A        if (rxPktBytes > 0) {
1288854SN/A            rxState = rxFragWrite;
12891027SN/A            // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
12901027SN/A            // check holds
1291854SN/A            rxXferLen = rxPktBytes;
1292854SN/A
1293854SN/A            rxDmaAddr = rxFragPtr & 0x3fffffff;
1294854SN/A            rxDmaData = rxPacketBufPtr;
1295854SN/A            rxDmaLen = rxXferLen;
1296854SN/A            rxDmaFree = dmaDataFree;
1297854SN/A
1298854SN/A            if (doRxDmaWrite())
1299854SN/A                goto exit;
1300854SN/A
1301837SN/A        } else {
1302854SN/A            rxState = rxDescWrite;
1303837SN/A
1304854SN/A            //if (rxPktBytes == 0) {  /* packet is done */
1305854SN/A            assert(rxPktBytes == 0);
1306927SN/A            DPRINTF(EthernetSM, "done with receiving packet\n");
1307837SN/A
13081909SN/A            cmdsts |= CMDSTS_OWN;
13091909SN/A            cmdsts &= ~CMDSTS_MORE;
13101909SN/A            cmdsts |= CMDSTS_OK;
13111909SN/A            cmdsts &= 0xffff0000;
13121909SN/A            cmdsts += rxPacket->length;   //i.e. set CMDSTS_SIZE
1313837SN/A
1314854SN/A#if 0
13151027SN/A            /*
13161027SN/A             * all the driver uses these are for its own stats keeping
13171027SN/A             * which we don't care about, aren't necessary for
13181027SN/A             * functionality and doing this would just slow us down.
13191027SN/A             * if they end up using this in a later version for
13201027SN/A             * functional purposes, just undef
13211027SN/A             */
1322837SN/A            if (rxFilterEnable) {
13231909SN/A                cmdsts &= ~CMDSTS_DEST_MASK;
13241114SN/A                const EthAddr &dst = rxFifoFront()->dst();
13251114SN/A                if (dst->unicast())
13261909SN/A                    cmdsts |= CMDSTS_DEST_SELF;
13271114SN/A                if (dst->multicast())
13281909SN/A                    cmdsts |= CMDSTS_DEST_MULTI;
13291114SN/A                if (dst->broadcast())
13301909SN/A                    cmdsts |= CMDSTS_DEST_MASK;
1331837SN/A            }
1332854SN/A#endif
1333837SN/A
13341114SN/A            IpPtr ip(rxPacket);
13351114SN/A            if (extstsEnable && ip) {
13361909SN/A                extsts |= EXTSTS_IPPKT;
13371078SN/A                rxIpChecksums++;
13381114SN/A                if (cksum(ip) != 0) {
1339927SN/A                    DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
13401909SN/A                    extsts |= EXTSTS_IPERR;
1341927SN/A                }
13421114SN/A                TcpPtr tcp(ip);
13431114SN/A                UdpPtr udp(ip);
13441114SN/A                if (tcp) {
13451909SN/A                    extsts |= EXTSTS_TCPPKT;
13461078SN/A                    rxTcpChecksums++;
13471114SN/A                    if (cksum(tcp) != 0) {
1348927SN/A                        DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
13491909SN/A                        extsts |= EXTSTS_TCPERR;
1350961SN/A
1351927SN/A                    }
13521114SN/A                } else if (udp) {
13531909SN/A                    extsts |= EXTSTS_UDPPKT;
13541078SN/A                    rxUdpChecksums++;
13551114SN/A                    if (cksum(udp) != 0) {
1356927SN/A                        DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
13571909SN/A                        extsts |= EXTSTS_UDPERR;
1358927SN/A                    }
1359837SN/A                }
1360837SN/A            }
1361881SN/A            rxPacket = 0;
1362881SN/A
13631027SN/A            /*
13641027SN/A             * the driver seems to always receive into desc buffers
13651027SN/A             * of size 1514, so you never have a pkt that is split
13661027SN/A             * into multiple descriptors on the receive side, so
13671027SN/A             * i don't implement that case, hence the assert above.
13681027SN/A             */
13691027SN/A
13701027SN/A            DPRINTF(EthernetDesc,
13711909SN/A                    "rxDesc: addr=%08x writeback cmdsts extsts\n",
13721036SN/A                    regs.rxdp & 0x3fffffff);
13731036SN/A            DPRINTF(EthernetDesc,
13741909SN/A                    "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
13751909SN/A                    link, bufptr, cmdsts, extsts);
13761909SN/A
13771909SN/A            rxDmaAddr = regs.rxdp & 0x3fffffff;
13781909SN/A            rxDmaData = &cmdsts;
13791909SN/A            if (is64bit) {
13801909SN/A                rxDmaAddr += offsetof(ns_desc64, cmdsts);
13811909SN/A                rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts);
13821909SN/A            } else {
13831909SN/A                rxDmaAddr += offsetof(ns_desc32, cmdsts);
13841909SN/A                rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts);
13851909SN/A            }
1386854SN/A            rxDmaFree = dmaDescFree;
1387854SN/A
1388961SN/A            descDmaWrites++;
1389961SN/A            descDmaWrBytes += rxDmaLen;
1390961SN/A
1391854SN/A            if (doRxDmaWrite())
1392854SN/A                goto exit;
1393837SN/A        }
1394854SN/A        break;
1395837SN/A
1396854SN/A      case rxFragWrite:
1397854SN/A        if (rxDmaState != dmaIdle)
1398854SN/A            goto exit;
1399854SN/A
1400854SN/A        rxPacketBufPtr += rxXferLen;
1401854SN/A        rxFragPtr += rxXferLen;
1402854SN/A        rxPktBytes -= rxXferLen;
1403854SN/A
1404854SN/A        rxState = rxFifoBlock;
1405854SN/A        break;
1406854SN/A
1407854SN/A      case rxDescWrite:
1408854SN/A        if (rxDmaState != dmaIdle)
1409854SN/A            goto exit;
1410854SN/A
14111909SN/A        assert(cmdsts & CMDSTS_OWN);
1412854SN/A
1413854SN/A        assert(rxPacket == 0);
1414854SN/A        devIntrPost(ISR_RXOK);
1415854SN/A
14161909SN/A        if (cmdsts & CMDSTS_INTR)
1417854SN/A            devIntrPost(ISR_RXDESC);
1418854SN/A
14191035SN/A        if (!rxEnable) {
1420927SN/A            DPRINTF(EthernetSM, "Halting the RX state machine\n");
1421854SN/A            rxState = rxIdle;
14221035SN/A            goto exit;
1423854SN/A        } else
1424854SN/A            rxState = rxAdvance;
1425854SN/A        break;
1426854SN/A
1427854SN/A      case rxAdvance:
14281909SN/A        if (link == 0) {
14291035SN/A            devIntrPost(ISR_RXIDLE);
1430854SN/A            rxState = rxIdle;
14311035SN/A            CRDD = true;
14321035SN/A            goto exit;
1433854SN/A        } else {
14341893SN/A            if (rxDmaState != dmaIdle)
14351893SN/A                goto exit;
1436854SN/A            rxState = rxDescRead;
14371909SN/A            regs.rxdp = link;
1438854SN/A            CRDD = false;
1439854SN/A
1440854SN/A            rxDmaAddr = regs.rxdp & 0x3fffffff;
14411909SN/A            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
14421909SN/A            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1443854SN/A            rxDmaFree = dmaDescFree;
1444854SN/A
1445854SN/A            if (doRxDmaRead())
1446854SN/A                goto exit;
1447854SN/A        }
1448854SN/A        break;
1449854SN/A
1450854SN/A      default:
1451854SN/A        panic("Invalid rxState!");
1452837SN/A    }
1453837SN/A
14541036SN/A    DPRINTF(EthernetSM, "entering next rxState=%s\n",
1455854SN/A            NsRxStateStrings[rxState]);
1456854SN/A    goto next;
1457837SN/A
1458854SN/A  exit:
1459854SN/A    /**
1460854SN/A     * @todo do we want to schedule a future kick?
1461854SN/A     */
14621036SN/A    DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
1463854SN/A            NsRxStateStrings[rxState]);
14641801SN/A
14659417SN/A    if (!rxKickEvent.scheduled())
14665606SN/A        schedule(rxKickEvent, rxKickTick);
1467837SN/A}
1468837SN/A
1469837SN/Avoid
1470879SN/ANSGigE::transmit()
1471837SN/A{
1472837SN/A    if (txFifo.empty()) {
1473837SN/A        DPRINTF(Ethernet, "nothing to transmit\n");
1474837SN/A        return;
1475837SN/A    }
1476837SN/A
14771036SN/A    DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",
14781154SN/A            txFifo.size());
1479927SN/A    if (interface->sendPacket(txFifo.front())) {
14801011SN/A#if TRACING_ON
1481927SN/A        if (DTRACE(Ethernet)) {
14821114SN/A            IpPtr ip(txFifo.front());
14831078SN/A            if (ip) {
14841078SN/A                DPRINTF(Ethernet, "ID is %d\n", ip->id());
14851114SN/A                TcpPtr tcp(ip);
14861078SN/A                if (tcp) {
14871561SN/A                    DPRINTF(Ethernet,
14881561SN/A                            "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
14891909SN/A                            tcp->sport(), tcp->dport(), tcp->seq(),
14901909SN/A                            tcp->ack());
1491927SN/A                }
1492927SN/A            }
1493927SN/A        }
14941011SN/A#endif
1495927SN/A
14961561SN/A        DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length);
1497837SN/A        txBytes += txFifo.front()->length;
1498837SN/A        txPackets++;
1499837SN/A
15001027SN/A        DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
15011154SN/A                txFifo.avail());
15021154SN/A        txFifo.pop();
1503837SN/A
15041027SN/A        /*
15051027SN/A         * normally do a writeback of the descriptor here, and ONLY
15061027SN/A         * after that is done, send this interrupt.  but since our
15071027SN/A         * stuff never actually fails, just do this interrupt here,
15081027SN/A         * otherwise the code has to stray from this nice format.
15091027SN/A         * besides, it's functionally the same.
15101027SN/A         */
1511854SN/A        devIntrPost(ISR_TXOK);
15121027SN/A    }
1513854SN/A
1514854SN/A   if (!txFifo.empty() && !txEvent.scheduled()) {
1515854SN/A       DPRINTF(Ethernet, "reschedule transmit\n");
15167823SN/A       schedule(txEvent, curTick() + retryTime);
1517854SN/A   }
1518854SN/A}
1519854SN/A
1520854SN/Abool
1521879SN/ANSGigE::doTxDmaRead()
1522854SN/A{
1523854SN/A    assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
1524854SN/A    txDmaState = dmaReading;
1525854SN/A
152610913SN/A    if (dmaPending() || drainState() != DrainState::Running)
15272566SN/A        txDmaState = dmaReadWaiting;
15282566SN/A    else
15292566SN/A        dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData);
15302566SN/A
1531854SN/A    return true;
1532854SN/A}
1533837SN/A
1534854SN/Avoid
1535879SN/ANSGigE::txDmaReadDone()
1536854SN/A{
1537854SN/A    assert(txDmaState == dmaReading);
15382566SN/A    txDmaState = dmaIdle;
15392566SN/A
15402566SN/A    DPRINTF(EthernetDMA, "tx dma read  paddr=%#x len=%d\n",
15412566SN/A            txDmaAddr, txDmaLen);
15422566SN/A    DDUMP(EthernetDMA, txDmaData, txDmaLen);
1543837SN/A
1544854SN/A    // If the receive state machine  has a pending DMA, let it go first
1545854SN/A    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1546854SN/A        rxKick();
1547837SN/A
1548854SN/A    txKick();
1549854SN/A}
1550837SN/A
1551854SN/Abool
1552879SN/ANSGigE::doTxDmaWrite()
1553854SN/A{
1554854SN/A    assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
1555854SN/A    txDmaState = dmaWriting;
1556854SN/A
155710913SN/A    if (dmaPending() || drainState() != DrainState::Running)
15582566SN/A        txDmaState = dmaWriteWaiting;
15592566SN/A    else
15602566SN/A        dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData);
1561854SN/A    return true;
1562854SN/A}
1563854SN/A
1564854SN/Avoid
1565879SN/ANSGigE::txDmaWriteDone()
1566854SN/A{
1567854SN/A    assert(txDmaState == dmaWriting);
15682566SN/A    txDmaState = dmaIdle;
15692566SN/A
15702566SN/A    DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n",
15712566SN/A            txDmaAddr, txDmaLen);
15722566SN/A    DDUMP(EthernetDMA, txDmaData, txDmaLen);
1573854SN/A
1574854SN/A    // If the receive state machine  has a pending DMA, let it go first
1575854SN/A    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1576854SN/A        rxKick();
1577854SN/A
1578854SN/A    txKick();
1579837SN/A}
1580837SN/A
1581837SN/Avoid
1582879SN/ANSGigE::txKick()
1583837SN/A{
15841909SN/A    bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
15851909SN/A
15861909SN/A    DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n",
15871909SN/A            NsTxStateStrings[txState], is64bit ? 64 : 32);
15881909SN/A
15891909SN/A    Addr link, bufptr;
15901909SN/A    uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts;
15911909SN/A    uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts;
1592927SN/A
15931801SN/A  next:
15949417SN/A    if (txKickTick > curTick()) {
15959417SN/A        DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
15969417SN/A                txKickTick);
15979417SN/A        goto exit;
15989417SN/A    }
15991801SN/A
16009417SN/A    // Go to the next state machine clock tick.
16019417SN/A    txKickTick = clockEdge(Cycles(1));
1602837SN/A
1603854SN/A    switch(txDmaState) {
1604854SN/A      case dmaReadWaiting:
1605854SN/A        if (doTxDmaRead())
1606854SN/A            goto exit;
1607854SN/A        break;
1608854SN/A      case dmaWriteWaiting:
1609854SN/A        if (doTxDmaWrite())
1610854SN/A            goto exit;
1611854SN/A        break;
1612854SN/A      default:
1613854SN/A        break;
1614854SN/A    }
1615837SN/A
16161909SN/A    link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link;
16171909SN/A    bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr;
1618854SN/A    switch (txState) {
1619854SN/A      case txIdle:
16201035SN/A        if (!txEnable) {
1621927SN/A            DPRINTF(EthernetSM, "Transmit disabled.  Nothing to do.\n");
1622854SN/A            goto exit;
1623854SN/A        }
1624837SN/A
1625854SN/A        if (CTDD) {
1626854SN/A            txState = txDescRefr;
1627837SN/A
1628881SN/A            txDmaAddr = regs.txdp & 0x3fffffff;
16291909SN/A            txDmaData =
16301909SN/A                is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link;
16311909SN/A            txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link);
1632854SN/A            txDmaFree = dmaDescFree;
1633837SN/A
1634961SN/A            descDmaReads++;
1635961SN/A            descDmaRdBytes += txDmaLen;
1636961SN/A
1637854SN/A            if (doTxDmaRead())
1638854SN/A                goto exit;
1639854SN/A
1640854SN/A        } else {
1641854SN/A            txState = txDescRead;
1642854SN/A
1643854SN/A            txDmaAddr = regs.txdp & 0x3fffffff;
16441909SN/A            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
16451909SN/A            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
1646854SN/A            txDmaFree = dmaDescFree;
1647854SN/A
1648961SN/A            descDmaReads++;
1649961SN/A            descDmaRdBytes += txDmaLen;
1650961SN/A
1651854SN/A            if (doTxDmaRead())
1652854SN/A                goto exit;
1653837SN/A        }
1654854SN/A        break;
1655837SN/A
1656854SN/A      case txDescRefr:
1657854SN/A        if (txDmaState != dmaIdle)
1658854SN/A            goto exit;
1659854SN/A
1660854SN/A        txState = txAdvance;
1661854SN/A        break;
1662854SN/A
1663854SN/A      case txDescRead:
1664854SN/A        if (txDmaState != dmaIdle)
1665854SN/A            goto exit;
1666854SN/A
16671909SN/A        DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n",
16681801SN/A                regs.txdp & 0x3fffffff);
1669927SN/A        DPRINTF(EthernetDesc,
16701909SN/A                "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n",
16711909SN/A                link, bufptr, cmdsts, extsts);
16721909SN/A
16731909SN/A        if (cmdsts & CMDSTS_OWN) {
1674854SN/A            txState = txFifoBlock;
16751909SN/A            txFragPtr = bufptr;
16761909SN/A            txDescCnt = cmdsts & CMDSTS_LEN_MASK;
1677854SN/A        } else {
16781035SN/A            devIntrPost(ISR_TXIDLE);
1679854SN/A            txState = txIdle;
16801035SN/A            goto exit;
1681854SN/A        }
1682854SN/A        break;
1683854SN/A
1684854SN/A      case txFifoBlock:
1685854SN/A        if (!txPacket) {
16861036SN/A            DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
168710469SN/A            txPacket = make_shared<EthPacketData>(16384);
1688854SN/A            txPacketBufPtr = txPacket->data;
1689854SN/A        }
1690854SN/A
1691854SN/A        if (txDescCnt == 0) {
1692927SN/A            DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");
16931909SN/A            if (cmdsts & CMDSTS_MORE) {
1694927SN/A                DPRINTF(EthernetSM, "there are more descriptors to come\n");
1695854SN/A                txState = txDescWrite;
1696854SN/A
16971909SN/A                cmdsts &= ~CMDSTS_OWN;
16981909SN/A
16991909SN/A                txDmaAddr = regs.txdp & 0x3fffffff;
17001909SN/A                txDmaData = &cmdsts;
17011909SN/A                if (is64bit) {
17021909SN/A                    txDmaAddr += offsetof(ns_desc64, cmdsts);
17031909SN/A                    txDmaLen = sizeof(txDesc64.cmdsts);
17041909SN/A                } else {
17051909SN/A                    txDmaAddr += offsetof(ns_desc32, cmdsts);
17061909SN/A                    txDmaLen = sizeof(txDesc32.cmdsts);
17071909SN/A                }
1708854SN/A                txDmaFree = dmaDescFree;
1709854SN/A
1710854SN/A                if (doTxDmaWrite())
1711854SN/A                    goto exit;
1712854SN/A
1713854SN/A            } else { /* this packet is totally done */
1714927SN/A                DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
1715854SN/A                /* deal with the the packet that just finished */
1716854SN/A                if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
17171114SN/A                    IpPtr ip(txPacket);
17181909SN/A                    if (extsts & EXTSTS_UDPPKT) {
17191114SN/A                        UdpPtr udp(ip);
17205484SN/A                        if (udp) {
17215484SN/A                            udp->sum(0);
17225484SN/A                            udp->sum(cksum(udp));
17235484SN/A                            txUdpChecksums++;
17245484SN/A                        } else {
17258231SN/A                            Debug::breakpoint();
17265484SN/A                            warn_once("UDPPKT set, but not UDP!\n");
17275484SN/A                        }
17281909SN/A                    } else if (extsts & EXTSTS_TCPPKT) {
17291114SN/A                        TcpPtr tcp(ip);
17305484SN/A                        if (tcp) {
17315484SN/A                            tcp->sum(0);
17325484SN/A                            tcp->sum(cksum(tcp));
17335484SN/A                            txTcpChecksums++;
17345484SN/A                        } else {
17355484SN/A                            warn_once("TCPPKT set, but not UDP!\n");
17365484SN/A                        }
1737944SN/A                    }
17381909SN/A                    if (extsts & EXTSTS_IPPKT) {
17395484SN/A                        if (ip) {
17405484SN/A                            ip->sum(0);
17415484SN/A                            ip->sum(cksum(ip));
17425484SN/A                            txIpChecksums++;
17435484SN/A                        } else {
17445484SN/A                            warn_once("IPPKT set, but not UDP!\n");
17455484SN/A                        }
1746854SN/A                    }
1747854SN/A                }
1748854SN/A
174911701Smichael.lebeane@amd.com                txPacket->simLength = txPacketBufPtr - txPacket->data;
1750854SN/A                txPacket->length = txPacketBufPtr - txPacket->data;
17511027SN/A                // this is just because the receive can't handle a
17521027SN/A                // packet bigger want to make sure
17531909SN/A                if (txPacket->length > 1514)
17541909SN/A                    panic("transmit packet too large, %s > 1514\n",
17551909SN/A                          txPacket->length);
17561909SN/A
17571205SN/A#ifndef NDEBUG
17581205SN/A                bool success =
17591205SN/A#endif
17601205SN/A                    txFifo.push(txPacket);
17611205SN/A                assert(success);
1762854SN/A
17631027SN/A                /*
17641027SN/A                 * this following section is not tqo spec, but
17651027SN/A                 * functionally shouldn't be any different.  normally,
17661027SN/A                 * the chip will wait til the transmit has occurred
17671027SN/A                 * before writing back the descriptor because it has
17681027SN/A                 * to wait to see that it was successfully transmitted
17691027SN/A                 * to decide whether to set CMDSTS_OK or not.
17701027SN/A                 * however, in the simulator since it is always
17711027SN/A                 * successfully transmitted, and writing it exactly to
17721027SN/A                 * spec would complicate the code, we just do it here
17731027SN/A                 */
1774927SN/A
17751909SN/A                cmdsts &= ~CMDSTS_OWN;
17761909SN/A                cmdsts |= CMDSTS_OK;
1777854SN/A
1778927SN/A                DPRINTF(EthernetDesc,
17791036SN/A                        "txDesc writeback: cmdsts=%08x extsts=%08x\n",
17801909SN/A                        cmdsts, extsts);
17811909SN/A
1782854SN/A                txDmaFree = dmaDescFree;
17831909SN/A                txDmaAddr = regs.txdp & 0x3fffffff;
17841909SN/A                txDmaData = &cmdsts;
17851909SN/A                if (is64bit) {
17861909SN/A                    txDmaAddr += offsetof(ns_desc64, cmdsts);
17871909SN/A                    txDmaLen =
17881909SN/A                        sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts);
17891909SN/A                } else {
17901909SN/A                    txDmaAddr += offsetof(ns_desc32, cmdsts);
17911909SN/A                    txDmaLen =
17921909SN/A                        sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts);
17931909SN/A                }
1794854SN/A
1795961SN/A                descDmaWrites++;
1796961SN/A                descDmaWrBytes += txDmaLen;
1797961SN/A
1798927SN/A                transmit();
1799854SN/A                txPacket = 0;
1800854SN/A
18011035SN/A                if (!txEnable) {
1802927SN/A                    DPRINTF(EthernetSM, "halting TX state machine\n");
1803854SN/A                    txState = txIdle;
18041035SN/A                    goto exit;
1805854SN/A                } else
1806854SN/A                    txState = txAdvance;
1807986SN/A
1808986SN/A                if (doTxDmaWrite())
1809986SN/A                    goto exit;
1810854SN/A            }
1811854SN/A        } else {
1812927SN/A            DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
18131154SN/A            if (!txFifo.full()) {
1814992SN/A                txState = txFragRead;
1815992SN/A
18161027SN/A                /*
18171027SN/A                 * The number of bytes transferred is either whatever
18181027SN/A                 * is left in the descriptor (txDescCnt), or if there
18191027SN/A                 * is not enough room in the fifo, just whatever room
18201027SN/A                 * is left in the fifo
18211027SN/A                 */
18221154SN/A                txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());
1823992SN/A
1824992SN/A                txDmaAddr = txFragPtr & 0x3fffffff;
1825992SN/A                txDmaData = txPacketBufPtr;
1826992SN/A                txDmaLen = txXferLen;
1827992SN/A                txDmaFree = dmaDataFree;
1828992SN/A
1829992SN/A                if (doTxDmaRead())
1830992SN/A                    goto exit;
1831992SN/A            } else {
1832992SN/A                txState = txFifoBlock;
1833992SN/A                transmit();
1834992SN/A
1835998SN/A                goto exit;
1836992SN/A            }
1837992SN/A
1838854SN/A        }
1839854SN/A        break;
1840854SN/A
1841854SN/A      case txFragRead:
1842854SN/A        if (txDmaState != dmaIdle)
1843854SN/A            goto exit;
1844854SN/A
1845854SN/A        txPacketBufPtr += txXferLen;
1846854SN/A        txFragPtr += txXferLen;
1847854SN/A        txDescCnt -= txXferLen;
18481205SN/A        txFifo.reserve(txXferLen);
1849854SN/A
1850854SN/A        txState = txFifoBlock;
1851854SN/A        break;
1852854SN/A
1853854SN/A      case txDescWrite:
1854854SN/A        if (txDmaState != dmaIdle)
1855854SN/A            goto exit;
1856854SN/A
18571909SN/A        if (cmdsts & CMDSTS_INTR)
1858854SN/A            devIntrPost(ISR_TXDESC);
1859854SN/A
18601801SN/A        if (!txEnable) {
18611801SN/A            DPRINTF(EthernetSM, "halting TX state machine\n");
18621801SN/A            txState = txIdle;
18631801SN/A            goto exit;
18641801SN/A        } else
18651801SN/A            txState = txAdvance;
1866854SN/A        break;
1867854SN/A
1868854SN/A      case txAdvance:
18691909SN/A        if (link == 0) {
18701035SN/A            devIntrPost(ISR_TXIDLE);
1871837SN/A            txState = txIdle;
18721035SN/A            goto exit;
1873837SN/A        } else {
18741893SN/A            if (txDmaState != dmaIdle)
18751893SN/A                goto exit;
1876837SN/A            txState = txDescRead;
18771909SN/A            regs.txdp = link;
1878837SN/A            CTDD = false;
1879854SN/A
18801909SN/A            txDmaAddr = link & 0x3fffffff;
18811909SN/A            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
18821909SN/A            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
1883854SN/A            txDmaFree = dmaDescFree;
1884854SN/A
1885854SN/A            if (doTxDmaRead())
1886854SN/A                goto exit;
1887837SN/A        }
1888854SN/A        break;
1889837SN/A
1890854SN/A      default:
1891854SN/A        panic("invalid state");
1892837SN/A    }
1893837SN/A
18941036SN/A    DPRINTF(EthernetSM, "entering next txState=%s\n",
1895854SN/A            NsTxStateStrings[txState]);
1896854SN/A    goto next;
1897837SN/A
1898854SN/A  exit:
1899854SN/A    /**
1900854SN/A     * @todo do we want to schedule a future kick?
1901854SN/A     */
19021036SN/A    DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
1903854SN/A            NsTxStateStrings[txState]);
19041801SN/A
19059417SN/A    if (!txKickEvent.scheduled())
19065606SN/A        schedule(txKickEvent, txKickTick);
1907837SN/A}
1908837SN/A
19091843SN/A/**
19101843SN/A * Advance the EEPROM state machine
19111843SN/A * Called on rising edge of EEPROM clock bit in MEAR
19121843SN/A */
19131843SN/Avoid
19141843SN/ANSGigE::eepromKick()
19151843SN/A{
19161843SN/A    switch (eepromState) {
19171843SN/A
19181843SN/A      case eepromStart:
19191843SN/A
19201843SN/A        // Wait for start bit
19211843SN/A        if (regs.mear & MEAR_EEDI) {
19221843SN/A            // Set up to get 2 opcode bits
19231843SN/A            eepromState = eepromGetOpcode;
19241843SN/A            eepromBitsToRx = 2;
19251843SN/A            eepromOpcode = 0;
19261843SN/A        }
19271843SN/A        break;
19281843SN/A
19291843SN/A      case eepromGetOpcode:
19301843SN/A        eepromOpcode <<= 1;
19311843SN/A        eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0;
19321843SN/A        --eepromBitsToRx;
19331843SN/A
19341843SN/A        // Done getting opcode
19351843SN/A        if (eepromBitsToRx == 0) {
19361843SN/A            if (eepromOpcode != EEPROM_READ)
19371843SN/A                panic("only EEPROM reads are implemented!");
19381843SN/A
19391843SN/A            // Set up to get address
19401843SN/A            eepromState = eepromGetAddress;
19411843SN/A            eepromBitsToRx = 6;
19421843SN/A            eepromAddress = 0;
19431843SN/A        }
19441843SN/A        break;
19451843SN/A
19461843SN/A      case eepromGetAddress:
19471843SN/A        eepromAddress <<= 1;
19481843SN/A        eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0;
19491843SN/A        --eepromBitsToRx;
19501843SN/A
19511843SN/A        // Done getting address
19521843SN/A        if (eepromBitsToRx == 0) {
19531843SN/A
19541843SN/A            if (eepromAddress >= EEPROM_SIZE)
19551843SN/A                panic("EEPROM read access out of range!");
19561843SN/A
19571843SN/A            switch (eepromAddress) {
19581843SN/A
19591843SN/A              case EEPROM_PMATCH2_ADDR:
19601843SN/A                eepromData = rom.perfectMatch[5];
19611843SN/A                eepromData <<= 8;
19621843SN/A                eepromData += rom.perfectMatch[4];
19631843SN/A                break;
19641843SN/A
19651843SN/A              case EEPROM_PMATCH1_ADDR:
19661843SN/A                eepromData = rom.perfectMatch[3];
19671843SN/A                eepromData <<= 8;
19681843SN/A                eepromData += rom.perfectMatch[2];
19691843SN/A                break;
19701843SN/A
19711843SN/A              case EEPROM_PMATCH0_ADDR:
19721843SN/A                eepromData = rom.perfectMatch[1];
19731843SN/A                eepromData <<= 8;
19741843SN/A                eepromData += rom.perfectMatch[0];
19751843SN/A                break;
19761843SN/A
19771843SN/A              default:
19781843SN/A                panic("FreeBSD driver only uses EEPROM to read PMATCH!");
19791843SN/A            }
19801843SN/A            // Set up to read data
19811843SN/A            eepromState = eepromRead;
19821843SN/A            eepromBitsToRx = 16;
19831843SN/A
19841843SN/A            // Clear data in bit
19851843SN/A            regs.mear &= ~MEAR_EEDI;
19861843SN/A        }
19871843SN/A        break;
19881843SN/A
19891843SN/A      case eepromRead:
19901843SN/A        // Clear Data Out bit
19911843SN/A        regs.mear &= ~MEAR_EEDO;
19921843SN/A        // Set bit to value of current EEPROM bit
19931843SN/A        regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0;
19941843SN/A
19951843SN/A        eepromData <<= 1;
19961843SN/A        --eepromBitsToRx;
19971843SN/A
19981843SN/A        // All done
19991843SN/A        if (eepromBitsToRx == 0) {
20001843SN/A            eepromState = eepromStart;
20011843SN/A        }
20021843SN/A        break;
20031843SN/A
20041843SN/A      default:
20051843SN/A        panic("invalid EEPROM state");
20061843SN/A    }
20071843SN/A
20081843SN/A}
20091843SN/A
2010837SN/Avoid
2011879SN/ANSGigE::transferDone()
2012837SN/A{
20131036SN/A    if (txFifo.empty()) {
20141036SN/A        DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
2015837SN/A        return;
20161036SN/A    }
20171036SN/A
20181036SN/A    DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
2019837SN/A
20209417SN/A    reschedule(txEvent, clockEdge(Cycles(1)), true);
2021837SN/A}
2022837SN/A
2023837SN/Abool
20242566SN/ANSGigE::rxFilter(const EthPacketPtr &packet)
2025837SN/A{
20261114SN/A    EthPtr eth = packet;
2027837SN/A    bool drop = true;
2028837SN/A    string type;
2029837SN/A
20301114SN/A    const EthAddr &dst = eth->dst();
20311114SN/A    if (dst.unicast()) {
2032837SN/A        // If we're accepting all unicast addresses
2033837SN/A        if (acceptUnicast)
2034837SN/A            drop = false;
2035837SN/A
2036837SN/A        // If we make a perfect match
20371114SN/A        if (acceptPerfect && dst == rom.perfectMatch)
2038837SN/A            drop = false;
2039837SN/A
20401078SN/A        if (acceptArp && eth->type() == ETH_TYPE_ARP)
2041837SN/A            drop = false;
2042837SN/A
20431114SN/A    } else if (dst.broadcast()) {
2044837SN/A        // if we're accepting broadcasts
2045837SN/A        if (acceptBroadcast)
2046837SN/A            drop = false;
2047837SN/A
20481114SN/A    } else if (dst.multicast()) {
2049837SN/A        // if we're accepting all multicasts
2050837SN/A        if (acceptMulticast)
2051837SN/A            drop = false;
2052837SN/A
20531843SN/A        // Multicast hashing faked - all packets accepted
20541843SN/A        if (multicastHashEnable)
20551843SN/A            drop = false;
2056837SN/A    }
2057837SN/A
2058837SN/A    if (drop) {
2059837SN/A        DPRINTF(Ethernet, "rxFilter drop\n");
2060837SN/A        DDUMP(EthernetData, packet->data, packet->length);
2061837SN/A    }
2062837SN/A
2063837SN/A    return drop;
2064837SN/A}
2065837SN/A
2066837SN/Abool
20672566SN/ANSGigE::recvPacket(EthPacketPtr packet)
2068837SN/A{
2069837SN/A    rxBytes += packet->length;
2070837SN/A    rxPackets++;
2071837SN/A
20721036SN/A    DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n",
20731154SN/A            rxFifo.avail());
2074927SN/A
20751035SN/A    if (!rxEnable) {
2076837SN/A        DPRINTF(Ethernet, "receive disabled...packet dropped\n");
2077837SN/A        return true;
2078837SN/A    }
2079837SN/A
20801843SN/A    if (!rxFilterEnable) {
20811843SN/A        DPRINTF(Ethernet,
20821843SN/A            "receive packet filtering disabled . . . packet dropped\n");
20831843SN/A        return true;
20841843SN/A    }
20851843SN/A
20861843SN/A    if (rxFilter(packet)) {
2087837SN/A        DPRINTF(Ethernet, "packet filtered...dropped\n");
2088837SN/A        return true;
2089837SN/A    }
2090837SN/A
20911154SN/A    if (rxFifo.avail() < packet->length) {
20921561SN/A#if TRACING_ON
20931561SN/A        IpPtr ip(packet);
20941561SN/A        TcpPtr tcp(ip);
20951561SN/A        if (ip) {
20961561SN/A            DPRINTF(Ethernet,
20971561SN/A                    "packet won't fit in receive buffer...pkt ID %d dropped\n",
20981561SN/A                    ip->id());
20991561SN/A            if (tcp) {
21001561SN/A                DPRINTF(Ethernet, "Seq=%d\n", tcp->seq());
21011561SN/A            }
21021561SN/A        }
21031561SN/A#endif
21041263SN/A        droppedPackets++;
2105837SN/A        devIntrPost(ISR_RXORN);
2106837SN/A        return false;
2107837SN/A    }
2108837SN/A
21091154SN/A    rxFifo.push(packet);
2110837SN/A
2111854SN/A    rxKick();
2112837SN/A    return true;
2113837SN/A}
2114837SN/A
21152901SN/A
21162901SN/Avoid
21179342SN/ANSGigE::drainResume()
21182901SN/A{
21199342SN/A    Drainable::drainResume();
21202901SN/A
21212901SN/A    // During drain we could have left the state machines in a waiting state and
21222901SN/A    // they wouldn't get out until some other event occured to kick them.
21232901SN/A    // This way they'll get out immediately
21242901SN/A    txKick();
21252901SN/A    rxKick();
21262901SN/A}
21272901SN/A
21282901SN/A
2129837SN/A//=====================================================================
2130837SN/A//
2131837SN/A//
2132837SN/Avoid
213310905SN/ANSGigE::serialize(CheckpointOut &cp) const
2134837SN/A{
21359807SN/A    // Serialize the PciDevice base class
213610905SN/A    PciDevice::serialize(cp);
2137897SN/A
2138854SN/A    /*
2139854SN/A     * Finalize any DMA events now.
2140854SN/A     */
21412566SN/A    // @todo will mem system save pending dma?
2142837SN/A
2143854SN/A    /*
2144854SN/A     * Serialize the device registers
2145854SN/A     */
2146854SN/A    SERIALIZE_SCALAR(regs.command);
2147854SN/A    SERIALIZE_SCALAR(regs.config);
2148854SN/A    SERIALIZE_SCALAR(regs.mear);
2149854SN/A    SERIALIZE_SCALAR(regs.ptscr);
2150854SN/A    SERIALIZE_SCALAR(regs.isr);
2151854SN/A    SERIALIZE_SCALAR(regs.imr);
2152854SN/A    SERIALIZE_SCALAR(regs.ier);
2153854SN/A    SERIALIZE_SCALAR(regs.ihr);
2154854SN/A    SERIALIZE_SCALAR(regs.txdp);
2155854SN/A    SERIALIZE_SCALAR(regs.txdp_hi);
2156854SN/A    SERIALIZE_SCALAR(regs.txcfg);
2157854SN/A    SERIALIZE_SCALAR(regs.gpior);
2158854SN/A    SERIALIZE_SCALAR(regs.rxdp);
2159854SN/A    SERIALIZE_SCALAR(regs.rxdp_hi);
2160854SN/A    SERIALIZE_SCALAR(regs.rxcfg);
2161854SN/A    SERIALIZE_SCALAR(regs.pqcr);
2162854SN/A    SERIALIZE_SCALAR(regs.wcsr);
2163854SN/A    SERIALIZE_SCALAR(regs.pcr);
2164854SN/A    SERIALIZE_SCALAR(regs.rfcr);
2165854SN/A    SERIALIZE_SCALAR(regs.rfdr);
21661843SN/A    SERIALIZE_SCALAR(regs.brar);
21671843SN/A    SERIALIZE_SCALAR(regs.brdr);
2168854SN/A    SERIALIZE_SCALAR(regs.srr);
2169854SN/A    SERIALIZE_SCALAR(regs.mibc);
2170854SN/A    SERIALIZE_SCALAR(regs.vrcr);
2171854SN/A    SERIALIZE_SCALAR(regs.vtcr);
2172854SN/A    SERIALIZE_SCALAR(regs.vdr);
2173854SN/A    SERIALIZE_SCALAR(regs.ccsr);
2174854SN/A    SERIALIZE_SCALAR(regs.tbicr);
2175854SN/A    SERIALIZE_SCALAR(regs.tbisr);
2176854SN/A    SERIALIZE_SCALAR(regs.tanar);
2177854SN/A    SERIALIZE_SCALAR(regs.tanlpar);
2178854SN/A    SERIALIZE_SCALAR(regs.taner);
2179854SN/A    SERIALIZE_SCALAR(regs.tesr);
2180837SN/A
21811114SN/A    SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
21821843SN/A    SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2183837SN/A
2184927SN/A    SERIALIZE_SCALAR(ioEnable);
2185917SN/A
2186854SN/A    /*
2187915SN/A     * Serialize the data Fifos
2188915SN/A     */
218910905SN/A    rxFifo.serialize("rxFifo", cp);
219010905SN/A    txFifo.serialize("txFifo", cp);
2191915SN/A
2192915SN/A    /*
2193854SN/A     * Serialize the various helper variables
2194854SN/A     */
219510469SN/A    bool txPacketExists = txPacket != nullptr;
2196915SN/A    SERIALIZE_SCALAR(txPacketExists);
2197915SN/A    if (txPacketExists) {
219811701Smichael.lebeane@amd.com        txPacket->simLength = txPacketBufPtr - txPacket->data;
21991337SN/A        txPacket->length = txPacketBufPtr - txPacket->data;
220010905SN/A        txPacket->serialize("txPacket", cp);
2201915SN/A        uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
2202915SN/A        SERIALIZE_SCALAR(txPktBufPtr);
2203915SN/A    }
2204915SN/A
220510469SN/A    bool rxPacketExists = rxPacket != nullptr;
2206915SN/A    SERIALIZE_SCALAR(rxPacketExists);
2207915SN/A    if (rxPacketExists) {
220810905SN/A        rxPacket->serialize("rxPacket", cp);
2209915SN/A        uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
2210915SN/A        SERIALIZE_SCALAR(rxPktBufPtr);
2211915SN/A    }
2212915SN/A
2213854SN/A    SERIALIZE_SCALAR(txXferLen);
2214854SN/A    SERIALIZE_SCALAR(rxXferLen);
2215837SN/A
2216854SN/A    /*
22171909SN/A     * Serialize Cached Descriptors
2218854SN/A     */
22191909SN/A    SERIALIZE_SCALAR(rxDesc64.link);
22201909SN/A    SERIALIZE_SCALAR(rxDesc64.bufptr);
22211909SN/A    SERIALIZE_SCALAR(rxDesc64.cmdsts);
22221909SN/A    SERIALIZE_SCALAR(rxDesc64.extsts);
22231909SN/A    SERIALIZE_SCALAR(txDesc64.link);
22241909SN/A    SERIALIZE_SCALAR(txDesc64.bufptr);
22251909SN/A    SERIALIZE_SCALAR(txDesc64.cmdsts);
22261909SN/A    SERIALIZE_SCALAR(txDesc64.extsts);
22271909SN/A    SERIALIZE_SCALAR(rxDesc32.link);
22281909SN/A    SERIALIZE_SCALAR(rxDesc32.bufptr);
22291909SN/A    SERIALIZE_SCALAR(rxDesc32.cmdsts);
22301909SN/A    SERIALIZE_SCALAR(rxDesc32.extsts);
22311909SN/A    SERIALIZE_SCALAR(txDesc32.link);
22321909SN/A    SERIALIZE_SCALAR(txDesc32.bufptr);
22331909SN/A    SERIALIZE_SCALAR(txDesc32.cmdsts);
22341909SN/A    SERIALIZE_SCALAR(txDesc32.extsts);
22351801SN/A    SERIALIZE_SCALAR(extstsEnable);
2236837SN/A
2237854SN/A    /*
2238854SN/A     * Serialize tx state machine
2239854SN/A     */
2240854SN/A    int txState = this->txState;
2241854SN/A    SERIALIZE_SCALAR(txState);
22421035SN/A    SERIALIZE_SCALAR(txEnable);
2243854SN/A    SERIALIZE_SCALAR(CTDD);
2244854SN/A    SERIALIZE_SCALAR(txFragPtr);
2245854SN/A    SERIALIZE_SCALAR(txDescCnt);
2246854SN/A    int txDmaState = this->txDmaState;
2247854SN/A    SERIALIZE_SCALAR(txDmaState);
22481801SN/A    SERIALIZE_SCALAR(txKickTick);
2249854SN/A
2250854SN/A    /*
2251854SN/A     * Serialize rx state machine
2252854SN/A     */
2253854SN/A    int rxState = this->rxState;
2254854SN/A    SERIALIZE_SCALAR(rxState);
22551035SN/A    SERIALIZE_SCALAR(rxEnable);
2256854SN/A    SERIALIZE_SCALAR(CRDD);
2257854SN/A    SERIALIZE_SCALAR(rxPktBytes);
22581224SN/A    SERIALIZE_SCALAR(rxFragPtr);
2259854SN/A    SERIALIZE_SCALAR(rxDescCnt);
2260854SN/A    int rxDmaState = this->rxDmaState;
2261854SN/A    SERIALIZE_SCALAR(rxDmaState);
22621801SN/A    SERIALIZE_SCALAR(rxKickTick);
2263854SN/A
2264915SN/A    /*
22651843SN/A     * Serialize EEPROM state machine
22661843SN/A     */
22671843SN/A    int eepromState = this->eepromState;
22681843SN/A    SERIALIZE_SCALAR(eepromState);
22691843SN/A    SERIALIZE_SCALAR(eepromClk);
22701843SN/A    SERIALIZE_SCALAR(eepromBitsToRx);
22711843SN/A    SERIALIZE_SCALAR(eepromOpcode);
22721843SN/A    SERIALIZE_SCALAR(eepromAddress);
22731843SN/A    SERIALIZE_SCALAR(eepromData);
22741843SN/A
22751843SN/A    /*
2276854SN/A     * If there's a pending transmit, store the time so we can
2277854SN/A     * reschedule it later
2278854SN/A     */
22797823SN/A    Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick() : 0;
2280854SN/A    SERIALIZE_SCALAR(transmitTick);
2281854SN/A
2282854SN/A    /*
2283915SN/A     * receive address filter settings
2284915SN/A     */
2285915SN/A    SERIALIZE_SCALAR(rxFilterEnable);
2286915SN/A    SERIALIZE_SCALAR(acceptBroadcast);
2287915SN/A    SERIALIZE_SCALAR(acceptMulticast);
2288915SN/A    SERIALIZE_SCALAR(acceptUnicast);
2289915SN/A    SERIALIZE_SCALAR(acceptPerfect);
2290915SN/A    SERIALIZE_SCALAR(acceptArp);
22911843SN/A    SERIALIZE_SCALAR(multicastHashEnable);
2292915SN/A
2293915SN/A    /*
2294854SN/A     * Keep track of pending interrupt status.
2295854SN/A     */
2296854SN/A    SERIALIZE_SCALAR(intrTick);
2297854SN/A    SERIALIZE_SCALAR(cpuPendingIntr);
2298854SN/A    Tick intrEventTick = 0;
2299854SN/A    if (intrEvent)
2300854SN/A        intrEventTick = intrEvent->when();
2301854SN/A    SERIALIZE_SCALAR(intrEventTick);
2302854SN/A
2303837SN/A}
2304837SN/A
2305837SN/Avoid
230610905SN/ANSGigE::unserialize(CheckpointIn &cp)
2307837SN/A{
23089807SN/A    // Unserialize the PciDevice base class
230910905SN/A    PciDevice::unserialize(cp);
2310897SN/A
2311854SN/A    UNSERIALIZE_SCALAR(regs.command);
2312854SN/A    UNSERIALIZE_SCALAR(regs.config);
2313854SN/A    UNSERIALIZE_SCALAR(regs.mear);
2314854SN/A    UNSERIALIZE_SCALAR(regs.ptscr);
2315854SN/A    UNSERIALIZE_SCALAR(regs.isr);
2316854SN/A    UNSERIALIZE_SCALAR(regs.imr);
2317854SN/A    UNSERIALIZE_SCALAR(regs.ier);
2318854SN/A    UNSERIALIZE_SCALAR(regs.ihr);
2319854SN/A    UNSERIALIZE_SCALAR(regs.txdp);
2320854SN/A    UNSERIALIZE_SCALAR(regs.txdp_hi);
2321854SN/A    UNSERIALIZE_SCALAR(regs.txcfg);
2322854SN/A    UNSERIALIZE_SCALAR(regs.gpior);
2323854SN/A    UNSERIALIZE_SCALAR(regs.rxdp);
2324854SN/A    UNSERIALIZE_SCALAR(regs.rxdp_hi);
2325854SN/A    UNSERIALIZE_SCALAR(regs.rxcfg);
2326854SN/A    UNSERIALIZE_SCALAR(regs.pqcr);
2327854SN/A    UNSERIALIZE_SCALAR(regs.wcsr);
2328854SN/A    UNSERIALIZE_SCALAR(regs.pcr);
2329854SN/A    UNSERIALIZE_SCALAR(regs.rfcr);
2330854SN/A    UNSERIALIZE_SCALAR(regs.rfdr);
23311843SN/A    UNSERIALIZE_SCALAR(regs.brar);
23321843SN/A    UNSERIALIZE_SCALAR(regs.brdr);
2333854SN/A    UNSERIALIZE_SCALAR(regs.srr);
2334854SN/A    UNSERIALIZE_SCALAR(regs.mibc);
2335854SN/A    UNSERIALIZE_SCALAR(regs.vrcr);
2336854SN/A    UNSERIALIZE_SCALAR(regs.vtcr);
2337854SN/A    UNSERIALIZE_SCALAR(regs.vdr);
2338854SN/A    UNSERIALIZE_SCALAR(regs.ccsr);
2339854SN/A    UNSERIALIZE_SCALAR(regs.tbicr);
2340854SN/A    UNSERIALIZE_SCALAR(regs.tbisr);
2341854SN/A    UNSERIALIZE_SCALAR(regs.tanar);
2342854SN/A    UNSERIALIZE_SCALAR(regs.tanlpar);
2343854SN/A    UNSERIALIZE_SCALAR(regs.taner);
2344854SN/A    UNSERIALIZE_SCALAR(regs.tesr);
2345837SN/A
23461114SN/A    UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
23471843SN/A    UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2348837SN/A
2349927SN/A    UNSERIALIZE_SCALAR(ioEnable);
2350917SN/A
2351854SN/A    /*
2352915SN/A     * unserialize the data fifos
2353915SN/A     */
235410905SN/A    rxFifo.unserialize("rxFifo", cp);
235510905SN/A    txFifo.unserialize("txFifo", cp);
2356915SN/A
2357915SN/A    /*
2358854SN/A     * unserialize the various helper variables
2359854SN/A     */
2360915SN/A    bool txPacketExists;
2361915SN/A    UNSERIALIZE_SCALAR(txPacketExists);
2362915SN/A    if (txPacketExists) {
236311719Smichael.lebeane@amd.com        txPacket = make_shared<EthPacketData>(16384);
236410905SN/A        txPacket->unserialize("txPacket", cp);
2365915SN/A        uint32_t txPktBufPtr;
2366915SN/A        UNSERIALIZE_SCALAR(txPktBufPtr);
2367915SN/A        txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
2368915SN/A    } else
2369915SN/A        txPacket = 0;
2370915SN/A
2371915SN/A    bool rxPacketExists;
2372915SN/A    UNSERIALIZE_SCALAR(rxPacketExists);
2373915SN/A    rxPacket = 0;
2374915SN/A    if (rxPacketExists) {
237511701Smichael.lebeane@amd.com        rxPacket = make_shared<EthPacketData>();
237610905SN/A        rxPacket->unserialize("rxPacket", cp);
2377915SN/A        uint32_t rxPktBufPtr;
2378915SN/A        UNSERIALIZE_SCALAR(rxPktBufPtr);
2379915SN/A        rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
2380915SN/A    } else
2381915SN/A        rxPacket = 0;
2382915SN/A
2383854SN/A    UNSERIALIZE_SCALAR(txXferLen);
2384854SN/A    UNSERIALIZE_SCALAR(rxXferLen);
2385837SN/A
2386854SN/A    /*
23871909SN/A     * Unserialize Cached Descriptors
2388854SN/A     */
23891909SN/A    UNSERIALIZE_SCALAR(rxDesc64.link);
23901909SN/A    UNSERIALIZE_SCALAR(rxDesc64.bufptr);
23911909SN/A    UNSERIALIZE_SCALAR(rxDesc64.cmdsts);
23921909SN/A    UNSERIALIZE_SCALAR(rxDesc64.extsts);
23931909SN/A    UNSERIALIZE_SCALAR(txDesc64.link);
23941909SN/A    UNSERIALIZE_SCALAR(txDesc64.bufptr);
23951909SN/A    UNSERIALIZE_SCALAR(txDesc64.cmdsts);
23961909SN/A    UNSERIALIZE_SCALAR(txDesc64.extsts);
23971909SN/A    UNSERIALIZE_SCALAR(rxDesc32.link);
23981909SN/A    UNSERIALIZE_SCALAR(rxDesc32.bufptr);
23991909SN/A    UNSERIALIZE_SCALAR(rxDesc32.cmdsts);
24001909SN/A    UNSERIALIZE_SCALAR(rxDesc32.extsts);
24011909SN/A    UNSERIALIZE_SCALAR(txDesc32.link);
24021909SN/A    UNSERIALIZE_SCALAR(txDesc32.bufptr);
24031909SN/A    UNSERIALIZE_SCALAR(txDesc32.cmdsts);
24041909SN/A    UNSERIALIZE_SCALAR(txDesc32.extsts);
24051801SN/A    UNSERIALIZE_SCALAR(extstsEnable);
2406854SN/A
2407854SN/A    /*
2408854SN/A     * unserialize tx state machine
2409854SN/A     */
2410854SN/A    int txState;
2411854SN/A    UNSERIALIZE_SCALAR(txState);
2412854SN/A    this->txState = (TxState) txState;
24131035SN/A    UNSERIALIZE_SCALAR(txEnable);
2414854SN/A    UNSERIALIZE_SCALAR(CTDD);
2415854SN/A    UNSERIALIZE_SCALAR(txFragPtr);
2416854SN/A    UNSERIALIZE_SCALAR(txDescCnt);
2417854SN/A    int txDmaState;
2418854SN/A    UNSERIALIZE_SCALAR(txDmaState);
2419854SN/A    this->txDmaState = (DmaState) txDmaState;
24201801SN/A    UNSERIALIZE_SCALAR(txKickTick);
24211801SN/A    if (txKickTick)
24225606SN/A        schedule(txKickEvent, txKickTick);
2423854SN/A
2424854SN/A    /*
2425854SN/A     * unserialize rx state machine
2426854SN/A     */
2427854SN/A    int rxState;
2428854SN/A    UNSERIALIZE_SCALAR(rxState);
2429854SN/A    this->rxState = (RxState) rxState;
24301035SN/A    UNSERIALIZE_SCALAR(rxEnable);
2431854SN/A    UNSERIALIZE_SCALAR(CRDD);
2432854SN/A    UNSERIALIZE_SCALAR(rxPktBytes);
24331224SN/A    UNSERIALIZE_SCALAR(rxFragPtr);
2434854SN/A    UNSERIALIZE_SCALAR(rxDescCnt);
2435854SN/A    int rxDmaState;
2436854SN/A    UNSERIALIZE_SCALAR(rxDmaState);
2437854SN/A    this->rxDmaState = (DmaState) rxDmaState;
24381801SN/A    UNSERIALIZE_SCALAR(rxKickTick);
24391801SN/A    if (rxKickTick)
24405606SN/A        schedule(rxKickEvent, rxKickTick);
2441854SN/A
24421843SN/A    /*
24431843SN/A     * Unserialize EEPROM state machine
24441843SN/A     */
24451843SN/A    int eepromState;
24461843SN/A    UNSERIALIZE_SCALAR(eepromState);
24471843SN/A    this->eepromState = (EEPROMState) eepromState;
24481843SN/A    UNSERIALIZE_SCALAR(eepromClk);
24491843SN/A    UNSERIALIZE_SCALAR(eepromBitsToRx);
24501843SN/A    UNSERIALIZE_SCALAR(eepromOpcode);
24511843SN/A    UNSERIALIZE_SCALAR(eepromAddress);
24521843SN/A    UNSERIALIZE_SCALAR(eepromData);
24531843SN/A
24541843SN/A    /*
2455915SN/A     * If there's a pending transmit, reschedule it now
2456854SN/A     */
2457854SN/A    Tick transmitTick;
2458854SN/A    UNSERIALIZE_SCALAR(transmitTick);
2459854SN/A    if (transmitTick)
24607823SN/A        schedule(txEvent, curTick() + transmitTick);
2461854SN/A
2462854SN/A    /*
2463915SN/A     * unserialize receive address filter settings
2464915SN/A     */
2465915SN/A    UNSERIALIZE_SCALAR(rxFilterEnable);
2466915SN/A    UNSERIALIZE_SCALAR(acceptBroadcast);
2467915SN/A    UNSERIALIZE_SCALAR(acceptMulticast);
2468915SN/A    UNSERIALIZE_SCALAR(acceptUnicast);
2469915SN/A    UNSERIALIZE_SCALAR(acceptPerfect);
2470915SN/A    UNSERIALIZE_SCALAR(acceptArp);
24711843SN/A    UNSERIALIZE_SCALAR(multicastHashEnable);
2472915SN/A
2473915SN/A    /*
2474854SN/A     * Keep track of pending interrupt status.
2475854SN/A     */
2476854SN/A    UNSERIALIZE_SCALAR(intrTick);
2477854SN/A    UNSERIALIZE_SCALAR(cpuPendingIntr);
2478854SN/A    Tick intrEventTick;
2479854SN/A    UNSERIALIZE_SCALAR(intrEventTick);
2480854SN/A    if (intrEventTick) {
248112087Sspwilson2@wisc.edu        intrEvent = new EventFunctionWrapper([this]{ cpuInterrupt(); },
248212087Sspwilson2@wisc.edu                                             name(), true);
24835606SN/A        schedule(intrEvent, intrEventTick);
2484854SN/A    }
2485854SN/A}
2486927SN/A
24874762SN/ANSGigE *
24884762SN/ANSGigEParams::create()
2489837SN/A{
24904762SN/A    return new NSGigE(this);
2491837SN/A}
2492