ns_gige.cc revision 11701
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),
1144093SN/A      rxDmaReadEvent(this), rxDmaWriteEvent(this),
115854SN/A      txDmaReadEvent(this), txDmaWriteEvent(this),
1161149SN/A      dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free),
1171149SN/A      txDelay(p->tx_delay), rxDelay(p->rx_delay),
1181801SN/A      rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this),
1194093SN/A      txEvent(this), rxFilterEnable(p->rx_filter),
1204093SN/A      acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false),
1211843SN/A      acceptPerfect(false), acceptArp(false), multicastHashEnable(false),
1224093SN/A      intrDelay(p->intr_delay), intrTick(0), cpuPendingIntr(false),
123995SN/A      intrEvent(0), interface(0)
124837SN/A{
125854SN/A
126854SN/A
1274981SN/A    interface = new NSGigEInt(name() + ".int0", this);
1284981SN/A
129837SN/A    regsReset();
1304762SN/A    memcpy(&rom.perfectMatch, p->hardware_address.bytes(), ETH_ADDR_LEN);
1311909SN/A
1321909SN/A    memset(&rxDesc32, 0, sizeof(rxDesc32));
1331909SN/A    memset(&txDesc32, 0, sizeof(txDesc32));
1341909SN/A    memset(&rxDesc64, 0, sizeof(rxDesc64));
1351909SN/A    memset(&txDesc64, 0, sizeof(txDesc64));
136837SN/A}
137837SN/A
138879SN/ANSGigE::~NSGigE()
1399086SN/A{
1409086SN/A    delete interface;
1419086SN/A}
142837SN/A
143855SN/A/**
144855SN/A * This is to write to the PCI general configuration registers
145855SN/A */
1462846SN/ATick
1473349SN/ANSGigE::writeConfig(PacketPtr pkt)
148837SN/A{
1492846SN/A    int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
150837SN/A    if (offset < PCI_DEVICE_SPECIFIC)
1519807SN/A        PciDevice::writeConfig(pkt);
152837SN/A    else
153897SN/A        panic("Device specific PCI config space not implemented!\n");
154897SN/A
155897SN/A    switch (offset) {
1561027SN/A        // seems to work fine without all these PCI settings, but i
1571027SN/A        // put in the IO to double check, an assertion will fail if we
1581027SN/A        // need to properly implement it
159917SN/A      case PCI_COMMAND:
160917SN/A        if (config.data[offset] & PCI_CMD_IOSE)
161927SN/A            ioEnable = true;
162917SN/A        else
163927SN/A            ioEnable = false;
164897SN/A        break;
165897SN/A    }
1664875SN/A
1672846SN/A    return configDelay;
168837SN/A}
169837SN/A
1704981SN/AEtherInt*
1714981SN/ANSGigE::getEthPort(const std::string &if_name, int idx)
1724981SN/A{
1734981SN/A    if (if_name == "interface") {
1744981SN/A       if (interface->getPeer())
1754981SN/A           panic("interface already connected to\n");
1764981SN/A       return interface;
1774981SN/A    }
1784981SN/A    return NULL;
1794981SN/A}
1804981SN/A
181855SN/A/**
182855SN/A * This reads the device registers, which are detailed in the NS83820
183855SN/A * spec sheet
184855SN/A */
1852566SN/ATick
1863349SN/ANSGigE::read(PacketPtr pkt)
187837SN/A{
188927SN/A    assert(ioEnable);
189917SN/A
190855SN/A    //The mask is to give you only the offset into the device register file
1912641SN/A    Addr daddr = pkt->getAddr() & 0xfff;
1922566SN/A    DPRINTF(EthernetPIO, "read  da=%#x pa=%#x size=%d\n",
1932641SN/A            daddr, pkt->getAddr(), pkt->getSize());
194837SN/A
195855SN/A
1961027SN/A    // there are some reserved registers, you can see ns_gige_reg.h and
1971027SN/A    // the spec sheet for details
198854SN/A    if (daddr > LAST && daddr <=  RESERVED) {
199837SN/A        panic("Accessing reserved register");
200854SN/A    } else if (daddr > RESERVED && daddr <= 0x3FC) {
2012846SN/A        return readConfig(pkt);
202854SN/A    } else if (daddr >= MIB_START && daddr <= MIB_END) {
203854SN/A        // don't implement all the MIB's.  hopefully the kernel
204854SN/A        // doesn't actually DEPEND upon their values
205855SN/A        // MIB are just hardware stats keepers
2062630SN/A        pkt->set<uint32_t>(0);
2074870SN/A        pkt->makeAtomicResponse();
2082566SN/A        return pioDelay;
209854SN/A    } else if (daddr > 0x3FC)
210854SN/A        panic("Something is messed up!\n");
211837SN/A
2122641SN/A    assert(pkt->getSize() == sizeof(uint32_t));
2132630SN/A        uint32_t &reg = *pkt->getPtr<uint32_t>();
2142566SN/A        uint16_t rfaddr;
2152566SN/A
2162566SN/A        switch (daddr) {
2172566SN/A          case CR:
2182566SN/A            reg = regs.command;
2192566SN/A            //these are supposed to be cleared on a read
2202566SN/A            reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR);
2212566SN/A            break;
2222566SN/A
2232566SN/A          case CFGR:
2242566SN/A            reg = regs.config;
2252566SN/A            break;
2262566SN/A
2272566SN/A          case MEAR:
2282566SN/A            reg = regs.mear;
2292566SN/A            break;
2302566SN/A
2312566SN/A          case PTSCR:
2322566SN/A            reg = regs.ptscr;
2332566SN/A            break;
2342566SN/A
2352566SN/A          case ISR:
2362566SN/A            reg = regs.isr;
2372566SN/A            devIntrClear(ISR_ALL);
2382566SN/A            break;
2392566SN/A
2402566SN/A          case IMR:
2412566SN/A            reg = regs.imr;
2422566SN/A            break;
2432566SN/A
2442566SN/A          case IER:
2452566SN/A            reg = regs.ier;
2462566SN/A            break;
2472566SN/A
2482566SN/A          case IHR:
2492566SN/A            reg = regs.ihr;
2502566SN/A            break;
2512566SN/A
2522566SN/A          case TXDP:
2532566SN/A            reg = regs.txdp;
2542566SN/A            break;
2552566SN/A
2562566SN/A          case TXDP_HI:
2572566SN/A            reg = regs.txdp_hi;
2582566SN/A            break;
2592566SN/A
2602566SN/A          case TX_CFG:
2612566SN/A            reg = regs.txcfg;
2622566SN/A            break;
2632566SN/A
2642566SN/A          case GPIOR:
2652566SN/A            reg = regs.gpior;
2662566SN/A            break;
2672566SN/A
2682566SN/A          case RXDP:
2692566SN/A            reg = regs.rxdp;
2702566SN/A            break;
2712566SN/A
2722566SN/A          case RXDP_HI:
2732566SN/A            reg = regs.rxdp_hi;
2742566SN/A            break;
2752566SN/A
2762566SN/A          case RX_CFG:
2772566SN/A            reg = regs.rxcfg;
2782566SN/A            break;
2792566SN/A
2802566SN/A          case PQCR:
2812566SN/A            reg = regs.pqcr;
2822566SN/A            break;
2832566SN/A
2842566SN/A          case WCSR:
2852566SN/A            reg = regs.wcsr;
2862566SN/A            break;
2872566SN/A
2882566SN/A          case PCR:
2892566SN/A            reg = regs.pcr;
2902566SN/A            break;
2912566SN/A
2922566SN/A            // see the spec sheet for how RFCR and RFDR work
2932566SN/A            // basically, you write to RFCR to tell the machine
2942566SN/A            // what you want to do next, then you act upon RFDR,
2952566SN/A            // and the device will be prepared b/c of what you
2962566SN/A            // wrote to RFCR
2972566SN/A          case RFCR:
2982566SN/A            reg = regs.rfcr;
2992566SN/A            break;
3002566SN/A
3012566SN/A          case RFDR:
3022566SN/A            rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
3032566SN/A            switch (rfaddr) {
3042566SN/A              // Read from perfect match ROM octets
3052566SN/A              case 0x000:
3062566SN/A                reg = rom.perfectMatch[1];
3072566SN/A                reg = reg << 8;
3082566SN/A                reg += rom.perfectMatch[0];
309837SN/A                break;
3102566SN/A              case 0x002:
3112566SN/A                reg = rom.perfectMatch[3] << 8;
3122566SN/A                reg += rom.perfectMatch[2];
313837SN/A                break;
3142566SN/A              case 0x004:
3152566SN/A                reg = rom.perfectMatch[5] << 8;
3162566SN/A                reg += rom.perfectMatch[4];
317837SN/A                break;
3182566SN/A              default:
3192566SN/A                // Read filter hash table
3202566SN/A                if (rfaddr >= FHASH_ADDR &&
3212566SN/A                    rfaddr < FHASH_ADDR + FHASH_SIZE) {
3222566SN/A
3232566SN/A                    // Only word-aligned reads supported
3242566SN/A                    if (rfaddr % 2)
3252566SN/A                        panic("unaligned read from filter hash table!");
3262566SN/A
3272566SN/A                    reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8;
3282566SN/A                    reg += rom.filterHash[rfaddr - FHASH_ADDR];
329837SN/A                    break;
330837SN/A                }
3312566SN/A
3322566SN/A                panic("reading RFDR for something other than pattern"
3332566SN/A                      " matching or hashing! %#x\n", rfaddr);
334837SN/A            }
3352566SN/A            break;
3362566SN/A
3372566SN/A          case SRR:
3382566SN/A            reg = regs.srr;
3392566SN/A            break;
3402566SN/A
3412566SN/A          case MIBC:
3422566SN/A            reg = regs.mibc;
3432566SN/A            reg &= ~(MIBC_MIBS | MIBC_ACLR);
3442566SN/A            break;
3452566SN/A
3462566SN/A          case VRCR:
3472566SN/A            reg = regs.vrcr;
3482566SN/A            break;
3492566SN/A
3502566SN/A          case VTCR:
3512566SN/A            reg = regs.vtcr;
3522566SN/A            break;
3532566SN/A
3542566SN/A          case VDR:
3552566SN/A            reg = regs.vdr;
3562566SN/A            break;
3572566SN/A
3582566SN/A          case CCSR:
3592566SN/A            reg = regs.ccsr;
3602566SN/A            break;
3612566SN/A
3622566SN/A          case TBICR:
3632566SN/A            reg = regs.tbicr;
3642566SN/A            break;
3652566SN/A
3662566SN/A          case TBISR:
3672566SN/A            reg = regs.tbisr;
3682566SN/A            break;
3692566SN/A
3702566SN/A          case TANAR:
3712566SN/A            reg = regs.tanar;
3722566SN/A            break;
3732566SN/A
3742566SN/A          case TANLPAR:
3752566SN/A            reg = regs.tanlpar;
3762566SN/A            break;
3772566SN/A
3782566SN/A          case TANER:
3792566SN/A            reg = regs.taner;
3802566SN/A            break;
3812566SN/A
3822566SN/A          case TESR:
3832566SN/A            reg = regs.tesr;
3842566SN/A            break;
3852566SN/A
3862566SN/A          case M5REG:
3872566SN/A            reg = 0;
3882566SN/A            if (params()->rx_thread)
3892566SN/A                reg |= M5REG_RX_THREAD;
3902566SN/A            if (params()->tx_thread)
3912566SN/A                reg |= M5REG_TX_THREAD;
3922566SN/A            if (params()->rss)
3932566SN/A                reg |= M5REG_RSS;
3942566SN/A            break;
3952566SN/A
3962566SN/A          default:
3972566SN/A            panic("reading unimplemented register: addr=%#x", daddr);
398837SN/A        }
3992566SN/A
4002566SN/A        DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
4012566SN/A                daddr, reg, reg);
4022566SN/A
4034870SN/A    pkt->makeAtomicResponse();
4042566SN/A    return pioDelay;
405837SN/A}
406837SN/A
4072566SN/ATick
4083349SN/ANSGigE::write(PacketPtr pkt)
409837SN/A{
410927SN/A    assert(ioEnable);
411917SN/A
4122641SN/A    Addr daddr = pkt->getAddr() & 0xfff;
4132566SN/A    DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n",
4142641SN/A            daddr, pkt->getAddr(), pkt->getSize());
4152630SN/A
416854SN/A    if (daddr > LAST && daddr <=  RESERVED) {
417837SN/A        panic("Accessing reserved register");
418854SN/A    } else if (daddr > RESERVED && daddr <= 0x3FC) {
4192846SN/A        return writeConfig(pkt);
420854SN/A    } else if (daddr > 0x3FC)
421854SN/A        panic("Something is messed up!\n");
422837SN/A
4232641SN/A    if (pkt->getSize() == sizeof(uint32_t)) {
4242630SN/A        uint32_t reg = pkt->get<uint32_t>();
4251848SN/A        uint16_t rfaddr;
4261848SN/A
427854SN/A        DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg);
428837SN/A
429837SN/A        switch (daddr) {
430837SN/A          case CR:
431837SN/A            regs.command = reg;
4321035SN/A            if (reg & CR_TXD) {
4331035SN/A                txEnable = false;
434837SN/A            } else if (reg & CR_TXE) {
4352126SN/A                txEnable = true;
4362126SN/A
4372126SN/A                // the kernel is enabling the transmit machine
4382126SN/A                if (txState == txIdle)
4392126SN/A                    txKick();
440837SN/A            }
441837SN/A
4421035SN/A            if (reg & CR_RXD) {
4431035SN/A                rxEnable = false;
444837SN/A            } else if (reg & CR_RXE) {
4452126SN/A                rxEnable = true;
4462126SN/A
4472126SN/A                if (rxState == rxIdle)
4482126SN/A                    rxKick();
449837SN/A            }
450837SN/A
451837SN/A            if (reg & CR_TXR)
452837SN/A                txReset();
453837SN/A
454837SN/A            if (reg & CR_RXR)
455837SN/A                rxReset();
456837SN/A
457837SN/A            if (reg & CR_SWI)
458837SN/A                devIntrPost(ISR_SWI);
459837SN/A
460837SN/A            if (reg & CR_RST) {
461837SN/A                txReset();
462837SN/A                rxReset();
463854SN/A
464837SN/A                regsReset();
465837SN/A            }
466837SN/A            break;
467837SN/A
4681690SN/A          case CFGR:
4691690SN/A            if (reg & CFGR_LNKSTS ||
4701690SN/A                reg & CFGR_SPDSTS ||
4711690SN/A                reg & CFGR_DUPSTS ||
4721690SN/A                reg & CFGR_RESERVED ||
4731690SN/A                reg & CFGR_T64ADDR ||
4748726SN/A                reg & CFGR_PCI64_DET) {
4758726SN/A                // First clear all writable bits
4768726SN/A                regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
4778726SN/A                    CFGR_RESERVED | CFGR_T64ADDR |
4788726SN/A                    CFGR_PCI64_DET;
4798726SN/A                // Now set the appropriate writable bits
4808726SN/A                regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
4818726SN/A                                       CFGR_RESERVED | CFGR_T64ADDR |
4828726SN/A                                       CFGR_PCI64_DET);
4838726SN/A            }
4841027SN/A
4851027SN/A// all these #if 0's are because i don't THINK the kernel needs to
4861027SN/A// have these implemented. if there is a problem relating to one of
4871027SN/A// these, you may need to add functionality in.
4888737SN/A
4898737SN/A// grouped together and #if 0'ed to avoid empty if body and make clang happy
4908737SN/A#if 0
4911690SN/A            if (reg & CFGR_TBI_EN) ;
4921690SN/A            if (reg & CFGR_MODE_1000) ;
493837SN/A
4941690SN/A            if (reg & CFGR_PINT_DUPSTS ||
4951690SN/A                reg & CFGR_PINT_LNKSTS ||
4961690SN/A                reg & CFGR_PINT_SPDSTS)
4971027SN/A                ;
4981027SN/A
4991690SN/A            if (reg & CFGR_TMRTEST) ;
5001690SN/A            if (reg & CFGR_MRM_DIS) ;
5011690SN/A            if (reg & CFGR_MWI_DIS) ;
5021690SN/A
5031690SN/A            if (reg & CFGR_DATA64_EN) ;
5041690SN/A            if (reg & CFGR_M64ADDR) ;
5051690SN/A            if (reg & CFGR_PHY_RST) ;
5061690SN/A            if (reg & CFGR_PHY_DIS) ;
507837SN/A
5081909SN/A            if (reg & CFGR_REQALG) ;
5091909SN/A            if (reg & CFGR_SB) ;
5101909SN/A            if (reg & CFGR_POW) ;
5111909SN/A            if (reg & CFGR_EXD) ;
5121909SN/A            if (reg & CFGR_PESEL) ;
5131909SN/A            if (reg & CFGR_BROM_DIS) ;
5141909SN/A            if (reg & CFGR_EXT_125) ;
5151909SN/A            if (reg & CFGR_BEM) ;
5168737SN/A
5178737SN/A            if (reg & CFGR_T64ADDR) ;
5188737SN/A            // panic("CFGR_T64ADDR is read only register!\n");
5198737SN/A#endif
5208737SN/A            if (reg & CFGR_AUTO_1000)
5218737SN/A                panic("CFGR_AUTO_1000 not implemented!\n");
5228737SN/A
5238737SN/A            if (reg & CFGR_PCI64_DET)
5248737SN/A                panic("CFGR_PCI64_DET is read only register!\n");
5258737SN/A
5268737SN/A            if (reg & CFGR_EXTSTS_EN)
5278737SN/A                extstsEnable = true;
5288737SN/A            else
5298737SN/A                extstsEnable = false;
530837SN/A            break;
531837SN/A
532837SN/A          case MEAR:
5331843SN/A            // Clear writable bits
5341843SN/A            regs.mear &= MEAR_EEDO;
5351843SN/A            // Set appropriate writable bits
5361843SN/A            regs.mear |= reg & ~MEAR_EEDO;
5371843SN/A
5381843SN/A            // FreeBSD uses the EEPROM to read PMATCH (for the MAC address)
5391843SN/A            // even though it could get it through RFDR
5401843SN/A            if (reg & MEAR_EESEL) {
5411843SN/A                // Rising edge of clock
5421843SN/A                if (reg & MEAR_EECLK && !eepromClk)
5431843SN/A                    eepromKick();
5441843SN/A            }
5451843SN/A            else {
5461843SN/A                eepromState = eepromStart;
5471843SN/A                regs.mear &= ~MEAR_EEDI;
5481843SN/A            }
5491843SN/A
5501843SN/A            eepromClk = reg & MEAR_EECLK;
5511843SN/A
5521027SN/A            // since phy is completely faked, MEAR_MD* don't matter
5538737SN/A
5548737SN/A// grouped together and #if 0'ed to avoid empty if body and make clang happy
5558737SN/A#if 0
556837SN/A            if (reg & MEAR_MDIO) ;
557837SN/A            if (reg & MEAR_MDDIR) ;
558837SN/A            if (reg & MEAR_MDC) ;
5598737SN/A#endif
560837SN/A            break;
561837SN/A
562837SN/A          case PTSCR:
563854SN/A            regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY);
5641027SN/A            // these control BISTs for various parts of chip - we
5651027SN/A            // don't care or do just fake that the BIST is done
566854SN/A            if (reg & PTSCR_RBIST_EN)
567854SN/A                regs.ptscr |= PTSCR_RBIST_DONE;
568854SN/A            if (reg & PTSCR_EEBIST_EN)
569854SN/A                regs.ptscr &= ~PTSCR_EEBIST_EN;
570854SN/A            if (reg & PTSCR_EELOAD_EN)
571854SN/A                regs.ptscr &= ~PTSCR_EELOAD_EN;
572837SN/A            break;
573837SN/A
574837SN/A          case ISR: /* writing to the ISR has no effect */
575837SN/A            panic("ISR is a read only register!\n");
576837SN/A
577837SN/A          case IMR:
578837SN/A            regs.imr = reg;
579837SN/A            devIntrChangeMask();
580837SN/A            break;
581837SN/A
582837SN/A          case IER:
583837SN/A            regs.ier = reg;
584837SN/A            break;
585837SN/A
586837SN/A          case IHR:
587837SN/A            regs.ihr = reg;
588837SN/A            /* not going to implement real interrupt holdoff */
589837SN/A            break;
590837SN/A
591837SN/A          case TXDP:
592837SN/A            regs.txdp = (reg & 0xFFFFFFFC);
593837SN/A            assert(txState == txIdle);
594837SN/A            CTDD = false;
595837SN/A            break;
596837SN/A
597837SN/A          case TXDP_HI:
598837SN/A            regs.txdp_hi = reg;
599837SN/A            break;
600837SN/A
6011690SN/A          case TX_CFG:
602837SN/A            regs.txcfg = reg;
603837SN/A#if 0
6041690SN/A            if (reg & TX_CFG_CSI) ;
6051690SN/A            if (reg & TX_CFG_HBI) ;
6061690SN/A            if (reg & TX_CFG_MLB) ;
6071690SN/A            if (reg & TX_CFG_ATP) ;
6081690SN/A            if (reg & TX_CFG_ECRETRY) {
6091027SN/A                /*
6101027SN/A                 * this could easily be implemented, but considering
6111027SN/A                 * the network is just a fake pipe, wouldn't make
6121027SN/A                 * sense to do this
6131027SN/A                 */
6141027SN/A            }
615837SN/A
6161690SN/A            if (reg & TX_CFG_BRST_DIS) ;
617837SN/A#endif
618837SN/A
6191027SN/A#if 0
620854SN/A            /* we handle our own DMA, ignore the kernel's exhortations */
6211690SN/A            if (reg & TX_CFG_MXDMA) ;
6221027SN/A#endif
6231027SN/A
6241027SN/A            // also, we currently don't care about fill/drain
6251027SN/A            // thresholds though this may change in the future with
6261027SN/A            // more realistic networks or a driver which changes it
6271027SN/A            // according to feedback
628837SN/A
629837SN/A            break;
630837SN/A
631837SN/A          case GPIOR:
6321843SN/A            // Only write writable bits
6331843SN/A            regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
6341843SN/A                        | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN;
6351843SN/A            regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
6361843SN/A                                | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN);
637837SN/A            /* these just control general purpose i/o pins, don't matter */
638837SN/A            break;
639837SN/A
640854SN/A          case RXDP:
641854SN/A            regs.rxdp = reg;
6421035SN/A            CRDD = false;
643854SN/A            break;
644854SN/A
645854SN/A          case RXDP_HI:
646854SN/A            regs.rxdp_hi = reg;
647854SN/A            break;
648854SN/A
6491690SN/A          case RX_CFG:
650837SN/A            regs.rxcfg = reg;
651837SN/A#if 0
6521690SN/A            if (reg & RX_CFG_AEP) ;
6531690SN/A            if (reg & RX_CFG_ARP) ;
6541690SN/A            if (reg & RX_CFG_STRIPCRC) ;
6551690SN/A            if (reg & RX_CFG_RX_RD) ;
6561690SN/A            if (reg & RX_CFG_ALP) ;
6571690SN/A            if (reg & RX_CFG_AIRL) ;
658837SN/A
659854SN/A            /* we handle our own DMA, ignore what kernel says about it */
6601690SN/A            if (reg & RX_CFG_MXDMA) ;
6611027SN/A
662927SN/A            //also, we currently don't care about fill/drain thresholds
663927SN/A            //though this may change in the future with more realistic
664927SN/A            //networks or a driver which changes it according to feedback
6651690SN/A            if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ;
666837SN/A#endif
667837SN/A            break;
668837SN/A
669837SN/A          case PQCR:
670837SN/A            /* there is no priority queueing used in the linux 2.6 driver */
671837SN/A            regs.pqcr = reg;
672837SN/A            break;
673837SN/A
674837SN/A          case WCSR:
675837SN/A            /* not going to implement wake on LAN */
676837SN/A            regs.wcsr = reg;
677837SN/A            break;
678837SN/A
679837SN/A          case PCR:
680837SN/A            /* not going to implement pause control */
681837SN/A            regs.pcr = reg;
682837SN/A            break;
683837SN/A
684837SN/A          case RFCR:
685837SN/A            regs.rfcr = reg;
686854SN/A
687837SN/A            rxFilterEnable = (reg & RFCR_RFEN) ? true : false;
688837SN/A            acceptBroadcast = (reg & RFCR_AAB) ? true : false;
689837SN/A            acceptMulticast = (reg & RFCR_AAM) ? true : false;
690837SN/A            acceptUnicast = (reg & RFCR_AAU) ? true : false;
691837SN/A            acceptPerfect = (reg & RFCR_APM) ? true : false;
692837SN/A            acceptArp = (reg & RFCR_AARP) ? true : false;
6931843SN/A            multicastHashEnable = (reg & RFCR_MHEN) ? true : false;
694837SN/A
6951027SN/A#if 0
6961027SN/A            if (reg & RFCR_APAT)
6971027SN/A                panic("RFCR_APAT not implemented!\n");
6981027SN/A#endif
6991843SN/A            if (reg & RFCR_UHEN)
7001843SN/A                panic("Unicast hash filtering not used by drivers!\n");
701837SN/A
702837SN/A            if (reg & RFCR_ULM)
703837SN/A                panic("RFCR_ULM not implemented!\n");
704837SN/A
705837SN/A            break;
706837SN/A
707837SN/A          case RFDR:
7081848SN/A            rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
7091843SN/A            switch (rfaddr) {
7101843SN/A              case 0x000:
7111843SN/A                rom.perfectMatch[0] = (uint8_t)reg;
7121843SN/A                rom.perfectMatch[1] = (uint8_t)(reg >> 8);
7131843SN/A                break;
7141843SN/A              case 0x002:
7151843SN/A                rom.perfectMatch[2] = (uint8_t)reg;
7161843SN/A                rom.perfectMatch[3] = (uint8_t)(reg >> 8);
7171843SN/A                break;
7181843SN/A              case 0x004:
7191843SN/A                rom.perfectMatch[4] = (uint8_t)reg;
7201843SN/A                rom.perfectMatch[5] = (uint8_t)(reg >> 8);
7211843SN/A                break;
7221843SN/A              default:
7231843SN/A
7241843SN/A                if (rfaddr >= FHASH_ADDR &&
7251843SN/A                    rfaddr < FHASH_ADDR + FHASH_SIZE) {
7261843SN/A
7271843SN/A                    // Only word-aligned writes supported
7281843SN/A                    if (rfaddr % 2)
7291843SN/A                        panic("unaligned write to filter hash table!");
7301843SN/A
7311843SN/A                    rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg;
7321843SN/A                    rom.filterHash[rfaddr - FHASH_ADDR + 1]
7331843SN/A                        = (uint8_t)(reg >> 8);
7341843SN/A                    break;
7351843SN/A                }
73610367SN/A                panic("writing RFDR for something other than pattern matching "
73710367SN/A                    "or hashing! %#x\n", rfaddr);
7381843SN/A            }
739837SN/A
740837SN/A          case BRAR:
7411843SN/A            regs.brar = reg;
7421843SN/A            break;
743837SN/A
744837SN/A          case BRDR:
745837SN/A            panic("the driver never uses BRDR, something is wrong!\n");
746837SN/A
747837SN/A          case SRR:
748837SN/A            panic("SRR is read only register!\n");
749837SN/A
750837SN/A          case MIBC:
751837SN/A            panic("the driver never uses MIBC, something is wrong!\n");
752837SN/A
753837SN/A          case VRCR:
754837SN/A            regs.vrcr = reg;
755837SN/A            break;
756837SN/A
757837SN/A          case VTCR:
758837SN/A            regs.vtcr = reg;
759837SN/A            break;
760837SN/A
761837SN/A          case VDR:
762837SN/A            panic("the driver never uses VDR, something is wrong!\n");
763837SN/A
764837SN/A          case CCSR:
765837SN/A            /* not going to implement clockrun stuff */
766837SN/A            regs.ccsr = reg;
767837SN/A            break;
768837SN/A
769837SN/A          case TBICR:
770837SN/A            regs.tbicr = reg;
771837SN/A            if (reg & TBICR_MR_LOOPBACK)
772837SN/A                panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
773837SN/A
774837SN/A            if (reg & TBICR_MR_AN_ENABLE) {
775837SN/A                regs.tanlpar = regs.tanar;
776837SN/A                regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS);
777837SN/A            }
778837SN/A
779837SN/A#if 0
780837SN/A            if (reg & TBICR_MR_RESTART_AN) ;
781837SN/A#endif
782837SN/A
783837SN/A            break;
784837SN/A
785837SN/A          case TBISR:
786837SN/A            panic("TBISR is read only register!\n");
787837SN/A
788837SN/A          case TANAR:
7891843SN/A            // Only write the writable bits
7901843SN/A            regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED;
7911843SN/A            regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED);
7921843SN/A
7931843SN/A            // Pause capability unimplemented
7941843SN/A#if 0
7951843SN/A            if (reg & TANAR_PS2) ;
7961843SN/A            if (reg & TANAR_PS1) ;
7971843SN/A#endif
7981843SN/A
799837SN/A            break;
800837SN/A
801837SN/A          case TANLPAR:
802837SN/A            panic("this should only be written to by the fake phy!\n");
803837SN/A
804837SN/A          case TANER:
805837SN/A            panic("TANER is read only register!\n");
806837SN/A
807837SN/A          case TESR:
808837SN/A            regs.tesr = reg;
809837SN/A            break;
810837SN/A
811837SN/A          default:
8121027SN/A            panic("invalid register access daddr=%#x", daddr);
813837SN/A        }
8141027SN/A    } else {
815837SN/A        panic("Invalid Request Size");
8161027SN/A    }
8174870SN/A    pkt->makeAtomicResponse();
8182566SN/A    return pioDelay;
819837SN/A}
820837SN/A
821837SN/Avoid
822879SN/ANSGigE::devIntrPost(uint32_t interrupts)
823837SN/A{
824854SN/A    if (interrupts & ISR_RESERVE)
825854SN/A        panic("Cannot set a reserved interrupt");
826837SN/A
8271057SN/A    if (interrupts & ISR_NOIMPL)
8281057SN/A        warn("interrupt not implemented %#x\n", interrupts);
8291057SN/A
8301883SN/A    interrupts &= ISR_IMPL;
8311057SN/A    regs.isr |= interrupts;
8321057SN/A
8331263SN/A    if (interrupts & regs.imr) {
8341263SN/A        if (interrupts & ISR_SWI) {
8351263SN/A            totalSwi++;
8361263SN/A        }
8371263SN/A        if (interrupts & ISR_RXIDLE) {
8381263SN/A            totalRxIdle++;
8391263SN/A        }
8401263SN/A        if (interrupts & ISR_RXOK) {
8411263SN/A            totalRxOk++;
8421263SN/A        }
8431263SN/A        if (interrupts & ISR_RXDESC) {
8441263SN/A            totalRxDesc++;
8451263SN/A        }
8461263SN/A        if (interrupts & ISR_TXOK) {
8471263SN/A            totalTxOk++;
8481263SN/A        }
8491263SN/A        if (interrupts & ISR_TXIDLE) {
8501263SN/A            totalTxIdle++;
8511263SN/A        }
8521263SN/A        if (interrupts & ISR_TXDESC) {
8531263SN/A            totalTxDesc++;
8541263SN/A        }
8551263SN/A        if (interrupts & ISR_RXORN) {
8561263SN/A            totalRxOrn++;
8571263SN/A        }
8581263SN/A    }
8591263SN/A
8601057SN/A    DPRINTF(EthernetIntr,
8611057SN/A            "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
8621057SN/A            interrupts, regs.isr, regs.imr);
863837SN/A
864854SN/A    if ((regs.isr & regs.imr)) {
8657823SN/A        Tick when = curTick();
8661883SN/A        if ((regs.isr & regs.imr & ISR_NODELAY) == 0)
867854SN/A            when += intrDelay;
8685485SN/A        postedInterrupts++;
869854SN/A        cpuIntrPost(when);
870854SN/A    }
871837SN/A}
872837SN/A
8731263SN/A/* writing this interrupt counting stats inside this means that this function
8741263SN/A   is now limited to being used to clear all interrupts upon the kernel
8751263SN/A   reading isr and servicing.  just telling you in case you were thinking
8761263SN/A   of expanding use.
8771263SN/A*/
878837SN/Avoid
879879SN/ANSGigE::devIntrClear(uint32_t interrupts)
880837SN/A{
881837SN/A    if (interrupts & ISR_RESERVE)
882837SN/A        panic("Cannot clear a reserved interrupt");
883837SN/A
8841263SN/A    if (regs.isr & regs.imr & ISR_SWI) {
8851263SN/A        postedSwi++;
8861263SN/A    }
8871263SN/A    if (regs.isr & regs.imr & ISR_RXIDLE) {
8881263SN/A        postedRxIdle++;
8891263SN/A    }
8901263SN/A    if (regs.isr & regs.imr & ISR_RXOK) {
8911263SN/A        postedRxOk++;
8921263SN/A    }
8931263SN/A    if (regs.isr & regs.imr & ISR_RXDESC) {
8941263SN/A            postedRxDesc++;
8951263SN/A    }
8961263SN/A    if (regs.isr & regs.imr & ISR_TXOK) {
8971263SN/A        postedTxOk++;
8981263SN/A    }
8991263SN/A    if (regs.isr & regs.imr & ISR_TXIDLE) {
9001263SN/A        postedTxIdle++;
9011263SN/A    }
9021263SN/A    if (regs.isr & regs.imr & ISR_TXDESC) {
9031263SN/A        postedTxDesc++;
9041263SN/A    }
9051263SN/A    if (regs.isr & regs.imr & ISR_RXORN) {
9061263SN/A        postedRxOrn++;
9071263SN/A    }
9081263SN/A
9091057SN/A    interrupts &= ~ISR_NOIMPL;
9101057SN/A    regs.isr &= ~interrupts;
911837SN/A
9121027SN/A    DPRINTF(EthernetIntr,
9131027SN/A            "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",
914881SN/A            interrupts, regs.isr, regs.imr);
9151036SN/A
9161036SN/A    if (!(regs.isr & regs.imr))
9171036SN/A        cpuIntrClear();
918837SN/A}
919837SN/A
920837SN/Avoid
921879SN/ANSGigE::devIntrChangeMask()
922837SN/A{
9231036SN/A    DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n",
9241036SN/A            regs.isr, regs.imr, regs.isr & regs.imr);
925837SN/A
926837SN/A    if (regs.isr & regs.imr)
9277823SN/A        cpuIntrPost(curTick());
928837SN/A    else
929837SN/A        cpuIntrClear();
930837SN/A}
931837SN/A
932837SN/Avoid
933879SN/ANSGigE::cpuIntrPost(Tick when)
934837SN/A{
9351027SN/A    // If the interrupt you want to post is later than an interrupt
9361027SN/A    // already scheduled, just let it post in the coming one and don't
9371027SN/A    // schedule another.
9381027SN/A    // HOWEVER, must be sure that the scheduled intrTick is in the
9391027SN/A    // future (this was formerly the source of a bug)
9401035SN/A    /**
9411035SN/A     * @todo this warning should be removed and the intrTick code should
9421035SN/A     * be fixed.
9431035SN/A     */
9447823SN/A    assert(when >= curTick());
9457823SN/A    assert(intrTick >= curTick() || intrTick == 0);
9461072SN/A    if (when > intrTick && intrTick != 0) {
9471072SN/A        DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
9481072SN/A                intrTick);
9491072SN/A        return;
9501035SN/A    }
951854SN/A
952854SN/A    intrTick = when;
9537823SN/A    if (intrTick < curTick()) {
9547823SN/A        intrTick = curTick();
9551072SN/A    }
9561072SN/A
9571072SN/A    DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
9581072SN/A            intrTick);
9591072SN/A
9601072SN/A    if (intrEvent)
961854SN/A        intrEvent->squash();
9625606SN/A    intrEvent = new IntrEvent(this, true);
9635606SN/A    schedule(intrEvent, intrTick);
964854SN/A}
965854SN/A
966854SN/Avoid
967879SN/ANSGigE::cpuInterrupt()
968854SN/A{
9697823SN/A    assert(intrTick == curTick());
9701072SN/A
9711072SN/A    // Whether or not there's a pending interrupt, we don't care about
9721072SN/A    // it anymore
9731072SN/A    intrEvent = 0;
9741072SN/A    intrTick = 0;
9751072SN/A
976854SN/A    // Don't send an interrupt if there's already one
977927SN/A    if (cpuPendingIntr) {
978927SN/A        DPRINTF(EthernetIntr,
979927SN/A                "would send an interrupt now, but there's already pending\n");
9801072SN/A    } else {
9811072SN/A        // Send interrupt
9821072SN/A        cpuPendingIntr = true;
9831072SN/A
9841149SN/A        DPRINTF(EthernetIntr, "posting interrupt\n");
9851149SN/A        intrPost();
986927SN/A    }
987837SN/A}
988837SN/A
989837SN/Avoid
990879SN/ANSGigE::cpuIntrClear()
991837SN/A{
9921027SN/A    if (!cpuPendingIntr)
9931027SN/A        return;
9941027SN/A
9951072SN/A    if (intrEvent) {
9961072SN/A        intrEvent->squash();
9971072SN/A        intrEvent = 0;
9981072SN/A    }
9991072SN/A
10001072SN/A    intrTick = 0;
10011072SN/A
10021027SN/A    cpuPendingIntr = false;
10031057SN/A
10041149SN/A    DPRINTF(EthernetIntr, "clearing interrupt\n");
10051149SN/A    intrClear();
1006837SN/A}
1007837SN/A
1008837SN/Abool
1009879SN/ANSGigE::cpuIntrPending() const
1010837SN/A{ return cpuPendingIntr; }
1011837SN/A
1012837SN/Avoid
1013879SN/ANSGigE::txReset()
1014837SN/A{
1015837SN/A
1016837SN/A    DPRINTF(Ethernet, "transmit reset\n");
1017837SN/A
1018837SN/A    CTDD = false;
10191035SN/A    txEnable = false;;
1020854SN/A    txFragPtr = 0;
1021854SN/A    assert(txDescCnt == 0);
1022837SN/A    txFifo.clear();
1023837SN/A    txState = txIdle;
1024854SN/A    assert(txDmaState == dmaIdle);
1025837SN/A}
1026837SN/A
1027837SN/Avoid
1028879SN/ANSGigE::rxReset()
1029837SN/A{
1030837SN/A    DPRINTF(Ethernet, "receive reset\n");
1031837SN/A
1032837SN/A    CRDD = false;
1033854SN/A    assert(rxPktBytes == 0);
10341035SN/A    rxEnable = false;
1035854SN/A    rxFragPtr = 0;
1036854SN/A    assert(rxDescCnt == 0);
1037854SN/A    assert(rxDmaState == dmaIdle);
1038837SN/A    rxFifo.clear();
1039837SN/A    rxState = rxIdle;
1040837SN/A}
1041837SN/A
10421036SN/Avoid
10431036SN/ANSGigE::regsReset()
1044915SN/A{
1045915SN/A    memset(&regs, 0, sizeof(regs));
10461817SN/A    regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000);
10471843SN/A    regs.mear = 0x12;
10481057SN/A    regs.txcfg = 0x120; // set drain threshold to 1024 bytes and
10491057SN/A                        // fill threshold to 32 bytes
10501057SN/A    regs.rxcfg = 0x4;   // set drain threshold to 16 bytes
10511057SN/A    regs.srr = 0x0103;  // set the silicon revision to rev B or 0x103
10521057SN/A    regs.mibc = MIBC_FRZ;
10531057SN/A    regs.vdr = 0x81;    // set the vlan tag type to 802.1q
10541057SN/A    regs.tesr = 0xc000; // TBI capable of both full and half duplex
10551843SN/A    regs.brar = 0xffffffff;
1056927SN/A
1057927SN/A    extstsEnable = false;
1058927SN/A    acceptBroadcast = false;
1059927SN/A    acceptMulticast = false;
1060927SN/A    acceptUnicast = false;
1061927SN/A    acceptPerfect = false;
1062927SN/A    acceptArp = false;
1063915SN/A}
1064915SN/A
1065854SN/Abool
1066879SN/ANSGigE::doRxDmaRead()
1067854SN/A{
1068854SN/A    assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
1069854SN/A    rxDmaState = dmaReading;
1070854SN/A
107110913SN/A    if (dmaPending() || drainState() != DrainState::Running)
10722566SN/A        rxDmaState = dmaReadWaiting;
10732566SN/A    else
10742566SN/A        dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData);
10752566SN/A
1076854SN/A    return true;
1077854SN/A}
1078854SN/A
1079854SN/Avoid
1080879SN/ANSGigE::rxDmaReadDone()
1081854SN/A{
1082854SN/A    assert(rxDmaState == dmaReading);
10832566SN/A    rxDmaState = dmaIdle;
10842566SN/A
10852566SN/A    DPRINTF(EthernetDMA, "rx dma read  paddr=%#x len=%d\n",
10862566SN/A            rxDmaAddr, rxDmaLen);
10872566SN/A    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1088854SN/A
1089854SN/A    // If the transmit state machine has a pending DMA, let it go first
1090854SN/A    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1091854SN/A        txKick();
1092854SN/A
1093854SN/A    rxKick();
1094854SN/A}
1095854SN/A
1096854SN/Abool
1097879SN/ANSGigE::doRxDmaWrite()
1098854SN/A{
1099854SN/A    assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
1100854SN/A    rxDmaState = dmaWriting;
1101854SN/A
110210913SN/A    if (dmaPending() || drainState() != DrainState::Running)
11032566SN/A        rxDmaState = dmaWriteWaiting;
11042566SN/A    else
11052566SN/A        dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData);
1106854SN/A    return true;
1107854SN/A}
1108854SN/A
1109854SN/Avoid
1110879SN/ANSGigE::rxDmaWriteDone()
1111854SN/A{
1112854SN/A    assert(rxDmaState == dmaWriting);
11132566SN/A    rxDmaState = dmaIdle;
11142566SN/A
11152566SN/A    DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
11162566SN/A            rxDmaAddr, rxDmaLen);
11172566SN/A    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1118854SN/A
1119854SN/A    // If the transmit state machine has a pending DMA, let it go first
1120854SN/A    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1121854SN/A        txKick();
1122854SN/A
1123854SN/A    rxKick();
1124837SN/A}
1125837SN/A
1126837SN/Avoid
1127879SN/ANSGigE::rxKick()
1128837SN/A{
11291909SN/A    bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
11301909SN/A
11311909SN/A    DPRINTF(EthernetSM,
11321909SN/A            "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n",
11331909SN/A            NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32);
11341909SN/A
11351909SN/A    Addr link, bufptr;
11361909SN/A    uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts;
11371909SN/A    uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts;
1138837SN/A
11391801SN/A  next:
11409417SN/A    if (rxKickTick > curTick()) {
11419417SN/A        DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
11429417SN/A                rxKickTick);
11431801SN/A
11449417SN/A        goto exit;
11459417SN/A    }
11461801SN/A
11479417SN/A    // Go to the next state machine clock tick.
11489417SN/A    rxKickTick = clockEdge(Cycles(1));
1149837SN/A
1150854SN/A    switch(rxDmaState) {
1151854SN/A      case dmaReadWaiting:
1152854SN/A        if (doRxDmaRead())
1153854SN/A            goto exit;
1154854SN/A        break;
1155854SN/A      case dmaWriteWaiting:
1156854SN/A        if (doRxDmaWrite())
1157854SN/A            goto exit;
1158854SN/A        break;
1159854SN/A      default:
1160854SN/A        break;
1161854SN/A    }
1162837SN/A
11631909SN/A    link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link;
11641909SN/A    bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr;
11651909SN/A
1166855SN/A    // see state machine from spec for details
11671027SN/A    // the way this works is, if you finish work on one state and can
11681027SN/A    // go directly to another, you do that through jumping to the
11691027SN/A    // label "next".  however, if you have intermediate work, like DMA
11701027SN/A    // so that you can't go to the next state yet, you go to exit and
11711027SN/A    // exit the loop.  however, when the DMA is done it will trigger
11721027SN/A    // an event and come back to this loop.
1173854SN/A    switch (rxState) {
1174854SN/A      case rxIdle:
11751035SN/A        if (!rxEnable) {
1176927SN/A            DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");
1177854SN/A            goto exit;
1178854SN/A        }
1179837SN/A
1180854SN/A        if (CRDD) {
1181854SN/A            rxState = rxDescRefr;
1182837SN/A
1183854SN/A            rxDmaAddr = regs.rxdp & 0x3fffffff;
11841909SN/A            rxDmaData =
11851909SN/A                is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link;
11861909SN/A            rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link);
1187854SN/A            rxDmaFree = dmaDescFree;
1188854SN/A
1189961SN/A            descDmaReads++;
1190961SN/A            descDmaRdBytes += rxDmaLen;
1191961SN/A
1192854SN/A            if (doRxDmaRead())
1193854SN/A                goto exit;
1194837SN/A        } else {
1195837SN/A            rxState = rxDescRead;
1196854SN/A
1197854SN/A            rxDmaAddr = regs.rxdp & 0x3fffffff;
11981909SN/A            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
11991909SN/A            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1200854SN/A            rxDmaFree = dmaDescFree;
1201854SN/A
1202961SN/A            descDmaReads++;
1203961SN/A            descDmaRdBytes += rxDmaLen;
1204961SN/A
1205854SN/A            if (doRxDmaRead())
1206854SN/A                goto exit;
1207837SN/A        }
1208854SN/A        break;
1209854SN/A
1210854SN/A      case rxDescRefr:
1211854SN/A        if (rxDmaState != dmaIdle)
1212854SN/A            goto exit;
1213854SN/A
1214854SN/A        rxState = rxAdvance;
1215854SN/A        break;
1216854SN/A
1217854SN/A     case rxDescRead:
1218854SN/A        if (rxDmaState != dmaIdle)
1219854SN/A            goto exit;
1220854SN/A
12211909SN/A        DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n",
12221036SN/A                regs.rxdp & 0x3fffffff);
12231036SN/A        DPRINTF(EthernetDesc,
12241909SN/A                "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
12251909SN/A                link, bufptr, cmdsts, extsts);
12261909SN/A
12271909SN/A        if (cmdsts & CMDSTS_OWN) {
12281035SN/A            devIntrPost(ISR_RXIDLE);
1229837SN/A            rxState = rxIdle;
12301035SN/A            goto exit;
1231837SN/A        } else {
1232837SN/A            rxState = rxFifoBlock;
12331909SN/A            rxFragPtr = bufptr;
12341909SN/A            rxDescCnt = cmdsts & CMDSTS_LEN_MASK;
1235854SN/A        }
1236854SN/A        break;
1237837SN/A
1238854SN/A      case rxFifoBlock:
1239854SN/A        if (!rxPacket) {
1240854SN/A            /**
1241854SN/A             * @todo in reality, we should be able to start processing
1242854SN/A             * the packet as it arrives, and not have to wait for the
1243854SN/A             * full packet ot be in the receive fifo.
1244854SN/A             */
1245854SN/A            if (rxFifo.empty())
1246854SN/A                goto exit;
1247854SN/A
12481036SN/A            DPRINTF(EthernetSM, "****processing receive of new packet****\n");
1249927SN/A
1250854SN/A            // If we don't have a packet, grab a new one from the fifo.
1251854SN/A            rxPacket = rxFifo.front();
1252854SN/A            rxPktBytes = rxPacket->length;
1253854SN/A            rxPacketBufPtr = rxPacket->data;
1254854SN/A
12551011SN/A#if TRACING_ON
1256927SN/A            if (DTRACE(Ethernet)) {
12571114SN/A                IpPtr ip(rxPacket);
12581078SN/A                if (ip) {
12591078SN/A                    DPRINTF(Ethernet, "ID is %d\n", ip->id());
12601114SN/A                    TcpPtr tcp(ip);
12611078SN/A                    if (tcp) {
12621561SN/A                        DPRINTF(Ethernet,
12631561SN/A                                "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
12641561SN/A                                tcp->sport(), tcp->dport(), tcp->seq(),
12651561SN/A                                tcp->ack());
1266927SN/A                    }
1267927SN/A                }
1268927SN/A            }
12691011SN/A#endif
1270927SN/A
1271854SN/A            // sanity check - i think the driver behaves like this
1272854SN/A            assert(rxDescCnt >= rxPktBytes);
12731154SN/A            rxFifo.pop();
1274837SN/A        }
1275837SN/A
1276837SN/A
12771027SN/A        // dont' need the && rxDescCnt > 0 if driver sanity check
12781027SN/A        // above holds
1279854SN/A        if (rxPktBytes > 0) {
1280854SN/A            rxState = rxFragWrite;
12811027SN/A            // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
12821027SN/A            // check holds
1283854SN/A            rxXferLen = rxPktBytes;
1284854SN/A
1285854SN/A            rxDmaAddr = rxFragPtr & 0x3fffffff;
1286854SN/A            rxDmaData = rxPacketBufPtr;
1287854SN/A            rxDmaLen = rxXferLen;
1288854SN/A            rxDmaFree = dmaDataFree;
1289854SN/A
1290854SN/A            if (doRxDmaWrite())
1291854SN/A                goto exit;
1292854SN/A
1293837SN/A        } else {
1294854SN/A            rxState = rxDescWrite;
1295837SN/A
1296854SN/A            //if (rxPktBytes == 0) {  /* packet is done */
1297854SN/A            assert(rxPktBytes == 0);
1298927SN/A            DPRINTF(EthernetSM, "done with receiving packet\n");
1299837SN/A
13001909SN/A            cmdsts |= CMDSTS_OWN;
13011909SN/A            cmdsts &= ~CMDSTS_MORE;
13021909SN/A            cmdsts |= CMDSTS_OK;
13031909SN/A            cmdsts &= 0xffff0000;
13041909SN/A            cmdsts += rxPacket->length;   //i.e. set CMDSTS_SIZE
1305837SN/A
1306854SN/A#if 0
13071027SN/A            /*
13081027SN/A             * all the driver uses these are for its own stats keeping
13091027SN/A             * which we don't care about, aren't necessary for
13101027SN/A             * functionality and doing this would just slow us down.
13111027SN/A             * if they end up using this in a later version for
13121027SN/A             * functional purposes, just undef
13131027SN/A             */
1314837SN/A            if (rxFilterEnable) {
13151909SN/A                cmdsts &= ~CMDSTS_DEST_MASK;
13161114SN/A                const EthAddr &dst = rxFifoFront()->dst();
13171114SN/A                if (dst->unicast())
13181909SN/A                    cmdsts |= CMDSTS_DEST_SELF;
13191114SN/A                if (dst->multicast())
13201909SN/A                    cmdsts |= CMDSTS_DEST_MULTI;
13211114SN/A                if (dst->broadcast())
13221909SN/A                    cmdsts |= CMDSTS_DEST_MASK;
1323837SN/A            }
1324854SN/A#endif
1325837SN/A
13261114SN/A            IpPtr ip(rxPacket);
13271114SN/A            if (extstsEnable && ip) {
13281909SN/A                extsts |= EXTSTS_IPPKT;
13291078SN/A                rxIpChecksums++;
13301114SN/A                if (cksum(ip) != 0) {
1331927SN/A                    DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
13321909SN/A                    extsts |= EXTSTS_IPERR;
1333927SN/A                }
13341114SN/A                TcpPtr tcp(ip);
13351114SN/A                UdpPtr udp(ip);
13361114SN/A                if (tcp) {
13371909SN/A                    extsts |= EXTSTS_TCPPKT;
13381078SN/A                    rxTcpChecksums++;
13391114SN/A                    if (cksum(tcp) != 0) {
1340927SN/A                        DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
13411909SN/A                        extsts |= EXTSTS_TCPERR;
1342961SN/A
1343927SN/A                    }
13441114SN/A                } else if (udp) {
13451909SN/A                    extsts |= EXTSTS_UDPPKT;
13461078SN/A                    rxUdpChecksums++;
13471114SN/A                    if (cksum(udp) != 0) {
1348927SN/A                        DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
13491909SN/A                        extsts |= EXTSTS_UDPERR;
1350927SN/A                    }
1351837SN/A                }
1352837SN/A            }
1353881SN/A            rxPacket = 0;
1354881SN/A
13551027SN/A            /*
13561027SN/A             * the driver seems to always receive into desc buffers
13571027SN/A             * of size 1514, so you never have a pkt that is split
13581027SN/A             * into multiple descriptors on the receive side, so
13591027SN/A             * i don't implement that case, hence the assert above.
13601027SN/A             */
13611027SN/A
13621027SN/A            DPRINTF(EthernetDesc,
13631909SN/A                    "rxDesc: addr=%08x writeback cmdsts extsts\n",
13641036SN/A                    regs.rxdp & 0x3fffffff);
13651036SN/A            DPRINTF(EthernetDesc,
13661909SN/A                    "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
13671909SN/A                    link, bufptr, cmdsts, extsts);
13681909SN/A
13691909SN/A            rxDmaAddr = regs.rxdp & 0x3fffffff;
13701909SN/A            rxDmaData = &cmdsts;
13711909SN/A            if (is64bit) {
13721909SN/A                rxDmaAddr += offsetof(ns_desc64, cmdsts);
13731909SN/A                rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts);
13741909SN/A            } else {
13751909SN/A                rxDmaAddr += offsetof(ns_desc32, cmdsts);
13761909SN/A                rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts);
13771909SN/A            }
1378854SN/A            rxDmaFree = dmaDescFree;
1379854SN/A
1380961SN/A            descDmaWrites++;
1381961SN/A            descDmaWrBytes += rxDmaLen;
1382961SN/A
1383854SN/A            if (doRxDmaWrite())
1384854SN/A                goto exit;
1385837SN/A        }
1386854SN/A        break;
1387837SN/A
1388854SN/A      case rxFragWrite:
1389854SN/A        if (rxDmaState != dmaIdle)
1390854SN/A            goto exit;
1391854SN/A
1392854SN/A        rxPacketBufPtr += rxXferLen;
1393854SN/A        rxFragPtr += rxXferLen;
1394854SN/A        rxPktBytes -= rxXferLen;
1395854SN/A
1396854SN/A        rxState = rxFifoBlock;
1397854SN/A        break;
1398854SN/A
1399854SN/A      case rxDescWrite:
1400854SN/A        if (rxDmaState != dmaIdle)
1401854SN/A            goto exit;
1402854SN/A
14031909SN/A        assert(cmdsts & CMDSTS_OWN);
1404854SN/A
1405854SN/A        assert(rxPacket == 0);
1406854SN/A        devIntrPost(ISR_RXOK);
1407854SN/A
14081909SN/A        if (cmdsts & CMDSTS_INTR)
1409854SN/A            devIntrPost(ISR_RXDESC);
1410854SN/A
14111035SN/A        if (!rxEnable) {
1412927SN/A            DPRINTF(EthernetSM, "Halting the RX state machine\n");
1413854SN/A            rxState = rxIdle;
14141035SN/A            goto exit;
1415854SN/A        } else
1416854SN/A            rxState = rxAdvance;
1417854SN/A        break;
1418854SN/A
1419854SN/A      case rxAdvance:
14201909SN/A        if (link == 0) {
14211035SN/A            devIntrPost(ISR_RXIDLE);
1422854SN/A            rxState = rxIdle;
14231035SN/A            CRDD = true;
14241035SN/A            goto exit;
1425854SN/A        } else {
14261893SN/A            if (rxDmaState != dmaIdle)
14271893SN/A                goto exit;
1428854SN/A            rxState = rxDescRead;
14291909SN/A            regs.rxdp = link;
1430854SN/A            CRDD = false;
1431854SN/A
1432854SN/A            rxDmaAddr = regs.rxdp & 0x3fffffff;
14331909SN/A            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
14341909SN/A            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1435854SN/A            rxDmaFree = dmaDescFree;
1436854SN/A
1437854SN/A            if (doRxDmaRead())
1438854SN/A                goto exit;
1439854SN/A        }
1440854SN/A        break;
1441854SN/A
1442854SN/A      default:
1443854SN/A        panic("Invalid rxState!");
1444837SN/A    }
1445837SN/A
14461036SN/A    DPRINTF(EthernetSM, "entering next rxState=%s\n",
1447854SN/A            NsRxStateStrings[rxState]);
1448854SN/A    goto next;
1449837SN/A
1450854SN/A  exit:
1451854SN/A    /**
1452854SN/A     * @todo do we want to schedule a future kick?
1453854SN/A     */
14541036SN/A    DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
1455854SN/A            NsRxStateStrings[rxState]);
14561801SN/A
14579417SN/A    if (!rxKickEvent.scheduled())
14585606SN/A        schedule(rxKickEvent, rxKickTick);
1459837SN/A}
1460837SN/A
1461837SN/Avoid
1462879SN/ANSGigE::transmit()
1463837SN/A{
1464837SN/A    if (txFifo.empty()) {
1465837SN/A        DPRINTF(Ethernet, "nothing to transmit\n");
1466837SN/A        return;
1467837SN/A    }
1468837SN/A
14691036SN/A    DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",
14701154SN/A            txFifo.size());
1471927SN/A    if (interface->sendPacket(txFifo.front())) {
14721011SN/A#if TRACING_ON
1473927SN/A        if (DTRACE(Ethernet)) {
14741114SN/A            IpPtr ip(txFifo.front());
14751078SN/A            if (ip) {
14761078SN/A                DPRINTF(Ethernet, "ID is %d\n", ip->id());
14771114SN/A                TcpPtr tcp(ip);
14781078SN/A                if (tcp) {
14791561SN/A                    DPRINTF(Ethernet,
14801561SN/A                            "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
14811909SN/A                            tcp->sport(), tcp->dport(), tcp->seq(),
14821909SN/A                            tcp->ack());
1483927SN/A                }
1484927SN/A            }
1485927SN/A        }
14861011SN/A#endif
1487927SN/A
14881561SN/A        DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length);
1489837SN/A        txBytes += txFifo.front()->length;
1490837SN/A        txPackets++;
1491837SN/A
14921027SN/A        DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
14931154SN/A                txFifo.avail());
14941154SN/A        txFifo.pop();
1495837SN/A
14961027SN/A        /*
14971027SN/A         * normally do a writeback of the descriptor here, and ONLY
14981027SN/A         * after that is done, send this interrupt.  but since our
14991027SN/A         * stuff never actually fails, just do this interrupt here,
15001027SN/A         * otherwise the code has to stray from this nice format.
15011027SN/A         * besides, it's functionally the same.
15021027SN/A         */
1503854SN/A        devIntrPost(ISR_TXOK);
15041027SN/A    }
1505854SN/A
1506854SN/A   if (!txFifo.empty() && !txEvent.scheduled()) {
1507854SN/A       DPRINTF(Ethernet, "reschedule transmit\n");
15087823SN/A       schedule(txEvent, curTick() + retryTime);
1509854SN/A   }
1510854SN/A}
1511854SN/A
1512854SN/Abool
1513879SN/ANSGigE::doTxDmaRead()
1514854SN/A{
1515854SN/A    assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
1516854SN/A    txDmaState = dmaReading;
1517854SN/A
151810913SN/A    if (dmaPending() || drainState() != DrainState::Running)
15192566SN/A        txDmaState = dmaReadWaiting;
15202566SN/A    else
15212566SN/A        dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData);
15222566SN/A
1523854SN/A    return true;
1524854SN/A}
1525837SN/A
1526854SN/Avoid
1527879SN/ANSGigE::txDmaReadDone()
1528854SN/A{
1529854SN/A    assert(txDmaState == dmaReading);
15302566SN/A    txDmaState = dmaIdle;
15312566SN/A
15322566SN/A    DPRINTF(EthernetDMA, "tx dma read  paddr=%#x len=%d\n",
15332566SN/A            txDmaAddr, txDmaLen);
15342566SN/A    DDUMP(EthernetDMA, txDmaData, txDmaLen);
1535837SN/A
1536854SN/A    // If the receive state machine  has a pending DMA, let it go first
1537854SN/A    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1538854SN/A        rxKick();
1539837SN/A
1540854SN/A    txKick();
1541854SN/A}
1542837SN/A
1543854SN/Abool
1544879SN/ANSGigE::doTxDmaWrite()
1545854SN/A{
1546854SN/A    assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
1547854SN/A    txDmaState = dmaWriting;
1548854SN/A
154910913SN/A    if (dmaPending() || drainState() != DrainState::Running)
15502566SN/A        txDmaState = dmaWriteWaiting;
15512566SN/A    else
15522566SN/A        dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData);
1553854SN/A    return true;
1554854SN/A}
1555854SN/A
1556854SN/Avoid
1557879SN/ANSGigE::txDmaWriteDone()
1558854SN/A{
1559854SN/A    assert(txDmaState == dmaWriting);
15602566SN/A    txDmaState = dmaIdle;
15612566SN/A
15622566SN/A    DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n",
15632566SN/A            txDmaAddr, txDmaLen);
15642566SN/A    DDUMP(EthernetDMA, txDmaData, txDmaLen);
1565854SN/A
1566854SN/A    // If the receive state machine  has a pending DMA, let it go first
1567854SN/A    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1568854SN/A        rxKick();
1569854SN/A
1570854SN/A    txKick();
1571837SN/A}
1572837SN/A
1573837SN/Avoid
1574879SN/ANSGigE::txKick()
1575837SN/A{
15761909SN/A    bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
15771909SN/A
15781909SN/A    DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n",
15791909SN/A            NsTxStateStrings[txState], is64bit ? 64 : 32);
15801909SN/A
15811909SN/A    Addr link, bufptr;
15821909SN/A    uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts;
15831909SN/A    uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts;
1584927SN/A
15851801SN/A  next:
15869417SN/A    if (txKickTick > curTick()) {
15879417SN/A        DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
15889417SN/A                txKickTick);
15899417SN/A        goto exit;
15909417SN/A    }
15911801SN/A
15929417SN/A    // Go to the next state machine clock tick.
15939417SN/A    txKickTick = clockEdge(Cycles(1));
1594837SN/A
1595854SN/A    switch(txDmaState) {
1596854SN/A      case dmaReadWaiting:
1597854SN/A        if (doTxDmaRead())
1598854SN/A            goto exit;
1599854SN/A        break;
1600854SN/A      case dmaWriteWaiting:
1601854SN/A        if (doTxDmaWrite())
1602854SN/A            goto exit;
1603854SN/A        break;
1604854SN/A      default:
1605854SN/A        break;
1606854SN/A    }
1607837SN/A
16081909SN/A    link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link;
16091909SN/A    bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr;
1610854SN/A    switch (txState) {
1611854SN/A      case txIdle:
16121035SN/A        if (!txEnable) {
1613927SN/A            DPRINTF(EthernetSM, "Transmit disabled.  Nothing to do.\n");
1614854SN/A            goto exit;
1615854SN/A        }
1616837SN/A
1617854SN/A        if (CTDD) {
1618854SN/A            txState = txDescRefr;
1619837SN/A
1620881SN/A            txDmaAddr = regs.txdp & 0x3fffffff;
16211909SN/A            txDmaData =
16221909SN/A                is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link;
16231909SN/A            txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link);
1624854SN/A            txDmaFree = dmaDescFree;
1625837SN/A
1626961SN/A            descDmaReads++;
1627961SN/A            descDmaRdBytes += txDmaLen;
1628961SN/A
1629854SN/A            if (doTxDmaRead())
1630854SN/A                goto exit;
1631854SN/A
1632854SN/A        } else {
1633854SN/A            txState = txDescRead;
1634854SN/A
1635854SN/A            txDmaAddr = regs.txdp & 0x3fffffff;
16361909SN/A            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
16371909SN/A            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
1638854SN/A            txDmaFree = dmaDescFree;
1639854SN/A
1640961SN/A            descDmaReads++;
1641961SN/A            descDmaRdBytes += txDmaLen;
1642961SN/A
1643854SN/A            if (doTxDmaRead())
1644854SN/A                goto exit;
1645837SN/A        }
1646854SN/A        break;
1647837SN/A
1648854SN/A      case txDescRefr:
1649854SN/A        if (txDmaState != dmaIdle)
1650854SN/A            goto exit;
1651854SN/A
1652854SN/A        txState = txAdvance;
1653854SN/A        break;
1654854SN/A
1655854SN/A      case txDescRead:
1656854SN/A        if (txDmaState != dmaIdle)
1657854SN/A            goto exit;
1658854SN/A
16591909SN/A        DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n",
16601801SN/A                regs.txdp & 0x3fffffff);
1661927SN/A        DPRINTF(EthernetDesc,
16621909SN/A                "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n",
16631909SN/A                link, bufptr, cmdsts, extsts);
16641909SN/A
16651909SN/A        if (cmdsts & CMDSTS_OWN) {
1666854SN/A            txState = txFifoBlock;
16671909SN/A            txFragPtr = bufptr;
16681909SN/A            txDescCnt = cmdsts & CMDSTS_LEN_MASK;
1669854SN/A        } else {
16701035SN/A            devIntrPost(ISR_TXIDLE);
1671854SN/A            txState = txIdle;
16721035SN/A            goto exit;
1673854SN/A        }
1674854SN/A        break;
1675854SN/A
1676854SN/A      case txFifoBlock:
1677854SN/A        if (!txPacket) {
16781036SN/A            DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
167910469SN/A            txPacket = make_shared<EthPacketData>(16384);
1680854SN/A            txPacketBufPtr = txPacket->data;
1681854SN/A        }
1682854SN/A
1683854SN/A        if (txDescCnt == 0) {
1684927SN/A            DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");
16851909SN/A            if (cmdsts & CMDSTS_MORE) {
1686927SN/A                DPRINTF(EthernetSM, "there are more descriptors to come\n");
1687854SN/A                txState = txDescWrite;
1688854SN/A
16891909SN/A                cmdsts &= ~CMDSTS_OWN;
16901909SN/A
16911909SN/A                txDmaAddr = regs.txdp & 0x3fffffff;
16921909SN/A                txDmaData = &cmdsts;
16931909SN/A                if (is64bit) {
16941909SN/A                    txDmaAddr += offsetof(ns_desc64, cmdsts);
16951909SN/A                    txDmaLen = sizeof(txDesc64.cmdsts);
16961909SN/A                } else {
16971909SN/A                    txDmaAddr += offsetof(ns_desc32, cmdsts);
16981909SN/A                    txDmaLen = sizeof(txDesc32.cmdsts);
16991909SN/A                }
1700854SN/A                txDmaFree = dmaDescFree;
1701854SN/A
1702854SN/A                if (doTxDmaWrite())
1703854SN/A                    goto exit;
1704854SN/A
1705854SN/A            } else { /* this packet is totally done */
1706927SN/A                DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
1707854SN/A                /* deal with the the packet that just finished */
1708854SN/A                if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
17091114SN/A                    IpPtr ip(txPacket);
17101909SN/A                    if (extsts & EXTSTS_UDPPKT) {
17111114SN/A                        UdpPtr udp(ip);
17125484SN/A                        if (udp) {
17135484SN/A                            udp->sum(0);
17145484SN/A                            udp->sum(cksum(udp));
17155484SN/A                            txUdpChecksums++;
17165484SN/A                        } else {
17178231SN/A                            Debug::breakpoint();
17185484SN/A                            warn_once("UDPPKT set, but not UDP!\n");
17195484SN/A                        }
17201909SN/A                    } else if (extsts & EXTSTS_TCPPKT) {
17211114SN/A                        TcpPtr tcp(ip);
17225484SN/A                        if (tcp) {
17235484SN/A                            tcp->sum(0);
17245484SN/A                            tcp->sum(cksum(tcp));
17255484SN/A                            txTcpChecksums++;
17265484SN/A                        } else {
17275484SN/A                            warn_once("TCPPKT set, but not UDP!\n");
17285484SN/A                        }
1729944SN/A                    }
17301909SN/A                    if (extsts & EXTSTS_IPPKT) {
17315484SN/A                        if (ip) {
17325484SN/A                            ip->sum(0);
17335484SN/A                            ip->sum(cksum(ip));
17345484SN/A                            txIpChecksums++;
17355484SN/A                        } else {
17365484SN/A                            warn_once("IPPKT set, but not UDP!\n");
17375484SN/A                        }
1738854SN/A                    }
1739854SN/A                }
1740854SN/A
174111701Smichael.lebeane@amd.com                txPacket->simLength = txPacketBufPtr - txPacket->data;
1742854SN/A                txPacket->length = txPacketBufPtr - txPacket->data;
17431027SN/A                // this is just because the receive can't handle a
17441027SN/A                // packet bigger want to make sure
17451909SN/A                if (txPacket->length > 1514)
17461909SN/A                    panic("transmit packet too large, %s > 1514\n",
17471909SN/A                          txPacket->length);
17481909SN/A
17491205SN/A#ifndef NDEBUG
17501205SN/A                bool success =
17511205SN/A#endif
17521205SN/A                    txFifo.push(txPacket);
17531205SN/A                assert(success);
1754854SN/A
17551027SN/A                /*
17561027SN/A                 * this following section is not tqo spec, but
17571027SN/A                 * functionally shouldn't be any different.  normally,
17581027SN/A                 * the chip will wait til the transmit has occurred
17591027SN/A                 * before writing back the descriptor because it has
17601027SN/A                 * to wait to see that it was successfully transmitted
17611027SN/A                 * to decide whether to set CMDSTS_OK or not.
17621027SN/A                 * however, in the simulator since it is always
17631027SN/A                 * successfully transmitted, and writing it exactly to
17641027SN/A                 * spec would complicate the code, we just do it here
17651027SN/A                 */
1766927SN/A
17671909SN/A                cmdsts &= ~CMDSTS_OWN;
17681909SN/A                cmdsts |= CMDSTS_OK;
1769854SN/A
1770927SN/A                DPRINTF(EthernetDesc,
17711036SN/A                        "txDesc writeback: cmdsts=%08x extsts=%08x\n",
17721909SN/A                        cmdsts, extsts);
17731909SN/A
1774854SN/A                txDmaFree = dmaDescFree;
17751909SN/A                txDmaAddr = regs.txdp & 0x3fffffff;
17761909SN/A                txDmaData = &cmdsts;
17771909SN/A                if (is64bit) {
17781909SN/A                    txDmaAddr += offsetof(ns_desc64, cmdsts);
17791909SN/A                    txDmaLen =
17801909SN/A                        sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts);
17811909SN/A                } else {
17821909SN/A                    txDmaAddr += offsetof(ns_desc32, cmdsts);
17831909SN/A                    txDmaLen =
17841909SN/A                        sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts);
17851909SN/A                }
1786854SN/A
1787961SN/A                descDmaWrites++;
1788961SN/A                descDmaWrBytes += txDmaLen;
1789961SN/A
1790927SN/A                transmit();
1791854SN/A                txPacket = 0;
1792854SN/A
17931035SN/A                if (!txEnable) {
1794927SN/A                    DPRINTF(EthernetSM, "halting TX state machine\n");
1795854SN/A                    txState = txIdle;
17961035SN/A                    goto exit;
1797854SN/A                } else
1798854SN/A                    txState = txAdvance;
1799986SN/A
1800986SN/A                if (doTxDmaWrite())
1801986SN/A                    goto exit;
1802854SN/A            }
1803854SN/A        } else {
1804927SN/A            DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
18051154SN/A            if (!txFifo.full()) {
1806992SN/A                txState = txFragRead;
1807992SN/A
18081027SN/A                /*
18091027SN/A                 * The number of bytes transferred is either whatever
18101027SN/A                 * is left in the descriptor (txDescCnt), or if there
18111027SN/A                 * is not enough room in the fifo, just whatever room
18121027SN/A                 * is left in the fifo
18131027SN/A                 */
18141154SN/A                txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());
1815992SN/A
1816992SN/A                txDmaAddr = txFragPtr & 0x3fffffff;
1817992SN/A                txDmaData = txPacketBufPtr;
1818992SN/A                txDmaLen = txXferLen;
1819992SN/A                txDmaFree = dmaDataFree;
1820992SN/A
1821992SN/A                if (doTxDmaRead())
1822992SN/A                    goto exit;
1823992SN/A            } else {
1824992SN/A                txState = txFifoBlock;
1825992SN/A                transmit();
1826992SN/A
1827998SN/A                goto exit;
1828992SN/A            }
1829992SN/A
1830854SN/A        }
1831854SN/A        break;
1832854SN/A
1833854SN/A      case txFragRead:
1834854SN/A        if (txDmaState != dmaIdle)
1835854SN/A            goto exit;
1836854SN/A
1837854SN/A        txPacketBufPtr += txXferLen;
1838854SN/A        txFragPtr += txXferLen;
1839854SN/A        txDescCnt -= txXferLen;
18401205SN/A        txFifo.reserve(txXferLen);
1841854SN/A
1842854SN/A        txState = txFifoBlock;
1843854SN/A        break;
1844854SN/A
1845854SN/A      case txDescWrite:
1846854SN/A        if (txDmaState != dmaIdle)
1847854SN/A            goto exit;
1848854SN/A
18491909SN/A        if (cmdsts & CMDSTS_INTR)
1850854SN/A            devIntrPost(ISR_TXDESC);
1851854SN/A
18521801SN/A        if (!txEnable) {
18531801SN/A            DPRINTF(EthernetSM, "halting TX state machine\n");
18541801SN/A            txState = txIdle;
18551801SN/A            goto exit;
18561801SN/A        } else
18571801SN/A            txState = txAdvance;
1858854SN/A        break;
1859854SN/A
1860854SN/A      case txAdvance:
18611909SN/A        if (link == 0) {
18621035SN/A            devIntrPost(ISR_TXIDLE);
1863837SN/A            txState = txIdle;
18641035SN/A            goto exit;
1865837SN/A        } else {
18661893SN/A            if (txDmaState != dmaIdle)
18671893SN/A                goto exit;
1868837SN/A            txState = txDescRead;
18691909SN/A            regs.txdp = link;
1870837SN/A            CTDD = false;
1871854SN/A
18721909SN/A            txDmaAddr = link & 0x3fffffff;
18731909SN/A            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
18741909SN/A            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
1875854SN/A            txDmaFree = dmaDescFree;
1876854SN/A
1877854SN/A            if (doTxDmaRead())
1878854SN/A                goto exit;
1879837SN/A        }
1880854SN/A        break;
1881837SN/A
1882854SN/A      default:
1883854SN/A        panic("invalid state");
1884837SN/A    }
1885837SN/A
18861036SN/A    DPRINTF(EthernetSM, "entering next txState=%s\n",
1887854SN/A            NsTxStateStrings[txState]);
1888854SN/A    goto next;
1889837SN/A
1890854SN/A  exit:
1891854SN/A    /**
1892854SN/A     * @todo do we want to schedule a future kick?
1893854SN/A     */
18941036SN/A    DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
1895854SN/A            NsTxStateStrings[txState]);
18961801SN/A
18979417SN/A    if (!txKickEvent.scheduled())
18985606SN/A        schedule(txKickEvent, txKickTick);
1899837SN/A}
1900837SN/A
19011843SN/A/**
19021843SN/A * Advance the EEPROM state machine
19031843SN/A * Called on rising edge of EEPROM clock bit in MEAR
19041843SN/A */
19051843SN/Avoid
19061843SN/ANSGigE::eepromKick()
19071843SN/A{
19081843SN/A    switch (eepromState) {
19091843SN/A
19101843SN/A      case eepromStart:
19111843SN/A
19121843SN/A        // Wait for start bit
19131843SN/A        if (regs.mear & MEAR_EEDI) {
19141843SN/A            // Set up to get 2 opcode bits
19151843SN/A            eepromState = eepromGetOpcode;
19161843SN/A            eepromBitsToRx = 2;
19171843SN/A            eepromOpcode = 0;
19181843SN/A        }
19191843SN/A        break;
19201843SN/A
19211843SN/A      case eepromGetOpcode:
19221843SN/A        eepromOpcode <<= 1;
19231843SN/A        eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0;
19241843SN/A        --eepromBitsToRx;
19251843SN/A
19261843SN/A        // Done getting opcode
19271843SN/A        if (eepromBitsToRx == 0) {
19281843SN/A            if (eepromOpcode != EEPROM_READ)
19291843SN/A                panic("only EEPROM reads are implemented!");
19301843SN/A
19311843SN/A            // Set up to get address
19321843SN/A            eepromState = eepromGetAddress;
19331843SN/A            eepromBitsToRx = 6;
19341843SN/A            eepromAddress = 0;
19351843SN/A        }
19361843SN/A        break;
19371843SN/A
19381843SN/A      case eepromGetAddress:
19391843SN/A        eepromAddress <<= 1;
19401843SN/A        eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0;
19411843SN/A        --eepromBitsToRx;
19421843SN/A
19431843SN/A        // Done getting address
19441843SN/A        if (eepromBitsToRx == 0) {
19451843SN/A
19461843SN/A            if (eepromAddress >= EEPROM_SIZE)
19471843SN/A                panic("EEPROM read access out of range!");
19481843SN/A
19491843SN/A            switch (eepromAddress) {
19501843SN/A
19511843SN/A              case EEPROM_PMATCH2_ADDR:
19521843SN/A                eepromData = rom.perfectMatch[5];
19531843SN/A                eepromData <<= 8;
19541843SN/A                eepromData += rom.perfectMatch[4];
19551843SN/A                break;
19561843SN/A
19571843SN/A              case EEPROM_PMATCH1_ADDR:
19581843SN/A                eepromData = rom.perfectMatch[3];
19591843SN/A                eepromData <<= 8;
19601843SN/A                eepromData += rom.perfectMatch[2];
19611843SN/A                break;
19621843SN/A
19631843SN/A              case EEPROM_PMATCH0_ADDR:
19641843SN/A                eepromData = rom.perfectMatch[1];
19651843SN/A                eepromData <<= 8;
19661843SN/A                eepromData += rom.perfectMatch[0];
19671843SN/A                break;
19681843SN/A
19691843SN/A              default:
19701843SN/A                panic("FreeBSD driver only uses EEPROM to read PMATCH!");
19711843SN/A            }
19721843SN/A            // Set up to read data
19731843SN/A            eepromState = eepromRead;
19741843SN/A            eepromBitsToRx = 16;
19751843SN/A
19761843SN/A            // Clear data in bit
19771843SN/A            regs.mear &= ~MEAR_EEDI;
19781843SN/A        }
19791843SN/A        break;
19801843SN/A
19811843SN/A      case eepromRead:
19821843SN/A        // Clear Data Out bit
19831843SN/A        regs.mear &= ~MEAR_EEDO;
19841843SN/A        // Set bit to value of current EEPROM bit
19851843SN/A        regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0;
19861843SN/A
19871843SN/A        eepromData <<= 1;
19881843SN/A        --eepromBitsToRx;
19891843SN/A
19901843SN/A        // All done
19911843SN/A        if (eepromBitsToRx == 0) {
19921843SN/A            eepromState = eepromStart;
19931843SN/A        }
19941843SN/A        break;
19951843SN/A
19961843SN/A      default:
19971843SN/A        panic("invalid EEPROM state");
19981843SN/A    }
19991843SN/A
20001843SN/A}
20011843SN/A
2002837SN/Avoid
2003879SN/ANSGigE::transferDone()
2004837SN/A{
20051036SN/A    if (txFifo.empty()) {
20061036SN/A        DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
2007837SN/A        return;
20081036SN/A    }
20091036SN/A
20101036SN/A    DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
2011837SN/A
20129417SN/A    reschedule(txEvent, clockEdge(Cycles(1)), true);
2013837SN/A}
2014837SN/A
2015837SN/Abool
20162566SN/ANSGigE::rxFilter(const EthPacketPtr &packet)
2017837SN/A{
20181114SN/A    EthPtr eth = packet;
2019837SN/A    bool drop = true;
2020837SN/A    string type;
2021837SN/A
20221114SN/A    const EthAddr &dst = eth->dst();
20231114SN/A    if (dst.unicast()) {
2024837SN/A        // If we're accepting all unicast addresses
2025837SN/A        if (acceptUnicast)
2026837SN/A            drop = false;
2027837SN/A
2028837SN/A        // If we make a perfect match
20291114SN/A        if (acceptPerfect && dst == rom.perfectMatch)
2030837SN/A            drop = false;
2031837SN/A
20321078SN/A        if (acceptArp && eth->type() == ETH_TYPE_ARP)
2033837SN/A            drop = false;
2034837SN/A
20351114SN/A    } else if (dst.broadcast()) {
2036837SN/A        // if we're accepting broadcasts
2037837SN/A        if (acceptBroadcast)
2038837SN/A            drop = false;
2039837SN/A
20401114SN/A    } else if (dst.multicast()) {
2041837SN/A        // if we're accepting all multicasts
2042837SN/A        if (acceptMulticast)
2043837SN/A            drop = false;
2044837SN/A
20451843SN/A        // Multicast hashing faked - all packets accepted
20461843SN/A        if (multicastHashEnable)
20471843SN/A            drop = false;
2048837SN/A    }
2049837SN/A
2050837SN/A    if (drop) {
2051837SN/A        DPRINTF(Ethernet, "rxFilter drop\n");
2052837SN/A        DDUMP(EthernetData, packet->data, packet->length);
2053837SN/A    }
2054837SN/A
2055837SN/A    return drop;
2056837SN/A}
2057837SN/A
2058837SN/Abool
20592566SN/ANSGigE::recvPacket(EthPacketPtr packet)
2060837SN/A{
2061837SN/A    rxBytes += packet->length;
2062837SN/A    rxPackets++;
2063837SN/A
20641036SN/A    DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n",
20651154SN/A            rxFifo.avail());
2066927SN/A
20671035SN/A    if (!rxEnable) {
2068837SN/A        DPRINTF(Ethernet, "receive disabled...packet dropped\n");
2069837SN/A        return true;
2070837SN/A    }
2071837SN/A
20721843SN/A    if (!rxFilterEnable) {
20731843SN/A        DPRINTF(Ethernet,
20741843SN/A            "receive packet filtering disabled . . . packet dropped\n");
20751843SN/A        return true;
20761843SN/A    }
20771843SN/A
20781843SN/A    if (rxFilter(packet)) {
2079837SN/A        DPRINTF(Ethernet, "packet filtered...dropped\n");
2080837SN/A        return true;
2081837SN/A    }
2082837SN/A
20831154SN/A    if (rxFifo.avail() < packet->length) {
20841561SN/A#if TRACING_ON
20851561SN/A        IpPtr ip(packet);
20861561SN/A        TcpPtr tcp(ip);
20871561SN/A        if (ip) {
20881561SN/A            DPRINTF(Ethernet,
20891561SN/A                    "packet won't fit in receive buffer...pkt ID %d dropped\n",
20901561SN/A                    ip->id());
20911561SN/A            if (tcp) {
20921561SN/A                DPRINTF(Ethernet, "Seq=%d\n", tcp->seq());
20931561SN/A            }
20941561SN/A        }
20951561SN/A#endif
20961263SN/A        droppedPackets++;
2097837SN/A        devIntrPost(ISR_RXORN);
2098837SN/A        return false;
2099837SN/A    }
2100837SN/A
21011154SN/A    rxFifo.push(packet);
2102837SN/A
2103854SN/A    rxKick();
2104837SN/A    return true;
2105837SN/A}
2106837SN/A
21072901SN/A
21082901SN/Avoid
21099342SN/ANSGigE::drainResume()
21102901SN/A{
21119342SN/A    Drainable::drainResume();
21122901SN/A
21132901SN/A    // During drain we could have left the state machines in a waiting state and
21142901SN/A    // they wouldn't get out until some other event occured to kick them.
21152901SN/A    // This way they'll get out immediately
21162901SN/A    txKick();
21172901SN/A    rxKick();
21182901SN/A}
21192901SN/A
21202901SN/A
2121837SN/A//=====================================================================
2122837SN/A//
2123837SN/A//
2124837SN/Avoid
212510905SN/ANSGigE::serialize(CheckpointOut &cp) const
2126837SN/A{
21279807SN/A    // Serialize the PciDevice base class
212810905SN/A    PciDevice::serialize(cp);
2129897SN/A
2130854SN/A    /*
2131854SN/A     * Finalize any DMA events now.
2132854SN/A     */
21332566SN/A    // @todo will mem system save pending dma?
2134837SN/A
2135854SN/A    /*
2136854SN/A     * Serialize the device registers
2137854SN/A     */
2138854SN/A    SERIALIZE_SCALAR(regs.command);
2139854SN/A    SERIALIZE_SCALAR(regs.config);
2140854SN/A    SERIALIZE_SCALAR(regs.mear);
2141854SN/A    SERIALIZE_SCALAR(regs.ptscr);
2142854SN/A    SERIALIZE_SCALAR(regs.isr);
2143854SN/A    SERIALIZE_SCALAR(regs.imr);
2144854SN/A    SERIALIZE_SCALAR(regs.ier);
2145854SN/A    SERIALIZE_SCALAR(regs.ihr);
2146854SN/A    SERIALIZE_SCALAR(regs.txdp);
2147854SN/A    SERIALIZE_SCALAR(regs.txdp_hi);
2148854SN/A    SERIALIZE_SCALAR(regs.txcfg);
2149854SN/A    SERIALIZE_SCALAR(regs.gpior);
2150854SN/A    SERIALIZE_SCALAR(regs.rxdp);
2151854SN/A    SERIALIZE_SCALAR(regs.rxdp_hi);
2152854SN/A    SERIALIZE_SCALAR(regs.rxcfg);
2153854SN/A    SERIALIZE_SCALAR(regs.pqcr);
2154854SN/A    SERIALIZE_SCALAR(regs.wcsr);
2155854SN/A    SERIALIZE_SCALAR(regs.pcr);
2156854SN/A    SERIALIZE_SCALAR(regs.rfcr);
2157854SN/A    SERIALIZE_SCALAR(regs.rfdr);
21581843SN/A    SERIALIZE_SCALAR(regs.brar);
21591843SN/A    SERIALIZE_SCALAR(regs.brdr);
2160854SN/A    SERIALIZE_SCALAR(regs.srr);
2161854SN/A    SERIALIZE_SCALAR(regs.mibc);
2162854SN/A    SERIALIZE_SCALAR(regs.vrcr);
2163854SN/A    SERIALIZE_SCALAR(regs.vtcr);
2164854SN/A    SERIALIZE_SCALAR(regs.vdr);
2165854SN/A    SERIALIZE_SCALAR(regs.ccsr);
2166854SN/A    SERIALIZE_SCALAR(regs.tbicr);
2167854SN/A    SERIALIZE_SCALAR(regs.tbisr);
2168854SN/A    SERIALIZE_SCALAR(regs.tanar);
2169854SN/A    SERIALIZE_SCALAR(regs.tanlpar);
2170854SN/A    SERIALIZE_SCALAR(regs.taner);
2171854SN/A    SERIALIZE_SCALAR(regs.tesr);
2172837SN/A
21731114SN/A    SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
21741843SN/A    SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2175837SN/A
2176927SN/A    SERIALIZE_SCALAR(ioEnable);
2177917SN/A
2178854SN/A    /*
2179915SN/A     * Serialize the data Fifos
2180915SN/A     */
218110905SN/A    rxFifo.serialize("rxFifo", cp);
218210905SN/A    txFifo.serialize("txFifo", cp);
2183915SN/A
2184915SN/A    /*
2185854SN/A     * Serialize the various helper variables
2186854SN/A     */
218710469SN/A    bool txPacketExists = txPacket != nullptr;
2188915SN/A    SERIALIZE_SCALAR(txPacketExists);
2189915SN/A    if (txPacketExists) {
219011701Smichael.lebeane@amd.com        txPacket->simLength = txPacketBufPtr - txPacket->data;
21911337SN/A        txPacket->length = txPacketBufPtr - txPacket->data;
219210905SN/A        txPacket->serialize("txPacket", cp);
2193915SN/A        uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
2194915SN/A        SERIALIZE_SCALAR(txPktBufPtr);
2195915SN/A    }
2196915SN/A
219710469SN/A    bool rxPacketExists = rxPacket != nullptr;
2198915SN/A    SERIALIZE_SCALAR(rxPacketExists);
2199915SN/A    if (rxPacketExists) {
220010905SN/A        rxPacket->serialize("rxPacket", cp);
2201915SN/A        uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
2202915SN/A        SERIALIZE_SCALAR(rxPktBufPtr);
2203915SN/A    }
2204915SN/A
2205854SN/A    SERIALIZE_SCALAR(txXferLen);
2206854SN/A    SERIALIZE_SCALAR(rxXferLen);
2207837SN/A
2208854SN/A    /*
22091909SN/A     * Serialize Cached Descriptors
2210854SN/A     */
22111909SN/A    SERIALIZE_SCALAR(rxDesc64.link);
22121909SN/A    SERIALIZE_SCALAR(rxDesc64.bufptr);
22131909SN/A    SERIALIZE_SCALAR(rxDesc64.cmdsts);
22141909SN/A    SERIALIZE_SCALAR(rxDesc64.extsts);
22151909SN/A    SERIALIZE_SCALAR(txDesc64.link);
22161909SN/A    SERIALIZE_SCALAR(txDesc64.bufptr);
22171909SN/A    SERIALIZE_SCALAR(txDesc64.cmdsts);
22181909SN/A    SERIALIZE_SCALAR(txDesc64.extsts);
22191909SN/A    SERIALIZE_SCALAR(rxDesc32.link);
22201909SN/A    SERIALIZE_SCALAR(rxDesc32.bufptr);
22211909SN/A    SERIALIZE_SCALAR(rxDesc32.cmdsts);
22221909SN/A    SERIALIZE_SCALAR(rxDesc32.extsts);
22231909SN/A    SERIALIZE_SCALAR(txDesc32.link);
22241909SN/A    SERIALIZE_SCALAR(txDesc32.bufptr);
22251909SN/A    SERIALIZE_SCALAR(txDesc32.cmdsts);
22261909SN/A    SERIALIZE_SCALAR(txDesc32.extsts);
22271801SN/A    SERIALIZE_SCALAR(extstsEnable);
2228837SN/A
2229854SN/A    /*
2230854SN/A     * Serialize tx state machine
2231854SN/A     */
2232854SN/A    int txState = this->txState;
2233854SN/A    SERIALIZE_SCALAR(txState);
22341035SN/A    SERIALIZE_SCALAR(txEnable);
2235854SN/A    SERIALIZE_SCALAR(CTDD);
2236854SN/A    SERIALIZE_SCALAR(txFragPtr);
2237854SN/A    SERIALIZE_SCALAR(txDescCnt);
2238854SN/A    int txDmaState = this->txDmaState;
2239854SN/A    SERIALIZE_SCALAR(txDmaState);
22401801SN/A    SERIALIZE_SCALAR(txKickTick);
2241854SN/A
2242854SN/A    /*
2243854SN/A     * Serialize rx state machine
2244854SN/A     */
2245854SN/A    int rxState = this->rxState;
2246854SN/A    SERIALIZE_SCALAR(rxState);
22471035SN/A    SERIALIZE_SCALAR(rxEnable);
2248854SN/A    SERIALIZE_SCALAR(CRDD);
2249854SN/A    SERIALIZE_SCALAR(rxPktBytes);
22501224SN/A    SERIALIZE_SCALAR(rxFragPtr);
2251854SN/A    SERIALIZE_SCALAR(rxDescCnt);
2252854SN/A    int rxDmaState = this->rxDmaState;
2253854SN/A    SERIALIZE_SCALAR(rxDmaState);
22541801SN/A    SERIALIZE_SCALAR(rxKickTick);
2255854SN/A
2256915SN/A    /*
22571843SN/A     * Serialize EEPROM state machine
22581843SN/A     */
22591843SN/A    int eepromState = this->eepromState;
22601843SN/A    SERIALIZE_SCALAR(eepromState);
22611843SN/A    SERIALIZE_SCALAR(eepromClk);
22621843SN/A    SERIALIZE_SCALAR(eepromBitsToRx);
22631843SN/A    SERIALIZE_SCALAR(eepromOpcode);
22641843SN/A    SERIALIZE_SCALAR(eepromAddress);
22651843SN/A    SERIALIZE_SCALAR(eepromData);
22661843SN/A
22671843SN/A    /*
2268854SN/A     * If there's a pending transmit, store the time so we can
2269854SN/A     * reschedule it later
2270854SN/A     */
22717823SN/A    Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick() : 0;
2272854SN/A    SERIALIZE_SCALAR(transmitTick);
2273854SN/A
2274854SN/A    /*
2275915SN/A     * receive address filter settings
2276915SN/A     */
2277915SN/A    SERIALIZE_SCALAR(rxFilterEnable);
2278915SN/A    SERIALIZE_SCALAR(acceptBroadcast);
2279915SN/A    SERIALIZE_SCALAR(acceptMulticast);
2280915SN/A    SERIALIZE_SCALAR(acceptUnicast);
2281915SN/A    SERIALIZE_SCALAR(acceptPerfect);
2282915SN/A    SERIALIZE_SCALAR(acceptArp);
22831843SN/A    SERIALIZE_SCALAR(multicastHashEnable);
2284915SN/A
2285915SN/A    /*
2286854SN/A     * Keep track of pending interrupt status.
2287854SN/A     */
2288854SN/A    SERIALIZE_SCALAR(intrTick);
2289854SN/A    SERIALIZE_SCALAR(cpuPendingIntr);
2290854SN/A    Tick intrEventTick = 0;
2291854SN/A    if (intrEvent)
2292854SN/A        intrEventTick = intrEvent->when();
2293854SN/A    SERIALIZE_SCALAR(intrEventTick);
2294854SN/A
2295837SN/A}
2296837SN/A
2297837SN/Avoid
229810905SN/ANSGigE::unserialize(CheckpointIn &cp)
2299837SN/A{
23009807SN/A    // Unserialize the PciDevice base class
230110905SN/A    PciDevice::unserialize(cp);
2302897SN/A
2303854SN/A    UNSERIALIZE_SCALAR(regs.command);
2304854SN/A    UNSERIALIZE_SCALAR(regs.config);
2305854SN/A    UNSERIALIZE_SCALAR(regs.mear);
2306854SN/A    UNSERIALIZE_SCALAR(regs.ptscr);
2307854SN/A    UNSERIALIZE_SCALAR(regs.isr);
2308854SN/A    UNSERIALIZE_SCALAR(regs.imr);
2309854SN/A    UNSERIALIZE_SCALAR(regs.ier);
2310854SN/A    UNSERIALIZE_SCALAR(regs.ihr);
2311854SN/A    UNSERIALIZE_SCALAR(regs.txdp);
2312854SN/A    UNSERIALIZE_SCALAR(regs.txdp_hi);
2313854SN/A    UNSERIALIZE_SCALAR(regs.txcfg);
2314854SN/A    UNSERIALIZE_SCALAR(regs.gpior);
2315854SN/A    UNSERIALIZE_SCALAR(regs.rxdp);
2316854SN/A    UNSERIALIZE_SCALAR(regs.rxdp_hi);
2317854SN/A    UNSERIALIZE_SCALAR(regs.rxcfg);
2318854SN/A    UNSERIALIZE_SCALAR(regs.pqcr);
2319854SN/A    UNSERIALIZE_SCALAR(regs.wcsr);
2320854SN/A    UNSERIALIZE_SCALAR(regs.pcr);
2321854SN/A    UNSERIALIZE_SCALAR(regs.rfcr);
2322854SN/A    UNSERIALIZE_SCALAR(regs.rfdr);
23231843SN/A    UNSERIALIZE_SCALAR(regs.brar);
23241843SN/A    UNSERIALIZE_SCALAR(regs.brdr);
2325854SN/A    UNSERIALIZE_SCALAR(regs.srr);
2326854SN/A    UNSERIALIZE_SCALAR(regs.mibc);
2327854SN/A    UNSERIALIZE_SCALAR(regs.vrcr);
2328854SN/A    UNSERIALIZE_SCALAR(regs.vtcr);
2329854SN/A    UNSERIALIZE_SCALAR(regs.vdr);
2330854SN/A    UNSERIALIZE_SCALAR(regs.ccsr);
2331854SN/A    UNSERIALIZE_SCALAR(regs.tbicr);
2332854SN/A    UNSERIALIZE_SCALAR(regs.tbisr);
2333854SN/A    UNSERIALIZE_SCALAR(regs.tanar);
2334854SN/A    UNSERIALIZE_SCALAR(regs.tanlpar);
2335854SN/A    UNSERIALIZE_SCALAR(regs.taner);
2336854SN/A    UNSERIALIZE_SCALAR(regs.tesr);
2337837SN/A
23381114SN/A    UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
23391843SN/A    UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2340837SN/A
2341927SN/A    UNSERIALIZE_SCALAR(ioEnable);
2342917SN/A
2343854SN/A    /*
2344915SN/A     * unserialize the data fifos
2345915SN/A     */
234610905SN/A    rxFifo.unserialize("rxFifo", cp);
234710905SN/A    txFifo.unserialize("txFifo", cp);
2348915SN/A
2349915SN/A    /*
2350854SN/A     * unserialize the various helper variables
2351854SN/A     */
2352915SN/A    bool txPacketExists;
2353915SN/A    UNSERIALIZE_SCALAR(txPacketExists);
2354915SN/A    if (txPacketExists) {
235511701Smichael.lebeane@amd.com        txPacket = make_shared<EthPacketData>();
235610905SN/A        txPacket->unserialize("txPacket", cp);
2357915SN/A        uint32_t txPktBufPtr;
2358915SN/A        UNSERIALIZE_SCALAR(txPktBufPtr);
2359915SN/A        txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
2360915SN/A    } else
2361915SN/A        txPacket = 0;
2362915SN/A
2363915SN/A    bool rxPacketExists;
2364915SN/A    UNSERIALIZE_SCALAR(rxPacketExists);
2365915SN/A    rxPacket = 0;
2366915SN/A    if (rxPacketExists) {
236711701Smichael.lebeane@amd.com        rxPacket = make_shared<EthPacketData>();
236810905SN/A        rxPacket->unserialize("rxPacket", cp);
2369915SN/A        uint32_t rxPktBufPtr;
2370915SN/A        UNSERIALIZE_SCALAR(rxPktBufPtr);
2371915SN/A        rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
2372915SN/A    } else
2373915SN/A        rxPacket = 0;
2374915SN/A
2375854SN/A    UNSERIALIZE_SCALAR(txXferLen);
2376854SN/A    UNSERIALIZE_SCALAR(rxXferLen);
2377837SN/A
2378854SN/A    /*
23791909SN/A     * Unserialize Cached Descriptors
2380854SN/A     */
23811909SN/A    UNSERIALIZE_SCALAR(rxDesc64.link);
23821909SN/A    UNSERIALIZE_SCALAR(rxDesc64.bufptr);
23831909SN/A    UNSERIALIZE_SCALAR(rxDesc64.cmdsts);
23841909SN/A    UNSERIALIZE_SCALAR(rxDesc64.extsts);
23851909SN/A    UNSERIALIZE_SCALAR(txDesc64.link);
23861909SN/A    UNSERIALIZE_SCALAR(txDesc64.bufptr);
23871909SN/A    UNSERIALIZE_SCALAR(txDesc64.cmdsts);
23881909SN/A    UNSERIALIZE_SCALAR(txDesc64.extsts);
23891909SN/A    UNSERIALIZE_SCALAR(rxDesc32.link);
23901909SN/A    UNSERIALIZE_SCALAR(rxDesc32.bufptr);
23911909SN/A    UNSERIALIZE_SCALAR(rxDesc32.cmdsts);
23921909SN/A    UNSERIALIZE_SCALAR(rxDesc32.extsts);
23931909SN/A    UNSERIALIZE_SCALAR(txDesc32.link);
23941909SN/A    UNSERIALIZE_SCALAR(txDesc32.bufptr);
23951909SN/A    UNSERIALIZE_SCALAR(txDesc32.cmdsts);
23961909SN/A    UNSERIALIZE_SCALAR(txDesc32.extsts);
23971801SN/A    UNSERIALIZE_SCALAR(extstsEnable);
2398854SN/A
2399854SN/A    /*
2400854SN/A     * unserialize tx state machine
2401854SN/A     */
2402854SN/A    int txState;
2403854SN/A    UNSERIALIZE_SCALAR(txState);
2404854SN/A    this->txState = (TxState) txState;
24051035SN/A    UNSERIALIZE_SCALAR(txEnable);
2406854SN/A    UNSERIALIZE_SCALAR(CTDD);
2407854SN/A    UNSERIALIZE_SCALAR(txFragPtr);
2408854SN/A    UNSERIALIZE_SCALAR(txDescCnt);
2409854SN/A    int txDmaState;
2410854SN/A    UNSERIALIZE_SCALAR(txDmaState);
2411854SN/A    this->txDmaState = (DmaState) txDmaState;
24121801SN/A    UNSERIALIZE_SCALAR(txKickTick);
24131801SN/A    if (txKickTick)
24145606SN/A        schedule(txKickEvent, txKickTick);
2415854SN/A
2416854SN/A    /*
2417854SN/A     * unserialize rx state machine
2418854SN/A     */
2419854SN/A    int rxState;
2420854SN/A    UNSERIALIZE_SCALAR(rxState);
2421854SN/A    this->rxState = (RxState) rxState;
24221035SN/A    UNSERIALIZE_SCALAR(rxEnable);
2423854SN/A    UNSERIALIZE_SCALAR(CRDD);
2424854SN/A    UNSERIALIZE_SCALAR(rxPktBytes);
24251224SN/A    UNSERIALIZE_SCALAR(rxFragPtr);
2426854SN/A    UNSERIALIZE_SCALAR(rxDescCnt);
2427854SN/A    int rxDmaState;
2428854SN/A    UNSERIALIZE_SCALAR(rxDmaState);
2429854SN/A    this->rxDmaState = (DmaState) rxDmaState;
24301801SN/A    UNSERIALIZE_SCALAR(rxKickTick);
24311801SN/A    if (rxKickTick)
24325606SN/A        schedule(rxKickEvent, rxKickTick);
2433854SN/A
24341843SN/A    /*
24351843SN/A     * Unserialize EEPROM state machine
24361843SN/A     */
24371843SN/A    int eepromState;
24381843SN/A    UNSERIALIZE_SCALAR(eepromState);
24391843SN/A    this->eepromState = (EEPROMState) eepromState;
24401843SN/A    UNSERIALIZE_SCALAR(eepromClk);
24411843SN/A    UNSERIALIZE_SCALAR(eepromBitsToRx);
24421843SN/A    UNSERIALIZE_SCALAR(eepromOpcode);
24431843SN/A    UNSERIALIZE_SCALAR(eepromAddress);
24441843SN/A    UNSERIALIZE_SCALAR(eepromData);
24451843SN/A
24461843SN/A    /*
2447915SN/A     * If there's a pending transmit, reschedule it now
2448854SN/A     */
2449854SN/A    Tick transmitTick;
2450854SN/A    UNSERIALIZE_SCALAR(transmitTick);
2451854SN/A    if (transmitTick)
24527823SN/A        schedule(txEvent, curTick() + transmitTick);
2453854SN/A
2454854SN/A    /*
2455915SN/A     * unserialize receive address filter settings
2456915SN/A     */
2457915SN/A    UNSERIALIZE_SCALAR(rxFilterEnable);
2458915SN/A    UNSERIALIZE_SCALAR(acceptBroadcast);
2459915SN/A    UNSERIALIZE_SCALAR(acceptMulticast);
2460915SN/A    UNSERIALIZE_SCALAR(acceptUnicast);
2461915SN/A    UNSERIALIZE_SCALAR(acceptPerfect);
2462915SN/A    UNSERIALIZE_SCALAR(acceptArp);
24631843SN/A    UNSERIALIZE_SCALAR(multicastHashEnable);
2464915SN/A
2465915SN/A    /*
2466854SN/A     * Keep track of pending interrupt status.
2467854SN/A     */
2468854SN/A    UNSERIALIZE_SCALAR(intrTick);
2469854SN/A    UNSERIALIZE_SCALAR(cpuPendingIntr);
2470854SN/A    Tick intrEventTick;
2471854SN/A    UNSERIALIZE_SCALAR(intrEventTick);
2472854SN/A    if (intrEventTick) {
24735606SN/A        intrEvent = new IntrEvent(this, true);
24745606SN/A        schedule(intrEvent, intrEventTick);
2475854SN/A    }
2476854SN/A}
2477927SN/A
24784762SN/ANSGigE *
24794762SN/ANSGigEParams::create()
2480837SN/A{
24814762SN/A    return new NSGigE(this);
2482837SN/A}
2483