ns_gige.cc revision 2846
19244SN/A/*
29244SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
312268Sradhika.jagtap@arm.com * All rights reserved.
412268Sradhika.jagtap@arm.com *
512268Sradhika.jagtap@arm.com * Redistribution and use in source and binary forms, with or without
612268Sradhika.jagtap@arm.com * modification, are permitted provided that the following conditions are
712268Sradhika.jagtap@arm.com * met: redistributions of source code must retain the above copyright
812268Sradhika.jagtap@arm.com * notice, this list of conditions and the following disclaimer;
912268Sradhika.jagtap@arm.com * redistributions in binary form must reproduce the above copyright
1012268Sradhika.jagtap@arm.com * notice, this list of conditions and the following disclaimer in the
1112268Sradhika.jagtap@arm.com * documentation and/or other materials provided with the distribution;
1212268Sradhika.jagtap@arm.com * neither the name of the copyright holders nor the names of its
1312268Sradhika.jagtap@arm.com * contributors may be used to endorse or promote products derived from
1412268Sradhika.jagtap@arm.com * this software without specific prior written permission.
1512268Sradhika.jagtap@arm.com *
1612268Sradhika.jagtap@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712268Sradhika.jagtap@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812268Sradhika.jagtap@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912268Sradhika.jagtap@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012268Sradhika.jagtap@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112268Sradhika.jagtap@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212268Sradhika.jagtap@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312268Sradhika.jagtap@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412268Sradhika.jagtap@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512268Sradhika.jagtap@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612268Sradhika.jagtap@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712268Sradhika.jagtap@arm.com *
2812268Sradhika.jagtap@arm.com * Authors: Nathan Binkert
2912268Sradhika.jagtap@arm.com *          Lisa Hsu
3012268Sradhika.jagtap@arm.com */
3112268Sradhika.jagtap@arm.com
3212268Sradhika.jagtap@arm.com/** @file
3312268Sradhika.jagtap@arm.com * Device module for modelling the National Semiconductor
3412268Sradhika.jagtap@arm.com * DP83820 ethernet controller.  Does not support priority queueing
3512268Sradhika.jagtap@arm.com */
3612268Sradhika.jagtap@arm.com#include <deque>
3712268Sradhika.jagtap@arm.com#include <string>
3812268Sradhika.jagtap@arm.com
3912268Sradhika.jagtap@arm.com#include "arch/alpha/ev5.hh"
4012268Sradhika.jagtap@arm.com#include "base/inet.hh"
4112268Sradhika.jagtap@arm.com#include "cpu/thread_context.hh"
4212268Sradhika.jagtap@arm.com#include "dev/etherlink.hh"
4312268Sradhika.jagtap@arm.com#include "dev/ns_gige.hh"
4412268Sradhika.jagtap@arm.com#include "dev/pciconfigall.hh"
4512268Sradhika.jagtap@arm.com#include "mem/packet.hh"
4612268Sradhika.jagtap@arm.com#include "sim/builder.hh"
4712268Sradhika.jagtap@arm.com#include "sim/debug.hh"
4812268Sradhika.jagtap@arm.com#include "sim/host.hh"
4912268Sradhika.jagtap@arm.com#include "sim/stats.hh"
5012268Sradhika.jagtap@arm.com#include "sim/system.hh"
5112268Sradhika.jagtap@arm.com
5212268Sradhika.jagtap@arm.comconst char *NsRxStateStrings[] =
5312268Sradhika.jagtap@arm.com{
5412268Sradhika.jagtap@arm.com    "rxIdle",
5512268Sradhika.jagtap@arm.com    "rxDescRefr",
5612268Sradhika.jagtap@arm.com    "rxDescRead",
5712268Sradhika.jagtap@arm.com    "rxFifoBlock",
5812268Sradhika.jagtap@arm.com    "rxFragWrite",
5912268Sradhika.jagtap@arm.com    "rxDescWrite",
6012268Sradhika.jagtap@arm.com    "rxAdvance"
6112268Sradhika.jagtap@arm.com};
6212268Sradhika.jagtap@arm.com
6312268Sradhika.jagtap@arm.comconst char *NsTxStateStrings[] =
6412268Sradhika.jagtap@arm.com{
6512268Sradhika.jagtap@arm.com    "txIdle",
6612268Sradhika.jagtap@arm.com    "txDescRefr",
6712268Sradhika.jagtap@arm.com    "txDescRead",
6812268Sradhika.jagtap@arm.com    "txFifoBlock",
6912268Sradhika.jagtap@arm.com    "txFragRead",
7012268Sradhika.jagtap@arm.com    "txDescWrite",
7112268Sradhika.jagtap@arm.com    "txAdvance"
7212268Sradhika.jagtap@arm.com};
7312268Sradhika.jagtap@arm.com
7412268Sradhika.jagtap@arm.comconst char *NsDmaState[] =
7512268Sradhika.jagtap@arm.com{
7612268Sradhika.jagtap@arm.com    "dmaIdle",
7712268Sradhika.jagtap@arm.com    "dmaReading",
7812268Sradhika.jagtap@arm.com    "dmaWriting",
7912268Sradhika.jagtap@arm.com    "dmaReadWaiting",
8012268Sradhika.jagtap@arm.com    "dmaWriteWaiting"
8112268Sradhika.jagtap@arm.com};
8212268Sradhika.jagtap@arm.com
8312268Sradhika.jagtap@arm.comusing namespace std;
8412268Sradhika.jagtap@arm.comusing namespace Net;
8512268Sradhika.jagtap@arm.comusing namespace TheISA;
8612268Sradhika.jagtap@arm.com
8712268Sradhika.jagtap@arm.com///////////////////////////////////////////////////////////////////////
8812268Sradhika.jagtap@arm.com//
8912268Sradhika.jagtap@arm.com// NSGigE PCI Device
9012268Sradhika.jagtap@arm.com//
9112268Sradhika.jagtap@arm.comNSGigE::NSGigE(Params *p)
9212268Sradhika.jagtap@arm.com    : PciDev(p), ioEnable(false),
9312268Sradhika.jagtap@arm.com      txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size),
9412268Sradhika.jagtap@arm.com      txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
9512268Sradhika.jagtap@arm.com      txXferLen(0), rxXferLen(0), clock(p->clock),
9612268Sradhika.jagtap@arm.com      txState(txIdle), txEnable(false), CTDD(false),
9712268Sradhika.jagtap@arm.com      txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
9812268Sradhika.jagtap@arm.com      rxEnable(false), CRDD(false), rxPktBytes(0),
9912268Sradhika.jagtap@arm.com      rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false),
10012268Sradhika.jagtap@arm.com      eepromState(eepromStart), rxDmaReadEvent(this), rxDmaWriteEvent(this),
10112268Sradhika.jagtap@arm.com      txDmaReadEvent(this), txDmaWriteEvent(this),
10212268Sradhika.jagtap@arm.com      dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free),
10312268Sradhika.jagtap@arm.com      txDelay(p->tx_delay), rxDelay(p->rx_delay),
10412268Sradhika.jagtap@arm.com      rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this),
10512268Sradhika.jagtap@arm.com      txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false),
10612268Sradhika.jagtap@arm.com      acceptMulticast(false), acceptUnicast(false),
10712268Sradhika.jagtap@arm.com      acceptPerfect(false), acceptArp(false), multicastHashEnable(false),
10812268Sradhika.jagtap@arm.com      intrTick(0), cpuPendingIntr(false),
10912268Sradhika.jagtap@arm.com      intrEvent(0), interface(0)
11012268Sradhika.jagtap@arm.com{
11112268Sradhika.jagtap@arm.com
11212268Sradhika.jagtap@arm.com    intrDelay = p->intr_delay;
11312268Sradhika.jagtap@arm.com    dmaReadDelay = p->dma_read_delay;
11412268Sradhika.jagtap@arm.com    dmaWriteDelay = p->dma_write_delay;
11512268Sradhika.jagtap@arm.com    dmaReadFactor = p->dma_read_factor;
11612268Sradhika.jagtap@arm.com    dmaWriteFactor = p->dma_write_factor;
11712268Sradhika.jagtap@arm.com
11812268Sradhika.jagtap@arm.com    regsReset();
11912268Sradhika.jagtap@arm.com    memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN);
12012268Sradhika.jagtap@arm.com
12112268Sradhika.jagtap@arm.com    memset(&rxDesc32, 0, sizeof(rxDesc32));
12212268Sradhika.jagtap@arm.com    memset(&txDesc32, 0, sizeof(txDesc32));
12312268Sradhika.jagtap@arm.com    memset(&rxDesc64, 0, sizeof(rxDesc64));
12412268Sradhika.jagtap@arm.com    memset(&txDesc64, 0, sizeof(txDesc64));
12512268Sradhika.jagtap@arm.com}
12612268Sradhika.jagtap@arm.com
12712268Sradhika.jagtap@arm.comNSGigE::~NSGigE()
12812268Sradhika.jagtap@arm.com{}
12912268Sradhika.jagtap@arm.com
13012268Sradhika.jagtap@arm.comvoid
13112268Sradhika.jagtap@arm.comNSGigE::regStats()
13212268Sradhika.jagtap@arm.com{
13312268Sradhika.jagtap@arm.com    txBytes
13412268Sradhika.jagtap@arm.com        .name(name() + ".txBytes")
13512268Sradhika.jagtap@arm.com        .desc("Bytes Transmitted")
13612268Sradhika.jagtap@arm.com        .prereq(txBytes)
13712268Sradhika.jagtap@arm.com        ;
13812268Sradhika.jagtap@arm.com
13912268Sradhika.jagtap@arm.com    rxBytes
14012268Sradhika.jagtap@arm.com        .name(name() + ".rxBytes")
14112268Sradhika.jagtap@arm.com        .desc("Bytes Received")
14212268Sradhika.jagtap@arm.com        .prereq(rxBytes)
14312268Sradhika.jagtap@arm.com        ;
14412268Sradhika.jagtap@arm.com
14512268Sradhika.jagtap@arm.com    txPackets
14612268Sradhika.jagtap@arm.com        .name(name() + ".txPackets")
14712268Sradhika.jagtap@arm.com        .desc("Number of Packets Transmitted")
14812268Sradhika.jagtap@arm.com        .prereq(txBytes)
14912268Sradhika.jagtap@arm.com        ;
15012268Sradhika.jagtap@arm.com
15112268Sradhika.jagtap@arm.com    rxPackets
15212268Sradhika.jagtap@arm.com        .name(name() + ".rxPackets")
15312268Sradhika.jagtap@arm.com        .desc("Number of Packets Received")
15412268Sradhika.jagtap@arm.com        .prereq(rxBytes)
15512268Sradhika.jagtap@arm.com        ;
15612268Sradhika.jagtap@arm.com
15712268Sradhika.jagtap@arm.com    txIpChecksums
15812268Sradhika.jagtap@arm.com        .name(name() + ".txIpChecksums")
15912268Sradhika.jagtap@arm.com        .desc("Number of tx IP Checksums done by device")
16012268Sradhika.jagtap@arm.com        .precision(0)
16112268Sradhika.jagtap@arm.com        .prereq(txBytes)
16212268Sradhika.jagtap@arm.com        ;
16312268Sradhika.jagtap@arm.com
16412268Sradhika.jagtap@arm.com    rxIpChecksums
16512268Sradhika.jagtap@arm.com        .name(name() + ".rxIpChecksums")
16612268Sradhika.jagtap@arm.com        .desc("Number of rx IP Checksums done by device")
16712268Sradhika.jagtap@arm.com        .precision(0)
16812268Sradhika.jagtap@arm.com        .prereq(rxBytes)
16912268Sradhika.jagtap@arm.com        ;
17012268Sradhika.jagtap@arm.com
17112268Sradhika.jagtap@arm.com    txTcpChecksums
17212268Sradhika.jagtap@arm.com        .name(name() + ".txTcpChecksums")
17312268Sradhika.jagtap@arm.com        .desc("Number of tx TCP Checksums done by device")
17412268Sradhika.jagtap@arm.com        .precision(0)
17512268Sradhika.jagtap@arm.com        .prereq(txBytes)
17612268Sradhika.jagtap@arm.com        ;
17712268Sradhika.jagtap@arm.com
17812268Sradhika.jagtap@arm.com    rxTcpChecksums
17912268Sradhika.jagtap@arm.com        .name(name() + ".rxTcpChecksums")
18012268Sradhika.jagtap@arm.com        .desc("Number of rx TCP Checksums done by device")
18112268Sradhika.jagtap@arm.com        .precision(0)
18212268Sradhika.jagtap@arm.com        .prereq(rxBytes)
18312268Sradhika.jagtap@arm.com        ;
18412268Sradhika.jagtap@arm.com
18512268Sradhika.jagtap@arm.com    txUdpChecksums
18612268Sradhika.jagtap@arm.com        .name(name() + ".txUdpChecksums")
18712268Sradhika.jagtap@arm.com        .desc("Number of tx UDP Checksums done by device")
18812268Sradhika.jagtap@arm.com        .precision(0)
18912268Sradhika.jagtap@arm.com        .prereq(txBytes)
19012268Sradhika.jagtap@arm.com        ;
19112268Sradhika.jagtap@arm.com
19212268Sradhika.jagtap@arm.com    rxUdpChecksums
19312268Sradhika.jagtap@arm.com        .name(name() + ".rxUdpChecksums")
19412268Sradhika.jagtap@arm.com        .desc("Number of rx UDP Checksums done by device")
19512268Sradhika.jagtap@arm.com        .precision(0)
19612268Sradhika.jagtap@arm.com        .prereq(rxBytes)
19712268Sradhika.jagtap@arm.com        ;
19812268Sradhika.jagtap@arm.com
19912268Sradhika.jagtap@arm.com    descDmaReads
20012268Sradhika.jagtap@arm.com        .name(name() + ".descDMAReads")
20112268Sradhika.jagtap@arm.com        .desc("Number of descriptors the device read w/ DMA")
20212268Sradhika.jagtap@arm.com        .precision(0)
20312268Sradhika.jagtap@arm.com        ;
20412268Sradhika.jagtap@arm.com
20512268Sradhika.jagtap@arm.com    descDmaWrites
20612268Sradhika.jagtap@arm.com        .name(name() + ".descDMAWrites")
20712268Sradhika.jagtap@arm.com        .desc("Number of descriptors the device wrote w/ DMA")
20812268Sradhika.jagtap@arm.com        .precision(0)
20912268Sradhika.jagtap@arm.com        ;
21012268Sradhika.jagtap@arm.com
21112268Sradhika.jagtap@arm.com    descDmaRdBytes
21212268Sradhika.jagtap@arm.com        .name(name() + ".descDmaReadBytes")
21312268Sradhika.jagtap@arm.com        .desc("number of descriptor bytes read w/ DMA")
21412268Sradhika.jagtap@arm.com        .precision(0)
21512268Sradhika.jagtap@arm.com        ;
21612268Sradhika.jagtap@arm.com
21712268Sradhika.jagtap@arm.com   descDmaWrBytes
21812268Sradhika.jagtap@arm.com        .name(name() + ".descDmaWriteBytes")
21912268Sradhika.jagtap@arm.com        .desc("number of descriptor bytes write w/ DMA")
22012268Sradhika.jagtap@arm.com        .precision(0)
22112268Sradhika.jagtap@arm.com        ;
22212268Sradhika.jagtap@arm.com
22312268Sradhika.jagtap@arm.com    txBandwidth
22412268Sradhika.jagtap@arm.com        .name(name() + ".txBandwidth")
22512268Sradhika.jagtap@arm.com        .desc("Transmit Bandwidth (bits/s)")
22612268Sradhika.jagtap@arm.com        .precision(0)
22712268Sradhika.jagtap@arm.com        .prereq(txBytes)
22812268Sradhika.jagtap@arm.com        ;
22912268Sradhika.jagtap@arm.com
23012268Sradhika.jagtap@arm.com    rxBandwidth
23112268Sradhika.jagtap@arm.com        .name(name() + ".rxBandwidth")
23212268Sradhika.jagtap@arm.com        .desc("Receive Bandwidth (bits/s)")
23312268Sradhika.jagtap@arm.com        .precision(0)
23412268Sradhika.jagtap@arm.com        .prereq(rxBytes)
23512268Sradhika.jagtap@arm.com        ;
23612268Sradhika.jagtap@arm.com
23712268Sradhika.jagtap@arm.com    totBandwidth
23812268Sradhika.jagtap@arm.com        .name(name() + ".totBandwidth")
23912268Sradhika.jagtap@arm.com        .desc("Total Bandwidth (bits/s)")
24012268Sradhika.jagtap@arm.com        .precision(0)
24112268Sradhika.jagtap@arm.com        .prereq(totBytes)
24212268Sradhika.jagtap@arm.com        ;
24312268Sradhika.jagtap@arm.com
24412268Sradhika.jagtap@arm.com    totPackets
24512268Sradhika.jagtap@arm.com        .name(name() + ".totPackets")
24612268Sradhika.jagtap@arm.com        .desc("Total Packets")
24712268Sradhika.jagtap@arm.com        .precision(0)
24812268Sradhika.jagtap@arm.com        .prereq(totBytes)
24912268Sradhika.jagtap@arm.com        ;
25012268Sradhika.jagtap@arm.com
25112268Sradhika.jagtap@arm.com    totBytes
25212268Sradhika.jagtap@arm.com        .name(name() + ".totBytes")
25312268Sradhika.jagtap@arm.com        .desc("Total Bytes")
25412268Sradhika.jagtap@arm.com        .precision(0)
25512268Sradhika.jagtap@arm.com        .prereq(totBytes)
25612268Sradhika.jagtap@arm.com        ;
25712268Sradhika.jagtap@arm.com
25812268Sradhika.jagtap@arm.com    totPacketRate
25912268Sradhika.jagtap@arm.com        .name(name() + ".totPPS")
26012268Sradhika.jagtap@arm.com        .desc("Total Tranmission Rate (packets/s)")
26112268Sradhika.jagtap@arm.com        .precision(0)
26212268Sradhika.jagtap@arm.com        .prereq(totBytes)
26312268Sradhika.jagtap@arm.com        ;
26412268Sradhika.jagtap@arm.com
26512268Sradhika.jagtap@arm.com    txPacketRate
26612268Sradhika.jagtap@arm.com        .name(name() + ".txPPS")
26712268Sradhika.jagtap@arm.com        .desc("Packet Tranmission Rate (packets/s)")
26812268Sradhika.jagtap@arm.com        .precision(0)
26912268Sradhika.jagtap@arm.com        .prereq(txBytes)
27012268Sradhika.jagtap@arm.com        ;
27112268Sradhika.jagtap@arm.com
27212268Sradhika.jagtap@arm.com    rxPacketRate
27312268Sradhika.jagtap@arm.com        .name(name() + ".rxPPS")
27412268Sradhika.jagtap@arm.com        .desc("Packet Reception Rate (packets/s)")
27512268Sradhika.jagtap@arm.com        .precision(0)
27612268Sradhika.jagtap@arm.com        .prereq(rxBytes)
27712268Sradhika.jagtap@arm.com        ;
27812268Sradhika.jagtap@arm.com
27912268Sradhika.jagtap@arm.com    postedSwi
28012268Sradhika.jagtap@arm.com        .name(name() + ".postedSwi")
28112268Sradhika.jagtap@arm.com        .desc("number of software interrupts posted to CPU")
28212268Sradhika.jagtap@arm.com        .precision(0)
28312268Sradhika.jagtap@arm.com        ;
28412268Sradhika.jagtap@arm.com
28512268Sradhika.jagtap@arm.com    totalSwi
28612268Sradhika.jagtap@arm.com        .name(name() + ".totalSwi")
28712268Sradhika.jagtap@arm.com        .desc("total number of Swi written to ISR")
28812268Sradhika.jagtap@arm.com        .precision(0)
28912268Sradhika.jagtap@arm.com        ;
29012268Sradhika.jagtap@arm.com
29112268Sradhika.jagtap@arm.com    coalescedSwi
29212268Sradhika.jagtap@arm.com        .name(name() + ".coalescedSwi")
29312268Sradhika.jagtap@arm.com        .desc("average number of Swi's coalesced into each post")
29412268Sradhika.jagtap@arm.com        .precision(0)
29512268Sradhika.jagtap@arm.com        ;
29612268Sradhika.jagtap@arm.com
29712268Sradhika.jagtap@arm.com    postedRxIdle
29812268Sradhika.jagtap@arm.com        .name(name() + ".postedRxIdle")
29912268Sradhika.jagtap@arm.com        .desc("number of rxIdle interrupts posted to CPU")
30012268Sradhika.jagtap@arm.com        .precision(0)
30112268Sradhika.jagtap@arm.com        ;
30212268Sradhika.jagtap@arm.com
30312268Sradhika.jagtap@arm.com    totalRxIdle
30412268Sradhika.jagtap@arm.com        .name(name() + ".totalRxIdle")
30512268Sradhika.jagtap@arm.com        .desc("total number of RxIdle written to ISR")
30612268Sradhika.jagtap@arm.com        .precision(0)
30712268Sradhika.jagtap@arm.com        ;
30812268Sradhika.jagtap@arm.com
30912268Sradhika.jagtap@arm.com    coalescedRxIdle
31012268Sradhika.jagtap@arm.com        .name(name() + ".coalescedRxIdle")
31112268Sradhika.jagtap@arm.com        .desc("average number of RxIdle's coalesced into each post")
31212268Sradhika.jagtap@arm.com        .precision(0)
31312268Sradhika.jagtap@arm.com        ;
31412268Sradhika.jagtap@arm.com
31512268Sradhika.jagtap@arm.com    postedRxOk
31612268Sradhika.jagtap@arm.com        .name(name() + ".postedRxOk")
31712268Sradhika.jagtap@arm.com        .desc("number of RxOk interrupts posted to CPU")
31812268Sradhika.jagtap@arm.com        .precision(0)
31912268Sradhika.jagtap@arm.com        ;
32012268Sradhika.jagtap@arm.com
32112268Sradhika.jagtap@arm.com    totalRxOk
32212268Sradhika.jagtap@arm.com        .name(name() + ".totalRxOk")
32312268Sradhika.jagtap@arm.com        .desc("total number of RxOk written to ISR")
32412268Sradhika.jagtap@arm.com        .precision(0)
32512268Sradhika.jagtap@arm.com        ;
32612268Sradhika.jagtap@arm.com
32712268Sradhika.jagtap@arm.com    coalescedRxOk
32812268Sradhika.jagtap@arm.com        .name(name() + ".coalescedRxOk")
32912268Sradhika.jagtap@arm.com        .desc("average number of RxOk's coalesced into each post")
33012268Sradhika.jagtap@arm.com        .precision(0)
33112268Sradhika.jagtap@arm.com        ;
33212268Sradhika.jagtap@arm.com
33312268Sradhika.jagtap@arm.com    postedRxDesc
33412268Sradhika.jagtap@arm.com        .name(name() + ".postedRxDesc")
33512268Sradhika.jagtap@arm.com        .desc("number of RxDesc interrupts posted to CPU")
33612268Sradhika.jagtap@arm.com        .precision(0)
33712268Sradhika.jagtap@arm.com        ;
33812268Sradhika.jagtap@arm.com
33912268Sradhika.jagtap@arm.com    totalRxDesc
34012268Sradhika.jagtap@arm.com        .name(name() + ".totalRxDesc")
34112268Sradhika.jagtap@arm.com        .desc("total number of RxDesc written to ISR")
34212268Sradhika.jagtap@arm.com        .precision(0)
34312268Sradhika.jagtap@arm.com        ;
34412268Sradhika.jagtap@arm.com
34512268Sradhika.jagtap@arm.com    coalescedRxDesc
34612268Sradhika.jagtap@arm.com        .name(name() + ".coalescedRxDesc")
34712268Sradhika.jagtap@arm.com        .desc("average number of RxDesc's coalesced into each post")
34812268Sradhika.jagtap@arm.com        .precision(0)
34912268Sradhika.jagtap@arm.com        ;
35012268Sradhika.jagtap@arm.com
35112268Sradhika.jagtap@arm.com    postedTxOk
35212268Sradhika.jagtap@arm.com        .name(name() + ".postedTxOk")
35312268Sradhika.jagtap@arm.com        .desc("number of TxOk interrupts posted to CPU")
35412268Sradhika.jagtap@arm.com        .precision(0)
35512268Sradhika.jagtap@arm.com        ;
35612268Sradhika.jagtap@arm.com
35712268Sradhika.jagtap@arm.com    totalTxOk
35812268Sradhika.jagtap@arm.com        .name(name() + ".totalTxOk")
35912268Sradhika.jagtap@arm.com        .desc("total number of TxOk written to ISR")
36012268Sradhika.jagtap@arm.com        .precision(0)
36112268Sradhika.jagtap@arm.com        ;
36212268Sradhika.jagtap@arm.com
36312268Sradhika.jagtap@arm.com    coalescedTxOk
36412268Sradhika.jagtap@arm.com        .name(name() + ".coalescedTxOk")
36512268Sradhika.jagtap@arm.com        .desc("average number of TxOk's coalesced into each post")
36612268Sradhika.jagtap@arm.com        .precision(0)
36712268Sradhika.jagtap@arm.com        ;
36812268Sradhika.jagtap@arm.com
36912268Sradhika.jagtap@arm.com    postedTxIdle
37012268Sradhika.jagtap@arm.com        .name(name() + ".postedTxIdle")
37112268Sradhika.jagtap@arm.com        .desc("number of TxIdle interrupts posted to CPU")
37212268Sradhika.jagtap@arm.com        .precision(0)
37312268Sradhika.jagtap@arm.com        ;
37412268Sradhika.jagtap@arm.com
37512268Sradhika.jagtap@arm.com    totalTxIdle
37612268Sradhika.jagtap@arm.com        .name(name() + ".totalTxIdle")
37712268Sradhika.jagtap@arm.com        .desc("total number of TxIdle written to ISR")
37812268Sradhika.jagtap@arm.com        .precision(0)
37912268Sradhika.jagtap@arm.com        ;
38012268Sradhika.jagtap@arm.com
38112268Sradhika.jagtap@arm.com    coalescedTxIdle
38212268Sradhika.jagtap@arm.com        .name(name() + ".coalescedTxIdle")
38312268Sradhika.jagtap@arm.com        .desc("average number of TxIdle's coalesced into each post")
38412268Sradhika.jagtap@arm.com        .precision(0)
38512268Sradhika.jagtap@arm.com        ;
38612268Sradhika.jagtap@arm.com
38712268Sradhika.jagtap@arm.com    postedTxDesc
38812268Sradhika.jagtap@arm.com        .name(name() + ".postedTxDesc")
38912268Sradhika.jagtap@arm.com        .desc("number of TxDesc interrupts posted to CPU")
39012268Sradhika.jagtap@arm.com        .precision(0)
39112268Sradhika.jagtap@arm.com        ;
39212268Sradhika.jagtap@arm.com
39312268Sradhika.jagtap@arm.com    totalTxDesc
39412268Sradhika.jagtap@arm.com        .name(name() + ".totalTxDesc")
39512268Sradhika.jagtap@arm.com        .desc("total number of TxDesc written to ISR")
39612268Sradhika.jagtap@arm.com        .precision(0)
39712268Sradhika.jagtap@arm.com        ;
39812268Sradhika.jagtap@arm.com
39912268Sradhika.jagtap@arm.com    coalescedTxDesc
40012268Sradhika.jagtap@arm.com        .name(name() + ".coalescedTxDesc")
40112268Sradhika.jagtap@arm.com        .desc("average number of TxDesc's coalesced into each post")
40212268Sradhika.jagtap@arm.com        .precision(0)
40312268Sradhika.jagtap@arm.com        ;
40412268Sradhika.jagtap@arm.com
40512268Sradhika.jagtap@arm.com    postedRxOrn
40612268Sradhika.jagtap@arm.com        .name(name() + ".postedRxOrn")
40712268Sradhika.jagtap@arm.com        .desc("number of RxOrn posted to CPU")
40812268Sradhika.jagtap@arm.com        .precision(0)
40912268Sradhika.jagtap@arm.com        ;
41012268Sradhika.jagtap@arm.com
41112268Sradhika.jagtap@arm.com    totalRxOrn
41212268Sradhika.jagtap@arm.com        .name(name() + ".totalRxOrn")
41312268Sradhika.jagtap@arm.com        .desc("total number of RxOrn written to ISR")
41412268Sradhika.jagtap@arm.com        .precision(0)
41512268Sradhika.jagtap@arm.com        ;
41612268Sradhika.jagtap@arm.com
41712268Sradhika.jagtap@arm.com    coalescedRxOrn
41812268Sradhika.jagtap@arm.com        .name(name() + ".coalescedRxOrn")
41912268Sradhika.jagtap@arm.com        .desc("average number of RxOrn's coalesced into each post")
42012268Sradhika.jagtap@arm.com        .precision(0)
42112268Sradhika.jagtap@arm.com        ;
42212268Sradhika.jagtap@arm.com
42312268Sradhika.jagtap@arm.com    coalescedTotal
42412268Sradhika.jagtap@arm.com        .name(name() + ".coalescedTotal")
42512268Sradhika.jagtap@arm.com        .desc("average number of interrupts coalesced into each post")
42612268Sradhika.jagtap@arm.com        .precision(0)
42712268Sradhika.jagtap@arm.com        ;
42812268Sradhika.jagtap@arm.com
42912268Sradhika.jagtap@arm.com    postedInterrupts
43012268Sradhika.jagtap@arm.com        .name(name() + ".postedInterrupts")
43112268Sradhika.jagtap@arm.com        .desc("number of posts to CPU")
43212268Sradhika.jagtap@arm.com        .precision(0)
43312268Sradhika.jagtap@arm.com        ;
43412268Sradhika.jagtap@arm.com
43512268Sradhika.jagtap@arm.com    droppedPackets
43612268Sradhika.jagtap@arm.com        .name(name() + ".droppedPackets")
43712268Sradhika.jagtap@arm.com        .desc("number of packets dropped")
43812268Sradhika.jagtap@arm.com        .precision(0)
43912268Sradhika.jagtap@arm.com        ;
44012268Sradhika.jagtap@arm.com
44112268Sradhika.jagtap@arm.com    coalescedSwi = totalSwi / postedInterrupts;
44212268Sradhika.jagtap@arm.com    coalescedRxIdle = totalRxIdle / postedInterrupts;
44312268Sradhika.jagtap@arm.com    coalescedRxOk = totalRxOk / postedInterrupts;
44412268Sradhika.jagtap@arm.com    coalescedRxDesc = totalRxDesc / postedInterrupts;
44512268Sradhika.jagtap@arm.com    coalescedTxOk = totalTxOk / postedInterrupts;
44612268Sradhika.jagtap@arm.com    coalescedTxIdle = totalTxIdle / postedInterrupts;
44712268Sradhika.jagtap@arm.com    coalescedTxDesc = totalTxDesc / postedInterrupts;
44812268Sradhika.jagtap@arm.com    coalescedRxOrn = totalRxOrn / postedInterrupts;
44912268Sradhika.jagtap@arm.com
45012268Sradhika.jagtap@arm.com    coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc +
45112268Sradhika.jagtap@arm.com                      totalTxOk + totalTxIdle + totalTxDesc +
45212268Sradhika.jagtap@arm.com                      totalRxOrn) / postedInterrupts;
45312268Sradhika.jagtap@arm.com
45412268Sradhika.jagtap@arm.com    txBandwidth = txBytes * Stats::constant(8) / simSeconds;
45512268Sradhika.jagtap@arm.com    rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
45612268Sradhika.jagtap@arm.com    totBandwidth = txBandwidth + rxBandwidth;
45712268Sradhika.jagtap@arm.com    totBytes = txBytes + rxBytes;
45812268Sradhika.jagtap@arm.com    totPackets = txPackets + rxPackets;
45912268Sradhika.jagtap@arm.com
46012268Sradhika.jagtap@arm.com    txPacketRate = txPackets / simSeconds;
46112268Sradhika.jagtap@arm.com    rxPacketRate = rxPackets / simSeconds;
46212268Sradhika.jagtap@arm.com}
46312268Sradhika.jagtap@arm.com
46412268Sradhika.jagtap@arm.com
46512268Sradhika.jagtap@arm.com/**
46612268Sradhika.jagtap@arm.com * This is to write to the PCI general configuration registers
46712268Sradhika.jagtap@arm.com */
46812268Sradhika.jagtap@arm.comTick
46912268Sradhika.jagtap@arm.comNSGigE::writeConfig(Packet *pkt)
47012268Sradhika.jagtap@arm.com{
47112268Sradhika.jagtap@arm.com    int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
47212268Sradhika.jagtap@arm.com    if (offset < PCI_DEVICE_SPECIFIC)
47312268Sradhika.jagtap@arm.com        PciDev::writeConfig(pkt);
47412268Sradhika.jagtap@arm.com    else
47512268Sradhika.jagtap@arm.com        panic("Device specific PCI config space not implemented!\n");
47612268Sradhika.jagtap@arm.com
47712268Sradhika.jagtap@arm.com    switch (offset) {
47812268Sradhika.jagtap@arm.com        // seems to work fine without all these PCI settings, but i
47912268Sradhika.jagtap@arm.com        // put in the IO to double check, an assertion will fail if we
48012268Sradhika.jagtap@arm.com        // need to properly implement it
48112268Sradhika.jagtap@arm.com      case PCI_COMMAND:
48212268Sradhika.jagtap@arm.com        if (config.data[offset] & PCI_CMD_IOSE)
48312268Sradhika.jagtap@arm.com            ioEnable = true;
48412268Sradhika.jagtap@arm.com        else
48512268Sradhika.jagtap@arm.com            ioEnable = false;
48612268Sradhika.jagtap@arm.com        break;
48712268Sradhika.jagtap@arm.com    }
48812268Sradhika.jagtap@arm.com    pkt->result = Packet::Success;
48912268Sradhika.jagtap@arm.com    return configDelay;
49012268Sradhika.jagtap@arm.com}
49112268Sradhika.jagtap@arm.com
49212268Sradhika.jagtap@arm.com/**
49312268Sradhika.jagtap@arm.com * This reads the device registers, which are detailed in the NS83820
49412268Sradhika.jagtap@arm.com * spec sheet
49512268Sradhika.jagtap@arm.com */
49612268Sradhika.jagtap@arm.comTick
49712268Sradhika.jagtap@arm.comNSGigE::read(Packet *pkt)
49812268Sradhika.jagtap@arm.com{
49912268Sradhika.jagtap@arm.com    assert(ioEnable);
50012268Sradhika.jagtap@arm.com
50112268Sradhika.jagtap@arm.com    pkt->allocate();
50212268Sradhika.jagtap@arm.com
50312268Sradhika.jagtap@arm.com    //The mask is to give you only the offset into the device register file
50412268Sradhika.jagtap@arm.com    Addr daddr = pkt->getAddr() & 0xfff;
50512268Sradhika.jagtap@arm.com    DPRINTF(EthernetPIO, "read  da=%#x pa=%#x size=%d\n",
50612268Sradhika.jagtap@arm.com            daddr, pkt->getAddr(), pkt->getSize());
50712268Sradhika.jagtap@arm.com
50812268Sradhika.jagtap@arm.com
50912268Sradhika.jagtap@arm.com    // there are some reserved registers, you can see ns_gige_reg.h and
51012268Sradhika.jagtap@arm.com    // the spec sheet for details
51112268Sradhika.jagtap@arm.com    if (daddr > LAST && daddr <=  RESERVED) {
51212268Sradhika.jagtap@arm.com        panic("Accessing reserved register");
51312268Sradhika.jagtap@arm.com    } else if (daddr > RESERVED && daddr <= 0x3FC) {
51412268Sradhika.jagtap@arm.com        return readConfig(pkt);
51512268Sradhika.jagtap@arm.com    } else if (daddr >= MIB_START && daddr <= MIB_END) {
51612268Sradhika.jagtap@arm.com        // don't implement all the MIB's.  hopefully the kernel
51712268Sradhika.jagtap@arm.com        // doesn't actually DEPEND upon their values
51812268Sradhika.jagtap@arm.com        // MIB are just hardware stats keepers
51912268Sradhika.jagtap@arm.com        pkt->set<uint32_t>(0);
52012268Sradhika.jagtap@arm.com        pkt->result = Packet::Success;
52112268Sradhika.jagtap@arm.com        return pioDelay;
52212268Sradhika.jagtap@arm.com    } else if (daddr > 0x3FC)
52312268Sradhika.jagtap@arm.com        panic("Something is messed up!\n");
52412268Sradhika.jagtap@arm.com
52512268Sradhika.jagtap@arm.com    assert(pkt->getSize() == sizeof(uint32_t));
52612268Sradhika.jagtap@arm.com        uint32_t &reg = *pkt->getPtr<uint32_t>();
52712268Sradhika.jagtap@arm.com        uint16_t rfaddr;
52812268Sradhika.jagtap@arm.com
52912268Sradhika.jagtap@arm.com        switch (daddr) {
53012268Sradhika.jagtap@arm.com          case CR:
53112268Sradhika.jagtap@arm.com            reg = regs.command;
53212268Sradhika.jagtap@arm.com            //these are supposed to be cleared on a read
53312268Sradhika.jagtap@arm.com            reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR);
53412268Sradhika.jagtap@arm.com            break;
53512268Sradhika.jagtap@arm.com
53612268Sradhika.jagtap@arm.com          case CFGR:
53712268Sradhika.jagtap@arm.com            reg = regs.config;
53812268Sradhika.jagtap@arm.com            break;
53912268Sradhika.jagtap@arm.com
54012268Sradhika.jagtap@arm.com          case MEAR:
54112268Sradhika.jagtap@arm.com            reg = regs.mear;
54212268Sradhika.jagtap@arm.com            break;
54312268Sradhika.jagtap@arm.com
54412268Sradhika.jagtap@arm.com          case PTSCR:
54512268Sradhika.jagtap@arm.com            reg = regs.ptscr;
54612268Sradhika.jagtap@arm.com            break;
54712268Sradhika.jagtap@arm.com
54812268Sradhika.jagtap@arm.com          case ISR:
54912268Sradhika.jagtap@arm.com            reg = regs.isr;
55012268Sradhika.jagtap@arm.com            devIntrClear(ISR_ALL);
55112268Sradhika.jagtap@arm.com            break;
55212268Sradhika.jagtap@arm.com
55312268Sradhika.jagtap@arm.com          case IMR:
55412268Sradhika.jagtap@arm.com            reg = regs.imr;
55512268Sradhika.jagtap@arm.com            break;
55612268Sradhika.jagtap@arm.com
55712268Sradhika.jagtap@arm.com          case IER:
55812268Sradhika.jagtap@arm.com            reg = regs.ier;
55912268Sradhika.jagtap@arm.com            break;
56012268Sradhika.jagtap@arm.com
56112268Sradhika.jagtap@arm.com          case IHR:
56212268Sradhika.jagtap@arm.com            reg = regs.ihr;
56312268Sradhika.jagtap@arm.com            break;
56412268Sradhika.jagtap@arm.com
56512268Sradhika.jagtap@arm.com          case TXDP:
56612268Sradhika.jagtap@arm.com            reg = regs.txdp;
56712268Sradhika.jagtap@arm.com            break;
56812268Sradhika.jagtap@arm.com
56912268Sradhika.jagtap@arm.com          case TXDP_HI:
57012268Sradhika.jagtap@arm.com            reg = regs.txdp_hi;
57112268Sradhika.jagtap@arm.com            break;
57212268Sradhika.jagtap@arm.com
57312268Sradhika.jagtap@arm.com          case TX_CFG:
57412268Sradhika.jagtap@arm.com            reg = regs.txcfg;
57512268Sradhika.jagtap@arm.com            break;
57612268Sradhika.jagtap@arm.com
57712268Sradhika.jagtap@arm.com          case GPIOR:
57812268Sradhika.jagtap@arm.com            reg = regs.gpior;
57912268Sradhika.jagtap@arm.com            break;
58012268Sradhika.jagtap@arm.com
58112268Sradhika.jagtap@arm.com          case RXDP:
58212268Sradhika.jagtap@arm.com            reg = regs.rxdp;
58312268Sradhika.jagtap@arm.com            break;
58412268Sradhika.jagtap@arm.com
58512268Sradhika.jagtap@arm.com          case RXDP_HI:
58612268Sradhika.jagtap@arm.com            reg = regs.rxdp_hi;
58712268Sradhika.jagtap@arm.com            break;
58812268Sradhika.jagtap@arm.com
58912268Sradhika.jagtap@arm.com          case RX_CFG:
59012268Sradhika.jagtap@arm.com            reg = regs.rxcfg;
59112268Sradhika.jagtap@arm.com            break;
59212268Sradhika.jagtap@arm.com
59312268Sradhika.jagtap@arm.com          case PQCR:
59412268Sradhika.jagtap@arm.com            reg = regs.pqcr;
59512268Sradhika.jagtap@arm.com            break;
59612268Sradhika.jagtap@arm.com
59712268Sradhika.jagtap@arm.com          case WCSR:
59812268Sradhika.jagtap@arm.com            reg = regs.wcsr;
59912268Sradhika.jagtap@arm.com            break;
60012268Sradhika.jagtap@arm.com
60112268Sradhika.jagtap@arm.com          case PCR:
60212268Sradhika.jagtap@arm.com            reg = regs.pcr;
60312268Sradhika.jagtap@arm.com            break;
60412268Sradhika.jagtap@arm.com
60512268Sradhika.jagtap@arm.com            // see the spec sheet for how RFCR and RFDR work
60612268Sradhika.jagtap@arm.com            // basically, you write to RFCR to tell the machine
60712268Sradhika.jagtap@arm.com            // what you want to do next, then you act upon RFDR,
60812268Sradhika.jagtap@arm.com            // and the device will be prepared b/c of what you
60912268Sradhika.jagtap@arm.com            // wrote to RFCR
61012268Sradhika.jagtap@arm.com          case RFCR:
61112268Sradhika.jagtap@arm.com            reg = regs.rfcr;
61212268Sradhika.jagtap@arm.com            break;
61312268Sradhika.jagtap@arm.com
61412268Sradhika.jagtap@arm.com          case RFDR:
61512268Sradhika.jagtap@arm.com            rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
61612268Sradhika.jagtap@arm.com            switch (rfaddr) {
61712268Sradhika.jagtap@arm.com              // Read from perfect match ROM octets
61812268Sradhika.jagtap@arm.com              case 0x000:
61912268Sradhika.jagtap@arm.com                reg = rom.perfectMatch[1];
62012268Sradhika.jagtap@arm.com                reg = reg << 8;
62112268Sradhika.jagtap@arm.com                reg += rom.perfectMatch[0];
62212268Sradhika.jagtap@arm.com                break;
62312268Sradhika.jagtap@arm.com              case 0x002:
62412268Sradhika.jagtap@arm.com                reg = rom.perfectMatch[3] << 8;
62512268Sradhika.jagtap@arm.com                reg += rom.perfectMatch[2];
62612268Sradhika.jagtap@arm.com                break;
62712268Sradhika.jagtap@arm.com              case 0x004:
62812268Sradhika.jagtap@arm.com                reg = rom.perfectMatch[5] << 8;
62912268Sradhika.jagtap@arm.com                reg += rom.perfectMatch[4];
63012268Sradhika.jagtap@arm.com                break;
63112268Sradhika.jagtap@arm.com              default:
63212268Sradhika.jagtap@arm.com                // Read filter hash table
63312268Sradhika.jagtap@arm.com                if (rfaddr >= FHASH_ADDR &&
63412268Sradhika.jagtap@arm.com                    rfaddr < FHASH_ADDR + FHASH_SIZE) {
63512268Sradhika.jagtap@arm.com
63612268Sradhika.jagtap@arm.com                    // Only word-aligned reads supported
63712268Sradhika.jagtap@arm.com                    if (rfaddr % 2)
63812268Sradhika.jagtap@arm.com                        panic("unaligned read from filter hash table!");
63912268Sradhika.jagtap@arm.com
64012268Sradhika.jagtap@arm.com                    reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8;
6419244SN/A                    reg += rom.filterHash[rfaddr - FHASH_ADDR];
6429244SN/A                    break;
643                }
644
645                panic("reading RFDR for something other than pattern"
646                      " matching or hashing! %#x\n", rfaddr);
647            }
648            break;
649
650          case SRR:
651            reg = regs.srr;
652            break;
653
654          case MIBC:
655            reg = regs.mibc;
656            reg &= ~(MIBC_MIBS | MIBC_ACLR);
657            break;
658
659          case VRCR:
660            reg = regs.vrcr;
661            break;
662
663          case VTCR:
664            reg = regs.vtcr;
665            break;
666
667          case VDR:
668            reg = regs.vdr;
669            break;
670
671          case CCSR:
672            reg = regs.ccsr;
673            break;
674
675          case TBICR:
676            reg = regs.tbicr;
677            break;
678
679          case TBISR:
680            reg = regs.tbisr;
681            break;
682
683          case TANAR:
684            reg = regs.tanar;
685            break;
686
687          case TANLPAR:
688            reg = regs.tanlpar;
689            break;
690
691          case TANER:
692            reg = regs.taner;
693            break;
694
695          case TESR:
696            reg = regs.tesr;
697            break;
698
699          case M5REG:
700            reg = 0;
701            if (params()->rx_thread)
702                reg |= M5REG_RX_THREAD;
703            if (params()->tx_thread)
704                reg |= M5REG_TX_THREAD;
705            if (params()->rss)
706                reg |= M5REG_RSS;
707            break;
708
709          default:
710            panic("reading unimplemented register: addr=%#x", daddr);
711        }
712
713        DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
714                daddr, reg, reg);
715
716    pkt->result = Packet::Success;
717    return pioDelay;
718}
719
720Tick
721NSGigE::write(Packet *pkt)
722{
723    assert(ioEnable);
724
725    Addr daddr = pkt->getAddr() & 0xfff;
726    DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n",
727            daddr, pkt->getAddr(), pkt->getSize());
728
729    if (daddr > LAST && daddr <=  RESERVED) {
730        panic("Accessing reserved register");
731    } else if (daddr > RESERVED && daddr <= 0x3FC) {
732        return writeConfig(pkt);
733    } else if (daddr > 0x3FC)
734        panic("Something is messed up!\n");
735
736    if (pkt->getSize() == sizeof(uint32_t)) {
737        uint32_t reg = pkt->get<uint32_t>();
738        uint16_t rfaddr;
739
740        DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg);
741
742        switch (daddr) {
743          case CR:
744            regs.command = reg;
745            if (reg & CR_TXD) {
746                txEnable = false;
747            } else if (reg & CR_TXE) {
748                txEnable = true;
749
750                // the kernel is enabling the transmit machine
751                if (txState == txIdle)
752                    txKick();
753            }
754
755            if (reg & CR_RXD) {
756                rxEnable = false;
757            } else if (reg & CR_RXE) {
758                rxEnable = true;
759
760                if (rxState == rxIdle)
761                    rxKick();
762            }
763
764            if (reg & CR_TXR)
765                txReset();
766
767            if (reg & CR_RXR)
768                rxReset();
769
770            if (reg & CR_SWI)
771                devIntrPost(ISR_SWI);
772
773            if (reg & CR_RST) {
774                txReset();
775                rxReset();
776
777                regsReset();
778            }
779            break;
780
781          case CFGR:
782            if (reg & CFGR_LNKSTS ||
783                reg & CFGR_SPDSTS ||
784                reg & CFGR_DUPSTS ||
785                reg & CFGR_RESERVED ||
786                reg & CFGR_T64ADDR ||
787                reg & CFGR_PCI64_DET)
788
789            // First clear all writable bits
790            regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
791                                   CFGR_RESERVED | CFGR_T64ADDR |
792                                   CFGR_PCI64_DET;
793            // Now set the appropriate writable bits
794            regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
795                                   CFGR_RESERVED | CFGR_T64ADDR |
796                                   CFGR_PCI64_DET);
797
798// all these #if 0's are because i don't THINK the kernel needs to
799// have these implemented. if there is a problem relating to one of
800// these, you may need to add functionality in.
801            if (reg & CFGR_TBI_EN) ;
802            if (reg & CFGR_MODE_1000) ;
803
804            if (reg & CFGR_AUTO_1000)
805                panic("CFGR_AUTO_1000 not implemented!\n");
806
807            if (reg & CFGR_PINT_DUPSTS ||
808                reg & CFGR_PINT_LNKSTS ||
809                reg & CFGR_PINT_SPDSTS)
810                ;
811
812            if (reg & CFGR_TMRTEST) ;
813            if (reg & CFGR_MRM_DIS) ;
814            if (reg & CFGR_MWI_DIS) ;
815
816            if (reg & CFGR_T64ADDR) ;
817            // panic("CFGR_T64ADDR is read only register!\n");
818
819            if (reg & CFGR_PCI64_DET)
820                panic("CFGR_PCI64_DET is read only register!\n");
821
822            if (reg & CFGR_DATA64_EN) ;
823            if (reg & CFGR_M64ADDR) ;
824            if (reg & CFGR_PHY_RST) ;
825            if (reg & CFGR_PHY_DIS) ;
826
827            if (reg & CFGR_EXTSTS_EN)
828                extstsEnable = true;
829            else
830                extstsEnable = false;
831
832            if (reg & CFGR_REQALG) ;
833            if (reg & CFGR_SB) ;
834            if (reg & CFGR_POW) ;
835            if (reg & CFGR_EXD) ;
836            if (reg & CFGR_PESEL) ;
837            if (reg & CFGR_BROM_DIS) ;
838            if (reg & CFGR_EXT_125) ;
839            if (reg & CFGR_BEM) ;
840            break;
841
842          case MEAR:
843            // Clear writable bits
844            regs.mear &= MEAR_EEDO;
845            // Set appropriate writable bits
846            regs.mear |= reg & ~MEAR_EEDO;
847
848            // FreeBSD uses the EEPROM to read PMATCH (for the MAC address)
849            // even though it could get it through RFDR
850            if (reg & MEAR_EESEL) {
851                // Rising edge of clock
852                if (reg & MEAR_EECLK && !eepromClk)
853                    eepromKick();
854            }
855            else {
856                eepromState = eepromStart;
857                regs.mear &= ~MEAR_EEDI;
858            }
859
860            eepromClk = reg & MEAR_EECLK;
861
862            // since phy is completely faked, MEAR_MD* don't matter
863            if (reg & MEAR_MDIO) ;
864            if (reg & MEAR_MDDIR) ;
865            if (reg & MEAR_MDC) ;
866            break;
867
868          case PTSCR:
869            regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY);
870            // these control BISTs for various parts of chip - we
871            // don't care or do just fake that the BIST is done
872            if (reg & PTSCR_RBIST_EN)
873                regs.ptscr |= PTSCR_RBIST_DONE;
874            if (reg & PTSCR_EEBIST_EN)
875                regs.ptscr &= ~PTSCR_EEBIST_EN;
876            if (reg & PTSCR_EELOAD_EN)
877                regs.ptscr &= ~PTSCR_EELOAD_EN;
878            break;
879
880          case ISR: /* writing to the ISR has no effect */
881            panic("ISR is a read only register!\n");
882
883          case IMR:
884            regs.imr = reg;
885            devIntrChangeMask();
886            break;
887
888          case IER:
889            regs.ier = reg;
890            break;
891
892          case IHR:
893            regs.ihr = reg;
894            /* not going to implement real interrupt holdoff */
895            break;
896
897          case TXDP:
898            regs.txdp = (reg & 0xFFFFFFFC);
899            assert(txState == txIdle);
900            CTDD = false;
901            break;
902
903          case TXDP_HI:
904            regs.txdp_hi = reg;
905            break;
906
907          case TX_CFG:
908            regs.txcfg = reg;
909#if 0
910            if (reg & TX_CFG_CSI) ;
911            if (reg & TX_CFG_HBI) ;
912            if (reg & TX_CFG_MLB) ;
913            if (reg & TX_CFG_ATP) ;
914            if (reg & TX_CFG_ECRETRY) {
915                /*
916                 * this could easily be implemented, but considering
917                 * the network is just a fake pipe, wouldn't make
918                 * sense to do this
919                 */
920            }
921
922            if (reg & TX_CFG_BRST_DIS) ;
923#endif
924
925#if 0
926            /* we handle our own DMA, ignore the kernel's exhortations */
927            if (reg & TX_CFG_MXDMA) ;
928#endif
929
930            // also, we currently don't care about fill/drain
931            // thresholds though this may change in the future with
932            // more realistic networks or a driver which changes it
933            // according to feedback
934
935            break;
936
937          case GPIOR:
938            // Only write writable bits
939            regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
940                        | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN;
941            regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
942                                | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN);
943            /* these just control general purpose i/o pins, don't matter */
944            break;
945
946          case RXDP:
947            regs.rxdp = reg;
948            CRDD = false;
949            break;
950
951          case RXDP_HI:
952            regs.rxdp_hi = reg;
953            break;
954
955          case RX_CFG:
956            regs.rxcfg = reg;
957#if 0
958            if (reg & RX_CFG_AEP) ;
959            if (reg & RX_CFG_ARP) ;
960            if (reg & RX_CFG_STRIPCRC) ;
961            if (reg & RX_CFG_RX_RD) ;
962            if (reg & RX_CFG_ALP) ;
963            if (reg & RX_CFG_AIRL) ;
964
965            /* we handle our own DMA, ignore what kernel says about it */
966            if (reg & RX_CFG_MXDMA) ;
967
968            //also, we currently don't care about fill/drain thresholds
969            //though this may change in the future with more realistic
970            //networks or a driver which changes it according to feedback
971            if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ;
972#endif
973            break;
974
975          case PQCR:
976            /* there is no priority queueing used in the linux 2.6 driver */
977            regs.pqcr = reg;
978            break;
979
980          case WCSR:
981            /* not going to implement wake on LAN */
982            regs.wcsr = reg;
983            break;
984
985          case PCR:
986            /* not going to implement pause control */
987            regs.pcr = reg;
988            break;
989
990          case RFCR:
991            regs.rfcr = reg;
992
993            rxFilterEnable = (reg & RFCR_RFEN) ? true : false;
994            acceptBroadcast = (reg & RFCR_AAB) ? true : false;
995            acceptMulticast = (reg & RFCR_AAM) ? true : false;
996            acceptUnicast = (reg & RFCR_AAU) ? true : false;
997            acceptPerfect = (reg & RFCR_APM) ? true : false;
998            acceptArp = (reg & RFCR_AARP) ? true : false;
999            multicastHashEnable = (reg & RFCR_MHEN) ? true : false;
1000
1001#if 0
1002            if (reg & RFCR_APAT)
1003                panic("RFCR_APAT not implemented!\n");
1004#endif
1005            if (reg & RFCR_UHEN)
1006                panic("Unicast hash filtering not used by drivers!\n");
1007
1008            if (reg & RFCR_ULM)
1009                panic("RFCR_ULM not implemented!\n");
1010
1011            break;
1012
1013          case RFDR:
1014            rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
1015            switch (rfaddr) {
1016              case 0x000:
1017                rom.perfectMatch[0] = (uint8_t)reg;
1018                rom.perfectMatch[1] = (uint8_t)(reg >> 8);
1019                break;
1020              case 0x002:
1021                rom.perfectMatch[2] = (uint8_t)reg;
1022                rom.perfectMatch[3] = (uint8_t)(reg >> 8);
1023                break;
1024              case 0x004:
1025                rom.perfectMatch[4] = (uint8_t)reg;
1026                rom.perfectMatch[5] = (uint8_t)(reg >> 8);
1027                break;
1028              default:
1029
1030                if (rfaddr >= FHASH_ADDR &&
1031                    rfaddr < FHASH_ADDR + FHASH_SIZE) {
1032
1033                    // Only word-aligned writes supported
1034                    if (rfaddr % 2)
1035                        panic("unaligned write to filter hash table!");
1036
1037                    rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg;
1038                    rom.filterHash[rfaddr - FHASH_ADDR + 1]
1039                        = (uint8_t)(reg >> 8);
1040                    break;
1041                }
1042                panic("writing RFDR for something other than pattern matching\
1043                    or hashing! %#x\n", rfaddr);
1044            }
1045
1046          case BRAR:
1047            regs.brar = reg;
1048            break;
1049
1050          case BRDR:
1051            panic("the driver never uses BRDR, something is wrong!\n");
1052
1053          case SRR:
1054            panic("SRR is read only register!\n");
1055
1056          case MIBC:
1057            panic("the driver never uses MIBC, something is wrong!\n");
1058
1059          case VRCR:
1060            regs.vrcr = reg;
1061            break;
1062
1063          case VTCR:
1064            regs.vtcr = reg;
1065            break;
1066
1067          case VDR:
1068            panic("the driver never uses VDR, something is wrong!\n");
1069
1070          case CCSR:
1071            /* not going to implement clockrun stuff */
1072            regs.ccsr = reg;
1073            break;
1074
1075          case TBICR:
1076            regs.tbicr = reg;
1077            if (reg & TBICR_MR_LOOPBACK)
1078                panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
1079
1080            if (reg & TBICR_MR_AN_ENABLE) {
1081                regs.tanlpar = regs.tanar;
1082                regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS);
1083            }
1084
1085#if 0
1086            if (reg & TBICR_MR_RESTART_AN) ;
1087#endif
1088
1089            break;
1090
1091          case TBISR:
1092            panic("TBISR is read only register!\n");
1093
1094          case TANAR:
1095            // Only write the writable bits
1096            regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED;
1097            regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED);
1098
1099            // Pause capability unimplemented
1100#if 0
1101            if (reg & TANAR_PS2) ;
1102            if (reg & TANAR_PS1) ;
1103#endif
1104
1105            break;
1106
1107          case TANLPAR:
1108            panic("this should only be written to by the fake phy!\n");
1109
1110          case TANER:
1111            panic("TANER is read only register!\n");
1112
1113          case TESR:
1114            regs.tesr = reg;
1115            break;
1116
1117          default:
1118            panic("invalid register access daddr=%#x", daddr);
1119        }
1120    } else {
1121        panic("Invalid Request Size");
1122    }
1123    pkt->result = Packet::Success;
1124    return pioDelay;
1125}
1126
1127void
1128NSGigE::devIntrPost(uint32_t interrupts)
1129{
1130    if (interrupts & ISR_RESERVE)
1131        panic("Cannot set a reserved interrupt");
1132
1133    if (interrupts & ISR_NOIMPL)
1134        warn("interrupt not implemented %#x\n", interrupts);
1135
1136    interrupts &= ISR_IMPL;
1137    regs.isr |= interrupts;
1138
1139    if (interrupts & regs.imr) {
1140        if (interrupts & ISR_SWI) {
1141            totalSwi++;
1142        }
1143        if (interrupts & ISR_RXIDLE) {
1144            totalRxIdle++;
1145        }
1146        if (interrupts & ISR_RXOK) {
1147            totalRxOk++;
1148        }
1149        if (interrupts & ISR_RXDESC) {
1150            totalRxDesc++;
1151        }
1152        if (interrupts & ISR_TXOK) {
1153            totalTxOk++;
1154        }
1155        if (interrupts & ISR_TXIDLE) {
1156            totalTxIdle++;
1157        }
1158        if (interrupts & ISR_TXDESC) {
1159            totalTxDesc++;
1160        }
1161        if (interrupts & ISR_RXORN) {
1162            totalRxOrn++;
1163        }
1164    }
1165
1166    DPRINTF(EthernetIntr,
1167            "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
1168            interrupts, regs.isr, regs.imr);
1169
1170    if ((regs.isr & regs.imr)) {
1171        Tick when = curTick;
1172        if ((regs.isr & regs.imr & ISR_NODELAY) == 0)
1173            when += intrDelay;
1174        cpuIntrPost(when);
1175    }
1176}
1177
1178/* writing this interrupt counting stats inside this means that this function
1179   is now limited to being used to clear all interrupts upon the kernel
1180   reading isr and servicing.  just telling you in case you were thinking
1181   of expanding use.
1182*/
1183void
1184NSGigE::devIntrClear(uint32_t interrupts)
1185{
1186    if (interrupts & ISR_RESERVE)
1187        panic("Cannot clear a reserved interrupt");
1188
1189    if (regs.isr & regs.imr & ISR_SWI) {
1190        postedSwi++;
1191    }
1192    if (regs.isr & regs.imr & ISR_RXIDLE) {
1193        postedRxIdle++;
1194    }
1195    if (regs.isr & regs.imr & ISR_RXOK) {
1196        postedRxOk++;
1197    }
1198    if (regs.isr & regs.imr & ISR_RXDESC) {
1199            postedRxDesc++;
1200    }
1201    if (regs.isr & regs.imr & ISR_TXOK) {
1202        postedTxOk++;
1203    }
1204    if (regs.isr & regs.imr & ISR_TXIDLE) {
1205        postedTxIdle++;
1206    }
1207    if (regs.isr & regs.imr & ISR_TXDESC) {
1208        postedTxDesc++;
1209    }
1210    if (regs.isr & regs.imr & ISR_RXORN) {
1211        postedRxOrn++;
1212    }
1213
1214    if (regs.isr & regs.imr & ISR_IMPL)
1215        postedInterrupts++;
1216
1217    interrupts &= ~ISR_NOIMPL;
1218    regs.isr &= ~interrupts;
1219
1220    DPRINTF(EthernetIntr,
1221            "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",
1222            interrupts, regs.isr, regs.imr);
1223
1224    if (!(regs.isr & regs.imr))
1225        cpuIntrClear();
1226}
1227
1228void
1229NSGigE::devIntrChangeMask()
1230{
1231    DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n",
1232            regs.isr, regs.imr, regs.isr & regs.imr);
1233
1234    if (regs.isr & regs.imr)
1235        cpuIntrPost(curTick);
1236    else
1237        cpuIntrClear();
1238}
1239
1240void
1241NSGigE::cpuIntrPost(Tick when)
1242{
1243    // If the interrupt you want to post is later than an interrupt
1244    // already scheduled, just let it post in the coming one and don't
1245    // schedule another.
1246    // HOWEVER, must be sure that the scheduled intrTick is in the
1247    // future (this was formerly the source of a bug)
1248    /**
1249     * @todo this warning should be removed and the intrTick code should
1250     * be fixed.
1251     */
1252    assert(when >= curTick);
1253    assert(intrTick >= curTick || intrTick == 0);
1254    if (when > intrTick && intrTick != 0) {
1255        DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
1256                intrTick);
1257        return;
1258    }
1259
1260    intrTick = when;
1261    if (intrTick < curTick) {
1262        debug_break();
1263        intrTick = curTick;
1264    }
1265
1266    DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
1267            intrTick);
1268
1269    if (intrEvent)
1270        intrEvent->squash();
1271    intrEvent = new IntrEvent(this, true);
1272    intrEvent->schedule(intrTick);
1273}
1274
1275void
1276NSGigE::cpuInterrupt()
1277{
1278    assert(intrTick == curTick);
1279
1280    // Whether or not there's a pending interrupt, we don't care about
1281    // it anymore
1282    intrEvent = 0;
1283    intrTick = 0;
1284
1285    // Don't send an interrupt if there's already one
1286    if (cpuPendingIntr) {
1287        DPRINTF(EthernetIntr,
1288                "would send an interrupt now, but there's already pending\n");
1289    } else {
1290        // Send interrupt
1291        cpuPendingIntr = true;
1292
1293        DPRINTF(EthernetIntr, "posting interrupt\n");
1294        intrPost();
1295    }
1296}
1297
1298void
1299NSGigE::cpuIntrClear()
1300{
1301    if (!cpuPendingIntr)
1302        return;
1303
1304    if (intrEvent) {
1305        intrEvent->squash();
1306        intrEvent = 0;
1307    }
1308
1309    intrTick = 0;
1310
1311    cpuPendingIntr = false;
1312
1313    DPRINTF(EthernetIntr, "clearing interrupt\n");
1314    intrClear();
1315}
1316
1317bool
1318NSGigE::cpuIntrPending() const
1319{ return cpuPendingIntr; }
1320
1321void
1322NSGigE::txReset()
1323{
1324
1325    DPRINTF(Ethernet, "transmit reset\n");
1326
1327    CTDD = false;
1328    txEnable = false;;
1329    txFragPtr = 0;
1330    assert(txDescCnt == 0);
1331    txFifo.clear();
1332    txState = txIdle;
1333    assert(txDmaState == dmaIdle);
1334}
1335
1336void
1337NSGigE::rxReset()
1338{
1339    DPRINTF(Ethernet, "receive reset\n");
1340
1341    CRDD = false;
1342    assert(rxPktBytes == 0);
1343    rxEnable = false;
1344    rxFragPtr = 0;
1345    assert(rxDescCnt == 0);
1346    assert(rxDmaState == dmaIdle);
1347    rxFifo.clear();
1348    rxState = rxIdle;
1349}
1350
1351void
1352NSGigE::regsReset()
1353{
1354    memset(&regs, 0, sizeof(regs));
1355    regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000);
1356    regs.mear = 0x12;
1357    regs.txcfg = 0x120; // set drain threshold to 1024 bytes and
1358                        // fill threshold to 32 bytes
1359    regs.rxcfg = 0x4;   // set drain threshold to 16 bytes
1360    regs.srr = 0x0103;  // set the silicon revision to rev B or 0x103
1361    regs.mibc = MIBC_FRZ;
1362    regs.vdr = 0x81;    // set the vlan tag type to 802.1q
1363    regs.tesr = 0xc000; // TBI capable of both full and half duplex
1364    regs.brar = 0xffffffff;
1365
1366    extstsEnable = false;
1367    acceptBroadcast = false;
1368    acceptMulticast = false;
1369    acceptUnicast = false;
1370    acceptPerfect = false;
1371    acceptArp = false;
1372}
1373
1374bool
1375NSGigE::doRxDmaRead()
1376{
1377    assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
1378    rxDmaState = dmaReading;
1379
1380    if (dmaPending())
1381        rxDmaState = dmaReadWaiting;
1382    else
1383        dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData);
1384
1385    return true;
1386}
1387
1388void
1389NSGigE::rxDmaReadDone()
1390{
1391    assert(rxDmaState == dmaReading);
1392    rxDmaState = dmaIdle;
1393
1394    DPRINTF(EthernetDMA, "rx dma read  paddr=%#x len=%d\n",
1395            rxDmaAddr, rxDmaLen);
1396    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1397
1398    // If the transmit state machine has a pending DMA, let it go first
1399    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1400        txKick();
1401
1402    rxKick();
1403}
1404
1405bool
1406NSGigE::doRxDmaWrite()
1407{
1408    assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
1409    rxDmaState = dmaWriting;
1410
1411    if (dmaPending())
1412        rxDmaState = dmaWriteWaiting;
1413    else
1414        dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData);
1415    return true;
1416}
1417
1418void
1419NSGigE::rxDmaWriteDone()
1420{
1421    assert(rxDmaState == dmaWriting);
1422    rxDmaState = dmaIdle;
1423
1424    DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
1425            rxDmaAddr, rxDmaLen);
1426    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1427
1428    // If the transmit state machine has a pending DMA, let it go first
1429    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1430        txKick();
1431
1432    rxKick();
1433}
1434
1435void
1436NSGigE::rxKick()
1437{
1438    bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
1439
1440    DPRINTF(EthernetSM,
1441            "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n",
1442            NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32);
1443
1444    Addr link, bufptr;
1445    uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts;
1446    uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts;
1447
1448  next:
1449    if (clock) {
1450        if (rxKickTick > curTick) {
1451            DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
1452                    rxKickTick);
1453
1454            goto exit;
1455        }
1456
1457        // Go to the next state machine clock tick.
1458        rxKickTick = curTick + cycles(1);
1459    }
1460
1461    switch(rxDmaState) {
1462      case dmaReadWaiting:
1463        if (doRxDmaRead())
1464            goto exit;
1465        break;
1466      case dmaWriteWaiting:
1467        if (doRxDmaWrite())
1468            goto exit;
1469        break;
1470      default:
1471        break;
1472    }
1473
1474    link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link;
1475    bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr;
1476
1477    // see state machine from spec for details
1478    // the way this works is, if you finish work on one state and can
1479    // go directly to another, you do that through jumping to the
1480    // label "next".  however, if you have intermediate work, like DMA
1481    // so that you can't go to the next state yet, you go to exit and
1482    // exit the loop.  however, when the DMA is done it will trigger
1483    // an event and come back to this loop.
1484    switch (rxState) {
1485      case rxIdle:
1486        if (!rxEnable) {
1487            DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");
1488            goto exit;
1489        }
1490
1491        if (CRDD) {
1492            rxState = rxDescRefr;
1493
1494            rxDmaAddr = regs.rxdp & 0x3fffffff;
1495            rxDmaData =
1496                is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link;
1497            rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link);
1498            rxDmaFree = dmaDescFree;
1499
1500            descDmaReads++;
1501            descDmaRdBytes += rxDmaLen;
1502
1503            if (doRxDmaRead())
1504                goto exit;
1505        } else {
1506            rxState = rxDescRead;
1507
1508            rxDmaAddr = regs.rxdp & 0x3fffffff;
1509            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
1510            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1511            rxDmaFree = dmaDescFree;
1512
1513            descDmaReads++;
1514            descDmaRdBytes += rxDmaLen;
1515
1516            if (doRxDmaRead())
1517                goto exit;
1518        }
1519        break;
1520
1521      case rxDescRefr:
1522        if (rxDmaState != dmaIdle)
1523            goto exit;
1524
1525        rxState = rxAdvance;
1526        break;
1527
1528     case rxDescRead:
1529        if (rxDmaState != dmaIdle)
1530            goto exit;
1531
1532        DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n",
1533                regs.rxdp & 0x3fffffff);
1534        DPRINTF(EthernetDesc,
1535                "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
1536                link, bufptr, cmdsts, extsts);
1537
1538        if (cmdsts & CMDSTS_OWN) {
1539            devIntrPost(ISR_RXIDLE);
1540            rxState = rxIdle;
1541            goto exit;
1542        } else {
1543            rxState = rxFifoBlock;
1544            rxFragPtr = bufptr;
1545            rxDescCnt = cmdsts & CMDSTS_LEN_MASK;
1546        }
1547        break;
1548
1549      case rxFifoBlock:
1550        if (!rxPacket) {
1551            /**
1552             * @todo in reality, we should be able to start processing
1553             * the packet as it arrives, and not have to wait for the
1554             * full packet ot be in the receive fifo.
1555             */
1556            if (rxFifo.empty())
1557                goto exit;
1558
1559            DPRINTF(EthernetSM, "****processing receive of new packet****\n");
1560
1561            // If we don't have a packet, grab a new one from the fifo.
1562            rxPacket = rxFifo.front();
1563            rxPktBytes = rxPacket->length;
1564            rxPacketBufPtr = rxPacket->data;
1565
1566#if TRACING_ON
1567            if (DTRACE(Ethernet)) {
1568                IpPtr ip(rxPacket);
1569                if (ip) {
1570                    DPRINTF(Ethernet, "ID is %d\n", ip->id());
1571                    TcpPtr tcp(ip);
1572                    if (tcp) {
1573                        DPRINTF(Ethernet,
1574                                "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1575                                tcp->sport(), tcp->dport(), tcp->seq(),
1576                                tcp->ack());
1577                    }
1578                }
1579            }
1580#endif
1581
1582            // sanity check - i think the driver behaves like this
1583            assert(rxDescCnt >= rxPktBytes);
1584            rxFifo.pop();
1585        }
1586
1587
1588        // dont' need the && rxDescCnt > 0 if driver sanity check
1589        // above holds
1590        if (rxPktBytes > 0) {
1591            rxState = rxFragWrite;
1592            // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
1593            // check holds
1594            rxXferLen = rxPktBytes;
1595
1596            rxDmaAddr = rxFragPtr & 0x3fffffff;
1597            rxDmaData = rxPacketBufPtr;
1598            rxDmaLen = rxXferLen;
1599            rxDmaFree = dmaDataFree;
1600
1601            if (doRxDmaWrite())
1602                goto exit;
1603
1604        } else {
1605            rxState = rxDescWrite;
1606
1607            //if (rxPktBytes == 0) {  /* packet is done */
1608            assert(rxPktBytes == 0);
1609            DPRINTF(EthernetSM, "done with receiving packet\n");
1610
1611            cmdsts |= CMDSTS_OWN;
1612            cmdsts &= ~CMDSTS_MORE;
1613            cmdsts |= CMDSTS_OK;
1614            cmdsts &= 0xffff0000;
1615            cmdsts += rxPacket->length;   //i.e. set CMDSTS_SIZE
1616
1617#if 0
1618            /*
1619             * all the driver uses these are for its own stats keeping
1620             * which we don't care about, aren't necessary for
1621             * functionality and doing this would just slow us down.
1622             * if they end up using this in a later version for
1623             * functional purposes, just undef
1624             */
1625            if (rxFilterEnable) {
1626                cmdsts &= ~CMDSTS_DEST_MASK;
1627                const EthAddr &dst = rxFifoFront()->dst();
1628                if (dst->unicast())
1629                    cmdsts |= CMDSTS_DEST_SELF;
1630                if (dst->multicast())
1631                    cmdsts |= CMDSTS_DEST_MULTI;
1632                if (dst->broadcast())
1633                    cmdsts |= CMDSTS_DEST_MASK;
1634            }
1635#endif
1636
1637            IpPtr ip(rxPacket);
1638            if (extstsEnable && ip) {
1639                extsts |= EXTSTS_IPPKT;
1640                rxIpChecksums++;
1641                if (cksum(ip) != 0) {
1642                    DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
1643                    extsts |= EXTSTS_IPERR;
1644                }
1645                TcpPtr tcp(ip);
1646                UdpPtr udp(ip);
1647                if (tcp) {
1648                    extsts |= EXTSTS_TCPPKT;
1649                    rxTcpChecksums++;
1650                    if (cksum(tcp) != 0) {
1651                        DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
1652                        extsts |= EXTSTS_TCPERR;
1653
1654                    }
1655                } else if (udp) {
1656                    extsts |= EXTSTS_UDPPKT;
1657                    rxUdpChecksums++;
1658                    if (cksum(udp) != 0) {
1659                        DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
1660                        extsts |= EXTSTS_UDPERR;
1661                    }
1662                }
1663            }
1664            rxPacket = 0;
1665
1666            /*
1667             * the driver seems to always receive into desc buffers
1668             * of size 1514, so you never have a pkt that is split
1669             * into multiple descriptors on the receive side, so
1670             * i don't implement that case, hence the assert above.
1671             */
1672
1673            DPRINTF(EthernetDesc,
1674                    "rxDesc: addr=%08x writeback cmdsts extsts\n",
1675                    regs.rxdp & 0x3fffffff);
1676            DPRINTF(EthernetDesc,
1677                    "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
1678                    link, bufptr, cmdsts, extsts);
1679
1680            rxDmaAddr = regs.rxdp & 0x3fffffff;
1681            rxDmaData = &cmdsts;
1682            if (is64bit) {
1683                rxDmaAddr += offsetof(ns_desc64, cmdsts);
1684                rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts);
1685            } else {
1686                rxDmaAddr += offsetof(ns_desc32, cmdsts);
1687                rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts);
1688            }
1689            rxDmaFree = dmaDescFree;
1690
1691            descDmaWrites++;
1692            descDmaWrBytes += rxDmaLen;
1693
1694            if (doRxDmaWrite())
1695                goto exit;
1696        }
1697        break;
1698
1699      case rxFragWrite:
1700        if (rxDmaState != dmaIdle)
1701            goto exit;
1702
1703        rxPacketBufPtr += rxXferLen;
1704        rxFragPtr += rxXferLen;
1705        rxPktBytes -= rxXferLen;
1706
1707        rxState = rxFifoBlock;
1708        break;
1709
1710      case rxDescWrite:
1711        if (rxDmaState != dmaIdle)
1712            goto exit;
1713
1714        assert(cmdsts & CMDSTS_OWN);
1715
1716        assert(rxPacket == 0);
1717        devIntrPost(ISR_RXOK);
1718
1719        if (cmdsts & CMDSTS_INTR)
1720            devIntrPost(ISR_RXDESC);
1721
1722        if (!rxEnable) {
1723            DPRINTF(EthernetSM, "Halting the RX state machine\n");
1724            rxState = rxIdle;
1725            goto exit;
1726        } else
1727            rxState = rxAdvance;
1728        break;
1729
1730      case rxAdvance:
1731        if (link == 0) {
1732            devIntrPost(ISR_RXIDLE);
1733            rxState = rxIdle;
1734            CRDD = true;
1735            goto exit;
1736        } else {
1737            if (rxDmaState != dmaIdle)
1738                goto exit;
1739            rxState = rxDescRead;
1740            regs.rxdp = link;
1741            CRDD = false;
1742
1743            rxDmaAddr = regs.rxdp & 0x3fffffff;
1744            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
1745            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1746            rxDmaFree = dmaDescFree;
1747
1748            if (doRxDmaRead())
1749                goto exit;
1750        }
1751        break;
1752
1753      default:
1754        panic("Invalid rxState!");
1755    }
1756
1757    DPRINTF(EthernetSM, "entering next rxState=%s\n",
1758            NsRxStateStrings[rxState]);
1759    goto next;
1760
1761  exit:
1762    /**
1763     * @todo do we want to schedule a future kick?
1764     */
1765    DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
1766            NsRxStateStrings[rxState]);
1767
1768    if (clock && !rxKickEvent.scheduled())
1769        rxKickEvent.schedule(rxKickTick);
1770}
1771
1772void
1773NSGigE::transmit()
1774{
1775    if (txFifo.empty()) {
1776        DPRINTF(Ethernet, "nothing to transmit\n");
1777        return;
1778    }
1779
1780    DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",
1781            txFifo.size());
1782    if (interface->sendPacket(txFifo.front())) {
1783#if TRACING_ON
1784        if (DTRACE(Ethernet)) {
1785            IpPtr ip(txFifo.front());
1786            if (ip) {
1787                DPRINTF(Ethernet, "ID is %d\n", ip->id());
1788                TcpPtr tcp(ip);
1789                if (tcp) {
1790                    DPRINTF(Ethernet,
1791                            "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1792                            tcp->sport(), tcp->dport(), tcp->seq(),
1793                            tcp->ack());
1794                }
1795            }
1796        }
1797#endif
1798
1799        DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length);
1800        txBytes += txFifo.front()->length;
1801        txPackets++;
1802
1803        DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
1804                txFifo.avail());
1805        txFifo.pop();
1806
1807        /*
1808         * normally do a writeback of the descriptor here, and ONLY
1809         * after that is done, send this interrupt.  but since our
1810         * stuff never actually fails, just do this interrupt here,
1811         * otherwise the code has to stray from this nice format.
1812         * besides, it's functionally the same.
1813         */
1814        devIntrPost(ISR_TXOK);
1815    }
1816
1817   if (!txFifo.empty() && !txEvent.scheduled()) {
1818       DPRINTF(Ethernet, "reschedule transmit\n");
1819       txEvent.schedule(curTick + retryTime);
1820   }
1821}
1822
1823bool
1824NSGigE::doTxDmaRead()
1825{
1826    assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
1827    txDmaState = dmaReading;
1828
1829    if (dmaPending())
1830        txDmaState = dmaReadWaiting;
1831    else
1832        dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData);
1833
1834    return true;
1835}
1836
1837void
1838NSGigE::txDmaReadDone()
1839{
1840    assert(txDmaState == dmaReading);
1841    txDmaState = dmaIdle;
1842
1843    DPRINTF(EthernetDMA, "tx dma read  paddr=%#x len=%d\n",
1844            txDmaAddr, txDmaLen);
1845    DDUMP(EthernetDMA, txDmaData, txDmaLen);
1846
1847    // If the receive state machine  has a pending DMA, let it go first
1848    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1849        rxKick();
1850
1851    txKick();
1852}
1853
1854bool
1855NSGigE::doTxDmaWrite()
1856{
1857    assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
1858    txDmaState = dmaWriting;
1859
1860    if (dmaPending())
1861        txDmaState = dmaWriteWaiting;
1862    else
1863        dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData);
1864    return true;
1865}
1866
1867void
1868NSGigE::txDmaWriteDone()
1869{
1870    assert(txDmaState == dmaWriting);
1871    txDmaState = dmaIdle;
1872
1873    DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n",
1874            txDmaAddr, txDmaLen);
1875    DDUMP(EthernetDMA, txDmaData, txDmaLen);
1876
1877    // If the receive state machine  has a pending DMA, let it go first
1878    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1879        rxKick();
1880
1881    txKick();
1882}
1883
1884void
1885NSGigE::txKick()
1886{
1887    bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
1888
1889    DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n",
1890            NsTxStateStrings[txState], is64bit ? 64 : 32);
1891
1892    Addr link, bufptr;
1893    uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts;
1894    uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts;
1895
1896  next:
1897    if (clock) {
1898        if (txKickTick > curTick) {
1899            DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
1900                    txKickTick);
1901            goto exit;
1902        }
1903
1904        // Go to the next state machine clock tick.
1905        txKickTick = curTick + cycles(1);
1906    }
1907
1908    switch(txDmaState) {
1909      case dmaReadWaiting:
1910        if (doTxDmaRead())
1911            goto exit;
1912        break;
1913      case dmaWriteWaiting:
1914        if (doTxDmaWrite())
1915            goto exit;
1916        break;
1917      default:
1918        break;
1919    }
1920
1921    link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link;
1922    bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr;
1923    switch (txState) {
1924      case txIdle:
1925        if (!txEnable) {
1926            DPRINTF(EthernetSM, "Transmit disabled.  Nothing to do.\n");
1927            goto exit;
1928        }
1929
1930        if (CTDD) {
1931            txState = txDescRefr;
1932
1933            txDmaAddr = regs.txdp & 0x3fffffff;
1934            txDmaData =
1935                is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link;
1936            txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link);
1937            txDmaFree = dmaDescFree;
1938
1939            descDmaReads++;
1940            descDmaRdBytes += txDmaLen;
1941
1942            if (doTxDmaRead())
1943                goto exit;
1944
1945        } else {
1946            txState = txDescRead;
1947
1948            txDmaAddr = regs.txdp & 0x3fffffff;
1949            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
1950            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
1951            txDmaFree = dmaDescFree;
1952
1953            descDmaReads++;
1954            descDmaRdBytes += txDmaLen;
1955
1956            if (doTxDmaRead())
1957                goto exit;
1958        }
1959        break;
1960
1961      case txDescRefr:
1962        if (txDmaState != dmaIdle)
1963            goto exit;
1964
1965        txState = txAdvance;
1966        break;
1967
1968      case txDescRead:
1969        if (txDmaState != dmaIdle)
1970            goto exit;
1971
1972        DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n",
1973                regs.txdp & 0x3fffffff);
1974        DPRINTF(EthernetDesc,
1975                "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n",
1976                link, bufptr, cmdsts, extsts);
1977
1978        if (cmdsts & CMDSTS_OWN) {
1979            txState = txFifoBlock;
1980            txFragPtr = bufptr;
1981            txDescCnt = cmdsts & CMDSTS_LEN_MASK;
1982        } else {
1983            devIntrPost(ISR_TXIDLE);
1984            txState = txIdle;
1985            goto exit;
1986        }
1987        break;
1988
1989      case txFifoBlock:
1990        if (!txPacket) {
1991            DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
1992            txPacket = new EthPacketData(16384);
1993            txPacketBufPtr = txPacket->data;
1994        }
1995
1996        if (txDescCnt == 0) {
1997            DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");
1998            if (cmdsts & CMDSTS_MORE) {
1999                DPRINTF(EthernetSM, "there are more descriptors to come\n");
2000                txState = txDescWrite;
2001
2002                cmdsts &= ~CMDSTS_OWN;
2003
2004                txDmaAddr = regs.txdp & 0x3fffffff;
2005                txDmaData = &cmdsts;
2006                if (is64bit) {
2007                    txDmaAddr += offsetof(ns_desc64, cmdsts);
2008                    txDmaLen = sizeof(txDesc64.cmdsts);
2009                } else {
2010                    txDmaAddr += offsetof(ns_desc32, cmdsts);
2011                    txDmaLen = sizeof(txDesc32.cmdsts);
2012                }
2013                txDmaFree = dmaDescFree;
2014
2015                if (doTxDmaWrite())
2016                    goto exit;
2017
2018            } else { /* this packet is totally done */
2019                DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
2020                /* deal with the the packet that just finished */
2021                if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
2022                    IpPtr ip(txPacket);
2023                    if (extsts & EXTSTS_UDPPKT) {
2024                        UdpPtr udp(ip);
2025                        udp->sum(0);
2026                        udp->sum(cksum(udp));
2027                        txUdpChecksums++;
2028                    } else if (extsts & EXTSTS_TCPPKT) {
2029                        TcpPtr tcp(ip);
2030                        tcp->sum(0);
2031                        tcp->sum(cksum(tcp));
2032                        txTcpChecksums++;
2033                    }
2034                    if (extsts & EXTSTS_IPPKT) {
2035                        ip->sum(0);
2036                        ip->sum(cksum(ip));
2037                        txIpChecksums++;
2038                    }
2039                }
2040
2041                txPacket->length = txPacketBufPtr - txPacket->data;
2042                // this is just because the receive can't handle a
2043                // packet bigger want to make sure
2044                if (txPacket->length > 1514)
2045                    panic("transmit packet too large, %s > 1514\n",
2046                          txPacket->length);
2047
2048#ifndef NDEBUG
2049                bool success =
2050#endif
2051                    txFifo.push(txPacket);
2052                assert(success);
2053
2054                /*
2055                 * this following section is not tqo spec, but
2056                 * functionally shouldn't be any different.  normally,
2057                 * the chip will wait til the transmit has occurred
2058                 * before writing back the descriptor because it has
2059                 * to wait to see that it was successfully transmitted
2060                 * to decide whether to set CMDSTS_OK or not.
2061                 * however, in the simulator since it is always
2062                 * successfully transmitted, and writing it exactly to
2063                 * spec would complicate the code, we just do it here
2064                 */
2065
2066                cmdsts &= ~CMDSTS_OWN;
2067                cmdsts |= CMDSTS_OK;
2068
2069                DPRINTF(EthernetDesc,
2070                        "txDesc writeback: cmdsts=%08x extsts=%08x\n",
2071                        cmdsts, extsts);
2072
2073                txDmaFree = dmaDescFree;
2074                txDmaAddr = regs.txdp & 0x3fffffff;
2075                txDmaData = &cmdsts;
2076                if (is64bit) {
2077                    txDmaAddr += offsetof(ns_desc64, cmdsts);
2078                    txDmaLen =
2079                        sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts);
2080                } else {
2081                    txDmaAddr += offsetof(ns_desc32, cmdsts);
2082                    txDmaLen =
2083                        sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts);
2084                }
2085
2086                descDmaWrites++;
2087                descDmaWrBytes += txDmaLen;
2088
2089                transmit();
2090                txPacket = 0;
2091
2092                if (!txEnable) {
2093                    DPRINTF(EthernetSM, "halting TX state machine\n");
2094                    txState = txIdle;
2095                    goto exit;
2096                } else
2097                    txState = txAdvance;
2098
2099                if (doTxDmaWrite())
2100                    goto exit;
2101            }
2102        } else {
2103            DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
2104            if (!txFifo.full()) {
2105                txState = txFragRead;
2106
2107                /*
2108                 * The number of bytes transferred is either whatever
2109                 * is left in the descriptor (txDescCnt), or if there
2110                 * is not enough room in the fifo, just whatever room
2111                 * is left in the fifo
2112                 */
2113                txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());
2114
2115                txDmaAddr = txFragPtr & 0x3fffffff;
2116                txDmaData = txPacketBufPtr;
2117                txDmaLen = txXferLen;
2118                txDmaFree = dmaDataFree;
2119
2120                if (doTxDmaRead())
2121                    goto exit;
2122            } else {
2123                txState = txFifoBlock;
2124                transmit();
2125
2126                goto exit;
2127            }
2128
2129        }
2130        break;
2131
2132      case txFragRead:
2133        if (txDmaState != dmaIdle)
2134            goto exit;
2135
2136        txPacketBufPtr += txXferLen;
2137        txFragPtr += txXferLen;
2138        txDescCnt -= txXferLen;
2139        txFifo.reserve(txXferLen);
2140
2141        txState = txFifoBlock;
2142        break;
2143
2144      case txDescWrite:
2145        if (txDmaState != dmaIdle)
2146            goto exit;
2147
2148        if (cmdsts & CMDSTS_INTR)
2149            devIntrPost(ISR_TXDESC);
2150
2151        if (!txEnable) {
2152            DPRINTF(EthernetSM, "halting TX state machine\n");
2153            txState = txIdle;
2154            goto exit;
2155        } else
2156            txState = txAdvance;
2157        break;
2158
2159      case txAdvance:
2160        if (link == 0) {
2161            devIntrPost(ISR_TXIDLE);
2162            txState = txIdle;
2163            goto exit;
2164        } else {
2165            if (txDmaState != dmaIdle)
2166                goto exit;
2167            txState = txDescRead;
2168            regs.txdp = link;
2169            CTDD = false;
2170
2171            txDmaAddr = link & 0x3fffffff;
2172            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
2173            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
2174            txDmaFree = dmaDescFree;
2175
2176            if (doTxDmaRead())
2177                goto exit;
2178        }
2179        break;
2180
2181      default:
2182        panic("invalid state");
2183    }
2184
2185    DPRINTF(EthernetSM, "entering next txState=%s\n",
2186            NsTxStateStrings[txState]);
2187    goto next;
2188
2189  exit:
2190    /**
2191     * @todo do we want to schedule a future kick?
2192     */
2193    DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
2194            NsTxStateStrings[txState]);
2195
2196    if (clock && !txKickEvent.scheduled())
2197        txKickEvent.schedule(txKickTick);
2198}
2199
2200/**
2201 * Advance the EEPROM state machine
2202 * Called on rising edge of EEPROM clock bit in MEAR
2203 */
2204void
2205NSGigE::eepromKick()
2206{
2207    switch (eepromState) {
2208
2209      case eepromStart:
2210
2211        // Wait for start bit
2212        if (regs.mear & MEAR_EEDI) {
2213            // Set up to get 2 opcode bits
2214            eepromState = eepromGetOpcode;
2215            eepromBitsToRx = 2;
2216            eepromOpcode = 0;
2217        }
2218        break;
2219
2220      case eepromGetOpcode:
2221        eepromOpcode <<= 1;
2222        eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0;
2223        --eepromBitsToRx;
2224
2225        // Done getting opcode
2226        if (eepromBitsToRx == 0) {
2227            if (eepromOpcode != EEPROM_READ)
2228                panic("only EEPROM reads are implemented!");
2229
2230            // Set up to get address
2231            eepromState = eepromGetAddress;
2232            eepromBitsToRx = 6;
2233            eepromAddress = 0;
2234        }
2235        break;
2236
2237      case eepromGetAddress:
2238        eepromAddress <<= 1;
2239        eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0;
2240        --eepromBitsToRx;
2241
2242        // Done getting address
2243        if (eepromBitsToRx == 0) {
2244
2245            if (eepromAddress >= EEPROM_SIZE)
2246                panic("EEPROM read access out of range!");
2247
2248            switch (eepromAddress) {
2249
2250              case EEPROM_PMATCH2_ADDR:
2251                eepromData = rom.perfectMatch[5];
2252                eepromData <<= 8;
2253                eepromData += rom.perfectMatch[4];
2254                break;
2255
2256              case EEPROM_PMATCH1_ADDR:
2257                eepromData = rom.perfectMatch[3];
2258                eepromData <<= 8;
2259                eepromData += rom.perfectMatch[2];
2260                break;
2261
2262              case EEPROM_PMATCH0_ADDR:
2263                eepromData = rom.perfectMatch[1];
2264                eepromData <<= 8;
2265                eepromData += rom.perfectMatch[0];
2266                break;
2267
2268              default:
2269                panic("FreeBSD driver only uses EEPROM to read PMATCH!");
2270            }
2271            // Set up to read data
2272            eepromState = eepromRead;
2273            eepromBitsToRx = 16;
2274
2275            // Clear data in bit
2276            regs.mear &= ~MEAR_EEDI;
2277        }
2278        break;
2279
2280      case eepromRead:
2281        // Clear Data Out bit
2282        regs.mear &= ~MEAR_EEDO;
2283        // Set bit to value of current EEPROM bit
2284        regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0;
2285
2286        eepromData <<= 1;
2287        --eepromBitsToRx;
2288
2289        // All done
2290        if (eepromBitsToRx == 0) {
2291            eepromState = eepromStart;
2292        }
2293        break;
2294
2295      default:
2296        panic("invalid EEPROM state");
2297    }
2298
2299}
2300
2301void
2302NSGigE::transferDone()
2303{
2304    if (txFifo.empty()) {
2305        DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
2306        return;
2307    }
2308
2309    DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
2310
2311    if (txEvent.scheduled())
2312        txEvent.reschedule(curTick + cycles(1));
2313    else
2314        txEvent.schedule(curTick + cycles(1));
2315}
2316
2317bool
2318NSGigE::rxFilter(const EthPacketPtr &packet)
2319{
2320    EthPtr eth = packet;
2321    bool drop = true;
2322    string type;
2323
2324    const EthAddr &dst = eth->dst();
2325    if (dst.unicast()) {
2326        // If we're accepting all unicast addresses
2327        if (acceptUnicast)
2328            drop = false;
2329
2330        // If we make a perfect match
2331        if (acceptPerfect && dst == rom.perfectMatch)
2332            drop = false;
2333
2334        if (acceptArp && eth->type() == ETH_TYPE_ARP)
2335            drop = false;
2336
2337    } else if (dst.broadcast()) {
2338        // if we're accepting broadcasts
2339        if (acceptBroadcast)
2340            drop = false;
2341
2342    } else if (dst.multicast()) {
2343        // if we're accepting all multicasts
2344        if (acceptMulticast)
2345            drop = false;
2346
2347        // Multicast hashing faked - all packets accepted
2348        if (multicastHashEnable)
2349            drop = false;
2350    }
2351
2352    if (drop) {
2353        DPRINTF(Ethernet, "rxFilter drop\n");
2354        DDUMP(EthernetData, packet->data, packet->length);
2355    }
2356
2357    return drop;
2358}
2359
2360bool
2361NSGigE::recvPacket(EthPacketPtr packet)
2362{
2363    rxBytes += packet->length;
2364    rxPackets++;
2365
2366    DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n",
2367            rxFifo.avail());
2368
2369    if (!rxEnable) {
2370        DPRINTF(Ethernet, "receive disabled...packet dropped\n");
2371        return true;
2372    }
2373
2374    if (!rxFilterEnable) {
2375        DPRINTF(Ethernet,
2376            "receive packet filtering disabled . . . packet dropped\n");
2377        return true;
2378    }
2379
2380    if (rxFilter(packet)) {
2381        DPRINTF(Ethernet, "packet filtered...dropped\n");
2382        return true;
2383    }
2384
2385    if (rxFifo.avail() < packet->length) {
2386#if TRACING_ON
2387        IpPtr ip(packet);
2388        TcpPtr tcp(ip);
2389        if (ip) {
2390            DPRINTF(Ethernet,
2391                    "packet won't fit in receive buffer...pkt ID %d dropped\n",
2392                    ip->id());
2393            if (tcp) {
2394                DPRINTF(Ethernet, "Seq=%d\n", tcp->seq());
2395            }
2396        }
2397#endif
2398        droppedPackets++;
2399        devIntrPost(ISR_RXORN);
2400        return false;
2401    }
2402
2403    rxFifo.push(packet);
2404
2405    rxKick();
2406    return true;
2407}
2408
2409//=====================================================================
2410//
2411//
2412void
2413NSGigE::serialize(ostream &os)
2414{
2415    // Serialize the PciDev base class
2416    PciDev::serialize(os);
2417
2418    /*
2419     * Finalize any DMA events now.
2420     */
2421    // @todo will mem system save pending dma?
2422
2423    /*
2424     * Serialize the device registers
2425     */
2426    SERIALIZE_SCALAR(regs.command);
2427    SERIALIZE_SCALAR(regs.config);
2428    SERIALIZE_SCALAR(regs.mear);
2429    SERIALIZE_SCALAR(regs.ptscr);
2430    SERIALIZE_SCALAR(regs.isr);
2431    SERIALIZE_SCALAR(regs.imr);
2432    SERIALIZE_SCALAR(regs.ier);
2433    SERIALIZE_SCALAR(regs.ihr);
2434    SERIALIZE_SCALAR(regs.txdp);
2435    SERIALIZE_SCALAR(regs.txdp_hi);
2436    SERIALIZE_SCALAR(regs.txcfg);
2437    SERIALIZE_SCALAR(regs.gpior);
2438    SERIALIZE_SCALAR(regs.rxdp);
2439    SERIALIZE_SCALAR(regs.rxdp_hi);
2440    SERIALIZE_SCALAR(regs.rxcfg);
2441    SERIALIZE_SCALAR(regs.pqcr);
2442    SERIALIZE_SCALAR(regs.wcsr);
2443    SERIALIZE_SCALAR(regs.pcr);
2444    SERIALIZE_SCALAR(regs.rfcr);
2445    SERIALIZE_SCALAR(regs.rfdr);
2446    SERIALIZE_SCALAR(regs.brar);
2447    SERIALIZE_SCALAR(regs.brdr);
2448    SERIALIZE_SCALAR(regs.srr);
2449    SERIALIZE_SCALAR(regs.mibc);
2450    SERIALIZE_SCALAR(regs.vrcr);
2451    SERIALIZE_SCALAR(regs.vtcr);
2452    SERIALIZE_SCALAR(regs.vdr);
2453    SERIALIZE_SCALAR(regs.ccsr);
2454    SERIALIZE_SCALAR(regs.tbicr);
2455    SERIALIZE_SCALAR(regs.tbisr);
2456    SERIALIZE_SCALAR(regs.tanar);
2457    SERIALIZE_SCALAR(regs.tanlpar);
2458    SERIALIZE_SCALAR(regs.taner);
2459    SERIALIZE_SCALAR(regs.tesr);
2460
2461    SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
2462    SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2463
2464    SERIALIZE_SCALAR(ioEnable);
2465
2466    /*
2467     * Serialize the data Fifos
2468     */
2469    rxFifo.serialize("rxFifo", os);
2470    txFifo.serialize("txFifo", os);
2471
2472    /*
2473     * Serialize the various helper variables
2474     */
2475    bool txPacketExists = txPacket;
2476    SERIALIZE_SCALAR(txPacketExists);
2477    if (txPacketExists) {
2478        txPacket->length = txPacketBufPtr - txPacket->data;
2479        txPacket->serialize("txPacket", os);
2480        uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
2481        SERIALIZE_SCALAR(txPktBufPtr);
2482    }
2483
2484    bool rxPacketExists = rxPacket;
2485    SERIALIZE_SCALAR(rxPacketExists);
2486    if (rxPacketExists) {
2487        rxPacket->serialize("rxPacket", os);
2488        uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
2489        SERIALIZE_SCALAR(rxPktBufPtr);
2490    }
2491
2492    SERIALIZE_SCALAR(txXferLen);
2493    SERIALIZE_SCALAR(rxXferLen);
2494
2495    /*
2496     * Serialize Cached Descriptors
2497     */
2498    SERIALIZE_SCALAR(rxDesc64.link);
2499    SERIALIZE_SCALAR(rxDesc64.bufptr);
2500    SERIALIZE_SCALAR(rxDesc64.cmdsts);
2501    SERIALIZE_SCALAR(rxDesc64.extsts);
2502    SERIALIZE_SCALAR(txDesc64.link);
2503    SERIALIZE_SCALAR(txDesc64.bufptr);
2504    SERIALIZE_SCALAR(txDesc64.cmdsts);
2505    SERIALIZE_SCALAR(txDesc64.extsts);
2506    SERIALIZE_SCALAR(rxDesc32.link);
2507    SERIALIZE_SCALAR(rxDesc32.bufptr);
2508    SERIALIZE_SCALAR(rxDesc32.cmdsts);
2509    SERIALIZE_SCALAR(rxDesc32.extsts);
2510    SERIALIZE_SCALAR(txDesc32.link);
2511    SERIALIZE_SCALAR(txDesc32.bufptr);
2512    SERIALIZE_SCALAR(txDesc32.cmdsts);
2513    SERIALIZE_SCALAR(txDesc32.extsts);
2514    SERIALIZE_SCALAR(extstsEnable);
2515
2516    /*
2517     * Serialize tx state machine
2518     */
2519    int txState = this->txState;
2520    SERIALIZE_SCALAR(txState);
2521    SERIALIZE_SCALAR(txEnable);
2522    SERIALIZE_SCALAR(CTDD);
2523    SERIALIZE_SCALAR(txFragPtr);
2524    SERIALIZE_SCALAR(txDescCnt);
2525    int txDmaState = this->txDmaState;
2526    SERIALIZE_SCALAR(txDmaState);
2527    SERIALIZE_SCALAR(txKickTick);
2528
2529    /*
2530     * Serialize rx state machine
2531     */
2532    int rxState = this->rxState;
2533    SERIALIZE_SCALAR(rxState);
2534    SERIALIZE_SCALAR(rxEnable);
2535    SERIALIZE_SCALAR(CRDD);
2536    SERIALIZE_SCALAR(rxPktBytes);
2537    SERIALIZE_SCALAR(rxFragPtr);
2538    SERIALIZE_SCALAR(rxDescCnt);
2539    int rxDmaState = this->rxDmaState;
2540    SERIALIZE_SCALAR(rxDmaState);
2541    SERIALIZE_SCALAR(rxKickTick);
2542
2543    /*
2544     * Serialize EEPROM state machine
2545     */
2546    int eepromState = this->eepromState;
2547    SERIALIZE_SCALAR(eepromState);
2548    SERIALIZE_SCALAR(eepromClk);
2549    SERIALIZE_SCALAR(eepromBitsToRx);
2550    SERIALIZE_SCALAR(eepromOpcode);
2551    SERIALIZE_SCALAR(eepromAddress);
2552    SERIALIZE_SCALAR(eepromData);
2553
2554    /*
2555     * If there's a pending transmit, store the time so we can
2556     * reschedule it later
2557     */
2558    Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;
2559    SERIALIZE_SCALAR(transmitTick);
2560
2561    /*
2562     * receive address filter settings
2563     */
2564    SERIALIZE_SCALAR(rxFilterEnable);
2565    SERIALIZE_SCALAR(acceptBroadcast);
2566    SERIALIZE_SCALAR(acceptMulticast);
2567    SERIALIZE_SCALAR(acceptUnicast);
2568    SERIALIZE_SCALAR(acceptPerfect);
2569    SERIALIZE_SCALAR(acceptArp);
2570    SERIALIZE_SCALAR(multicastHashEnable);
2571
2572    /*
2573     * Keep track of pending interrupt status.
2574     */
2575    SERIALIZE_SCALAR(intrTick);
2576    SERIALIZE_SCALAR(cpuPendingIntr);
2577    Tick intrEventTick = 0;
2578    if (intrEvent)
2579        intrEventTick = intrEvent->when();
2580    SERIALIZE_SCALAR(intrEventTick);
2581
2582}
2583
2584void
2585NSGigE::unserialize(Checkpoint *cp, const std::string &section)
2586{
2587    // Unserialize the PciDev base class
2588    PciDev::unserialize(cp, section);
2589
2590    UNSERIALIZE_SCALAR(regs.command);
2591    UNSERIALIZE_SCALAR(regs.config);
2592    UNSERIALIZE_SCALAR(regs.mear);
2593    UNSERIALIZE_SCALAR(regs.ptscr);
2594    UNSERIALIZE_SCALAR(regs.isr);
2595    UNSERIALIZE_SCALAR(regs.imr);
2596    UNSERIALIZE_SCALAR(regs.ier);
2597    UNSERIALIZE_SCALAR(regs.ihr);
2598    UNSERIALIZE_SCALAR(regs.txdp);
2599    UNSERIALIZE_SCALAR(regs.txdp_hi);
2600    UNSERIALIZE_SCALAR(regs.txcfg);
2601    UNSERIALIZE_SCALAR(regs.gpior);
2602    UNSERIALIZE_SCALAR(regs.rxdp);
2603    UNSERIALIZE_SCALAR(regs.rxdp_hi);
2604    UNSERIALIZE_SCALAR(regs.rxcfg);
2605    UNSERIALIZE_SCALAR(regs.pqcr);
2606    UNSERIALIZE_SCALAR(regs.wcsr);
2607    UNSERIALIZE_SCALAR(regs.pcr);
2608    UNSERIALIZE_SCALAR(regs.rfcr);
2609    UNSERIALIZE_SCALAR(regs.rfdr);
2610    UNSERIALIZE_SCALAR(regs.brar);
2611    UNSERIALIZE_SCALAR(regs.brdr);
2612    UNSERIALIZE_SCALAR(regs.srr);
2613    UNSERIALIZE_SCALAR(regs.mibc);
2614    UNSERIALIZE_SCALAR(regs.vrcr);
2615    UNSERIALIZE_SCALAR(regs.vtcr);
2616    UNSERIALIZE_SCALAR(regs.vdr);
2617    UNSERIALIZE_SCALAR(regs.ccsr);
2618    UNSERIALIZE_SCALAR(regs.tbicr);
2619    UNSERIALIZE_SCALAR(regs.tbisr);
2620    UNSERIALIZE_SCALAR(regs.tanar);
2621    UNSERIALIZE_SCALAR(regs.tanlpar);
2622    UNSERIALIZE_SCALAR(regs.taner);
2623    UNSERIALIZE_SCALAR(regs.tesr);
2624
2625    UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
2626    UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2627
2628    UNSERIALIZE_SCALAR(ioEnable);
2629
2630    /*
2631     * unserialize the data fifos
2632     */
2633    rxFifo.unserialize("rxFifo", cp, section);
2634    txFifo.unserialize("txFifo", cp, section);
2635
2636    /*
2637     * unserialize the various helper variables
2638     */
2639    bool txPacketExists;
2640    UNSERIALIZE_SCALAR(txPacketExists);
2641    if (txPacketExists) {
2642        txPacket = new EthPacketData(16384);
2643        txPacket->unserialize("txPacket", cp, section);
2644        uint32_t txPktBufPtr;
2645        UNSERIALIZE_SCALAR(txPktBufPtr);
2646        txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
2647    } else
2648        txPacket = 0;
2649
2650    bool rxPacketExists;
2651    UNSERIALIZE_SCALAR(rxPacketExists);
2652    rxPacket = 0;
2653    if (rxPacketExists) {
2654        rxPacket = new EthPacketData(16384);
2655        rxPacket->unserialize("rxPacket", cp, section);
2656        uint32_t rxPktBufPtr;
2657        UNSERIALIZE_SCALAR(rxPktBufPtr);
2658        rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
2659    } else
2660        rxPacket = 0;
2661
2662    UNSERIALIZE_SCALAR(txXferLen);
2663    UNSERIALIZE_SCALAR(rxXferLen);
2664
2665    /*
2666     * Unserialize Cached Descriptors
2667     */
2668    UNSERIALIZE_SCALAR(rxDesc64.link);
2669    UNSERIALIZE_SCALAR(rxDesc64.bufptr);
2670    UNSERIALIZE_SCALAR(rxDesc64.cmdsts);
2671    UNSERIALIZE_SCALAR(rxDesc64.extsts);
2672    UNSERIALIZE_SCALAR(txDesc64.link);
2673    UNSERIALIZE_SCALAR(txDesc64.bufptr);
2674    UNSERIALIZE_SCALAR(txDesc64.cmdsts);
2675    UNSERIALIZE_SCALAR(txDesc64.extsts);
2676    UNSERIALIZE_SCALAR(rxDesc32.link);
2677    UNSERIALIZE_SCALAR(rxDesc32.bufptr);
2678    UNSERIALIZE_SCALAR(rxDesc32.cmdsts);
2679    UNSERIALIZE_SCALAR(rxDesc32.extsts);
2680    UNSERIALIZE_SCALAR(txDesc32.link);
2681    UNSERIALIZE_SCALAR(txDesc32.bufptr);
2682    UNSERIALIZE_SCALAR(txDesc32.cmdsts);
2683    UNSERIALIZE_SCALAR(txDesc32.extsts);
2684    UNSERIALIZE_SCALAR(extstsEnable);
2685
2686    /*
2687     * unserialize tx state machine
2688     */
2689    int txState;
2690    UNSERIALIZE_SCALAR(txState);
2691    this->txState = (TxState) txState;
2692    UNSERIALIZE_SCALAR(txEnable);
2693    UNSERIALIZE_SCALAR(CTDD);
2694    UNSERIALIZE_SCALAR(txFragPtr);
2695    UNSERIALIZE_SCALAR(txDescCnt);
2696    int txDmaState;
2697    UNSERIALIZE_SCALAR(txDmaState);
2698    this->txDmaState = (DmaState) txDmaState;
2699    UNSERIALIZE_SCALAR(txKickTick);
2700    if (txKickTick)
2701        txKickEvent.schedule(txKickTick);
2702
2703    /*
2704     * unserialize rx state machine
2705     */
2706    int rxState;
2707    UNSERIALIZE_SCALAR(rxState);
2708    this->rxState = (RxState) rxState;
2709    UNSERIALIZE_SCALAR(rxEnable);
2710    UNSERIALIZE_SCALAR(CRDD);
2711    UNSERIALIZE_SCALAR(rxPktBytes);
2712    UNSERIALIZE_SCALAR(rxFragPtr);
2713    UNSERIALIZE_SCALAR(rxDescCnt);
2714    int rxDmaState;
2715    UNSERIALIZE_SCALAR(rxDmaState);
2716    this->rxDmaState = (DmaState) rxDmaState;
2717    UNSERIALIZE_SCALAR(rxKickTick);
2718    if (rxKickTick)
2719        rxKickEvent.schedule(rxKickTick);
2720
2721    /*
2722     * Unserialize EEPROM state machine
2723     */
2724    int eepromState;
2725    UNSERIALIZE_SCALAR(eepromState);
2726    this->eepromState = (EEPROMState) eepromState;
2727    UNSERIALIZE_SCALAR(eepromClk);
2728    UNSERIALIZE_SCALAR(eepromBitsToRx);
2729    UNSERIALIZE_SCALAR(eepromOpcode);
2730    UNSERIALIZE_SCALAR(eepromAddress);
2731    UNSERIALIZE_SCALAR(eepromData);
2732
2733    /*
2734     * If there's a pending transmit, reschedule it now
2735     */
2736    Tick transmitTick;
2737    UNSERIALIZE_SCALAR(transmitTick);
2738    if (transmitTick)
2739        txEvent.schedule(curTick + transmitTick);
2740
2741    /*
2742     * unserialize receive address filter settings
2743     */
2744    UNSERIALIZE_SCALAR(rxFilterEnable);
2745    UNSERIALIZE_SCALAR(acceptBroadcast);
2746    UNSERIALIZE_SCALAR(acceptMulticast);
2747    UNSERIALIZE_SCALAR(acceptUnicast);
2748    UNSERIALIZE_SCALAR(acceptPerfect);
2749    UNSERIALIZE_SCALAR(acceptArp);
2750    UNSERIALIZE_SCALAR(multicastHashEnable);
2751
2752    /*
2753     * Keep track of pending interrupt status.
2754     */
2755    UNSERIALIZE_SCALAR(intrTick);
2756    UNSERIALIZE_SCALAR(cpuPendingIntr);
2757    Tick intrEventTick;
2758    UNSERIALIZE_SCALAR(intrEventTick);
2759    if (intrEventTick) {
2760        intrEvent = new IntrEvent(this, true);
2761        intrEvent->schedule(intrEventTick);
2762    }
2763}
2764
2765BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
2766
2767    SimObjectParam<EtherInt *> peer;
2768    SimObjectParam<NSGigE *> device;
2769
2770END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
2771
2772BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
2773
2774    INIT_PARAM_DFLT(peer, "peer interface", NULL),
2775    INIT_PARAM(device, "Ethernet device of this interface")
2776
2777END_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
2778
2779CREATE_SIM_OBJECT(NSGigEInt)
2780{
2781    NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device);
2782
2783    EtherInt *p = (EtherInt *)peer;
2784    if (p) {
2785        dev_int->setPeer(p);
2786        p->setPeer(dev_int);
2787    }
2788
2789    return dev_int;
2790}
2791
2792REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt)
2793
2794
2795BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
2796
2797    SimObjectParam<System *> system;
2798    SimObjectParam<Platform *> platform;
2799    SimObjectParam<PciConfigData *> configdata;
2800    Param<uint32_t> pci_bus;
2801    Param<uint32_t> pci_dev;
2802    Param<uint32_t> pci_func;
2803    Param<Tick> pio_latency;
2804
2805    Param<Tick> clock;
2806    Param<bool> dma_desc_free;
2807    Param<bool> dma_data_free;
2808    Param<Tick> dma_read_delay;
2809    Param<Tick> dma_write_delay;
2810    Param<Tick> dma_read_factor;
2811    Param<Tick> dma_write_factor;
2812    Param<bool> dma_no_allocate;
2813    Param<Tick> intr_delay;
2814
2815    Param<Tick> rx_delay;
2816    Param<Tick> tx_delay;
2817    Param<uint32_t> rx_fifo_size;
2818    Param<uint32_t> tx_fifo_size;
2819
2820    Param<bool> rx_filter;
2821    Param<string> hardware_address;
2822    Param<bool> rx_thread;
2823    Param<bool> tx_thread;
2824    Param<bool> rss;
2825
2826END_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
2827
2828BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
2829
2830    INIT_PARAM(system, "System pointer"),
2831    INIT_PARAM(platform, "Platform pointer"),
2832    INIT_PARAM(configdata, "PCI Config data"),
2833    INIT_PARAM(pci_bus, "PCI bus ID"),
2834    INIT_PARAM(pci_dev, "PCI device number"),
2835    INIT_PARAM(pci_func, "PCI function code"),
2836    INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
2837    INIT_PARAM(clock, "State machine cycle time"),
2838
2839    INIT_PARAM(dma_desc_free, "DMA of Descriptors is free"),
2840    INIT_PARAM(dma_data_free, "DMA of Data is free"),
2841    INIT_PARAM(dma_read_delay, "fixed delay for dma reads"),
2842    INIT_PARAM(dma_write_delay, "fixed delay for dma writes"),
2843    INIT_PARAM(dma_read_factor, "multiplier for dma reads"),
2844    INIT_PARAM(dma_write_factor, "multiplier for dma writes"),
2845    INIT_PARAM(dma_no_allocate, "Should DMA reads allocate cache lines"),
2846    INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"),
2847
2848    INIT_PARAM(rx_delay, "Receive Delay"),
2849    INIT_PARAM(tx_delay, "Transmit Delay"),
2850    INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"),
2851    INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"),
2852
2853    INIT_PARAM(rx_filter, "Enable Receive Filter"),
2854    INIT_PARAM(hardware_address, "Ethernet Hardware Address"),
2855    INIT_PARAM(rx_thread, ""),
2856    INIT_PARAM(tx_thread, ""),
2857    INIT_PARAM(rss, "")
2858
2859END_INIT_SIM_OBJECT_PARAMS(NSGigE)
2860
2861
2862CREATE_SIM_OBJECT(NSGigE)
2863{
2864    NSGigE::Params *params = new NSGigE::Params;
2865
2866    params->name = getInstanceName();
2867    params->platform = platform;
2868    params->system = system;
2869    params->configData = configdata;
2870    params->busNum = pci_bus;
2871    params->deviceNum = pci_dev;
2872    params->functionNum = pci_func;
2873    params->pio_delay = pio_latency;
2874
2875    params->clock = clock;
2876    params->dma_desc_free = dma_desc_free;
2877    params->dma_data_free = dma_data_free;
2878    params->dma_read_delay = dma_read_delay;
2879    params->dma_write_delay = dma_write_delay;
2880    params->dma_read_factor = dma_read_factor;
2881    params->dma_write_factor = dma_write_factor;
2882    params->dma_no_allocate = dma_no_allocate;
2883    params->pio_delay = pio_latency;
2884    params->intr_delay = intr_delay;
2885
2886    params->rx_delay = rx_delay;
2887    params->tx_delay = tx_delay;
2888    params->rx_fifo_size = rx_fifo_size;
2889    params->tx_fifo_size = tx_fifo_size;
2890
2891    params->rx_filter = rx_filter;
2892    params->eaddr = hardware_address;
2893    params->rx_thread = rx_thread;
2894    params->tx_thread = tx_thread;
2895    params->rss = rss;
2896
2897    return new NSGigE(params);
2898}
2899
2900REGISTER_SIM_OBJECT("NSGigE", NSGigE)
2901