ns_gige.cc revision 1893
11156SN/A/*
21762SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
31156SN/A * All rights reserved.
41156SN/A *
51156SN/A * Redistribution and use in source and binary forms, with or without
61156SN/A * modification, are permitted provided that the following conditions are
71156SN/A * met: redistributions of source code must retain the above copyright
81156SN/A * notice, this list of conditions and the following disclaimer;
91156SN/A * redistributions in binary form must reproduce the above copyright
101156SN/A * notice, this list of conditions and the following disclaimer in the
111156SN/A * documentation and/or other materials provided with the distribution;
121156SN/A * neither the name of the copyright holders nor the names of its
131156SN/A * contributors may be used to endorse or promote products derived from
141156SN/A * this software without specific prior written permission.
151156SN/A *
161156SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171156SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181156SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191156SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201156SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211156SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221156SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231156SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241156SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251156SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261156SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665SN/A */
282665SN/A
291156SN/A/** @file
301156SN/A * Device module for modelling the National Semiconductor
3111263Sandreas.sandberg@arm.com * DP83820 ethernet controller.  Does not support priority queueing
3211263Sandreas.sandberg@arm.com */
331156SN/A#include <cstdio>
342566SN/A#include <deque>
351156SN/A#include <string>
361156SN/A
379850SN/A#include "base/inet.hh"
384762SN/A#include "cpu/exec_context.hh"
3911263Sandreas.sandberg@arm.com#include "dev/etherlink.hh"
409850SN/A#include "dev/ns_gige.hh"
418641SN/A#include "dev/pciconfigall.hh"
425882SN/A#include "mem/bus/bus.hh"
431156SN/A#include "mem/bus/dma_interface.hh"
446216SN/A#include "mem/bus/pio_interface.hh"
456658SN/A#include "mem/bus/pio_interface_impl.hh"
468232SN/A#include "mem/functional/memory_control.hh"
4711263Sandreas.sandberg@arm.com#include "mem/functional/physical.hh"
482566SN/A#include "sim/builder.hh"
493348SN/A#include "sim/debug.hh"
501156SN/A#include "sim/host.hh"
511157SN/A#include "sim/stats.hh"
521156SN/A#include "targetarch/vtophys.hh"
535603SN/A
541156SN/Aconst char *NsRxStateStrings[] =
552107SN/A{
561156SN/A    "rxIdle",
571156SN/A    "rxDescRefr",
581156SN/A    "rxDescRead",
591156SN/A    "rxFifoBlock",
601156SN/A    "rxFragWrite",
611156SN/A    "rxDescWrite",
621156SN/A    "rxAdvance"
631156SN/A};
641156SN/A
651156SN/Aconst char *NsTxStateStrings[] =
661156SN/A{
671156SN/A    "txIdle",
681156SN/A    "txDescRefr",
691156SN/A    "txDescRead",
701156SN/A    "txFifoBlock",
711156SN/A    "txFragRead",
721156SN/A    "txDescWrite",
731156SN/A    "txAdvance"
741156SN/A};
751156SN/A
761156SN/Aconst char *NsDmaState[] =
771156SN/A{
781156SN/A    "dmaIdle",
791156SN/A    "dmaReading",
801156SN/A    "dmaWriting",
811156SN/A    "dmaReadWaiting",
824981SN/A    "dmaWriteWaiting"
839339SN/A};
841634SN/A
851634SN/Ausing namespace std;
861156SN/Ausing namespace Net;
871156SN/A
881156SN/A///////////////////////////////////////////////////////////////////////
894981SN/A//
902627SN/A// NSGigE PCI Device
912282SN/A//
922627SN/ANSGigE::NSGigE(Params *p)
931156SN/A    : PciDev(p), ioEnable(false),
941156SN/A      txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size),
951156SN/A      txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
961156SN/A      txXferLen(0), rxXferLen(0), clock(p->clock),
971156SN/A      txState(txIdle), txEnable(false), CTDD(false),
984981SN/A      txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
991156SN/A      rxEnable(false), CRDD(false), rxPktBytes(0),
1001156SN/A      rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false),
1011156SN/A      eepromState(eepromStart), rxDmaReadEvent(this), rxDmaWriteEvent(this),
1021156SN/A      txDmaReadEvent(this), txDmaWriteEvent(this),
1031156SN/A      dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free),
1041156SN/A      txDelay(p->tx_delay), rxDelay(p->rx_delay),
1051156SN/A      rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this),
1061156SN/A      txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false),
1071156SN/A      acceptMulticast(false), acceptUnicast(false),
1081156SN/A      acceptPerfect(false), acceptArp(false), multicastHashEnable(false),
1099339SN/A      physmem(p->pmem), intrTick(0), cpuPendingIntr(false),
1105603SN/A      intrEvent(0), interface(0)
1115603SN/A{
1125603SN/A    if (p->header_bus) {
1135603SN/A        pioInterface = newPioInterface(name() + ".pio", p->hier,
1145603SN/A                                       p->header_bus, this,
1155603SN/A                                       &NSGigE::cacheAccess);
1165603SN/A
1175603SN/A        pioLatency = p->pio_latency * p->header_bus->clockRate;
1185603SN/A
1195603SN/A        if (p->payload_bus)
1205603SN/A            dmaInterface = new DMAInterface<Bus>(name() + ".dma",
1215603SN/A                                                 p->header_bus,
1225603SN/A                                                 p->payload_bus, 1,
1235603SN/A                                                 p->dma_no_allocate);
1245603SN/A        else
1255603SN/A            dmaInterface = new DMAInterface<Bus>(name() + ".dma",
1265603SN/A                                                 p->header_bus,
1275603SN/A                                                 p->header_bus, 1,
1285603SN/A                                                 p->dma_no_allocate);
1295603SN/A    } else if (p->payload_bus) {
1305603SN/A        pioInterface = newPioInterface(name() + ".pio2", p->hier,
1315603SN/A                                       p->payload_bus, this,
1325603SN/A                                       &NSGigE::cacheAccess);
1335603SN/A
1345603SN/A        pioLatency = p->pio_latency * p->payload_bus->clockRate;
1355603SN/A
1365603SN/A        dmaInterface = new DMAInterface<Bus>(name() + ".dma",
1375603SN/A                                             p->payload_bus,
1389339SN/A                                             p->payload_bus, 1,
1399339SN/A                                             p->dma_no_allocate);
1405603SN/A    }
1411156SN/A
1421156SN/A
1434981SN/A    intrDelay = p->intr_delay;
1444981SN/A    dmaReadDelay = p->dma_read_delay;
1454981SN/A    dmaWriteDelay = p->dma_write_delay;
1464981SN/A    dmaReadFactor = p->dma_read_factor;
1474981SN/A    dmaWriteFactor = p->dma_write_factor;
1484981SN/A
1494981SN/A    regsReset();
1504981SN/A    memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN);
1514981SN/A}
1524981SN/A
1534981SN/ANSGigE::~NSGigE()
1544981SN/A{}
1554981SN/A
1561939SN/Avoid
15711005SN/ANSGigE::regStats()
1582008SN/A{
1592008SN/A    txBytes
1602282SN/A        .name(name() + ".txBytes")
1612282SN/A        .desc("Bytes Transmitted")
1622282SN/A        .prereq(txBytes)
1632008SN/A        ;
1642008SN/A
1655603SN/A    rxBytes
1665603SN/A        .name(name() + ".rxBytes")
1675603SN/A        .desc("Bytes Received")
1685603SN/A        .prereq(rxBytes)
1692008SN/A        ;
17011005SN/A
1712008SN/A    txPackets
1722008SN/A        .name(name() + ".txPackets")
1732008SN/A        .desc("Number of Packets Transmitted")
1742008SN/A        .prereq(txBytes)
1752008SN/A        ;
1762008SN/A
1772008SN/A    rxPackets
1782008SN/A        .name(name() + ".rxPackets")
1792282SN/A        .desc("Number of Packets Received")
1802282SN/A        .prereq(rxBytes)
1815603SN/A        ;
1822282SN/A
1832008SN/A    txIpChecksums
1842008SN/A        .name(name() + ".txIpChecksums")
1852008SN/A        .desc("Number of tx IP Checksums done by device")
1862008SN/A        .precision(0)
1872008SN/A        .prereq(txBytes)
1882008SN/A        ;
1892008SN/A
1902008SN/A    rxIpChecksums
1915603SN/A        .name(name() + ".rxIpChecksums")
1922008SN/A        .desc("Number of rx IP Checksums done by device")
1932008SN/A        .precision(0)
1942008SN/A        .prereq(rxBytes)
1955603SN/A        ;
1965603SN/A
1975603SN/A    txTcpChecksums
1985603SN/A        .name(name() + ".txTcpChecksums")
1995603SN/A        .desc("Number of tx TCP Checksums done by device")
2005603SN/A        .precision(0)
2015603SN/A        .prereq(txBytes)
2025603SN/A        ;
2035603SN/A
2045603SN/A    rxTcpChecksums
2055603SN/A        .name(name() + ".rxTcpChecksums")
2065603SN/A        .desc("Number of rx TCP Checksums done by device")
2075603SN/A        .precision(0)
2082008SN/A        .prereq(rxBytes)
2092008SN/A        ;
2102008SN/A
21111005SN/A    txUdpChecksums
2121997SN/A        .name(name() + ".txUdpChecksums")
2132008SN/A        .desc("Number of tx UDP Checksums done by device")
2141997SN/A        .precision(0)
2151997SN/A        .prereq(txBytes)
2161156SN/A        ;
2171939SN/A
2181156SN/A    rxUdpChecksums
2192566SN/A        .name(name() + ".rxUdpChecksums")
2203349SN/A        .desc("Number of rx UDP Checksums done by device")
2211156SN/A        .precision(0)
2221817SN/A        .prereq(rxBytes)
2232641SN/A        ;
2241156SN/A
22511005SN/A    descDmaReads
2262641SN/A        .name(name() + ".descDMAReads")
2272008SN/A        .desc("Number of descriptors the device read w/ DMA")
2282008SN/A        .precision(0)
2291997SN/A        ;
2302008SN/A
2312617SN/A    descDmaWrites
2322641SN/A        .name(name() + ".descDMAWrites")
2331156SN/A        .desc("Number of descriptors the device wrote w/ DMA")
2342008SN/A        .precision(0)
2351939SN/A        ;
2362279SN/A
2372617SN/A    descDmaRdBytes
2382641SN/A        .name(name() + ".descDmaReadBytes")
2391939SN/A        .desc("number of descriptor bytes read w/ DMA")
2402279SN/A        .precision(0)
2412617SN/A        ;
2422641SN/A
2431156SN/A   descDmaWrBytes
2442008SN/A        .name(name() + ".descDmaWriteBytes")
2451156SN/A        .desc("number of descriptor bytes write w/ DMA")
2468641SN/A        .precision(0)
2472641SN/A        ;
2482566SN/A
2492630SN/A    txBandwidth
2501939SN/A        .name(name() + ".txBandwidth")
2511156SN/A        .desc("Transmit Bandwidth (bits/s)")
2521156SN/A        .precision(0)
2532641SN/A        .prereq(txBytes)
2542566SN/A        ;
2552630SN/A
2561939SN/A    rxBandwidth
2571939SN/A        .name(name() + ".rxBandwidth")
2581939SN/A        .desc("Receive Bandwidth (bits/s)")
2591998SN/A        .precision(0)
2602617SN/A        .prereq(rxBytes)
2612641SN/A        ;
2621939SN/A
2631939SN/A    totBandwidth
2641939SN/A        .name(name() + ".totBandwidth")
2652008SN/A        .desc("Total Bandwidth (bits/s)")
2661939SN/A        .precision(0)
2671156SN/A        .prereq(totBytes)
2682566SN/A        ;
2691156SN/A
2701156SN/A    totPackets
2711939SN/A        .name(name() + ".totPackets")
2721939SN/A        .desc("Total Packets")
2732566SN/A        .precision(0)
2742566SN/A        .prereq(totBytes)
27511005SN/A        ;
2761939SN/A
2771939SN/A    totBytes
2781939SN/A        .name(name() + ".totBytes")
2791939SN/A        .desc("Total Bytes")
2801939SN/A        .precision(0)
2811939SN/A        .prereq(totBytes)
2821998SN/A        ;
2831939SN/A
2841998SN/A    totPacketRate
2851998SN/A        .name(name() + ".totPPS")
2861939SN/A        .desc("Total Tranmission Rate (packets/s)")
2872008SN/A        .precision(0)
2881939SN/A        .prereq(totBytes)
2891939SN/A        ;
2901939SN/A
2911939SN/A    txPacketRate
2921939SN/A        .name(name() + ".txPPS")
2931939SN/A        .desc("Packet Tranmission Rate (packets/s)")
2941939SN/A        .precision(0)
2951998SN/A        .prereq(txBytes)
2961998SN/A        ;
2971939SN/A
2982090SN/A    rxPacketRate
2991939SN/A        .name(name() + ".rxPPS")
3002566SN/A        .desc("Packet Reception Rate (packets/s)")
3011939SN/A        .precision(0)
3021939SN/A        .prereq(rxBytes)
3031939SN/A        ;
3042566SN/A
3053349SN/A    postedSwi
3061156SN/A        .name(name() + ".postedSwi")
3071817SN/A        .desc("number of software interrupts posted to CPU")
3082641SN/A        .precision(0)
3091939SN/A        ;
31011005SN/A
3112641SN/A    totalSwi
3122008SN/A        .name(name() + ".totalSwi")
3132008SN/A        .desc("number of total Swi written to ISR")
3141997SN/A        .precision(0)
3152008SN/A        ;
3162566SN/A
3172641SN/A    coalescedSwi
3181156SN/A        .name(name() + ".coalescedSwi")
3192008SN/A        .desc("average number of Swi's coalesced into each post")
3201939SN/A        .precision(0)
3212279SN/A        ;
3222617SN/A
3232641SN/A    postedRxIdle
3241939SN/A        .name(name() + ".postedRxIdle")
3252641SN/A        .desc("number of rxIdle interrupts posted to CPU")
3262279SN/A        .precision(0)
3272617SN/A        ;
3282641SN/A
3291156SN/A    totalRxIdle
3302176SN/A        .name(name() + ".totalRxIdle")
3312176SN/A        .desc("number of total RxIdle written to ISR")
3321998SN/A        .precision(0)
3332617SN/A        ;
3342630SN/A
3352641SN/A    coalescedRxIdle
3361156SN/A        .name(name() + ".coalescedRxIdle")
3372008SN/A        .desc("average number of RxIdle's coalesced into each post")
3381156SN/A        .precision(0)
3392008SN/A        ;
3401156SN/A
3412630SN/A    postedRxOk
3421156SN/A        .name(name() + ".postedRxOk")
3431156SN/A        .desc("number of RxOk interrupts posted to CPU")
3441939SN/A        .precision(0)
3452630SN/A        ;
3461156SN/A
3471156SN/A    totalRxOk
3481939SN/A        .name(name() + ".totalRxOk")
3492630SN/A        .desc("number of total RxOk written to ISR")
3501156SN/A        .precision(0)
3511156SN/A        ;
3521156SN/A
3532630SN/A    coalescedRxOk
3541156SN/A        .name(name() + ".coalescedRxOk")
3551156SN/A        .desc("average number of RxOk's coalesced into each post")
3561156SN/A        .precision(0)
3572008SN/A        ;
3581939SN/A
3591939SN/A    postedRxDesc
3601156SN/A        .name(name() + ".postedRxDesc")
3612282SN/A        .desc("number of RxDesc interrupts posted to CPU")
3622008SN/A        .precision(0)
3632630SN/A        ;
3645603SN/A
3652282SN/A    totalRxDesc
3662630SN/A        .name(name() + ".totalRxDesc")
3672627SN/A        .desc("number of total RxDesc written to ISR")
3685603SN/A        .precision(0)
3695603SN/A        ;
3702282SN/A
3712282SN/A    coalescedRxDesc
3722282SN/A        .name(name() + ".coalescedRxDesc")
3732282SN/A        .desc("average number of RxDesc's coalesced into each post")
3742282SN/A        .precision(0)
3755603SN/A        ;
3765603SN/A
3772282SN/A    postedTxOk
3782282SN/A        .name(name() + ".postedTxOk")
3792282SN/A        .desc("number of TxOk interrupts posted to CPU")
3802282SN/A        .precision(0)
3812282SN/A        ;
3825603SN/A
3832282SN/A    totalTxOk
3842282SN/A        .name(name() + ".totalTxOk")
3852282SN/A        .desc("number of total TxOk written to ISR")
3862282SN/A        .precision(0)
3872282SN/A        ;
3882282SN/A
3892282SN/A    coalescedTxOk
3902282SN/A        .name(name() + ".coalescedTxOk")
3911156SN/A        .desc("average number of TxOk's coalesced into each post")
3921156SN/A        .precision(0)
3931156SN/A        ;
3941156SN/A
3951156SN/A    postedTxIdle
3961156SN/A        .name(name() + ".postedTxIdle")
3972008SN/A        .desc("number of TxIdle interrupts posted to CPU")
3981939SN/A        .precision(0)
3991939SN/A        ;
4001156SN/A
4012282SN/A    totalTxIdle
4022008SN/A        .name(name() + ".totalTxIdle")
4032282SN/A        .desc("number of total TxIdle written to ISR")
4042630SN/A        .precision(0)
4052617SN/A        ;
4065603SN/A
4075603SN/A    coalescedTxIdle
4082282SN/A        .name(name() + ".coalescedTxIdle")
4095603SN/A        .desc("average number of TxIdle's coalesced into each post")
4102282SN/A        .precision(0)
4112282SN/A        ;
4122282SN/A
4135603SN/A    postedTxDesc
4145603SN/A        .name(name() + ".postedTxDesc")
4152282SN/A        .desc("number of TxDesc interrupts posted to CPU")
4165603SN/A        .precision(0)
4172282SN/A        ;
4182282SN/A
4192282SN/A    totalTxDesc
4202008SN/A        .name(name() + ".totalTxDesc")
4212008SN/A        .desc("number of total TxDesc written to ISR")
4222010SN/A        .precision(0)
4231156SN/A        ;
4241156SN/A
4251156SN/A    coalescedTxDesc
4261156SN/A        .name(name() + ".coalescedTxDesc")
4271156SN/A        .desc("average number of TxDesc's coalesced into each post")
4282176SN/A        .precision(0)
4292566SN/A        ;
4301156SN/A
4311156SN/A    postedRxOrn
4321156SN/A        .name(name() + ".postedRxOrn")
4331156SN/A        .desc("number of RxOrn posted to CPU")
4341156SN/A        .precision(0)
4351156SN/A        ;
4361156SN/A
4371156SN/A    totalRxOrn
4381156SN/A        .name(name() + ".totalRxOrn")
4391156SN/A        .desc("number of total RxOrn written to ISR")
4401156SN/A        .precision(0)
4411156SN/A        ;
4421156SN/A
4431156SN/A    coalescedRxOrn
4441939SN/A        .name(name() + ".coalescedRxOrn")
4451939SN/A        .desc("average number of RxOrn's coalesced into each post")
4461939SN/A        .precision(0)
4471939SN/A        ;
4481939SN/A
4491939SN/A    coalescedTotal
4501939SN/A        .name(name() + ".coalescedTotal")
4511939SN/A        .desc("average number of interrupts coalesced into each post")
4521939SN/A        .precision(0)
4531939SN/A        ;
4541939SN/A
4551939SN/A    postedInterrupts
4561939SN/A        .name(name() + ".postedInterrupts")
4571939SN/A        .desc("number of posts to CPU")
4581939SN/A        .precision(0)
4591939SN/A        ;
4601939SN/A
4617823SN/A    droppedPackets
4621939SN/A        .name(name() + ".droppedPackets")
4631156SN/A        .desc("number of packets dropped")
4641156SN/A        .precision(0)
4651156SN/A        ;
4661156SN/A
4671156SN/A    coalescedSwi = totalSwi / postedInterrupts;
4681156SN/A    coalescedRxIdle = totalRxIdle / postedInterrupts;
4691156SN/A    coalescedRxOk = totalRxOk / postedInterrupts;
4701156SN/A    coalescedRxDesc = totalRxDesc / postedInterrupts;
4711156SN/A    coalescedTxOk = totalTxOk / postedInterrupts;
4721156SN/A    coalescedTxIdle = totalTxIdle / postedInterrupts;
4731156SN/A    coalescedTxDesc = totalTxDesc / postedInterrupts;
4741156SN/A    coalescedRxOrn = totalRxOrn / postedInterrupts;
4751156SN/A
4761156SN/A    coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc +
4771156SN/A                      totalTxOk + totalTxIdle + totalTxDesc +
4781156SN/A                      totalRxOrn) / postedInterrupts;
4791156SN/A
4801156SN/A    txBandwidth = txBytes * Stats::constant(8) / simSeconds;
4811156SN/A    rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
4821156SN/A    totBandwidth = txBandwidth + rxBandwidth;
4831156SN/A    totBytes = txBytes + rxBytes;
4841156SN/A    totPackets = txPackets + rxPackets;
4851156SN/A
4861156SN/A    txPacketRate = txPackets / simSeconds;
4871156SN/A    rxPacketRate = rxPackets / simSeconds;
4881156SN/A}
4891156SN/A
4901156SN/A/**
4911156SN/A * This is to read the PCI general configuration registers
4921156SN/A */
4931156SN/Avoid
4941156SN/ANSGigE::readConfig(int offset, int size, uint8_t *data)
4951156SN/A{
4961156SN/A    if (offset < PCI_DEVICE_SPECIFIC)
4977823SN/A        PciDev::readConfig(offset, size, data);
4981156SN/A    else
4991156SN/A        panic("Device specific PCI config space not implemented!\n");
5001156SN/A}
5011156SN/A
5021156SN/A/**
5031156SN/A * This is to write to the PCI general configuration registers
5041156SN/A */
5051156SN/Avoid
5061156SN/ANSGigE::writeConfig(int offset, int size, const uint8_t* data)
5071156SN/A{
5081156SN/A    if (offset < PCI_DEVICE_SPECIFIC)
5091156SN/A        PciDev::writeConfig(offset, size, data);
5101156SN/A    else
5111156SN/A        panic("Device specific PCI config space not implemented!\n");
5121156SN/A
5131156SN/A    // Need to catch writes to BARs to update the PIO interface
5147823SN/A    switch (offset) {
5157823SN/A        // seems to work fine without all these PCI settings, but i
5161156SN/A        // put in the IO to double check, an assertion will fail if we
5171156SN/A        // need to properly implement it
5181156SN/A      case PCI_COMMAND:
5191156SN/A        if (config.data[offset] & PCI_CMD_IOSE)
5201156SN/A            ioEnable = true;
5211156SN/A        else
5221156SN/A            ioEnable = false;
5231156SN/A
5241156SN/A#if 0
5251156SN/A        if (config.data[offset] & PCI_CMD_BME) {
5261156SN/A            bmEnabled = true;
5271156SN/A        }
5281156SN/A        else {
5297823SN/A            bmEnabled = false;
5307823SN/A        }
5311156SN/A
5321156SN/A        if (config.data[offset] & PCI_CMD_MSE) {
5331156SN/A            memEnable = true;
5341156SN/A        }
5351156SN/A        else {
5361156SN/A            memEnable = false;
5371156SN/A        }
5385606SN/A#endif
5395606SN/A        break;
5401156SN/A
5411156SN/A      case PCI0_BASE_ADDR0:
5421156SN/A        if (BARAddrs[0] != 0) {
5431156SN/A            if (pioInterface)
5441156SN/A                pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
5457823SN/A
5461156SN/A            BARAddrs[0] &= EV5::PAddrUncachedMask;
5471156SN/A        }
5481156SN/A        break;
5491156SN/A      case PCI0_BASE_ADDR1:
5501156SN/A        if (BARAddrs[1] != 0) {
5511156SN/A            if (pioInterface)
5521156SN/A                pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1]));
5531156SN/A
5541156SN/A            BARAddrs[1] &= EV5::PAddrUncachedMask;
5551156SN/A        }
5561156SN/A        break;
5571156SN/A    }
5581156SN/A}
5591156SN/A
5601156SN/A/**
5611156SN/A * This reads the device registers, which are detailed in the NS83820
5621156SN/A * spec sheet
5631156SN/A */
5641156SN/AFault
5651156SN/ANSGigE::read(MemReqPtr &req, uint8_t *data)
5661156SN/A{
5671156SN/A    assert(ioEnable);
5681156SN/A
5691156SN/A    //The mask is to give you only the offset into the device register file
5701156SN/A    Addr daddr = req->paddr & 0xfff;
5711156SN/A    DPRINTF(EthernetPIO, "read  da=%#x pa=%#x va=%#x size=%d\n",
5721156SN/A            daddr, req->paddr, req->vaddr, req->size);
5731156SN/A
5741156SN/A
5751156SN/A    // there are some reserved registers, you can see ns_gige_reg.h and
5761156SN/A    // the spec sheet for details
5771156SN/A    if (daddr > LAST && daddr <=  RESERVED) {
5781156SN/A        panic("Accessing reserved register");
5791156SN/A    } else if (daddr > RESERVED && daddr <= 0x3FC) {
5801156SN/A        readConfig(daddr & 0xff, req->size, data);
5811156SN/A        return No_Fault;
5821156SN/A    } else if (daddr >= MIB_START && daddr <= MIB_END) {
5831156SN/A        // don't implement all the MIB's.  hopefully the kernel
5841156SN/A        // doesn't actually DEPEND upon their values
5851156SN/A        // MIB are just hardware stats keepers
5861156SN/A        uint32_t &reg = *(uint32_t *) data;
5871156SN/A        reg = 0;
5881156SN/A        return No_Fault;
5891156SN/A    } else if (daddr > 0x3FC)
5901156SN/A        panic("Something is messed up!\n");
5911156SN/A
5921156SN/A    switch (req->size) {
5931156SN/A      case sizeof(uint32_t):
5941156SN/A        {
5951156SN/A            uint32_t &reg = *(uint32_t *)data;
5961156SN/A            uint16_t rfaddr;
5971156SN/A
5981156SN/A            switch (daddr) {
5991156SN/A              case CR:
6001156SN/A                reg = regs.command;
6017823SN/A                //these are supposed to be cleared on a read
6021156SN/A                reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR);
6031156SN/A                break;
6041156SN/A
6051156SN/A              case CFGR:
6061156SN/A                reg = regs.config;
6071156SN/A                break;
6081156SN/A
6091156SN/A              case MEAR:
6101156SN/A                reg = regs.mear;
6111156SN/A                break;
6121156SN/A
6131156SN/A              case PTSCR:
6141156SN/A                reg = regs.ptscr;
6151156SN/A                break;
6161156SN/A
6171156SN/A              case ISR:
6181156SN/A                reg = regs.isr;
6191156SN/A                devIntrClear(ISR_ALL);
6201156SN/A                break;
6211939SN/A
6221939SN/A              case IMR:
6232008SN/A                reg = regs.imr;
6242008SN/A                break;
6252008SN/A
6261939SN/A              case IER:
6271939SN/A                reg = regs.ier;
6281939SN/A                break;
6291939SN/A
6301939SN/A              case IHR:
6311156SN/A                reg = regs.ihr;
6321156SN/A                break;
6331156SN/A
6341939SN/A              case TXDP:
6351156SN/A                reg = regs.txdp;
6361939SN/A                break;
6371939SN/A
6382008SN/A              case TXDP_HI:
6392008SN/A                reg = regs.txdp_hi;
6402008SN/A                break;
6412008SN/A
6422210SN/A              case TX_CFG:
6432210SN/A                reg = regs.txcfg;
6442282SN/A                break;
6452282SN/A
6462282SN/A              case GPIOR:
6472282SN/A                reg = regs.gpior;
6482282SN/A                break;
6492282SN/A
6502282SN/A              case RXDP:
6512282SN/A                reg = regs.rxdp;
6522282SN/A                break;
6532282SN/A
6542008SN/A              case RXDP_HI:
6551156SN/A                reg = regs.rxdp_hi;
6561156SN/A                break;
6575603SN/A
6585603SN/A              case RX_CFG:
6595603SN/A                reg = regs.rxcfg;
6601939SN/A                break;
6611939SN/A
6621939SN/A              case PQCR:
6635603SN/A                reg = regs.pqcr;
6645603SN/A                break;
6655603SN/A
6665603SN/A              case WCSR:
6674762SN/A                reg = regs.wcsr;
6681156SN/A                break;
6695603SN/A
6705603SN/A              case PCR:
6715603SN/A                reg = regs.pcr;
6725603SN/A                break;
6735603SN/A
6745603SN/A                // see the spec sheet for how RFCR and RFDR work
6752008SN/A                // basically, you write to RFCR to tell the machine
6762282SN/A                // what you want to do next, then you act upon RFDR,
6772282SN/A                // and the device will be prepared b/c of what you
6782008SN/A                // wrote to RFCR
6795603SN/A              case RFCR:
6805603SN/A                reg = regs.rfcr;
6815603SN/A                break;
6822008SN/A
6831156SN/A              case RFDR:
6841156SN/A                rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
6851156SN/A                switch (rfaddr) {
6861156SN/A                  // Read from perfect match ROM octets
6872008SN/A                  case 0x000:
6881156SN/A                    reg = rom.perfectMatch[1];
6891939SN/A                    reg = reg << 8;
6902282SN/A                    reg += rom.perfectMatch[0];
6911939SN/A                    break;
6922008SN/A                  case 0x002:
6932008SN/A                    reg = rom.perfectMatch[3] << 8;
6942008SN/A                    reg += rom.perfectMatch[2];
6952008SN/A                    break;
6962008SN/A                  case 0x004:
6975603SN/A                    reg = rom.perfectMatch[5] << 8;
6981156SN/A                    reg += rom.perfectMatch[4];
6991156SN/A                    break;
7001156SN/A                  default:
7012566SN/A                    // Read filter hash table
7021156SN/A                    if (rfaddr >= FHASH_ADDR &&
7031156SN/A                        rfaddr < FHASH_ADDR + FHASH_SIZE) {
7041156SN/A
7052280SN/A                        // Only word-aligned reads supported
7061156SN/A                        if (rfaddr % 2)
7071939SN/A                            panic("unaligned read from filter hash table!");
7081939SN/A
7091939SN/A                        reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8;
7101939SN/A                        reg += rom.filterHash[rfaddr - FHASH_ADDR];
7111939SN/A                        break;
7121939SN/A                    }
7131156SN/A
7141156SN/A                    panic("reading RFDR for something other than pattern"
7151156SN/A                          " matching or hashing! %#x\n", rfaddr);
7161156SN/A                }
7171156SN/A                break;
7181156SN/A
7192282SN/A              case SRR:
7202008SN/A                reg = regs.srr;
7212279SN/A                break;
7221156SN/A
7231156SN/A              case MIBC:
7247823SN/A                reg = regs.mibc;
7252279SN/A                reg &= ~(MIBC_MIBS | MIBC_ACLR);
7261156SN/A                break;
7271156SN/A
7281156SN/A              case VRCR:
7291156SN/A                reg = regs.vrcr;
7301156SN/A                break;
7315603SN/A
7322008SN/A              case VTCR:
7331156SN/A                reg = regs.vtcr;
7341156SN/A                break;
7352282SN/A
7362282SN/A              case VDR:
7372282SN/A                reg = regs.vdr;
7382008SN/A                break;
7392282SN/A
7402282SN/A              case CCSR:
7412282SN/A                reg = regs.ccsr;
7422282SN/A                break;
7432282SN/A
7442282SN/A              case TBICR:
7452282SN/A                reg = regs.tbicr;
7462282SN/A                break;
7472008SN/A
7482008SN/A              case TBISR:
7491156SN/A                reg = regs.tbisr;
7502282SN/A                break;
7512282SN/A
7522282SN/A              case TANAR:
7532282SN/A                reg = regs.tanar;
7542282SN/A                break;
7555603SN/A
7565603SN/A              case TANLPAR:
7578641SN/A                reg = regs.tanlpar;
7585603SN/A                break;
7595603SN/A
7605603SN/A              case TANER:
7615603SN/A                reg = regs.taner;
7625603SN/A                break;
7635603SN/A
7645603SN/A              case TESR:
7655603SN/A                reg = regs.tesr;
7665603SN/A                break;
7675603SN/A
7685603SN/A              case M5REG:
7695603SN/A                reg = params()->m5reg;
7702282SN/A                break;
7715603SN/A
7725603SN/A              default:
7735603SN/A                panic("reading unimplemented register: addr=%#x", daddr);
7745603SN/A            }
7758641SN/A
7765603SN/A            DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
7775603SN/A                    daddr, reg, reg);
7785603SN/A        }
7792282SN/A        break;
7802282SN/A
7812282SN/A      default:
7822282SN/A        panic("accessing register with invalid size: addr=%#x, size=%d",
7832282SN/A              daddr, req->size);
7842282SN/A    }
7852282SN/A
7862282SN/A    return No_Fault;
7872282SN/A}
7885603SN/A
7892282SN/AFault
7902282SN/ANSGigE::write(MemReqPtr &req, const uint8_t *data)
7912282SN/A{
7922282SN/A    assert(ioEnable);
7932282SN/A
7942282SN/A    Addr daddr = req->paddr & 0xfff;
7951156SN/A    DPRINTF(EthernetPIO, "write da=%#x pa=%#x va=%#x size=%d\n",
7962282SN/A            daddr, req->paddr, req->vaddr, req->size);
7975603SN/A
7985603SN/A    if (daddr > LAST && daddr <=  RESERVED) {
7995603SN/A        panic("Accessing reserved register");
8005603SN/A    } else if (daddr > RESERVED && daddr <= 0x3FC) {
8015603SN/A        writeConfig(daddr & 0xff, req->size, data);
8025603SN/A        return No_Fault;
8035603SN/A    } else if (daddr > 0x3FC)
8045603SN/A        panic("Something is messed up!\n");
8051156SN/A
8061156SN/A    if (req->size == sizeof(uint32_t)) {
8071156SN/A        uint32_t reg = *(uint32_t *)data;
8082008SN/A        uint16_t rfaddr;
8091156SN/A
8101156SN/A        DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg);
8111156SN/A
8121156SN/A        switch (daddr) {
8132282SN/A          case CR:
8142282SN/A            regs.command = reg;
8152282SN/A            if (reg & CR_TXD) {
8162008SN/A                txEnable = false;
8172008SN/A            } else if (reg & CR_TXE) {
8182282SN/A                txEnable = true;
8192282SN/A
8202282SN/A                // the kernel is enabling the transmit machine
8212282SN/A                if (txState == txIdle)
8222282SN/A                    txKick();
8232282SN/A            }
8242282SN/A
8252282SN/A            if (reg & CR_RXD) {
8261156SN/A                rxEnable = false;
8275603SN/A            } else if (reg & CR_RXE) {
8285603SN/A                rxEnable = true;
8292008SN/A
8305603SN/A                if (rxState == rxIdle)
8312008SN/A                    rxKick();
8325603SN/A            }
8331156SN/A
8342008SN/A            if (reg & CR_TXR)
8351156SN/A                txReset();
8365603SN/A
8371156SN/A            if (reg & CR_RXR)
8382280SN/A                rxReset();
8392008SN/A
8401156SN/A            if (reg & CR_SWI)
8411156SN/A                devIntrPost(ISR_SWI);
8421156SN/A
8432008SN/A            if (reg & CR_RST) {
8441156SN/A                txReset();
8451156SN/A                rxReset();
8461156SN/A
8471156SN/A                regsReset();
8482279SN/A            }
8492279SN/A            break;
8502279SN/A
8512279SN/A          case CFGR:
8522008SN/A            if (reg & CFGR_LNKSTS ||
8531156SN/A                reg & CFGR_SPDSTS ||
8541156SN/A                reg & CFGR_DUPSTS ||
8551156SN/A                reg & CFGR_RESERVED ||
8562008SN/A                reg & CFGR_T64ADDR ||
8571156SN/A                reg & CFGR_PCI64_DET)
8581156SN/A
8592008SN/A            // First clear all writable bits
8601156SN/A            regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
8611156SN/A                                   CFGR_RESERVED | CFGR_T64ADDR |
8621156SN/A                                   CFGR_PCI64_DET;
8632008SN/A            // Now set the appropriate writable bits
8641156SN/A            regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
8651156SN/A                                   CFGR_RESERVED | CFGR_T64ADDR |
8661156SN/A                                   CFGR_PCI64_DET);
8671156SN/A
8681156SN/A// all these #if 0's are because i don't THINK the kernel needs to
8691156SN/A// have these implemented. if there is a problem relating to one of
8701156SN/A// these, you may need to add functionality in.
8711156SN/A#if 0
87210913SN/A            if (reg & CFGR_TBI_EN) ;
8731939SN/A            if (reg & CFGR_MODE_1000) ;
8741939SN/A#endif
87511202SN/A
8766227SN/A            if (reg & CFGR_AUTO_1000)
8776227SN/A                panic("CFGR_AUTO_1000 not implemented!\n");
8785603SN/A
8795603SN/A#if 0
8805603SN/A            if (reg & CFGR_PINT_DUPSTS ||
8815603SN/A                reg & CFGR_PINT_LNKSTS ||
8825603SN/A                reg & CFGR_PINT_SPDSTS)
8835603SN/A                ;
8845603SN/A
8855603SN/A            if (reg & CFGR_TMRTEST) ;
8865603SN/A            if (reg & CFGR_MRM_DIS) ;
8875603SN/A            if (reg & CFGR_MWI_DIS) ;
8885603SN/A
8895603SN/A            if (reg & CFGR_T64ADDR)
8901939SN/A                panic("CFGR_T64ADDR is read only register!\n");
8912282SN/A
8922282SN/A            if (reg & CFGR_PCI64_DET)
8932282SN/A                panic("CFGR_PCI64_DET is read only register!\n");
8942282SN/A
8952282SN/A            if (reg & CFGR_DATA64_EN) ;
8962566SN/A            if (reg & CFGR_M64ADDR) ;
8971156SN/A            if (reg & CFGR_PHY_RST) ;
8981156SN/A            if (reg & CFGR_PHY_DIS) ;
8991156SN/A#endif
9001156SN/A
9011156SN/A            if (reg & CFGR_EXTSTS_EN)
9021156SN/A                extstsEnable = true;
9031156SN/A            else
9042282SN/A                extstsEnable = false;
9052008SN/A
9065603SN/A#if 0
9071156SN/A              if (reg & CFGR_REQALG) ;
9082008SN/A              if (reg & CFGR_SB) ;
9095603SN/A              if (reg & CFGR_POW) ;
9105603SN/A              if (reg & CFGR_EXD) ;
9115603SN/A              if (reg & CFGR_PESEL) ;
9122282SN/A              if (reg & CFGR_BROM_DIS) ;
9132282SN/A              if (reg & CFGR_EXT_125) ;
9142282SN/A              if (reg & CFGR_BEM) ;
9152282SN/A#endif
9162282SN/A            break;
9172282SN/A
9185603SN/A          case MEAR:
9195603SN/A            // Clear writable bits
9205603SN/A            regs.mear &= MEAR_EEDO;
9211156SN/A            // Set appropriate writable bits
9225603SN/A            regs.mear |= reg & ~MEAR_EEDO;
9235603SN/A
9245603SN/A            // FreeBSD uses the EEPROM to read PMATCH (for the MAC address)
9252008SN/A            // even though it could get it through RFDR
9262008SN/A            if (reg & MEAR_EESEL) {
9272282SN/A                // Rising edge of clock
9282282SN/A                if (reg & MEAR_EECLK && !eepromClk)
9292282SN/A                    eepromKick();
9302010SN/A            }
9312282SN/A            else {
9322282SN/A                eepromState = eepromStart;
9332282SN/A                regs.mear &= ~MEAR_EEDI;
9341156SN/A            }
9351156SN/A
9362282SN/A            eepromClk = reg & MEAR_EECLK;
9372282SN/A
9382008SN/A            // since phy is completely faked, MEAR_MD* don't matter
9392008SN/A#if 0
9402008SN/A            if (reg & MEAR_MDIO) ;
9412008SN/A            if (reg & MEAR_MDDIR) ;
9422008SN/A            if (reg & MEAR_MDC) ;
9432008SN/A#endif
9445603SN/A            break;
9452282SN/A
9462282SN/A          case PTSCR:
9475603SN/A            regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY);
9482282SN/A            // these control BISTs for various parts of chip - we
9492282SN/A            // don't care or do just fake that the BIST is done
9501939SN/A            if (reg & PTSCR_RBIST_EN)
9511156SN/A                regs.ptscr |= PTSCR_RBIST_DONE;
9521156SN/A            if (reg & PTSCR_EEBIST_EN)
9531156SN/A                regs.ptscr &= ~PTSCR_EEBIST_EN;
9541156SN/A            if (reg & PTSCR_EELOAD_EN)
9551156SN/A                regs.ptscr &= ~PTSCR_EELOAD_EN;
9561156SN/A            break;
9571156SN/A
9581156SN/A          case ISR: /* writing to the ISR has no effect */
9591156SN/A            panic("ISR is a read only register!\n");
9601156SN/A
9611156SN/A          case IMR:
9621156SN/A            regs.imr = reg;
9631156SN/A            devIntrChangeMask();
9641156SN/A            break;
9651156SN/A
9661156SN/A          case IER:
9671156SN/A            regs.ier = reg;
9681156SN/A            break;
9691156SN/A
9701156SN/A          case IHR:
9712566SN/A            regs.ihr = reg;
9721156SN/A            /* not going to implement real interrupt holdoff */
9731156SN/A            break;
9741156SN/A
9751156SN/A          case TXDP:
9761156SN/A            regs.txdp = (reg & 0xFFFFFFFC);
9771939SN/A            assert(txState == txIdle);
9781939SN/A            CTDD = false;
9791939SN/A            break;
9801939SN/A
9811939SN/A          case TXDP_HI:
9821939SN/A            regs.txdp_hi = reg;
9831156SN/A            break;
9841156SN/A
9851156SN/A          case TX_CFG:
9861156SN/A            regs.txcfg = reg;
9871156SN/A#if 0
9881156SN/A            if (reg & TX_CFG_CSI) ;
9891156SN/A            if (reg & TX_CFG_HBI) ;
9901156SN/A            if (reg & TX_CFG_MLB) ;
9911156SN/A            if (reg & TX_CFG_ATP) ;
9921156SN/A            if (reg & TX_CFG_ECRETRY) {
9931156SN/A                /*
9941939SN/A                 * this could easily be implemented, but considering
9952566SN/A                 * the network is just a fake pipe, wouldn't make
9961156SN/A                 * sense to do this
9971156SN/A                 */
9981156SN/A            }
9995603SN/A
10001156SN/A            if (reg & TX_CFG_BRST_DIS) ;
10011156SN/A#endif
10021156SN/A
10031156SN/A#if 0
10041156SN/A            /* we handle our own DMA, ignore the kernel's exhortations */
10051156SN/A            if (reg & TX_CFG_MXDMA) ;
10061156SN/A#endif
10071156SN/A
10081156SN/A            // also, we currently don't care about fill/drain
10091156SN/A            // thresholds though this may change in the future with
10102280SN/A            // more realistic networks or a driver which changes it
10112280SN/A            // according to feedback
10122280SN/A
10132280SN/A            break;
10141156SN/A
10151156SN/A          case GPIOR:
10161156SN/A            // Only write writable bits
10171156SN/A            regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
10181156SN/A                        | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN;
10191939SN/A            regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
10201156SN/A                                | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN);
10211156SN/A            /* these just control general purpose i/o pins, don't matter */
10221156SN/A            break;
10231156SN/A
10241156SN/A          case RXDP:
10251156SN/A            regs.rxdp = reg;
10261939SN/A            CRDD = false;
10275603SN/A            break;
10281939SN/A
10291939SN/A          case RXDP_HI:
10301156SN/A            regs.rxdp_hi = reg;
10311156SN/A            break;
10321156SN/A
10331156SN/A          case RX_CFG:
10341156SN/A            regs.rxcfg = reg;
10352008SN/A#if 0
10362279SN/A            if (reg & RX_CFG_AEP) ;
10371156SN/A            if (reg & RX_CFG_ARP) ;
10381156SN/A            if (reg & RX_CFG_STRIPCRC) ;
10397823SN/A            if (reg & RX_CFG_RX_RD) ;
10402279SN/A            if (reg & RX_CFG_ALP) ;
10411156SN/A            if (reg & RX_CFG_AIRL) ;
10421156SN/A
10431156SN/A            /* we handle our own DMA, ignore what kernel says about it */
10441156SN/A            if (reg & RX_CFG_MXDMA) ;
10451156SN/A
10462008SN/A            //also, we currently don't care about fill/drain thresholds
10471156SN/A            //though this may change in the future with more realistic
10481156SN/A            //networks or a driver which changes it according to feedback
10492008SN/A            if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ;
10502008SN/A#endif
10512008SN/A            break;
10522008SN/A
10531156SN/A          case PQCR:
10542280SN/A            /* there is no priority queueing used in the linux 2.6 driver */
10551156SN/A            regs.pqcr = reg;
10561156SN/A            break;
105710469SN/A
10582008SN/A          case WCSR:
10591156SN/A            /* not going to implement wake on LAN */
10601156SN/A            regs.wcsr = reg;
10611156SN/A            break;
10622008SN/A
10631156SN/A          case PCR:
10641156SN/A            /* not going to implement pause control */
10651156SN/A            regs.pcr = reg;
10661156SN/A            break;
10671156SN/A
10681156SN/A          case RFCR:
10691156SN/A            regs.rfcr = reg;
10701156SN/A
107110913SN/A            rxFilterEnable = (reg & RFCR_RFEN) ? true : false;
10721939SN/A            acceptBroadcast = (reg & RFCR_AAB) ? true : false;
10731939SN/A            acceptMulticast = (reg & RFCR_AAM) ? true : false;
107411202SN/A            acceptUnicast = (reg & RFCR_AAU) ? true : false;
10752008SN/A            acceptPerfect = (reg & RFCR_APM) ? true : false;
10762008SN/A            acceptArp = (reg & RFCR_AARP) ? true : false;
10771939SN/A            multicastHashEnable = (reg & RFCR_MHEN) ? true : false;
10781156SN/A
10792566SN/A#if 0
10801156SN/A            if (reg & RFCR_APAT)
10811156SN/A                panic("RFCR_APAT not implemented!\n");
10821156SN/A#endif
10831156SN/A            if (reg & RFCR_UHEN)
10841156SN/A                panic("Unicast hash filtering not used by drivers!\n");
10851156SN/A
10861156SN/A            if (reg & RFCR_ULM)
10872008SN/A                panic("RFCR_ULM not implemented!\n");
108811701Smichael.lebeane@amd.com
10891156SN/A            break;
10902008SN/A
10912008SN/A          case RFDR:
10922008SN/A            rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
10932008SN/A            switch (rfaddr) {
10942008SN/A              case 0x000:
10951156SN/A                rom.perfectMatch[0] = (uint8_t)reg;
10961156SN/A                rom.perfectMatch[1] = (uint8_t)(reg >> 8);
10972008SN/A                break;
10982008SN/A              case 0x002:
10992008SN/A                rom.perfectMatch[2] = (uint8_t)reg;
11002008SN/A                rom.perfectMatch[3] = (uint8_t)(reg >> 8);
11012008SN/A                break;
11022008SN/A              case 0x004:
11032008SN/A                rom.perfectMatch[4] = (uint8_t)reg;
11042008SN/A                rom.perfectMatch[5] = (uint8_t)(reg >> 8);
11052008SN/A                break;
11062008SN/A              default:
11072008SN/A
11082008SN/A                if (rfaddr >= FHASH_ADDR &&
11092008SN/A                    rfaddr < FHASH_ADDR + FHASH_SIZE) {
11102008SN/A
11112008SN/A                    // Only word-aligned writes supported
11122008SN/A                    if (rfaddr % 2)
11132008SN/A                        panic("unaligned write to filter hash table!");
11142008SN/A
11152008SN/A                    rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg;
11162008SN/A                    rom.filterHash[rfaddr - FHASH_ADDR + 1]
11172008SN/A                        = (uint8_t)(reg >> 8);
11182008SN/A                    break;
11192008SN/A                }
11202008SN/A                panic("writing RFDR for something other than pattern matching\
11212008SN/A                    or hashing! %#x\n", rfaddr);
11222008SN/A            }
11232008SN/A
11242008SN/A          case BRAR:
11252008SN/A            regs.brar = reg;
11262008SN/A            break;
11272008SN/A
11282008SN/A          case BRDR:
11292008SN/A            panic("the driver never uses BRDR, something is wrong!\n");
11301939SN/A
11311156SN/A          case SRR:
11321156SN/A            panic("SRR is read only register!\n");
11331156SN/A
11341156SN/A          case MIBC:
11351156SN/A            panic("the driver never uses MIBC, something is wrong!\n");
11361156SN/A
11371156SN/A          case VRCR:
11381156SN/A            regs.vrcr = reg;
11391156SN/A            break;
11401156SN/A
11411156SN/A          case VTCR:
11421156SN/A            regs.vtcr = reg;
11431156SN/A            break;
11441156SN/A
11451156SN/A          case VDR:
11461156SN/A            panic("the driver never uses VDR, something is wrong!\n");
11471156SN/A
11481156SN/A          case CCSR:
11491156SN/A            /* not going to implement clockrun stuff */
11501156SN/A            regs.ccsr = reg;
11511156SN/A            break;
11521156SN/A
11531156SN/A          case TBICR:
11541156SN/A            regs.tbicr = reg;
11551156SN/A            if (reg & TBICR_MR_LOOPBACK)
11561156SN/A                panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
11571156SN/A
11581156SN/A            if (reg & TBICR_MR_AN_ENABLE) {
11591156SN/A                regs.tanlpar = regs.tanar;
11609417SN/A                regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS);
11611156SN/A            }
11621156SN/A
11631156SN/A#if 0
11642566SN/A            if (reg & TBICR_MR_RESTART_AN) ;
11651156SN/A#endif
11661156SN/A
11671156SN/A            break;
11681156SN/A
11691156SN/A          case TBISR:
11701156SN/A            panic("TBISR is read only register!\n");
11711156SN/A
11721156SN/A          case TANAR:
11731156SN/A            // Only write the writable bits
11741156SN/A            regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED;
11751156SN/A            regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED);
11761156SN/A
11771156SN/A            // Pause capability unimplemented
11781156SN/A#if 0
11791156SN/A            if (reg & TANAR_PS2) ;
11801156SN/A            if (reg & TANAR_PS1) ;
11811156SN/A#endif
11821156SN/A
11831156SN/A            break;
11841156SN/A
11851156SN/A          case TANLPAR:
11861156SN/A            panic("this should only be written to by the fake phy!\n");
11871156SN/A
11881156SN/A          case TANER:
11891156SN/A            panic("TANER is read only register!\n");
11901156SN/A
11911156SN/A          case TESR:
11921156SN/A            regs.tesr = reg;
11931156SN/A            break;
11941156SN/A
11951156SN/A          default:
11961156SN/A            panic("invalid register access daddr=%#x", daddr);
11971156SN/A        }
11981156SN/A    } else {
11991156SN/A        panic("Invalid Request Size");
12001156SN/A    }
12011156SN/A
12021156SN/A    return No_Fault;
12031156SN/A}
12041156SN/A
12051156SN/Avoid
12061156SN/ANSGigE::devIntrPost(uint32_t interrupts)
12071156SN/A{
12081156SN/A    if (interrupts & ISR_RESERVE)
12092566SN/A        panic("Cannot set a reserved interrupt");
12101156SN/A
12111156SN/A    if (interrupts & ISR_NOIMPL)
12121156SN/A        warn("interrupt not implemented %#x\n", interrupts);
12131156SN/A
12141156SN/A    interrupts &= ISR_IMPL;
12151156SN/A    regs.isr |= interrupts;
12161156SN/A
12171156SN/A    if (interrupts & regs.imr) {
12181156SN/A        if (interrupts & ISR_SWI) {
12191156SN/A            totalSwi++;
12201156SN/A        }
12211156SN/A        if (interrupts & ISR_RXIDLE) {
12221156SN/A            totalRxIdle++;
12231156SN/A        }
12241156SN/A        if (interrupts & ISR_RXOK) {
12251156SN/A            totalRxOk++;
12261156SN/A        }
12275603SN/A        if (interrupts & ISR_RXDESC) {
12281939SN/A            totalRxDesc++;
12291156SN/A        }
12301156SN/A        if (interrupts & ISR_TXOK) {
12311156SN/A            totalTxOk++;
12321156SN/A        }
12331156SN/A        if (interrupts & ISR_TXIDLE) {
12341156SN/A            totalTxIdle++;
12351156SN/A        }
12362008SN/A        if (interrupts & ISR_TXDESC) {
12372008SN/A            totalTxDesc++;
12382008SN/A        }
12392008SN/A        if (interrupts & ISR_RXORN) {
12402008SN/A            totalRxOrn++;
12411939SN/A        }
12421156SN/A    }
12431156SN/A
12441156SN/A    DPRINTF(EthernetIntr,
12451156SN/A            "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
12462901SN/A            interrupts, regs.isr, regs.imr);
12479342SN/A
12482901SN/A    if ((regs.isr & regs.imr)) {
12499342SN/A        Tick when = curTick;
12502901SN/A        if ((regs.isr & regs.imr & ISR_NODELAY) == 0)
12512901SN/A            when += intrDelay;
12522901SN/A        cpuIntrPost(when);
12532901SN/A    }
12542901SN/A}
12552901SN/A
12562901SN/A/* writing this interrupt counting stats inside this means that this function
12572901SN/A   is now limited to being used to clear all interrupts upon the kernel
12581156SN/A   reading isr and servicing.  just telling you in case you were thinking
12591156SN/A   of expanding use.
12601156SN/A*/
12611156SN/Avoid
126210905SN/ANSGigE::devIntrClear(uint32_t interrupts)
12631156SN/A{
12649807SN/A    if (interrupts & ISR_RESERVE)
126510905SN/A        panic("Cannot clear a reserved interrupt");
12661156SN/A
12671156SN/A    if (regs.isr & regs.imr & ISR_SWI) {
12681156SN/A        postedSwi++;
12691156SN/A    }
12701156SN/A    if (regs.isr & regs.imr & ISR_RXIDLE) {
12711156SN/A        postedRxIdle++;
12721156SN/A    }
12731156SN/A    if (regs.isr & regs.imr & ISR_RXOK) {
12741156SN/A        postedRxOk++;
12751156SN/A    }
12761156SN/A    if (regs.isr & regs.imr & ISR_RXDESC) {
12771156SN/A            postedRxDesc++;
12781156SN/A    }
12791156SN/A    if (regs.isr & regs.imr & ISR_TXOK) {
12801156SN/A        postedTxOk++;
12811156SN/A    }
12821156SN/A    if (regs.isr & regs.imr & ISR_TXIDLE) {
128310905SN/A        postedTxIdle++;
12841156SN/A    }
12859807SN/A    if (regs.isr & regs.imr & ISR_TXDESC) {
128610905SN/A        postedTxDesc++;
12871156SN/A    }
12881156SN/A    if (regs.isr & regs.imr & ISR_RXORN) {
12891156SN/A        postedRxOrn++;
12901156SN/A    }
12911156SN/A
12921156SN/A    if (regs.isr & regs.imr & ISR_IMPL)
12931156SN/A        postedInterrupts++;
12941156SN/A
12951156SN/A    interrupts &= ~ISR_NOIMPL;
12961156SN/A    regs.isr &= ~interrupts;
12971156SN/A
12981156SN/A    DPRINTF(EthernetIntr,
12991156SN/A            "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",
13005606SN/A            interrupts, regs.isr, regs.imr);
13015606SN/A
13021156SN/A    if (!(regs.isr & regs.imr))
13031156SN/A        cpuIntrClear();
13041156SN/A}
13051156SN/A
130611006SN/Avoid
13071156SN/ANSGigE::devIntrChangeMask()
13082287SN/A{
13092287SN/A    DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n",
13109807SN/A            regs.isr, regs.imr, regs.isr & regs.imr);
131110905SN/A
13121156SN/A    if (regs.isr & regs.imr)
13131939SN/A        cpuIntrPost(curTick);
13141939SN/A    else
13151939SN/A        cpuIntrClear();
13161156SN/A}
13171939SN/A
13181939SN/Avoid
13191939SN/ANSGigE::cpuIntrPost(Tick when)
13201156SN/A{
13211156SN/A    // If the interrupt you want to post is later than an interrupt
13225603SN/A    // already scheduled, just let it post in the coming one and don't
13231156SN/A    // schedule another.
13241156SN/A    // HOWEVER, must be sure that the scheduled intrTick is in the
13251939SN/A    // future (this was formerly the source of a bug)
13261939SN/A    /**
13271156SN/A     * @todo this warning should be removed and the intrTick code should
13281156SN/A     * be fixed.
13291156SN/A     */
13301156SN/A    assert(when >= curTick);
13312008SN/A    assert(intrTick >= curTick || intrTick == 0);
13322008SN/A    if (when > intrTick && intrTick != 0) {
13332008SN/A        DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
13342008SN/A                intrTick);
13352008SN/A        return;
133610905SN/A    }
13372008SN/A
13382566SN/A    intrTick = when;
133910905SN/A    if (intrTick < curTick) {
134010905SN/A        debug_break();
134110905SN/A        intrTick = curTick;
134210905SN/A    }
13432008SN/A
13445603SN/A    DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
134510905SN/A            intrTick);
13462008SN/A
13472008SN/A    if (intrEvent)
134811006SN/A        intrEvent->squash();
13495603SN/A    intrEvent = new IntrEvent(this, true);
13502008SN/A    intrEvent->schedule(intrTick);
13512008SN/A}
13522008SN/A
13532008SN/Avoid
13542008SN/ANSGigE::cpuInterrupt()
135510905SN/A{
135610905SN/A    assert(intrTick == curTick);
135710905SN/A
13582008SN/A    // Whether or not there's a pending interrupt, we don't care about
135910905SN/A    // it anymore
13602008SN/A    intrEvent = 0;
13612008SN/A    intrTick = 0;
13625603SN/A
13635603SN/A    // Don't send an interrupt if there's already one
13645603SN/A    if (cpuPendingIntr) {
13652282SN/A        DPRINTF(EthernetIntr,
13662282SN/A                "would send an interrupt now, but there's already pending\n");
13672282SN/A    } else {
13685603SN/A        // Send interrupt
13695603SN/A        cpuPendingIntr = true;
13705603SN/A
13712282SN/A        DPRINTF(EthernetIntr, "posting interrupt\n");
137211006SN/A        intrPost();
13732008SN/A    }
137410905SN/A}
13752282SN/A
13762282SN/Avoid
13772008SN/ANSGigE::cpuIntrClear()
13782282SN/A{
137910905SN/A    if (!cpuPendingIntr)
13802282SN/A        return;
13812282SN/A
13822282SN/A    if (intrEvent) {
13832008SN/A        intrEvent->squash();
138410905SN/A        intrEvent = 0;
13852282SN/A    }
13862282SN/A
13872008SN/A    intrTick = 0;
13882008SN/A
13891156SN/A    cpuPendingIntr = false;
13901156SN/A
13911156SN/A    DPRINTF(EthernetIntr, "clearing interrupt\n");
13921156SN/A    intrClear();
13931939SN/A}
13942282SN/A
139510905SN/Abool
13961156SN/ANSGigE::cpuIntrPending() const
13971156SN/A{ return cpuPendingIntr; }
13981156SN/A
13991156SN/Avoid
14001156SN/ANSGigE::txReset()
14011156SN/A{
14021939SN/A
140310905SN/A    DPRINTF(Ethernet, "transmit reset\n");
140410469SN/A
14051156SN/A    CTDD = false;
14061156SN/A    txEnable = false;;
140710905SN/A    txFragPtr = 0;
14082008SN/A    assert(txDescCnt == 0);
14092008SN/A    txFifo.clear();
14101156SN/A    txState = txIdle;
14111156SN/A    assert(txDmaState == dmaIdle);
14121156SN/A}
14131156SN/A
14141156SN/Avoid
14151156SN/ANSGigE::rxReset()
14167823SN/A{
14171156SN/A    DPRINTF(Ethernet, "receive reset\n");
14181156SN/A
14191156SN/A    CRDD = false;
14201156SN/A    assert(rxPktBytes == 0);
142110905SN/A    rxEnable = false;
14221156SN/A    rxFragPtr = 0;
14239807SN/A    assert(rxDescCnt == 0);
142410905SN/A    assert(rxDmaState == dmaIdle);
14251156SN/A    rxFifo.clear();
14261156SN/A    rxState = rxIdle;
14275603SN/A}
14281156SN/A
14291156SN/Avoid
14301939SN/ANSGigE::regsReset()
14311939SN/A{
14321156SN/A    memset(&regs, 0, sizeof(regs));
14331156SN/A    regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000);
14341156SN/A    regs.mear = 0x12;
14352282SN/A    regs.txcfg = 0x120; // set drain threshold to 1024 bytes and
14365603SN/A                        // fill threshold to 32 bytes
14375603SN/A    regs.rxcfg = 0x4;   // set drain threshold to 16 bytes
14385603SN/A    regs.srr = 0x0103;  // set the silicon revision to rev B or 0x103
14392282SN/A    regs.mibc = MIBC_FRZ;
14402008SN/A    regs.vdr = 0x81;    // set the vlan tag type to 802.1q
14412008SN/A    regs.tesr = 0xc000; // TBI capable of both full and half duplex
14422008SN/A    regs.brar = 0xffffffff;
14432008SN/A
14442008SN/A    extstsEnable = false;
144510905SN/A    acceptBroadcast = false;
14462008SN/A    acceptMulticast = false;
14472008SN/A    acceptUnicast = false;
14482008SN/A    acceptPerfect = false;
14492282SN/A    acceptArp = false;
14502282SN/A}
14512282SN/A
14522282SN/Avoid
14532282SN/ANSGigE::rxDmaReadCopy()
145410905SN/A{
14552282SN/A    assert(rxDmaState == dmaReading);
14562282SN/A
14572282SN/A    physmem->dma_read((uint8_t *)rxDmaData, rxDmaAddr, rxDmaLen);
14582008SN/A    rxDmaState = dmaIdle;
14592008SN/A
14602008SN/A    DPRINTF(EthernetDMA, "rx dma read  paddr=%#x len=%d\n",
14612008SN/A            rxDmaAddr, rxDmaLen);
14622008SN/A    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
146310905SN/A}
14642008SN/A
14652008SN/Abool
14662008SN/ANSGigE::doRxDmaRead()
14671156SN/A{
14681156SN/A    assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
14691156SN/A    rxDmaState = dmaReading;
14701156SN/A
14711156SN/A    if (dmaInterface && !rxDmaFree) {
14721939SN/A        if (dmaInterface->busy())
14732282SN/A            rxDmaState = dmaReadWaiting;
14741156SN/A        else
147510905SN/A            dmaInterface->doDMA(Read, rxDmaAddr, rxDmaLen, curTick,
14761156SN/A                                &rxDmaReadEvent, true);
14772282SN/A        return true;
14782282SN/A    }
14795603SN/A
14805603SN/A    if (dmaReadDelay == 0 && dmaReadFactor == 0) {
14815603SN/A        rxDmaReadCopy();
14825603SN/A        return false;
14835603SN/A    }
14845603SN/A
14855603SN/A    Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor;
14862282SN/A    Tick start = curTick + dmaReadDelay + factor;
14871156SN/A    rxDmaReadEvent.schedule(start);
14881156SN/A    return true;
14891156SN/A}
14901156SN/A
14911156SN/Avoid
14921939SN/ANSGigE::rxDmaReadDone()
14931156SN/A{
149410905SN/A    assert(rxDmaState == dmaReading);
14951156SN/A    rxDmaReadCopy();
14961156SN/A
14971156SN/A    // If the transmit state machine has a pending DMA, let it go first
14981156SN/A    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
149911719Smichael.lebeane@amd.com        txKick();
150010905SN/A
15012008SN/A    rxKick();
15022008SN/A}
15032008SN/A
15042008SN/Avoid
15052008SN/ANSGigE::rxDmaWriteCopy()
15062008SN/A{
15072008SN/A    assert(rxDmaState == dmaWriting);
15082008SN/A
15092008SN/A    physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen);
15102008SN/A    rxDmaState = dmaIdle;
15112008SN/A
15122008SN/A    DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
15132008SN/A            rxDmaAddr, rxDmaLen);
15142008SN/A    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
15152008SN/A}
15162008SN/A
15172566SN/Abool
15182008SN/ANSGigE::doRxDmaWrite()
151910905SN/A{
152010905SN/A    assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
152110905SN/A    rxDmaState = dmaWriting;
152210905SN/A
15232008SN/A    if (dmaInterface && !rxDmaFree) {
15242282SN/A        if (dmaInterface->busy())
15252282SN/A            rxDmaState = dmaWriteWaiting;
15262282SN/A        else
15272008SN/A            dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, curTick,
152810905SN/A                                &rxDmaWriteEvent, true);
15292008SN/A        return true;
15302008SN/A    }
153110905SN/A
15325603SN/A    if (dmaWriteDelay == 0 && dmaWriteFactor == 0) {
15332008SN/A        rxDmaWriteCopy();
15345603SN/A        return false;
15352008SN/A    }
153610905SN/A
15372008SN/A    Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor;
153810905SN/A    Tick start = curTick + dmaWriteDelay + factor;
15392008SN/A    rxDmaWriteEvent.schedule(start);
15405603SN/A    return true;
15412008SN/A}
154210905SN/A
15431156SN/Avoid
15441156SN/ANSGigE::rxDmaWriteDone()
15451156SN/A{
15461156SN/A    assert(rxDmaState == dmaWriting);
15471156SN/A    rxDmaWriteCopy();
15481156SN/A
15491156SN/A    // If the transmit state machine has a pending DMA, let it go first
15501156SN/A    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
15517823SN/A        txKick();
15521156SN/A
15538851SN/A    rxKick();
15542566SN/A}
15551156SN/A
15561156SN/Avoid
15577811SN/ANSGigE::rxKick()
15581156SN/A{
15594762SN/A    DPRINTF(EthernetSM, "receive kick rxState=%s (rxBuf.size=%d)\n",
15604762SN/A            NsRxStateStrings[rxState], rxFifo.size());
15611156SN/A
15624762SN/A  next:
15631156SN/A    if (clock) {
1564        if (rxKickTick > curTick) {
1565            DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
1566                    rxKickTick);
1567
1568            goto exit;
1569        }
1570
1571        // Go to the next state machine clock tick.
1572        rxKickTick = curTick + cycles(1);
1573    }
1574
1575    switch(rxDmaState) {
1576      case dmaReadWaiting:
1577        if (doRxDmaRead())
1578            goto exit;
1579        break;
1580      case dmaWriteWaiting:
1581        if (doRxDmaWrite())
1582            goto exit;
1583        break;
1584      default:
1585        break;
1586    }
1587
1588    // see state machine from spec for details
1589    // the way this works is, if you finish work on one state and can
1590    // go directly to another, you do that through jumping to the
1591    // label "next".  however, if you have intermediate work, like DMA
1592    // so that you can't go to the next state yet, you go to exit and
1593    // exit the loop.  however, when the DMA is done it will trigger
1594    // an event and come back to this loop.
1595    switch (rxState) {
1596      case rxIdle:
1597        if (!rxEnable) {
1598            DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");
1599            goto exit;
1600        }
1601
1602        if (CRDD) {
1603            rxState = rxDescRefr;
1604
1605            rxDmaAddr = regs.rxdp & 0x3fffffff;
1606            rxDmaData = &rxDescCache + offsetof(ns_desc, link);
1607            rxDmaLen = sizeof(rxDescCache.link);
1608            rxDmaFree = dmaDescFree;
1609
1610            descDmaReads++;
1611            descDmaRdBytes += rxDmaLen;
1612
1613            if (doRxDmaRead())
1614                goto exit;
1615        } else {
1616            rxState = rxDescRead;
1617
1618            rxDmaAddr = regs.rxdp & 0x3fffffff;
1619            rxDmaData = &rxDescCache;
1620            rxDmaLen = sizeof(ns_desc);
1621            rxDmaFree = dmaDescFree;
1622
1623            descDmaReads++;
1624            descDmaRdBytes += rxDmaLen;
1625
1626            if (doRxDmaRead())
1627                goto exit;
1628        }
1629        break;
1630
1631      case rxDescRefr:
1632        if (rxDmaState != dmaIdle)
1633            goto exit;
1634
1635        rxState = rxAdvance;
1636        break;
1637
1638     case rxDescRead:
1639        if (rxDmaState != dmaIdle)
1640            goto exit;
1641
1642        DPRINTF(EthernetDesc, "rxDescCache: addr=%08x read descriptor\n",
1643                regs.rxdp & 0x3fffffff);
1644        DPRINTF(EthernetDesc,
1645                "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n",
1646                rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts,
1647                rxDescCache.extsts);
1648
1649        if (rxDescCache.cmdsts & CMDSTS_OWN) {
1650            devIntrPost(ISR_RXIDLE);
1651            rxState = rxIdle;
1652            goto exit;
1653        } else {
1654            rxState = rxFifoBlock;
1655            rxFragPtr = rxDescCache.bufptr;
1656            rxDescCnt = rxDescCache.cmdsts & CMDSTS_LEN_MASK;
1657        }
1658        break;
1659
1660      case rxFifoBlock:
1661        if (!rxPacket) {
1662            /**
1663             * @todo in reality, we should be able to start processing
1664             * the packet as it arrives, and not have to wait for the
1665             * full packet ot be in the receive fifo.
1666             */
1667            if (rxFifo.empty())
1668                goto exit;
1669
1670            DPRINTF(EthernetSM, "****processing receive of new packet****\n");
1671
1672            // If we don't have a packet, grab a new one from the fifo.
1673            rxPacket = rxFifo.front();
1674            rxPktBytes = rxPacket->length;
1675            rxPacketBufPtr = rxPacket->data;
1676
1677#if TRACING_ON
1678            if (DTRACE(Ethernet)) {
1679                IpPtr ip(rxPacket);
1680                if (ip) {
1681                    DPRINTF(Ethernet, "ID is %d\n", ip->id());
1682                    TcpPtr tcp(ip);
1683                    if (tcp) {
1684                        DPRINTF(Ethernet,
1685                                "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1686                                tcp->sport(), tcp->dport(), tcp->seq(),
1687                                tcp->ack());
1688                    }
1689                }
1690            }
1691#endif
1692
1693            // sanity check - i think the driver behaves like this
1694            assert(rxDescCnt >= rxPktBytes);
1695            rxFifo.pop();
1696        }
1697
1698
1699        // dont' need the && rxDescCnt > 0 if driver sanity check
1700        // above holds
1701        if (rxPktBytes > 0) {
1702            rxState = rxFragWrite;
1703            // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
1704            // check holds
1705            rxXferLen = rxPktBytes;
1706
1707            rxDmaAddr = rxFragPtr & 0x3fffffff;
1708            rxDmaData = rxPacketBufPtr;
1709            rxDmaLen = rxXferLen;
1710            rxDmaFree = dmaDataFree;
1711
1712            if (doRxDmaWrite())
1713                goto exit;
1714
1715        } else {
1716            rxState = rxDescWrite;
1717
1718            //if (rxPktBytes == 0) {  /* packet is done */
1719            assert(rxPktBytes == 0);
1720            DPRINTF(EthernetSM, "done with receiving packet\n");
1721
1722            rxDescCache.cmdsts |= CMDSTS_OWN;
1723            rxDescCache.cmdsts &= ~CMDSTS_MORE;
1724            rxDescCache.cmdsts |= CMDSTS_OK;
1725            rxDescCache.cmdsts &= 0xffff0000;
1726            rxDescCache.cmdsts += rxPacket->length;   //i.e. set CMDSTS_SIZE
1727
1728#if 0
1729            /*
1730             * all the driver uses these are for its own stats keeping
1731             * which we don't care about, aren't necessary for
1732             * functionality and doing this would just slow us down.
1733             * if they end up using this in a later version for
1734             * functional purposes, just undef
1735             */
1736            if (rxFilterEnable) {
1737                rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK;
1738                const EthAddr &dst = rxFifoFront()->dst();
1739                if (dst->unicast())
1740                    rxDescCache.cmdsts |= CMDSTS_DEST_SELF;
1741                if (dst->multicast())
1742                    rxDescCache.cmdsts |= CMDSTS_DEST_MULTI;
1743                if (dst->broadcast())
1744                    rxDescCache.cmdsts |= CMDSTS_DEST_MASK;
1745            }
1746#endif
1747
1748            IpPtr ip(rxPacket);
1749            if (extstsEnable && ip) {
1750                rxDescCache.extsts |= EXTSTS_IPPKT;
1751                rxIpChecksums++;
1752                if (cksum(ip) != 0) {
1753                    DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
1754                    rxDescCache.extsts |= EXTSTS_IPERR;
1755                }
1756                TcpPtr tcp(ip);
1757                UdpPtr udp(ip);
1758                if (tcp) {
1759                    rxDescCache.extsts |= EXTSTS_TCPPKT;
1760                    rxTcpChecksums++;
1761                    if (cksum(tcp) != 0) {
1762                        DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
1763                        rxDescCache.extsts |= EXTSTS_TCPERR;
1764
1765                    }
1766                } else if (udp) {
1767                    rxDescCache.extsts |= EXTSTS_UDPPKT;
1768                    rxUdpChecksums++;
1769                    if (cksum(udp) != 0) {
1770                        DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
1771                        rxDescCache.extsts |= EXTSTS_UDPERR;
1772                    }
1773                }
1774            }
1775            rxPacket = 0;
1776
1777            /*
1778             * the driver seems to always receive into desc buffers
1779             * of size 1514, so you never have a pkt that is split
1780             * into multiple descriptors on the receive side, so
1781             * i don't implement that case, hence the assert above.
1782             */
1783
1784            DPRINTF(EthernetDesc,
1785                    "rxDescCache: addr=%08x writeback cmdsts extsts\n",
1786                    regs.rxdp & 0x3fffffff);
1787            DPRINTF(EthernetDesc,
1788                    "rxDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n",
1789                    rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts,
1790                    rxDescCache.extsts);
1791
1792            rxDmaAddr = (regs.rxdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff;
1793            rxDmaData = &(rxDescCache.cmdsts);
1794            rxDmaLen = sizeof(rxDescCache.cmdsts) + sizeof(rxDescCache.extsts);
1795            rxDmaFree = dmaDescFree;
1796
1797            descDmaWrites++;
1798            descDmaWrBytes += rxDmaLen;
1799
1800            if (doRxDmaWrite())
1801                goto exit;
1802        }
1803        break;
1804
1805      case rxFragWrite:
1806        if (rxDmaState != dmaIdle)
1807            goto exit;
1808
1809        rxPacketBufPtr += rxXferLen;
1810        rxFragPtr += rxXferLen;
1811        rxPktBytes -= rxXferLen;
1812
1813        rxState = rxFifoBlock;
1814        break;
1815
1816      case rxDescWrite:
1817        if (rxDmaState != dmaIdle)
1818            goto exit;
1819
1820        assert(rxDescCache.cmdsts & CMDSTS_OWN);
1821
1822        assert(rxPacket == 0);
1823        devIntrPost(ISR_RXOK);
1824
1825        if (rxDescCache.cmdsts & CMDSTS_INTR)
1826            devIntrPost(ISR_RXDESC);
1827
1828        if (!rxEnable) {
1829            DPRINTF(EthernetSM, "Halting the RX state machine\n");
1830            rxState = rxIdle;
1831            goto exit;
1832        } else
1833            rxState = rxAdvance;
1834        break;
1835
1836      case rxAdvance:
1837        if (rxDescCache.link == 0) {
1838            devIntrPost(ISR_RXIDLE);
1839            rxState = rxIdle;
1840            CRDD = true;
1841            goto exit;
1842        } else {
1843            if (rxDmaState != dmaIdle)
1844                goto exit;
1845            rxState = rxDescRead;
1846            regs.rxdp = rxDescCache.link;
1847            CRDD = false;
1848
1849            rxDmaAddr = regs.rxdp & 0x3fffffff;
1850            rxDmaData = &rxDescCache;
1851            rxDmaLen = sizeof(ns_desc);
1852            rxDmaFree = dmaDescFree;
1853
1854            if (doRxDmaRead())
1855                goto exit;
1856        }
1857        break;
1858
1859      default:
1860        panic("Invalid rxState!");
1861    }
1862
1863    DPRINTF(EthernetSM, "entering next rxState=%s\n",
1864            NsRxStateStrings[rxState]);
1865    goto next;
1866
1867  exit:
1868    /**
1869     * @todo do we want to schedule a future kick?
1870     */
1871    DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
1872            NsRxStateStrings[rxState]);
1873
1874    if (clock && !rxKickEvent.scheduled())
1875        rxKickEvent.schedule(rxKickTick);
1876}
1877
1878void
1879NSGigE::transmit()
1880{
1881    if (txFifo.empty()) {
1882        DPRINTF(Ethernet, "nothing to transmit\n");
1883        return;
1884    }
1885
1886    DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",
1887            txFifo.size());
1888    if (interface->sendPacket(txFifo.front())) {
1889#if TRACING_ON
1890        if (DTRACE(Ethernet)) {
1891            IpPtr ip(txFifo.front());
1892            if (ip) {
1893                DPRINTF(Ethernet, "ID is %d\n", ip->id());
1894                TcpPtr tcp(ip);
1895                if (tcp) {
1896                    DPRINTF(Ethernet,
1897                            "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1898                            tcp->sport(), tcp->dport(), tcp->seq(), tcp->ack());
1899                }
1900            }
1901        }
1902#endif
1903
1904        DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length);
1905        txBytes += txFifo.front()->length;
1906        txPackets++;
1907
1908        DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
1909                txFifo.avail());
1910        txFifo.pop();
1911
1912        /*
1913         * normally do a writeback of the descriptor here, and ONLY
1914         * after that is done, send this interrupt.  but since our
1915         * stuff never actually fails, just do this interrupt here,
1916         * otherwise the code has to stray from this nice format.
1917         * besides, it's functionally the same.
1918         */
1919        devIntrPost(ISR_TXOK);
1920    }
1921
1922   if (!txFifo.empty() && !txEvent.scheduled()) {
1923       DPRINTF(Ethernet, "reschedule transmit\n");
1924       txEvent.schedule(curTick + retryTime);
1925   }
1926}
1927
1928void
1929NSGigE::txDmaReadCopy()
1930{
1931    assert(txDmaState == dmaReading);
1932
1933    physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen);
1934    txDmaState = dmaIdle;
1935
1936    DPRINTF(EthernetDMA, "tx dma read  paddr=%#x len=%d\n",
1937            txDmaAddr, txDmaLen);
1938    DDUMP(EthernetDMA, txDmaData, txDmaLen);
1939}
1940
1941bool
1942NSGigE::doTxDmaRead()
1943{
1944    assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
1945    txDmaState = dmaReading;
1946
1947    if (dmaInterface && !txDmaFree) {
1948        if (dmaInterface->busy())
1949            txDmaState = dmaReadWaiting;
1950        else
1951            dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, curTick,
1952                                &txDmaReadEvent, true);
1953        return true;
1954    }
1955
1956    if (dmaReadDelay == 0 && dmaReadFactor == 0.0) {
1957        txDmaReadCopy();
1958        return false;
1959    }
1960
1961    Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor;
1962    Tick start = curTick + dmaReadDelay + factor;
1963    txDmaReadEvent.schedule(start);
1964    return true;
1965}
1966
1967void
1968NSGigE::txDmaReadDone()
1969{
1970    assert(txDmaState == dmaReading);
1971    txDmaReadCopy();
1972
1973    // If the receive state machine  has a pending DMA, let it go first
1974    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1975        rxKick();
1976
1977    txKick();
1978}
1979
1980void
1981NSGigE::txDmaWriteCopy()
1982{
1983    assert(txDmaState == dmaWriting);
1984
1985    physmem->dma_write(txDmaAddr, (uint8_t *)txDmaData, txDmaLen);
1986    txDmaState = dmaIdle;
1987
1988    DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n",
1989            txDmaAddr, txDmaLen);
1990    DDUMP(EthernetDMA, txDmaData, txDmaLen);
1991}
1992
1993bool
1994NSGigE::doTxDmaWrite()
1995{
1996    assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
1997    txDmaState = dmaWriting;
1998
1999    if (dmaInterface && !txDmaFree) {
2000        if (dmaInterface->busy())
2001            txDmaState = dmaWriteWaiting;
2002        else
2003            dmaInterface->doDMA(WriteInvalidate, txDmaAddr, txDmaLen, curTick,
2004                                &txDmaWriteEvent, true);
2005        return true;
2006    }
2007
2008    if (dmaWriteDelay == 0 && dmaWriteFactor == 0.0) {
2009        txDmaWriteCopy();
2010        return false;
2011    }
2012
2013    Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor;
2014    Tick start = curTick + dmaWriteDelay + factor;
2015    txDmaWriteEvent.schedule(start);
2016    return true;
2017}
2018
2019void
2020NSGigE::txDmaWriteDone()
2021{
2022    assert(txDmaState == dmaWriting);
2023    txDmaWriteCopy();
2024
2025    // If the receive state machine  has a pending DMA, let it go first
2026    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
2027        rxKick();
2028
2029    txKick();
2030}
2031
2032void
2033NSGigE::txKick()
2034{
2035    DPRINTF(EthernetSM, "transmit kick txState=%s\n",
2036            NsTxStateStrings[txState]);
2037
2038  next:
2039    if (clock) {
2040        if (txKickTick > curTick) {
2041            DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
2042                    txKickTick);
2043            goto exit;
2044        }
2045
2046        // Go to the next state machine clock tick.
2047        txKickTick = curTick + cycles(1);
2048    }
2049
2050    switch(txDmaState) {
2051      case dmaReadWaiting:
2052        if (doTxDmaRead())
2053            goto exit;
2054        break;
2055      case dmaWriteWaiting:
2056        if (doTxDmaWrite())
2057            goto exit;
2058        break;
2059      default:
2060        break;
2061    }
2062
2063    switch (txState) {
2064      case txIdle:
2065        if (!txEnable) {
2066            DPRINTF(EthernetSM, "Transmit disabled.  Nothing to do.\n");
2067            goto exit;
2068        }
2069
2070        if (CTDD) {
2071            txState = txDescRefr;
2072
2073            txDmaAddr = regs.txdp & 0x3fffffff;
2074            txDmaData = &txDescCache + offsetof(ns_desc, link);
2075            txDmaLen = sizeof(txDescCache.link);
2076            txDmaFree = dmaDescFree;
2077
2078            descDmaReads++;
2079            descDmaRdBytes += txDmaLen;
2080
2081            if (doTxDmaRead())
2082                goto exit;
2083
2084        } else {
2085            txState = txDescRead;
2086
2087            txDmaAddr = regs.txdp & 0x3fffffff;
2088            txDmaData = &txDescCache;
2089            txDmaLen = sizeof(ns_desc);
2090            txDmaFree = dmaDescFree;
2091
2092            descDmaReads++;
2093            descDmaRdBytes += txDmaLen;
2094
2095            if (doTxDmaRead())
2096                goto exit;
2097        }
2098        break;
2099
2100      case txDescRefr:
2101        if (txDmaState != dmaIdle)
2102            goto exit;
2103
2104        txState = txAdvance;
2105        break;
2106
2107      case txDescRead:
2108        if (txDmaState != dmaIdle)
2109            goto exit;
2110
2111        DPRINTF(EthernetDesc, "txDescCache: addr=%08x read descriptor\n",
2112                regs.txdp & 0x3fffffff);
2113        DPRINTF(EthernetDesc,
2114                "txDescCache: link=%08x bufptr=%08x cmdsts=%08x extsts=%08x\n",
2115                txDescCache.link, txDescCache.bufptr, txDescCache.cmdsts,
2116                txDescCache.extsts);
2117
2118        if (txDescCache.cmdsts & CMDSTS_OWN) {
2119            txState = txFifoBlock;
2120            txFragPtr = txDescCache.bufptr;
2121            txDescCnt = txDescCache.cmdsts & CMDSTS_LEN_MASK;
2122        } else {
2123            devIntrPost(ISR_TXIDLE);
2124            txState = txIdle;
2125            goto exit;
2126        }
2127        break;
2128
2129      case txFifoBlock:
2130        if (!txPacket) {
2131            DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
2132            txPacket = new PacketData(16384);
2133            txPacketBufPtr = txPacket->data;
2134        }
2135
2136        if (txDescCnt == 0) {
2137            DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");
2138            if (txDescCache.cmdsts & CMDSTS_MORE) {
2139                DPRINTF(EthernetSM, "there are more descriptors to come\n");
2140                txState = txDescWrite;
2141
2142                txDescCache.cmdsts &= ~CMDSTS_OWN;
2143
2144                txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts);
2145                txDmaAddr &= 0x3fffffff;
2146                txDmaData = &(txDescCache.cmdsts);
2147                txDmaLen = sizeof(txDescCache.cmdsts);
2148                txDmaFree = dmaDescFree;
2149
2150                if (doTxDmaWrite())
2151                    goto exit;
2152
2153            } else { /* this packet is totally done */
2154                DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
2155                /* deal with the the packet that just finished */
2156                if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
2157                    IpPtr ip(txPacket);
2158                    if (txDescCache.extsts & EXTSTS_UDPPKT) {
2159                        UdpPtr udp(ip);
2160                        udp->sum(0);
2161                        udp->sum(cksum(udp));
2162                        txUdpChecksums++;
2163                    } else if (txDescCache.extsts & EXTSTS_TCPPKT) {
2164                        TcpPtr tcp(ip);
2165                        tcp->sum(0);
2166                        tcp->sum(cksum(tcp));
2167                        txTcpChecksums++;
2168                    }
2169                    if (txDescCache.extsts & EXTSTS_IPPKT) {
2170                        ip->sum(0);
2171                        ip->sum(cksum(ip));
2172                        txIpChecksums++;
2173                    }
2174                }
2175
2176                txPacket->length = txPacketBufPtr - txPacket->data;
2177                // this is just because the receive can't handle a
2178                // packet bigger want to make sure
2179                assert(txPacket->length <= 1514);
2180#ifndef NDEBUG
2181                bool success =
2182#endif
2183                    txFifo.push(txPacket);
2184                assert(success);
2185
2186                /*
2187                 * this following section is not tqo spec, but
2188                 * functionally shouldn't be any different.  normally,
2189                 * the chip will wait til the transmit has occurred
2190                 * before writing back the descriptor because it has
2191                 * to wait to see that it was successfully transmitted
2192                 * to decide whether to set CMDSTS_OK or not.
2193                 * however, in the simulator since it is always
2194                 * successfully transmitted, and writing it exactly to
2195                 * spec would complicate the code, we just do it here
2196                 */
2197
2198                txDescCache.cmdsts &= ~CMDSTS_OWN;
2199                txDescCache.cmdsts |= CMDSTS_OK;
2200
2201                DPRINTF(EthernetDesc,
2202                        "txDesc writeback: cmdsts=%08x extsts=%08x\n",
2203                        txDescCache.cmdsts, txDescCache.extsts);
2204
2205                txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts);
2206                txDmaAddr &= 0x3fffffff;
2207                txDmaData = &(txDescCache.cmdsts);
2208                txDmaLen = sizeof(txDescCache.cmdsts) +
2209                    sizeof(txDescCache.extsts);
2210                txDmaFree = dmaDescFree;
2211
2212                descDmaWrites++;
2213                descDmaWrBytes += txDmaLen;
2214
2215                transmit();
2216                txPacket = 0;
2217
2218                if (!txEnable) {
2219                    DPRINTF(EthernetSM, "halting TX state machine\n");
2220                    txState = txIdle;
2221                    goto exit;
2222                } else
2223                    txState = txAdvance;
2224
2225                if (doTxDmaWrite())
2226                    goto exit;
2227            }
2228        } else {
2229            DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
2230            if (!txFifo.full()) {
2231                txState = txFragRead;
2232
2233                /*
2234                 * The number of bytes transferred is either whatever
2235                 * is left in the descriptor (txDescCnt), or if there
2236                 * is not enough room in the fifo, just whatever room
2237                 * is left in the fifo
2238                 */
2239                txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());
2240
2241                txDmaAddr = txFragPtr & 0x3fffffff;
2242                txDmaData = txPacketBufPtr;
2243                txDmaLen = txXferLen;
2244                txDmaFree = dmaDataFree;
2245
2246                if (doTxDmaRead())
2247                    goto exit;
2248            } else {
2249                txState = txFifoBlock;
2250                transmit();
2251
2252                goto exit;
2253            }
2254
2255        }
2256        break;
2257
2258      case txFragRead:
2259        if (txDmaState != dmaIdle)
2260            goto exit;
2261
2262        txPacketBufPtr += txXferLen;
2263        txFragPtr += txXferLen;
2264        txDescCnt -= txXferLen;
2265        txFifo.reserve(txXferLen);
2266
2267        txState = txFifoBlock;
2268        break;
2269
2270      case txDescWrite:
2271        if (txDmaState != dmaIdle)
2272            goto exit;
2273
2274        if (txDescCache.cmdsts & CMDSTS_INTR)
2275            devIntrPost(ISR_TXDESC);
2276
2277        if (!txEnable) {
2278            DPRINTF(EthernetSM, "halting TX state machine\n");
2279            txState = txIdle;
2280            goto exit;
2281        } else
2282            txState = txAdvance;
2283        break;
2284
2285      case txAdvance:
2286        if (txDescCache.link == 0) {
2287            devIntrPost(ISR_TXIDLE);
2288            txState = txIdle;
2289            goto exit;
2290        } else {
2291            if (txDmaState != dmaIdle)
2292                goto exit;
2293            txState = txDescRead;
2294            regs.txdp = txDescCache.link;
2295            CTDD = false;
2296
2297            txDmaAddr = txDescCache.link & 0x3fffffff;
2298            txDmaData = &txDescCache;
2299            txDmaLen = sizeof(ns_desc);
2300            txDmaFree = dmaDescFree;
2301
2302            if (doTxDmaRead())
2303                goto exit;
2304        }
2305        break;
2306
2307      default:
2308        panic("invalid state");
2309    }
2310
2311    DPRINTF(EthernetSM, "entering next txState=%s\n",
2312            NsTxStateStrings[txState]);
2313    goto next;
2314
2315  exit:
2316    /**
2317     * @todo do we want to schedule a future kick?
2318     */
2319    DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
2320            NsTxStateStrings[txState]);
2321
2322    if (clock && !txKickEvent.scheduled())
2323        txKickEvent.schedule(txKickTick);
2324}
2325
2326/**
2327 * Advance the EEPROM state machine
2328 * Called on rising edge of EEPROM clock bit in MEAR
2329 */
2330void
2331NSGigE::eepromKick()
2332{
2333    switch (eepromState) {
2334
2335      case eepromStart:
2336
2337        // Wait for start bit
2338        if (regs.mear & MEAR_EEDI) {
2339            // Set up to get 2 opcode bits
2340            eepromState = eepromGetOpcode;
2341            eepromBitsToRx = 2;
2342            eepromOpcode = 0;
2343        }
2344        break;
2345
2346      case eepromGetOpcode:
2347        eepromOpcode <<= 1;
2348        eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0;
2349        --eepromBitsToRx;
2350
2351        // Done getting opcode
2352        if (eepromBitsToRx == 0) {
2353            if (eepromOpcode != EEPROM_READ)
2354                panic("only EEPROM reads are implemented!");
2355
2356            // Set up to get address
2357            eepromState = eepromGetAddress;
2358            eepromBitsToRx = 6;
2359            eepromAddress = 0;
2360        }
2361        break;
2362
2363      case eepromGetAddress:
2364        eepromAddress <<= 1;
2365        eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0;
2366        --eepromBitsToRx;
2367
2368        // Done getting address
2369        if (eepromBitsToRx == 0) {
2370
2371            if (eepromAddress >= EEPROM_SIZE)
2372                panic("EEPROM read access out of range!");
2373
2374            switch (eepromAddress) {
2375
2376              case EEPROM_PMATCH2_ADDR:
2377                eepromData = rom.perfectMatch[5];
2378                eepromData <<= 8;
2379                eepromData += rom.perfectMatch[4];
2380                break;
2381
2382              case EEPROM_PMATCH1_ADDR:
2383                eepromData = rom.perfectMatch[3];
2384                eepromData <<= 8;
2385                eepromData += rom.perfectMatch[2];
2386                break;
2387
2388              case EEPROM_PMATCH0_ADDR:
2389                eepromData = rom.perfectMatch[1];
2390                eepromData <<= 8;
2391                eepromData += rom.perfectMatch[0];
2392                break;
2393
2394              default:
2395                panic("FreeBSD driver only uses EEPROM to read PMATCH!");
2396            }
2397            // Set up to read data
2398            eepromState = eepromRead;
2399            eepromBitsToRx = 16;
2400
2401            // Clear data in bit
2402            regs.mear &= ~MEAR_EEDI;
2403        }
2404        break;
2405
2406      case eepromRead:
2407        // Clear Data Out bit
2408        regs.mear &= ~MEAR_EEDO;
2409        // Set bit to value of current EEPROM bit
2410        regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0;
2411
2412        eepromData <<= 1;
2413        --eepromBitsToRx;
2414
2415        // All done
2416        if (eepromBitsToRx == 0) {
2417            eepromState = eepromStart;
2418        }
2419        break;
2420
2421      default:
2422        panic("invalid EEPROM state");
2423    }
2424
2425}
2426
2427void
2428NSGigE::transferDone()
2429{
2430    if (txFifo.empty()) {
2431        DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
2432        return;
2433    }
2434
2435    DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
2436
2437    if (txEvent.scheduled())
2438        txEvent.reschedule(curTick + cycles(1));
2439    else
2440        txEvent.schedule(curTick + cycles(1));
2441}
2442
2443bool
2444NSGigE::rxFilter(const PacketPtr &packet)
2445{
2446    EthPtr eth = packet;
2447    bool drop = true;
2448    string type;
2449
2450    const EthAddr &dst = eth->dst();
2451    if (dst.unicast()) {
2452        // If we're accepting all unicast addresses
2453        if (acceptUnicast)
2454            drop = false;
2455
2456        // If we make a perfect match
2457        if (acceptPerfect && dst == rom.perfectMatch)
2458            drop = false;
2459
2460        if (acceptArp && eth->type() == ETH_TYPE_ARP)
2461            drop = false;
2462
2463    } else if (dst.broadcast()) {
2464        // if we're accepting broadcasts
2465        if (acceptBroadcast)
2466            drop = false;
2467
2468    } else if (dst.multicast()) {
2469        // if we're accepting all multicasts
2470        if (acceptMulticast)
2471            drop = false;
2472
2473        // Multicast hashing faked - all packets accepted
2474        if (multicastHashEnable)
2475            drop = false;
2476    }
2477
2478    if (drop) {
2479        DPRINTF(Ethernet, "rxFilter drop\n");
2480        DDUMP(EthernetData, packet->data, packet->length);
2481    }
2482
2483    return drop;
2484}
2485
2486bool
2487NSGigE::recvPacket(PacketPtr packet)
2488{
2489    rxBytes += packet->length;
2490    rxPackets++;
2491
2492    DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n",
2493            rxFifo.avail());
2494
2495    if (!rxEnable) {
2496        DPRINTF(Ethernet, "receive disabled...packet dropped\n");
2497        interface->recvDone();
2498        return true;
2499    }
2500
2501    if (!rxFilterEnable) {
2502        DPRINTF(Ethernet,
2503            "receive packet filtering disabled . . . packet dropped\n");
2504        interface->recvDone();
2505        return true;
2506    }
2507
2508    if (rxFilter(packet)) {
2509        DPRINTF(Ethernet, "packet filtered...dropped\n");
2510        interface->recvDone();
2511        return true;
2512    }
2513
2514    if (rxFifo.avail() < packet->length) {
2515#if TRACING_ON
2516        IpPtr ip(packet);
2517        TcpPtr tcp(ip);
2518        if (ip) {
2519            DPRINTF(Ethernet,
2520                    "packet won't fit in receive buffer...pkt ID %d dropped\n",
2521                    ip->id());
2522            if (tcp) {
2523                DPRINTF(Ethernet, "Seq=%d\n", tcp->seq());
2524            }
2525        }
2526#endif
2527        droppedPackets++;
2528        devIntrPost(ISR_RXORN);
2529        return false;
2530    }
2531
2532    rxFifo.push(packet);
2533    interface->recvDone();
2534
2535    rxKick();
2536    return true;
2537}
2538
2539//=====================================================================
2540//
2541//
2542void
2543NSGigE::serialize(ostream &os)
2544{
2545    // Serialize the PciDev base class
2546    PciDev::serialize(os);
2547
2548    /*
2549     * Finalize any DMA events now.
2550     */
2551    if (rxDmaReadEvent.scheduled())
2552        rxDmaReadCopy();
2553    if (rxDmaWriteEvent.scheduled())
2554        rxDmaWriteCopy();
2555    if (txDmaReadEvent.scheduled())
2556        txDmaReadCopy();
2557    if (txDmaWriteEvent.scheduled())
2558        txDmaWriteCopy();
2559
2560    /*
2561     * Serialize the device registers
2562     */
2563    SERIALIZE_SCALAR(regs.command);
2564    SERIALIZE_SCALAR(regs.config);
2565    SERIALIZE_SCALAR(regs.mear);
2566    SERIALIZE_SCALAR(regs.ptscr);
2567    SERIALIZE_SCALAR(regs.isr);
2568    SERIALIZE_SCALAR(regs.imr);
2569    SERIALIZE_SCALAR(regs.ier);
2570    SERIALIZE_SCALAR(regs.ihr);
2571    SERIALIZE_SCALAR(regs.txdp);
2572    SERIALIZE_SCALAR(regs.txdp_hi);
2573    SERIALIZE_SCALAR(regs.txcfg);
2574    SERIALIZE_SCALAR(regs.gpior);
2575    SERIALIZE_SCALAR(regs.rxdp);
2576    SERIALIZE_SCALAR(regs.rxdp_hi);
2577    SERIALIZE_SCALAR(regs.rxcfg);
2578    SERIALIZE_SCALAR(regs.pqcr);
2579    SERIALIZE_SCALAR(regs.wcsr);
2580    SERIALIZE_SCALAR(regs.pcr);
2581    SERIALIZE_SCALAR(regs.rfcr);
2582    SERIALIZE_SCALAR(regs.rfdr);
2583    SERIALIZE_SCALAR(regs.brar);
2584    SERIALIZE_SCALAR(regs.brdr);
2585    SERIALIZE_SCALAR(regs.srr);
2586    SERIALIZE_SCALAR(regs.mibc);
2587    SERIALIZE_SCALAR(regs.vrcr);
2588    SERIALIZE_SCALAR(regs.vtcr);
2589    SERIALIZE_SCALAR(regs.vdr);
2590    SERIALIZE_SCALAR(regs.ccsr);
2591    SERIALIZE_SCALAR(regs.tbicr);
2592    SERIALIZE_SCALAR(regs.tbisr);
2593    SERIALIZE_SCALAR(regs.tanar);
2594    SERIALIZE_SCALAR(regs.tanlpar);
2595    SERIALIZE_SCALAR(regs.taner);
2596    SERIALIZE_SCALAR(regs.tesr);
2597
2598    SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
2599    SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2600
2601    SERIALIZE_SCALAR(ioEnable);
2602
2603    /*
2604     * Serialize the data Fifos
2605     */
2606    rxFifo.serialize("rxFifo", os);
2607    txFifo.serialize("txFifo", os);
2608
2609    /*
2610     * Serialize the various helper variables
2611     */
2612    bool txPacketExists = txPacket;
2613    SERIALIZE_SCALAR(txPacketExists);
2614    if (txPacketExists) {
2615        txPacket->length = txPacketBufPtr - txPacket->data;
2616        txPacket->serialize("txPacket", os);
2617        uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
2618        SERIALIZE_SCALAR(txPktBufPtr);
2619    }
2620
2621    bool rxPacketExists = rxPacket;
2622    SERIALIZE_SCALAR(rxPacketExists);
2623    if (rxPacketExists) {
2624        rxPacket->serialize("rxPacket", os);
2625        uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
2626        SERIALIZE_SCALAR(rxPktBufPtr);
2627    }
2628
2629    SERIALIZE_SCALAR(txXferLen);
2630    SERIALIZE_SCALAR(rxXferLen);
2631
2632    /*
2633     * Serialize DescCaches
2634     */
2635    SERIALIZE_SCALAR(txDescCache.link);
2636    SERIALIZE_SCALAR(txDescCache.bufptr);
2637    SERIALIZE_SCALAR(txDescCache.cmdsts);
2638    SERIALIZE_SCALAR(txDescCache.extsts);
2639    SERIALIZE_SCALAR(rxDescCache.link);
2640    SERIALIZE_SCALAR(rxDescCache.bufptr);
2641    SERIALIZE_SCALAR(rxDescCache.cmdsts);
2642    SERIALIZE_SCALAR(rxDescCache.extsts);
2643    SERIALIZE_SCALAR(extstsEnable);
2644
2645    /*
2646     * Serialize tx state machine
2647     */
2648    int txState = this->txState;
2649    SERIALIZE_SCALAR(txState);
2650    SERIALIZE_SCALAR(txEnable);
2651    SERIALIZE_SCALAR(CTDD);
2652    SERIALIZE_SCALAR(txFragPtr);
2653    SERIALIZE_SCALAR(txDescCnt);
2654    int txDmaState = this->txDmaState;
2655    SERIALIZE_SCALAR(txDmaState);
2656    SERIALIZE_SCALAR(txKickTick);
2657
2658    /*
2659     * Serialize rx state machine
2660     */
2661    int rxState = this->rxState;
2662    SERIALIZE_SCALAR(rxState);
2663    SERIALIZE_SCALAR(rxEnable);
2664    SERIALIZE_SCALAR(CRDD);
2665    SERIALIZE_SCALAR(rxPktBytes);
2666    SERIALIZE_SCALAR(rxFragPtr);
2667    SERIALIZE_SCALAR(rxDescCnt);
2668    int rxDmaState = this->rxDmaState;
2669    SERIALIZE_SCALAR(rxDmaState);
2670    SERIALIZE_SCALAR(rxKickTick);
2671
2672    /*
2673     * Serialize EEPROM state machine
2674     */
2675    int eepromState = this->eepromState;
2676    SERIALIZE_SCALAR(eepromState);
2677    SERIALIZE_SCALAR(eepromClk);
2678    SERIALIZE_SCALAR(eepromBitsToRx);
2679    SERIALIZE_SCALAR(eepromOpcode);
2680    SERIALIZE_SCALAR(eepromAddress);
2681    SERIALIZE_SCALAR(eepromData);
2682
2683    /*
2684     * If there's a pending transmit, store the time so we can
2685     * reschedule it later
2686     */
2687    Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;
2688    SERIALIZE_SCALAR(transmitTick);
2689
2690    /*
2691     * receive address filter settings
2692     */
2693    SERIALIZE_SCALAR(rxFilterEnable);
2694    SERIALIZE_SCALAR(acceptBroadcast);
2695    SERIALIZE_SCALAR(acceptMulticast);
2696    SERIALIZE_SCALAR(acceptUnicast);
2697    SERIALIZE_SCALAR(acceptPerfect);
2698    SERIALIZE_SCALAR(acceptArp);
2699    SERIALIZE_SCALAR(multicastHashEnable);
2700
2701    /*
2702     * Keep track of pending interrupt status.
2703     */
2704    SERIALIZE_SCALAR(intrTick);
2705    SERIALIZE_SCALAR(cpuPendingIntr);
2706    Tick intrEventTick = 0;
2707    if (intrEvent)
2708        intrEventTick = intrEvent->when();
2709    SERIALIZE_SCALAR(intrEventTick);
2710
2711}
2712
2713void
2714NSGigE::unserialize(Checkpoint *cp, const std::string &section)
2715{
2716    // Unserialize the PciDev base class
2717    PciDev::unserialize(cp, section);
2718
2719    UNSERIALIZE_SCALAR(regs.command);
2720    UNSERIALIZE_SCALAR(regs.config);
2721    UNSERIALIZE_SCALAR(regs.mear);
2722    UNSERIALIZE_SCALAR(regs.ptscr);
2723    UNSERIALIZE_SCALAR(regs.isr);
2724    UNSERIALIZE_SCALAR(regs.imr);
2725    UNSERIALIZE_SCALAR(regs.ier);
2726    UNSERIALIZE_SCALAR(regs.ihr);
2727    UNSERIALIZE_SCALAR(regs.txdp);
2728    UNSERIALIZE_SCALAR(regs.txdp_hi);
2729    UNSERIALIZE_SCALAR(regs.txcfg);
2730    UNSERIALIZE_SCALAR(regs.gpior);
2731    UNSERIALIZE_SCALAR(regs.rxdp);
2732    UNSERIALIZE_SCALAR(regs.rxdp_hi);
2733    UNSERIALIZE_SCALAR(regs.rxcfg);
2734    UNSERIALIZE_SCALAR(regs.pqcr);
2735    UNSERIALIZE_SCALAR(regs.wcsr);
2736    UNSERIALIZE_SCALAR(regs.pcr);
2737    UNSERIALIZE_SCALAR(regs.rfcr);
2738    UNSERIALIZE_SCALAR(regs.rfdr);
2739    UNSERIALIZE_SCALAR(regs.brar);
2740    UNSERIALIZE_SCALAR(regs.brdr);
2741    UNSERIALIZE_SCALAR(regs.srr);
2742    UNSERIALIZE_SCALAR(regs.mibc);
2743    UNSERIALIZE_SCALAR(regs.vrcr);
2744    UNSERIALIZE_SCALAR(regs.vtcr);
2745    UNSERIALIZE_SCALAR(regs.vdr);
2746    UNSERIALIZE_SCALAR(regs.ccsr);
2747    UNSERIALIZE_SCALAR(regs.tbicr);
2748    UNSERIALIZE_SCALAR(regs.tbisr);
2749    UNSERIALIZE_SCALAR(regs.tanar);
2750    UNSERIALIZE_SCALAR(regs.tanlpar);
2751    UNSERIALIZE_SCALAR(regs.taner);
2752    UNSERIALIZE_SCALAR(regs.tesr);
2753
2754    UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
2755    UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2756
2757    UNSERIALIZE_SCALAR(ioEnable);
2758
2759    /*
2760     * unserialize the data fifos
2761     */
2762    rxFifo.unserialize("rxFifo", cp, section);
2763    txFifo.unserialize("txFifo", cp, section);
2764
2765    /*
2766     * unserialize the various helper variables
2767     */
2768    bool txPacketExists;
2769    UNSERIALIZE_SCALAR(txPacketExists);
2770    if (txPacketExists) {
2771        txPacket = new PacketData(16384);
2772        txPacket->unserialize("txPacket", cp, section);
2773        uint32_t txPktBufPtr;
2774        UNSERIALIZE_SCALAR(txPktBufPtr);
2775        txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
2776    } else
2777        txPacket = 0;
2778
2779    bool rxPacketExists;
2780    UNSERIALIZE_SCALAR(rxPacketExists);
2781    rxPacket = 0;
2782    if (rxPacketExists) {
2783        rxPacket = new PacketData(16384);
2784        rxPacket->unserialize("rxPacket", cp, section);
2785        uint32_t rxPktBufPtr;
2786        UNSERIALIZE_SCALAR(rxPktBufPtr);
2787        rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
2788    } else
2789        rxPacket = 0;
2790
2791    UNSERIALIZE_SCALAR(txXferLen);
2792    UNSERIALIZE_SCALAR(rxXferLen);
2793
2794    /*
2795     * Unserialize DescCaches
2796     */
2797    UNSERIALIZE_SCALAR(txDescCache.link);
2798    UNSERIALIZE_SCALAR(txDescCache.bufptr);
2799    UNSERIALIZE_SCALAR(txDescCache.cmdsts);
2800    UNSERIALIZE_SCALAR(txDescCache.extsts);
2801    UNSERIALIZE_SCALAR(rxDescCache.link);
2802    UNSERIALIZE_SCALAR(rxDescCache.bufptr);
2803    UNSERIALIZE_SCALAR(rxDescCache.cmdsts);
2804    UNSERIALIZE_SCALAR(rxDescCache.extsts);
2805    UNSERIALIZE_SCALAR(extstsEnable);
2806
2807    /*
2808     * unserialize tx state machine
2809     */
2810    int txState;
2811    UNSERIALIZE_SCALAR(txState);
2812    this->txState = (TxState) txState;
2813    UNSERIALIZE_SCALAR(txEnable);
2814    UNSERIALIZE_SCALAR(CTDD);
2815    UNSERIALIZE_SCALAR(txFragPtr);
2816    UNSERIALIZE_SCALAR(txDescCnt);
2817    int txDmaState;
2818    UNSERIALIZE_SCALAR(txDmaState);
2819    this->txDmaState = (DmaState) txDmaState;
2820    UNSERIALIZE_SCALAR(txKickTick);
2821    if (txKickTick)
2822        txKickEvent.schedule(txKickTick);
2823
2824    /*
2825     * unserialize rx state machine
2826     */
2827    int rxState;
2828    UNSERIALIZE_SCALAR(rxState);
2829    this->rxState = (RxState) rxState;
2830    UNSERIALIZE_SCALAR(rxEnable);
2831    UNSERIALIZE_SCALAR(CRDD);
2832    UNSERIALIZE_SCALAR(rxPktBytes);
2833    UNSERIALIZE_SCALAR(rxFragPtr);
2834    UNSERIALIZE_SCALAR(rxDescCnt);
2835    int rxDmaState;
2836    UNSERIALIZE_SCALAR(rxDmaState);
2837    this->rxDmaState = (DmaState) rxDmaState;
2838    UNSERIALIZE_SCALAR(rxKickTick);
2839    if (rxKickTick)
2840        rxKickEvent.schedule(rxKickTick);
2841
2842    /*
2843     * Unserialize EEPROM state machine
2844     */
2845    int eepromState;
2846    UNSERIALIZE_SCALAR(eepromState);
2847    this->eepromState = (EEPROMState) eepromState;
2848    UNSERIALIZE_SCALAR(eepromClk);
2849    UNSERIALIZE_SCALAR(eepromBitsToRx);
2850    UNSERIALIZE_SCALAR(eepromOpcode);
2851    UNSERIALIZE_SCALAR(eepromAddress);
2852    UNSERIALIZE_SCALAR(eepromData);
2853
2854    /*
2855     * If there's a pending transmit, reschedule it now
2856     */
2857    Tick transmitTick;
2858    UNSERIALIZE_SCALAR(transmitTick);
2859    if (transmitTick)
2860        txEvent.schedule(curTick + transmitTick);
2861
2862    /*
2863     * unserialize receive address filter settings
2864     */
2865    UNSERIALIZE_SCALAR(rxFilterEnable);
2866    UNSERIALIZE_SCALAR(acceptBroadcast);
2867    UNSERIALIZE_SCALAR(acceptMulticast);
2868    UNSERIALIZE_SCALAR(acceptUnicast);
2869    UNSERIALIZE_SCALAR(acceptPerfect);
2870    UNSERIALIZE_SCALAR(acceptArp);
2871    UNSERIALIZE_SCALAR(multicastHashEnable);
2872
2873    /*
2874     * Keep track of pending interrupt status.
2875     */
2876    UNSERIALIZE_SCALAR(intrTick);
2877    UNSERIALIZE_SCALAR(cpuPendingIntr);
2878    Tick intrEventTick;
2879    UNSERIALIZE_SCALAR(intrEventTick);
2880    if (intrEventTick) {
2881        intrEvent = new IntrEvent(this, true);
2882        intrEvent->schedule(intrEventTick);
2883    }
2884
2885    /*
2886     * re-add addrRanges to bus bridges
2887     */
2888    if (pioInterface) {
2889        pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
2890        pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1]));
2891    }
2892}
2893
2894Tick
2895NSGigE::cacheAccess(MemReqPtr &req)
2896{
2897    DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n",
2898            req->paddr, req->paddr - addr);
2899    return curTick + pioLatency;
2900}
2901
2902BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
2903
2904    SimObjectParam<EtherInt *> peer;
2905    SimObjectParam<NSGigE *> device;
2906
2907END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
2908
2909BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
2910
2911    INIT_PARAM_DFLT(peer, "peer interface", NULL),
2912    INIT_PARAM(device, "Ethernet device of this interface")
2913
2914END_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
2915
2916CREATE_SIM_OBJECT(NSGigEInt)
2917{
2918    NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device);
2919
2920    EtherInt *p = (EtherInt *)peer;
2921    if (p) {
2922        dev_int->setPeer(p);
2923        p->setPeer(dev_int);
2924    }
2925
2926    return dev_int;
2927}
2928
2929REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt)
2930
2931
2932BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
2933
2934    Param<Addr> addr;
2935    Param<Tick> clock;
2936    Param<Tick> tx_delay;
2937    Param<Tick> rx_delay;
2938    Param<Tick> intr_delay;
2939    SimObjectParam<MemoryController *> mmu;
2940    SimObjectParam<PhysicalMemory *> physmem;
2941    Param<bool> rx_filter;
2942    Param<string> hardware_address;
2943    SimObjectParam<Bus*> io_bus;
2944    SimObjectParam<Bus*> payload_bus;
2945    SimObjectParam<HierParams *> hier;
2946    Param<Tick> pio_latency;
2947    Param<bool> dma_desc_free;
2948    Param<bool> dma_data_free;
2949    Param<Tick> dma_read_delay;
2950    Param<Tick> dma_write_delay;
2951    Param<Tick> dma_read_factor;
2952    Param<Tick> dma_write_factor;
2953    SimObjectParam<PciConfigAll *> configspace;
2954    SimObjectParam<PciConfigData *> configdata;
2955    SimObjectParam<Platform *> platform;
2956    Param<uint32_t> pci_bus;
2957    Param<uint32_t> pci_dev;
2958    Param<uint32_t> pci_func;
2959    Param<uint32_t> tx_fifo_size;
2960    Param<uint32_t> rx_fifo_size;
2961    Param<uint32_t> m5reg;
2962    Param<bool> dma_no_allocate;
2963
2964END_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
2965
2966BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
2967
2968    INIT_PARAM(addr, "Device Address"),
2969    INIT_PARAM(clock, "State machine processor frequency"),
2970    INIT_PARAM(tx_delay, "Transmit Delay"),
2971    INIT_PARAM(rx_delay, "Receive Delay"),
2972    INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"),
2973    INIT_PARAM(mmu, "Memory Controller"),
2974    INIT_PARAM(physmem, "Physical Memory"),
2975    INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true),
2976    INIT_PARAM(hardware_address, "Ethernet Hardware Address"),
2977    INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to for headers", NULL),
2978    INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL),
2979    INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams),
2980    INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
2981    INIT_PARAM_DFLT(dma_desc_free, "DMA of Descriptors is free", false),
2982    INIT_PARAM_DFLT(dma_data_free, "DMA of Data is free", false),
2983    INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0),
2984    INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0),
2985    INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0),
2986    INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0),
2987    INIT_PARAM(configspace, "PCI Configspace"),
2988    INIT_PARAM(configdata, "PCI Config data"),
2989    INIT_PARAM(platform, "Platform"),
2990    INIT_PARAM(pci_bus, "PCI bus"),
2991    INIT_PARAM(pci_dev, "PCI device number"),
2992    INIT_PARAM(pci_func, "PCI function code"),
2993    INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 131072),
2994    INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 131072),
2995    INIT_PARAM(m5reg, "m5 register"),
2996    INIT_PARAM_DFLT(dma_no_allocate, "Should DMA reads allocate cache lines", true)
2997
2998END_INIT_SIM_OBJECT_PARAMS(NSGigE)
2999
3000
3001CREATE_SIM_OBJECT(NSGigE)
3002{
3003    NSGigE::Params *params = new NSGigE::Params;
3004
3005    params->name = getInstanceName();
3006    params->mmu = mmu;
3007    params->configSpace = configspace;
3008    params->configData = configdata;
3009    params->plat = platform;
3010    params->busNum = pci_bus;
3011    params->deviceNum = pci_dev;
3012    params->functionNum = pci_func;
3013
3014    params->clock = clock;
3015    params->intr_delay = intr_delay;
3016    params->pmem = physmem;
3017    params->tx_delay = tx_delay;
3018    params->rx_delay = rx_delay;
3019    params->hier = hier;
3020    params->header_bus = io_bus;
3021    params->payload_bus = payload_bus;
3022    params->pio_latency = pio_latency;
3023    params->dma_desc_free = dma_desc_free;
3024    params->dma_data_free = dma_data_free;
3025    params->dma_read_delay = dma_read_delay;
3026    params->dma_write_delay = dma_write_delay;
3027    params->dma_read_factor = dma_read_factor;
3028    params->dma_write_factor = dma_write_factor;
3029    params->rx_filter = rx_filter;
3030    params->eaddr = hardware_address;
3031    params->tx_fifo_size = tx_fifo_size;
3032    params->rx_fifo_size = rx_fifo_size;
3033    params->m5reg = m5reg;
3034    params->dma_no_allocate = dma_no_allocate;
3035    return new NSGigE(params);
3036}
3037
3038REGISTER_SIM_OBJECT("NSGigE", NSGigE)
3039