ns_gige.cc revision 1035
16145SN/A/*
26386SN/A * Copyright (c) 2004 The Regents of The University of Michigan
37553SN/A * All rights reserved.
46386SN/A *
56386SN/A * Redistribution and use in source and binary forms, with or without
66386SN/A * modification, are permitted provided that the following conditions are
76386SN/A * met: redistributions of source code must retain the above copyright
86386SN/A * notice, this list of conditions and the following disclaimer;
96386SN/A * redistributions in binary form must reproduce the above copyright
106386SN/A * notice, this list of conditions and the following disclaimer in the
116386SN/A * documentation and/or other materials provided with the distribution;
126386SN/A * neither the name of the copyright holders nor the names of its
136386SN/A * contributors may be used to endorse or promote products derived from
146386SN/A * this software without specific prior written permission.
156386SN/A *
166386SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176386SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186386SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196386SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206386SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216386SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226386SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236386SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246386SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256386SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266386SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276386SN/A */
286386SN/A
296145SN/A/* @file
307632SBrad.Beckmann@amd.com * Device module for modelling the National Semiconductor
317632SBrad.Beckmann@amd.com * DP83820 ethernet controller.  Does not support priority queueing
327632SBrad.Beckmann@amd.com */
338232Snate@binkert.org#include <cstdio>
346145SN/A#include <deque>
357553SN/A#include <string>
367553SN/A
376145SN/A#include "base/inet.hh"
387553SN/A#include "cpu/exec_context.hh"
397553SN/A#include "cpu/intr_control.hh"
407553SN/A#include "dev/dma.hh"
417553SN/A#include "dev/etherlink.hh"
427553SN/A#include "dev/ns_gige.hh"
436145SN/A#include "dev/pciconfigall.hh"
446145SN/A#include "dev/tsunami_cchip.hh"
457553SN/A#include "mem/bus/bus.hh"
466145SN/A#include "mem/bus/dma_interface.hh"
476145SN/A#include "mem/bus/pio_interface.hh"
486145SN/A#include "mem/bus/pio_interface_impl.hh"
497553SN/A#include "mem/functional_mem/memory_control.hh"
507553SN/A#include "mem/functional_mem/physical_memory.hh"
516145SN/A#include "sim/builder.hh"
527553SN/A#include "sim/host.hh"
537553SN/A#include "sim/sim_stats.hh"
546145SN/A#include "targetarch/vtophys.hh"
558950Sandreas.hansson@arm.com
567553SN/Aconst char *NsRxStateStrings[] =
577553SN/A{
587553SN/A    "rxIdle",
597553SN/A    "rxDescRefr",
608832SAli.Saidi@ARM.com    "rxDescRead",
617553SN/A    "rxFifoBlock",
627553SN/A    "rxFragWrite",
637553SN/A    "rxDescWrite",
647553SN/A    "rxAdvance"
657553SN/A};
667553SN/A
676145SN/Aconst char *NsTxStateStrings[] =
688949Sandreas.hansson@arm.com{
697553SN/A    "txIdle",
707553SN/A    "txDescRefr",
717553SN/A    "txDescRead",
726145SN/A    "txFifoBlock",
738975Sandreas.hansson@arm.com    "txFragRead",
747553SN/A    "txDescWrite",
757553SN/A    "txAdvance"
767553SN/A};
777553SN/A
787553SN/Aconst char *NsDmaState[] =
797553SN/A{
807553SN/A    "dmaIdle",
817553SN/A    "dmaReading",
827553SN/A    "dmaWriting",
837553SN/A    "dmaReadWaiting",
847553SN/A    "dmaWriteWaiting"
857553SN/A};
867553SN/A
876145SN/Ausing namespace std;
886145SN/A
897553SN/A// helper function declarations
908655Sandreas.hansson@arm.com// These functions reverse Endianness so we can evaluate network data
916145SN/A// correctly
927553SN/Auint16_t reverseEnd16(uint16_t);
937553SN/Auint32_t reverseEnd32(uint32_t);
947553SN/A
956145SN/A///////////////////////////////////////////////////////////////////////
967553SN/A//
977553SN/A// NSGigE PCI Device
987553SN/A//
997553SN/ANSGigE::NSGigE(const std::string &name, IntrControl *i, Tick intr_delay,
1007553SN/A               PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay,
1017553SN/A               MemoryController *mmu, HierParams *hier, Bus *header_bus,
1027553SN/A               Bus *payload_bus, Tick pio_latency, bool dma_desc_free,
1037553SN/A               bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay,
1047553SN/A               Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf,
1057553SN/A               PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev,
1067553SN/A               uint32_t func, bool rx_filter, const int eaddr[6],
1076145SN/A               uint32_t tx_fifo_size, uint32_t rx_fifo_size)
1086145SN/A    : PciDev(name, mmu, cf, cd, bus, dev, func), tsunami(t), ioEnable(false),
1097553SN/A      maxTxFifoSize(tx_fifo_size), maxRxFifoSize(rx_fifo_size),
1107553SN/A      txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
1116145SN/A      txXferLen(0), rxXferLen(0), txState(txIdle), txEnable(false),
1127553SN/A      CTDD(false), txFifoAvail(tx_fifo_size),
1136145SN/A      txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
114      rxEnable(false), CRDD(false), rxPktBytes(0), rxFifoCnt(0),
115      rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false),
116      rxDmaReadEvent(this), rxDmaWriteEvent(this),
117      txDmaReadEvent(this), txDmaWriteEvent(this),
118      dmaDescFree(dma_desc_free), dmaDataFree(dma_data_free),
119      txDelay(tx_delay), rxDelay(rx_delay), rxKickTick(0), txKickTick(0),
120      txEvent(this), rxFilterEnable(rx_filter), acceptBroadcast(false),
121      acceptMulticast(false), acceptUnicast(false),
122      acceptPerfect(false), acceptArp(false),
123      physmem(pmem), intctrl(i), intrTick(0), cpuPendingIntr(false),
124      intrEvent(0), interface(0)
125{
126    tsunami->ethernet = this;
127
128    if (header_bus) {
129        pioInterface = newPioInterface(name, hier, header_bus, this,
130                                       &NSGigE::cacheAccess);
131
132        pioLatency = pio_latency * header_bus->clockRatio;
133
134        if (payload_bus)
135            dmaInterface = new DMAInterface<Bus>(name + ".dma",
136                                                 header_bus, payload_bus, 1);
137        else
138            dmaInterface = new DMAInterface<Bus>(name + ".dma",
139                                                 header_bus, header_bus, 1);
140    } else if (payload_bus) {
141        pioInterface = newPioInterface(name, hier, payload_bus, this,
142                                       &NSGigE::cacheAccess);
143
144        pioLatency = pio_latency * payload_bus->clockRatio;
145
146        dmaInterface = new DMAInterface<Bus>(name + ".dma", payload_bus,
147                                         payload_bus, 1);
148    }
149
150
151    intrDelay = US2Ticks(intr_delay);
152    dmaReadDelay = dma_read_delay;
153    dmaWriteDelay = dma_write_delay;
154    dmaReadFactor = dma_read_factor;
155    dmaWriteFactor = dma_write_factor;
156
157    regsReset();
158    rom.perfectMatch[0] = eaddr[0];
159    rom.perfectMatch[1] = eaddr[1];
160    rom.perfectMatch[2] = eaddr[2];
161    rom.perfectMatch[3] = eaddr[3];
162    rom.perfectMatch[4] = eaddr[4];
163    rom.perfectMatch[5] = eaddr[5];
164}
165
166NSGigE::~NSGigE()
167{}
168
169void
170NSGigE::regStats()
171{
172    txBytes
173        .name(name() + ".txBytes")
174        .desc("Bytes Transmitted")
175        .prereq(txBytes)
176        ;
177
178    rxBytes
179        .name(name() + ".rxBytes")
180        .desc("Bytes Received")
181        .prereq(rxBytes)
182        ;
183
184    txPackets
185        .name(name() + ".txPackets")
186        .desc("Number of Packets Transmitted")
187        .prereq(txBytes)
188        ;
189
190    rxPackets
191        .name(name() + ".rxPackets")
192        .desc("Number of Packets Received")
193        .prereq(rxBytes)
194        ;
195
196    txIPChecksums
197        .name(name() + ".txIPChecksums")
198        .desc("Number of tx IP Checksums done by device")
199        .precision(0)
200        .prereq(txBytes)
201        ;
202
203    rxIPChecksums
204        .name(name() + ".rxIPChecksums")
205        .desc("Number of rx IP Checksums done by device")
206        .precision(0)
207        .prereq(rxBytes)
208        ;
209
210    txTCPChecksums
211        .name(name() + ".txTCPChecksums")
212        .desc("Number of tx TCP Checksums done by device")
213        .precision(0)
214        .prereq(txBytes)
215        ;
216
217    rxTCPChecksums
218        .name(name() + ".rxTCPChecksums")
219        .desc("Number of rx TCP Checksums done by device")
220        .precision(0)
221        .prereq(rxBytes)
222        ;
223
224    descDmaReads
225        .name(name() + ".descDMAReads")
226        .desc("Number of descriptors the device read w/ DMA")
227        .precision(0)
228        ;
229
230    descDmaWrites
231        .name(name() + ".descDMAWrites")
232        .desc("Number of descriptors the device wrote w/ DMA")
233        .precision(0)
234        ;
235
236    descDmaRdBytes
237        .name(name() + ".descDmaReadBytes")
238        .desc("number of descriptor bytes read w/ DMA")
239        .precision(0)
240        ;
241
242   descDmaWrBytes
243        .name(name() + ".descDmaWriteBytes")
244        .desc("number of descriptor bytes write w/ DMA")
245        .precision(0)
246        ;
247
248
249    txBandwidth
250        .name(name() + ".txBandwidth")
251        .desc("Transmit Bandwidth (bits/s)")
252        .precision(0)
253        .prereq(txBytes)
254        ;
255
256    rxBandwidth
257        .name(name() + ".rxBandwidth")
258        .desc("Receive Bandwidth (bits/s)")
259        .precision(0)
260        .prereq(rxBytes)
261        ;
262
263    txPacketRate
264        .name(name() + ".txPPS")
265        .desc("Packet Tranmission Rate (packets/s)")
266        .precision(0)
267        .prereq(txBytes)
268        ;
269
270    rxPacketRate
271        .name(name() + ".rxPPS")
272        .desc("Packet Reception Rate (packets/s)")
273        .precision(0)
274        .prereq(rxBytes)
275        ;
276
277    txBandwidth = txBytes * Stats::constant(8) / simSeconds;
278    rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
279    txPacketRate = txPackets / simSeconds;
280    rxPacketRate = rxPackets / simSeconds;
281}
282
283/**
284 * This is to read the PCI general configuration registers
285 */
286void
287NSGigE::ReadConfig(int offset, int size, uint8_t *data)
288{
289    if (offset < PCI_DEVICE_SPECIFIC)
290        PciDev::ReadConfig(offset, size, data);
291    else
292        panic("Device specific PCI config space not implemented!\n");
293}
294
295/**
296 * This is to write to the PCI general configuration registers
297 */
298void
299NSGigE::WriteConfig(int offset, int size, uint32_t data)
300{
301    if (offset < PCI_DEVICE_SPECIFIC)
302        PciDev::WriteConfig(offset, size, data);
303    else
304        panic("Device specific PCI config space not implemented!\n");
305
306    // Need to catch writes to BARs to update the PIO interface
307    switch (offset) {
308        // seems to work fine without all these PCI settings, but i
309        // put in the IO to double check, an assertion will fail if we
310        // need to properly implement it
311      case PCI_COMMAND:
312        if (config.data[offset] & PCI_CMD_IOSE)
313            ioEnable = true;
314        else
315            ioEnable = false;
316
317#if 0
318        if (config.data[offset] & PCI_CMD_BME) {
319            bmEnabled = true;
320        }
321        else {
322            bmEnabled = false;
323        }
324
325        if (config.data[offset] & PCI_CMD_MSE) {
326            memEnable = true;
327        }
328        else {
329            memEnable = false;
330        }
331#endif
332        break;
333
334      case PCI0_BASE_ADDR0:
335        if (BARAddrs[0] != 0) {
336            if (pioInterface)
337                pioInterface->addAddrRange(BARAddrs[0],
338                                           BARAddrs[0] + BARSize[0] - 1);
339
340            BARAddrs[0] &= PA_UNCACHED_MASK;
341        }
342        break;
343      case PCI0_BASE_ADDR1:
344        if (BARAddrs[1] != 0) {
345            if (pioInterface)
346                pioInterface->addAddrRange(BARAddrs[1],
347                                           BARAddrs[1] + BARSize[1] - 1);
348
349            BARAddrs[1] &= PA_UNCACHED_MASK;
350        }
351        break;
352    }
353}
354
355/**
356 * This reads the device registers, which are detailed in the NS83820
357 * spec sheet
358 */
359Fault
360NSGigE::read(MemReqPtr &req, uint8_t *data)
361{
362    assert(ioEnable);
363
364    //The mask is to give you only the offset into the device register file
365    Addr daddr = req->paddr & 0xfff;
366    DPRINTF(EthernetPIO, "read  da=%#x pa=%#x va=%#x size=%d\n",
367            daddr, req->paddr, req->vaddr, req->size);
368
369
370    // there are some reserved registers, you can see ns_gige_reg.h and
371    // the spec sheet for details
372    if (daddr > LAST && daddr <=  RESERVED) {
373        panic("Accessing reserved register");
374    } else if (daddr > RESERVED && daddr <= 0x3FC) {
375        ReadConfig(daddr & 0xff, req->size, data);
376        return No_Fault;
377    } else if (daddr >= MIB_START && daddr <= MIB_END) {
378        // don't implement all the MIB's.  hopefully the kernel
379        // doesn't actually DEPEND upon their values
380        // MIB are just hardware stats keepers
381        uint32_t &reg = *(uint32_t *) data;
382        reg = 0;
383        return No_Fault;
384    } else if (daddr > 0x3FC)
385        panic("Something is messed up!\n");
386
387    switch (req->size) {
388      case sizeof(uint32_t):
389        {
390            uint32_t &reg = *(uint32_t *)data;
391
392            switch (daddr) {
393              case CR:
394                reg = regs.command;
395                //these are supposed to be cleared on a read
396                reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR);
397                break;
398
399              case CFG:
400                reg = regs.config;
401                break;
402
403              case MEAR:
404                reg = regs.mear;
405                break;
406
407              case PTSCR:
408                reg = regs.ptscr;
409                break;
410
411              case ISR:
412                reg = regs.isr;
413                devIntrClear(ISR_ALL);
414                break;
415
416              case IMR:
417                reg = regs.imr;
418                break;
419
420              case IER:
421                reg = regs.ier;
422                break;
423
424              case IHR:
425                reg = regs.ihr;
426                break;
427
428              case TXDP:
429                reg = regs.txdp;
430                break;
431
432              case TXDP_HI:
433                reg = regs.txdp_hi;
434                break;
435
436              case TXCFG:
437                reg = regs.txcfg;
438                break;
439
440              case GPIOR:
441                reg = regs.gpior;
442                break;
443
444              case RXDP:
445                reg = regs.rxdp;
446                break;
447
448              case RXDP_HI:
449                reg = regs.rxdp_hi;
450                break;
451
452              case RXCFG:
453                reg = regs.rxcfg;
454                break;
455
456              case PQCR:
457                reg = regs.pqcr;
458                break;
459
460              case WCSR:
461                reg = regs.wcsr;
462                break;
463
464              case PCR:
465                reg = regs.pcr;
466                break;
467
468                // see the spec sheet for how RFCR and RFDR work
469                // basically, you write to RFCR to tell the machine
470                // what you want to do next, then you act upon RFDR,
471                // and the device will be prepared b/c of what you
472                // wrote to RFCR
473              case RFCR:
474                reg = regs.rfcr;
475                break;
476
477              case RFDR:
478                switch (regs.rfcr & RFCR_RFADDR) {
479                  case 0x000:
480                    reg = rom.perfectMatch[1];
481                    reg = reg << 8;
482                    reg += rom.perfectMatch[0];
483                    break;
484                  case 0x002:
485                    reg = rom.perfectMatch[3] << 8;
486                    reg += rom.perfectMatch[2];
487                    break;
488                  case 0x004:
489                    reg = rom.perfectMatch[5] << 8;
490                    reg += rom.perfectMatch[4];
491                    break;
492                  default:
493                    panic("reading RFDR for something other than PMATCH!\n");
494                    // didn't implement other RFDR functionality b/c
495                    // driver didn't use it
496                }
497                break;
498
499              case SRR:
500                reg = regs.srr;
501                break;
502
503              case MIBC:
504                reg = regs.mibc;
505                reg &= ~(MIBC_MIBS | MIBC_ACLR);
506                break;
507
508              case VRCR:
509                reg = regs.vrcr;
510                break;
511
512              case VTCR:
513                reg = regs.vtcr;
514                break;
515
516              case VDR:
517                reg = regs.vdr;
518                break;
519
520              case CCSR:
521                reg = regs.ccsr;
522                break;
523
524              case TBICR:
525                reg = regs.tbicr;
526                break;
527
528              case TBISR:
529                reg = regs.tbisr;
530                break;
531
532              case TANAR:
533                reg = regs.tanar;
534                break;
535
536              case TANLPAR:
537                reg = regs.tanlpar;
538                break;
539
540              case TANER:
541                reg = regs.taner;
542                break;
543
544              case TESR:
545                reg = regs.tesr;
546                break;
547
548              default:
549                panic("reading unimplemented register: addr = %#x", daddr);
550            }
551
552            DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
553                    daddr, reg, reg);
554        }
555        break;
556
557      default:
558        panic("accessing register with invalid size: addr=%#x, size=%d",
559              daddr, req->size);
560    }
561
562    return No_Fault;
563}
564
565Fault
566NSGigE::write(MemReqPtr &req, const uint8_t *data)
567{
568    assert(ioEnable);
569
570    Addr daddr = req->paddr & 0xfff;
571    DPRINTF(EthernetPIO, "write da=%#x pa=%#x va=%#x size=%d\n",
572            daddr, req->paddr, req->vaddr, req->size);
573
574    if (daddr > LAST && daddr <=  RESERVED) {
575        panic("Accessing reserved register");
576    } else if (daddr > RESERVED && daddr <= 0x3FC) {
577        WriteConfig(daddr & 0xff, req->size, *(uint32_t *)data);
578        return No_Fault;
579    } else if (daddr > 0x3FC)
580        panic("Something is messed up!\n");
581
582    if (req->size == sizeof(uint32_t)) {
583        uint32_t reg = *(uint32_t *)data;
584        DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg);
585
586        switch (daddr) {
587          case CR:
588            regs.command = reg;
589            if (reg & CR_TXD) {
590                txEnable = false;
591            } else if (reg & CR_TXE) {
592                txEnable = true;
593
594                // the kernel is enabling the transmit machine
595                if (txState == txIdle)
596                    txKick();
597            }
598
599            if (reg & CR_RXD) {
600                rxEnable = false;
601            } else if (reg & CR_RXE) {
602                rxEnable = true;
603
604                if (rxState == rxIdle)
605                    rxKick();
606            }
607
608            if (reg & CR_TXR)
609                txReset();
610
611            if (reg & CR_RXR)
612                rxReset();
613
614            if (reg & CR_SWI)
615                devIntrPost(ISR_SWI);
616
617            if (reg & CR_RST) {
618                txReset();
619                rxReset();
620
621                regsReset();
622            }
623            break;
624
625          case CFG:
626            if (reg & CFG_LNKSTS ||
627                reg & CFG_SPDSTS ||
628                reg & CFG_DUPSTS ||
629                reg & CFG_RESERVED ||
630                reg & CFG_T64ADDR ||
631                reg & CFG_PCI64_DET)
632                panic("writing to read-only or reserved CFG bits!\n");
633
634            regs.config |= reg & ~(CFG_LNKSTS | CFG_SPDSTS | CFG_DUPSTS |
635                                   CFG_RESERVED | CFG_T64ADDR | CFG_PCI64_DET);
636
637// all these #if 0's are because i don't THINK the kernel needs to
638// have these implemented. if there is a problem relating to one of
639// these, you may need to add functionality in.
640#if 0
641            if (reg & CFG_TBI_EN) ;
642            if (reg & CFG_MODE_1000) ;
643#endif
644
645            if (reg & CFG_AUTO_1000)
646                panic("CFG_AUTO_1000 not implemented!\n");
647
648#if 0
649            if (reg & CFG_PINT_DUPSTS ||
650                reg & CFG_PINT_LNKSTS ||
651                reg & CFG_PINT_SPDSTS)
652                ;
653
654            if (reg & CFG_TMRTEST) ;
655            if (reg & CFG_MRM_DIS) ;
656            if (reg & CFG_MWI_DIS) ;
657
658            if (reg & CFG_T64ADDR)
659                panic("CFG_T64ADDR is read only register!\n");
660
661            if (reg & CFG_PCI64_DET)
662                panic("CFG_PCI64_DET is read only register!\n");
663
664            if (reg & CFG_DATA64_EN) ;
665            if (reg & CFG_M64ADDR) ;
666            if (reg & CFG_PHY_RST) ;
667            if (reg & CFG_PHY_DIS) ;
668#endif
669
670            if (reg & CFG_EXTSTS_EN)
671                extstsEnable = true;
672            else
673                extstsEnable = false;
674
675#if 0
676              if (reg & CFG_REQALG) ;
677              if (reg & CFG_SB) ;
678              if (reg & CFG_POW) ;
679              if (reg & CFG_EXD) ;
680              if (reg & CFG_PESEL) ;
681              if (reg & CFG_BROM_DIS) ;
682              if (reg & CFG_EXT_125) ;
683              if (reg & CFG_BEM) ;
684#endif
685            break;
686
687          case MEAR:
688            regs.mear = reg;
689            // since phy is completely faked, MEAR_MD* don't matter
690            // and since the driver never uses MEAR_EE*, they don't
691            // matter
692#if 0
693            if (reg & MEAR_EEDI) ;
694            if (reg & MEAR_EEDO) ; // this one is read only
695            if (reg & MEAR_EECLK) ;
696            if (reg & MEAR_EESEL) ;
697            if (reg & MEAR_MDIO) ;
698            if (reg & MEAR_MDDIR) ;
699            if (reg & MEAR_MDC) ;
700#endif
701            break;
702
703          case PTSCR:
704            regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY);
705            // these control BISTs for various parts of chip - we
706            // don't care or do just fake that the BIST is done
707            if (reg & PTSCR_RBIST_EN)
708                regs.ptscr |= PTSCR_RBIST_DONE;
709            if (reg & PTSCR_EEBIST_EN)
710                regs.ptscr &= ~PTSCR_EEBIST_EN;
711            if (reg & PTSCR_EELOAD_EN)
712                regs.ptscr &= ~PTSCR_EELOAD_EN;
713            break;
714
715          case ISR: /* writing to the ISR has no effect */
716            panic("ISR is a read only register!\n");
717
718          case IMR:
719            regs.imr = reg;
720            devIntrChangeMask();
721            break;
722
723          case IER:
724            regs.ier = reg;
725            break;
726
727          case IHR:
728            regs.ihr = reg;
729            /* not going to implement real interrupt holdoff */
730            break;
731
732          case TXDP:
733            regs.txdp = (reg & 0xFFFFFFFC);
734            assert(txState == txIdle);
735            CTDD = false;
736            break;
737
738          case TXDP_HI:
739            regs.txdp_hi = reg;
740            break;
741
742          case TXCFG:
743            regs.txcfg = reg;
744#if 0
745            if (reg & TXCFG_CSI) ;
746            if (reg & TXCFG_HBI) ;
747            if (reg & TXCFG_MLB) ;
748            if (reg & TXCFG_ATP) ;
749            if (reg & TXCFG_ECRETRY) {
750                /*
751                 * this could easily be implemented, but considering
752                 * the network is just a fake pipe, wouldn't make
753                 * sense to do this
754                 */
755            }
756
757            if (reg & TXCFG_BRST_DIS) ;
758#endif
759
760#if 0
761            /* we handle our own DMA, ignore the kernel's exhortations */
762            if (reg & TXCFG_MXDMA) ;
763#endif
764
765            // also, we currently don't care about fill/drain
766            // thresholds though this may change in the future with
767            // more realistic networks or a driver which changes it
768            // according to feedback
769
770            break;
771
772          case GPIOR:
773            regs.gpior = reg;
774            /* these just control general purpose i/o pins, don't matter */
775            break;
776
777          case RXDP:
778            regs.rxdp = reg;
779            CRDD = false;
780            break;
781
782          case RXDP_HI:
783            regs.rxdp_hi = reg;
784            break;
785
786          case RXCFG:
787            regs.rxcfg = reg;
788#if 0
789            if (reg & RXCFG_AEP) ;
790            if (reg & RXCFG_ARP) ;
791            if (reg & RXCFG_STRIPCRC) ;
792            if (reg & RXCFG_RX_RD) ;
793            if (reg & RXCFG_ALP) ;
794            if (reg & RXCFG_AIRL) ;
795
796            /* we handle our own DMA, ignore what kernel says about it */
797            if (reg & RXCFG_MXDMA) ;
798
799            //also, we currently don't care about fill/drain thresholds
800            //though this may change in the future with more realistic
801            //networks or a driver which changes it according to feedback
802            if (reg & (RXCFG_DRTH | RXCFG_DRTH0)) ;
803#endif
804            break;
805
806          case PQCR:
807            /* there is no priority queueing used in the linux 2.6 driver */
808            regs.pqcr = reg;
809            break;
810
811          case WCSR:
812            /* not going to implement wake on LAN */
813            regs.wcsr = reg;
814            break;
815
816          case PCR:
817            /* not going to implement pause control */
818            regs.pcr = reg;
819            break;
820
821          case RFCR:
822            regs.rfcr = reg;
823
824            rxFilterEnable = (reg & RFCR_RFEN) ? true : false;
825            acceptBroadcast = (reg & RFCR_AAB) ? true : false;
826            acceptMulticast = (reg & RFCR_AAM) ? true : false;
827            acceptUnicast = (reg & RFCR_AAU) ? true : false;
828            acceptPerfect = (reg & RFCR_APM) ? true : false;
829            acceptArp = (reg & RFCR_AARP) ? true : false;
830
831#if 0
832            if (reg & RFCR_APAT)
833                panic("RFCR_APAT not implemented!\n");
834#endif
835
836            if (reg & RFCR_MHEN || reg & RFCR_UHEN)
837                panic("hash filtering not implemented!\n");
838
839            if (reg & RFCR_ULM)
840                panic("RFCR_ULM not implemented!\n");
841
842            break;
843
844          case RFDR:
845            panic("the driver never writes to RFDR, something is wrong!\n");
846
847          case BRAR:
848            panic("the driver never uses BRAR, something is wrong!\n");
849
850          case BRDR:
851            panic("the driver never uses BRDR, something is wrong!\n");
852
853          case SRR:
854            panic("SRR is read only register!\n");
855
856          case MIBC:
857            panic("the driver never uses MIBC, something is wrong!\n");
858
859          case VRCR:
860            regs.vrcr = reg;
861            break;
862
863          case VTCR:
864            regs.vtcr = reg;
865            break;
866
867          case VDR:
868            panic("the driver never uses VDR, something is wrong!\n");
869            break;
870
871          case CCSR:
872            /* not going to implement clockrun stuff */
873            regs.ccsr = reg;
874            break;
875
876          case TBICR:
877            regs.tbicr = reg;
878            if (reg & TBICR_MR_LOOPBACK)
879                panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
880
881            if (reg & TBICR_MR_AN_ENABLE) {
882                regs.tanlpar = regs.tanar;
883                regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS);
884            }
885
886#if 0
887            if (reg & TBICR_MR_RESTART_AN) ;
888#endif
889
890            break;
891
892          case TBISR:
893            panic("TBISR is read only register!\n");
894
895          case TANAR:
896            regs.tanar = reg;
897            if (reg & TANAR_PS2)
898                panic("this isn't used in driver, something wrong!\n");
899
900            if (reg & TANAR_PS1)
901                panic("this isn't used in driver, something wrong!\n");
902            break;
903
904          case TANLPAR:
905            panic("this should only be written to by the fake phy!\n");
906
907          case TANER:
908            panic("TANER is read only register!\n");
909
910          case TESR:
911            regs.tesr = reg;
912            break;
913
914          default:
915            panic("invalid register access daddr=%#x", daddr);
916        }
917    } else {
918        panic("Invalid Request Size");
919    }
920
921    return No_Fault;
922}
923
924void
925NSGigE::devIntrPost(uint32_t interrupts)
926{
927    bool delay = false;
928
929    if (interrupts & ISR_RESERVE)
930        panic("Cannot set a reserved interrupt");
931
932    if (interrupts & ISR_TXRCMP)
933        regs.isr |= ISR_TXRCMP;
934
935    if (interrupts & ISR_RXRCMP)
936        regs.isr |= ISR_RXRCMP;
937
938//ISR_DPERR  not implemented
939//ISR_SSERR not implemented
940//ISR_RMABT not implemented
941//ISR_RXSOVR not implemented
942//ISR_HIBINT not implemented
943//ISR_PHY not implemented
944//ISR_PME not implemented
945
946    if (interrupts & ISR_SWI)
947        regs.isr |= ISR_SWI;
948
949//ISR_MIB not implemented
950//ISR_TXURN not implemented
951
952    if (interrupts & ISR_TXIDLE)
953        regs.isr |= ISR_TXIDLE;
954
955    if (interrupts & ISR_TXERR)
956        regs.isr |= ISR_TXERR;
957
958    if (interrupts & ISR_TXDESC)
959        regs.isr |= ISR_TXDESC;
960
961    if (interrupts & ISR_TXOK) {
962        regs.isr |= ISR_TXOK;
963        delay = true;
964    }
965
966    if (interrupts & ISR_RXORN)
967        regs.isr |= ISR_RXORN;
968
969    if (interrupts & ISR_RXIDLE)
970        regs.isr |= ISR_RXIDLE;
971
972//ISR_RXEARLY not implemented
973
974    if (interrupts & ISR_RXERR)
975        regs.isr |= ISR_RXERR;
976
977    if (interrupts & ISR_RXDESC)
978        regs.isr |= ISR_RXDESC;
979
980    if (interrupts & ISR_RXOK) {
981        delay = true;
982        regs.isr |= ISR_RXOK;
983    }
984
985    if ((regs.isr & regs.imr)) {
986        Tick when = curTick;
987        if (delay)
988            when += intrDelay;
989        cpuIntrPost(when);
990    }
991
992    DPRINTF(EthernetIntr,
993            "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
994            interrupts, regs.isr, regs.imr);
995}
996
997void
998NSGigE::devIntrClear(uint32_t interrupts)
999{
1000    if (interrupts & ISR_RESERVE)
1001        panic("Cannot clear a reserved interrupt");
1002
1003    if (interrupts & ISR_TXRCMP)
1004        regs.isr &= ~ISR_TXRCMP;
1005
1006    if (interrupts & ISR_RXRCMP)
1007        regs.isr &= ~ISR_RXRCMP;
1008
1009//ISR_DPERR  not implemented
1010//ISR_SSERR not implemented
1011//ISR_RMABT not implemented
1012//ISR_RXSOVR not implemented
1013//ISR_HIBINT not implemented
1014//ISR_PHY not implemented
1015//ISR_PME not implemented
1016
1017    if (interrupts & ISR_SWI)
1018        regs.isr &= ~ISR_SWI;
1019
1020//ISR_MIB not implemented
1021//ISR_TXURN not implemented
1022
1023    if (interrupts & ISR_TXIDLE)
1024        regs.isr &= ~ISR_TXIDLE;
1025
1026    if (interrupts & ISR_TXERR)
1027        regs.isr &= ~ISR_TXERR;
1028
1029    if (interrupts & ISR_TXDESC)
1030        regs.isr &= ~ISR_TXDESC;
1031
1032    if (interrupts & ISR_TXOK)
1033        regs.isr &= ~ISR_TXOK;
1034
1035    if (interrupts & ISR_RXORN)
1036        regs.isr &= ~ISR_RXORN;
1037
1038    if (interrupts & ISR_RXIDLE)
1039        regs.isr &= ~ISR_RXIDLE;
1040
1041//ISR_RXEARLY not implemented
1042
1043    if (interrupts & ISR_RXERR)
1044        regs.isr &= ~ISR_RXERR;
1045
1046    if (interrupts & ISR_RXDESC)
1047        regs.isr &= ~ISR_RXDESC;
1048
1049    if (interrupts & ISR_RXOK)
1050        regs.isr &= ~ISR_RXOK;
1051
1052    if (!(regs.isr & regs.imr))
1053        cpuIntrClear();
1054
1055    DPRINTF(EthernetIntr,
1056            "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",
1057            interrupts, regs.isr, regs.imr);
1058}
1059
1060void
1061NSGigE::devIntrChangeMask()
1062{
1063    DPRINTF(EthernetIntr, "interrupt mask changed\n");
1064
1065    if (regs.isr & regs.imr)
1066        cpuIntrPost(curTick);
1067    else
1068        cpuIntrClear();
1069}
1070
1071void
1072NSGigE::cpuIntrPost(Tick when)
1073{
1074    // If the interrupt you want to post is later than an interrupt
1075    // already scheduled, just let it post in the coming one and don't
1076    // schedule another.
1077    // HOWEVER, must be sure that the scheduled intrTick is in the
1078    // future (this was formerly the source of a bug)
1079    /**
1080     * @todo this warning should be removed and the intrTick code should
1081     * be fixed.
1082     */
1083    if (intrTick < curTick && intrTick != 0) {
1084        warn("intrTick < curTick !!!  intrTick=%d curTick=%d\n",
1085             intrTick, curTick);
1086        intrTick = 0;
1087    }
1088    assert((intrTick >= curTick) || (intrTick == 0));
1089    if (when > intrTick && intrTick != 0)
1090        return;
1091
1092    intrTick = when;
1093
1094    if (intrEvent) {
1095        intrEvent->squash();
1096        intrEvent = 0;
1097    }
1098
1099    if (when < curTick) {
1100        cpuInterrupt();
1101    } else {
1102        DPRINTF(EthernetIntr,
1103                "going to schedule an interrupt for intrTick=%d\n",
1104                intrTick);
1105        intrEvent = new IntrEvent(this, true);
1106        intrEvent->schedule(intrTick);
1107    }
1108}
1109
1110void
1111NSGigE::cpuInterrupt()
1112{
1113    // Don't send an interrupt if there's already one
1114    if (cpuPendingIntr) {
1115        DPRINTF(EthernetIntr,
1116                "would send an interrupt now, but there's already pending\n");
1117        intrTick = 0;
1118        return;
1119    }
1120    // Don't send an interrupt if it's supposed to be delayed
1121    if (intrTick > curTick) {
1122        DPRINTF(EthernetIntr,
1123                "an interrupt is scheduled for %d, wait til then\n",
1124                intrTick);
1125        return;
1126    }
1127
1128    // Whether or not there's a pending interrupt, we don't care about
1129    // it anymore
1130    intrEvent = 0;
1131    intrTick = 0;
1132
1133    // Send interrupt
1134    cpuPendingIntr = true;
1135    /** @todo rework the intctrl to be tsunami ok */
1136    //intctrl->post(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET);
1137    DPRINTF(EthernetIntr, "Posting interrupts to cchip!\n");
1138    tsunami->cchip->postDRIR(configData->config.hdr.pci0.interruptLine);
1139}
1140
1141void
1142NSGigE::cpuIntrClear()
1143{
1144    if (!cpuPendingIntr)
1145        return;
1146
1147    cpuPendingIntr = false;
1148    /** @todo rework the intctrl to be tsunami ok */
1149    //intctrl->clear(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET);
1150    DPRINTF(EthernetIntr, "clearing all interrupts from cchip\n");
1151    tsunami->cchip->clearDRIR(configData->config.hdr.pci0.interruptLine);
1152}
1153
1154bool
1155NSGigE::cpuIntrPending() const
1156{ return cpuPendingIntr; }
1157
1158void
1159NSGigE::txReset()
1160{
1161
1162    DPRINTF(Ethernet, "transmit reset\n");
1163
1164    CTDD = false;
1165    txFifoAvail = maxTxFifoSize;
1166    txEnable = false;;
1167    txFragPtr = 0;
1168    assert(txDescCnt == 0);
1169    txFifo.clear();
1170    txState = txIdle;
1171    assert(txDmaState == dmaIdle);
1172}
1173
1174void
1175NSGigE::rxReset()
1176{
1177    DPRINTF(Ethernet, "receive reset\n");
1178
1179    CRDD = false;
1180    assert(rxPktBytes == 0);
1181    rxFifoCnt = 0;
1182    rxEnable = false;
1183    rxFragPtr = 0;
1184    assert(rxDescCnt == 0);
1185    assert(rxDmaState == dmaIdle);
1186    rxFifo.clear();
1187    rxState = rxIdle;
1188}
1189
1190void NSGigE::regsReset()
1191{
1192    memset(&regs, 0, sizeof(regs));
1193    regs.config = 0x80000000;
1194    regs.mear = 0x12;
1195    regs.isr = 0x00608000;
1196    regs.txcfg = 0x120;
1197    regs.rxcfg = 0x4;
1198    regs.srr = 0x0103;
1199    regs.mibc = 0x2;
1200    regs.vdr = 0x81;
1201    regs.tesr = 0xc000;
1202
1203    extstsEnable = false;
1204    acceptBroadcast = false;
1205    acceptMulticast = false;
1206    acceptUnicast = false;
1207    acceptPerfect = false;
1208    acceptArp = false;
1209}
1210
1211void
1212NSGigE::rxDmaReadCopy()
1213{
1214    assert(rxDmaState == dmaReading);
1215
1216    physmem->dma_read((uint8_t *)rxDmaData, rxDmaAddr, rxDmaLen);
1217    rxDmaState = dmaIdle;
1218
1219    DPRINTF(EthernetDMA, "rx dma read  paddr=%#x len=%d\n",
1220            rxDmaAddr, rxDmaLen);
1221    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1222}
1223
1224bool
1225NSGigE::doRxDmaRead()
1226{
1227    assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
1228    rxDmaState = dmaReading;
1229
1230    if (dmaInterface && !rxDmaFree) {
1231        if (dmaInterface->busy())
1232            rxDmaState = dmaReadWaiting;
1233        else
1234            dmaInterface->doDMA(Read, rxDmaAddr, rxDmaLen, curTick,
1235                                &rxDmaReadEvent, true);
1236        return true;
1237    }
1238
1239    if (dmaReadDelay == 0 && dmaReadFactor == 0) {
1240        rxDmaReadCopy();
1241        return false;
1242    }
1243
1244    Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor;
1245    Tick start = curTick + dmaReadDelay + factor;
1246    rxDmaReadEvent.schedule(start);
1247    return true;
1248}
1249
1250void
1251NSGigE::rxDmaReadDone()
1252{
1253    assert(rxDmaState == dmaReading);
1254    rxDmaReadCopy();
1255
1256    // If the transmit state machine has a pending DMA, let it go first
1257    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1258        txKick();
1259
1260    rxKick();
1261}
1262
1263void
1264NSGigE::rxDmaWriteCopy()
1265{
1266    assert(rxDmaState == dmaWriting);
1267
1268    physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen);
1269    rxDmaState = dmaIdle;
1270
1271    DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
1272            rxDmaAddr, rxDmaLen);
1273    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1274}
1275
1276bool
1277NSGigE::doRxDmaWrite()
1278{
1279    assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
1280    rxDmaState = dmaWriting;
1281
1282    if (dmaInterface && !rxDmaFree) {
1283        if (dmaInterface->busy())
1284            rxDmaState = dmaWriteWaiting;
1285        else
1286            dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, curTick,
1287                                &rxDmaWriteEvent, true);
1288        return true;
1289    }
1290
1291    if (dmaWriteDelay == 0 && dmaWriteFactor == 0) {
1292        rxDmaWriteCopy();
1293        return false;
1294    }
1295
1296    Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor;
1297    Tick start = curTick + dmaWriteDelay + factor;
1298    rxDmaWriteEvent.schedule(start);
1299    return true;
1300}
1301
1302void
1303NSGigE::rxDmaWriteDone()
1304{
1305    assert(rxDmaState == dmaWriting);
1306    rxDmaWriteCopy();
1307
1308    // If the transmit state machine has a pending DMA, let it go first
1309    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1310        txKick();
1311
1312    rxKick();
1313}
1314
1315void
1316NSGigE::rxKick()
1317{
1318    DPRINTF(EthernetSM, "receive kick state=%s (rxBuf.size=%d)\n",
1319            NsRxStateStrings[rxState], rxFifo.size());
1320
1321    if (rxKickTick > curTick) {
1322        DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
1323                rxKickTick);
1324        return;
1325    }
1326
1327  next:
1328    switch(rxDmaState) {
1329      case dmaReadWaiting:
1330        if (doRxDmaRead())
1331            goto exit;
1332        break;
1333      case dmaWriteWaiting:
1334        if (doRxDmaWrite())
1335            goto exit;
1336        break;
1337      default:
1338        break;
1339    }
1340
1341    // see state machine from spec for details
1342    // the way this works is, if you finish work on one state and can
1343    // go directly to another, you do that through jumping to the
1344    // label "next".  however, if you have intermediate work, like DMA
1345    // so that you can't go to the next state yet, you go to exit and
1346    // exit the loop.  however, when the DMA is done it will trigger
1347    // an event and come back to this loop.
1348    switch (rxState) {
1349      case rxIdle:
1350        if (!rxEnable) {
1351            DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");
1352            goto exit;
1353        }
1354
1355        if (CRDD) {
1356            rxState = rxDescRefr;
1357
1358            rxDmaAddr = regs.rxdp & 0x3fffffff;
1359            rxDmaData = &rxDescCache + offsetof(ns_desc, link);
1360            rxDmaLen = sizeof(rxDescCache.link);
1361            rxDmaFree = dmaDescFree;
1362
1363            descDmaReads++;
1364            descDmaRdBytes += rxDmaLen;
1365
1366            if (doRxDmaRead())
1367                goto exit;
1368        } else {
1369            rxState = rxDescRead;
1370
1371            rxDmaAddr = regs.rxdp & 0x3fffffff;
1372            rxDmaData = &rxDescCache;
1373            rxDmaLen = sizeof(ns_desc);
1374            rxDmaFree = dmaDescFree;
1375
1376            descDmaReads++;
1377            descDmaRdBytes += rxDmaLen;
1378
1379            if (doRxDmaRead())
1380                goto exit;
1381        }
1382        break;
1383
1384      case rxDescRefr:
1385        if (rxDmaState != dmaIdle)
1386            goto exit;
1387
1388        rxState = rxAdvance;
1389        break;
1390
1391     case rxDescRead:
1392        if (rxDmaState != dmaIdle)
1393            goto exit;
1394
1395        DPRINTF(EthernetDesc,
1396                "rxDescCache:\n"
1397                "\tlink=%08x\n"
1398                "\tbufptr=%08x\n"
1399                "\tcmdsts=%08x\n"
1400                "\textsts=%08x\n",
1401                rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts,
1402                rxDescCache.extsts);
1403
1404        if (rxDescCache.cmdsts & CMDSTS_OWN) {
1405            devIntrPost(ISR_RXIDLE);
1406            rxState = rxIdle;
1407            goto exit;
1408        } else {
1409            rxState = rxFifoBlock;
1410            rxFragPtr = rxDescCache.bufptr;
1411            rxDescCnt = rxDescCache.cmdsts & CMDSTS_LEN_MASK;
1412        }
1413        break;
1414
1415      case rxFifoBlock:
1416        if (!rxPacket) {
1417            /**
1418             * @todo in reality, we should be able to start processing
1419             * the packet as it arrives, and not have to wait for the
1420             * full packet ot be in the receive fifo.
1421             */
1422            if (rxFifo.empty())
1423                goto exit;
1424
1425            DPRINTF(EthernetSM, "\n\n*****processing receive of new packet\n");
1426
1427            // If we don't have a packet, grab a new one from the fifo.
1428            rxPacket = rxFifo.front();
1429            rxPktBytes = rxPacket->length;
1430            rxPacketBufPtr = rxPacket->data;
1431
1432#if TRACING_ON
1433            if (DTRACE(Ethernet)) {
1434                if (rxPacket->isIpPkt()) {
1435                    ip_header *ip = rxPacket->getIpHdr();
1436                    DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID));
1437                    if (rxPacket->isTcpPkt()) {
1438                        tcp_header *tcp = rxPacket->getTcpHdr(ip);
1439                        DPRINTF(Ethernet, "Src Port = %d, Dest Port = %d\n",
1440                                reverseEnd16(tcp->src_port_num),
1441                                reverseEnd16(tcp->dest_port_num));
1442                    }
1443                }
1444            }
1445#endif
1446
1447            // sanity check - i think the driver behaves like this
1448            assert(rxDescCnt >= rxPktBytes);
1449
1450            // Must clear the value before popping to decrement the
1451            // reference count
1452            rxFifo.front() = NULL;
1453            rxFifo.pop_front();
1454            rxFifoCnt -= rxPacket->length;
1455        }
1456
1457
1458        // dont' need the && rxDescCnt > 0 if driver sanity check
1459        // above holds
1460        if (rxPktBytes > 0) {
1461            rxState = rxFragWrite;
1462            // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
1463            // check holds
1464            rxXferLen = rxPktBytes;
1465
1466            rxDmaAddr = rxFragPtr & 0x3fffffff;
1467            rxDmaData = rxPacketBufPtr;
1468            rxDmaLen = rxXferLen;
1469            rxDmaFree = dmaDataFree;
1470
1471            if (doRxDmaWrite())
1472                goto exit;
1473
1474        } else {
1475            rxState = rxDescWrite;
1476
1477            //if (rxPktBytes == 0) {  /* packet is done */
1478            assert(rxPktBytes == 0);
1479            DPRINTF(EthernetSM, "done with receiving packet\n");
1480
1481            rxDescCache.cmdsts |= CMDSTS_OWN;
1482            rxDescCache.cmdsts &= ~CMDSTS_MORE;
1483            rxDescCache.cmdsts |= CMDSTS_OK;
1484            rxDescCache.cmdsts &= 0xffff0000;
1485            rxDescCache.cmdsts += rxPacket->length;   //i.e. set CMDSTS_SIZE
1486
1487#if 0
1488            /*
1489             * all the driver uses these are for its own stats keeping
1490             * which we don't care about, aren't necessary for
1491             * functionality and doing this would just slow us down.
1492             * if they end up using this in a later version for
1493             * functional purposes, just undef
1494             */
1495            if (rxFilterEnable) {
1496                rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK;
1497                if (rxFifo.front()->IsUnicast())
1498                    rxDescCache.cmdsts |= CMDSTS_DEST_SELF;
1499                if (rxFifo.front()->IsMulticast())
1500                    rxDescCache.cmdsts |= CMDSTS_DEST_MULTI;
1501                if (rxFifo.front()->IsBroadcast())
1502                    rxDescCache.cmdsts |= CMDSTS_DEST_MASK;
1503            }
1504#endif
1505
1506            if (rxPacket->isIpPkt() && extstsEnable) {
1507                rxDescCache.extsts |= EXTSTS_IPPKT;
1508                rxIPChecksums++;
1509                if (!ipChecksum(rxPacket, false)) {
1510                    DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
1511                    rxDescCache.extsts |= EXTSTS_IPERR;
1512                }
1513                if (rxPacket->isTcpPkt()) {
1514                    rxDescCache.extsts |= EXTSTS_TCPPKT;
1515                    rxTCPChecksums++;
1516                    if (!tcpChecksum(rxPacket, false)) {
1517                        DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
1518                        rxDescCache.extsts |= EXTSTS_TCPERR;
1519
1520                    }
1521                } else if (rxPacket->isUdpPkt()) {
1522                    rxDescCache.extsts |= EXTSTS_UDPPKT;
1523                    if (!udpChecksum(rxPacket, false)) {
1524                        DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
1525                        rxDescCache.extsts |= EXTSTS_UDPERR;
1526                    }
1527                }
1528            }
1529            rxPacket = 0;
1530
1531            /*
1532             * the driver seems to always receive into desc buffers
1533             * of size 1514, so you never have a pkt that is split
1534             * into multiple descriptors on the receive side, so
1535             * i don't implement that case, hence the assert above.
1536             */
1537
1538            DPRINTF(EthernetDesc,
1539                    "rxDesc writeback:\n\tcmdsts=%08x\n\textsts=%08x\n",
1540                    rxDescCache.cmdsts, rxDescCache.extsts);
1541
1542            rxDmaAddr = (regs.rxdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff;
1543            rxDmaData = &(rxDescCache.cmdsts);
1544            rxDmaLen = sizeof(rxDescCache.cmdsts) + sizeof(rxDescCache.extsts);
1545            rxDmaFree = dmaDescFree;
1546
1547            descDmaWrites++;
1548            descDmaWrBytes += rxDmaLen;
1549
1550            if (doRxDmaWrite())
1551                goto exit;
1552        }
1553        break;
1554
1555      case rxFragWrite:
1556        if (rxDmaState != dmaIdle)
1557            goto exit;
1558
1559        rxPacketBufPtr += rxXferLen;
1560        rxFragPtr += rxXferLen;
1561        rxPktBytes -= rxXferLen;
1562
1563        rxState = rxFifoBlock;
1564        break;
1565
1566      case rxDescWrite:
1567        if (rxDmaState != dmaIdle)
1568            goto exit;
1569
1570        assert(rxDescCache.cmdsts & CMDSTS_OWN);
1571
1572        assert(rxPacket == 0);
1573        devIntrPost(ISR_RXOK);
1574
1575        if (rxDescCache.cmdsts & CMDSTS_INTR)
1576            devIntrPost(ISR_RXDESC);
1577
1578        if (!rxEnable) {
1579            DPRINTF(EthernetSM, "Halting the RX state machine\n");
1580            rxState = rxIdle;
1581            goto exit;
1582        } else
1583            rxState = rxAdvance;
1584        break;
1585
1586      case rxAdvance:
1587        if (rxDescCache.link == 0) {
1588            devIntrPost(ISR_RXIDLE);
1589            rxState = rxIdle;
1590            CRDD = true;
1591            goto exit;
1592        } else {
1593            rxState = rxDescRead;
1594            regs.rxdp = rxDescCache.link;
1595            CRDD = false;
1596
1597            rxDmaAddr = regs.rxdp & 0x3fffffff;
1598            rxDmaData = &rxDescCache;
1599            rxDmaLen = sizeof(ns_desc);
1600            rxDmaFree = dmaDescFree;
1601
1602            if (doRxDmaRead())
1603                goto exit;
1604        }
1605        break;
1606
1607      default:
1608        panic("Invalid rxState!");
1609    }
1610
1611
1612    DPRINTF(EthernetSM, "entering next rx state = %s\n",
1613            NsRxStateStrings[rxState]);
1614
1615    goto next;
1616
1617  exit:
1618    /**
1619     * @todo do we want to schedule a future kick?
1620     */
1621    DPRINTF(EthernetSM, "rx state machine exited state=%s\n",
1622            NsRxStateStrings[rxState]);
1623}
1624
1625void
1626NSGigE::transmit()
1627{
1628    if (txFifo.empty()) {
1629        DPRINTF(Ethernet, "nothing to transmit\n");
1630        return;
1631    }
1632
1633    DPRINTF(Ethernet, "\n\nAttempt Pkt Transmit: txFifo length = %d\n",
1634            maxTxFifoSize - txFifoAvail);
1635    if (interface->sendPacket(txFifo.front())) {
1636#if TRACING_ON
1637        if (DTRACE(Ethernet)) {
1638            if (txFifo.front()->isIpPkt()) {
1639                ip_header *ip = txFifo.front()->getIpHdr();
1640                DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID));
1641                if (txFifo.front()->isTcpPkt()) {
1642                    tcp_header *tcp = txFifo.front()->getTcpHdr(ip);
1643                    DPRINTF(Ethernet, "Src Port = %d, Dest Port = %d\n",
1644                            reverseEnd16(tcp->src_port_num),
1645                            reverseEnd16(tcp->dest_port_num));
1646                }
1647            }
1648        }
1649#endif
1650
1651        DDUMP(Ethernet, txFifo.front()->data, txFifo.front()->length);
1652        txBytes += txFifo.front()->length;
1653        txPackets++;
1654
1655        txFifoAvail += txFifo.front()->length;
1656
1657        DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
1658                txFifoAvail);
1659        txFifo.front() = NULL;
1660        txFifo.pop_front();
1661
1662        /*
1663         * normally do a writeback of the descriptor here, and ONLY
1664         * after that is done, send this interrupt.  but since our
1665         * stuff never actually fails, just do this interrupt here,
1666         * otherwise the code has to stray from this nice format.
1667         * besides, it's functionally the same.
1668         */
1669        devIntrPost(ISR_TXOK);
1670    } else {
1671        DPRINTF(Ethernet,
1672                "May need to rethink always sending the descriptors back?\n");
1673    }
1674
1675   if (!txFifo.empty() && !txEvent.scheduled()) {
1676       DPRINTF(Ethernet, "reschedule transmit\n");
1677       txEvent.schedule(curTick + 1000);
1678   }
1679}
1680
1681void
1682NSGigE::txDmaReadCopy()
1683{
1684    assert(txDmaState == dmaReading);
1685
1686    physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen);
1687    txDmaState = dmaIdle;
1688
1689    DPRINTF(EthernetDMA, "tx dma read  paddr=%#x len=%d\n",
1690            txDmaAddr, txDmaLen);
1691    DDUMP(EthernetDMA, txDmaData, txDmaLen);
1692}
1693
1694bool
1695NSGigE::doTxDmaRead()
1696{
1697    assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
1698    txDmaState = dmaReading;
1699
1700    if (dmaInterface && !txDmaFree) {
1701        if (dmaInterface->busy())
1702            txDmaState = dmaReadWaiting;
1703        else
1704            dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, curTick,
1705                                &txDmaReadEvent, true);
1706        return true;
1707    }
1708
1709    if (dmaReadDelay == 0 && dmaReadFactor == 0.0) {
1710        txDmaReadCopy();
1711        return false;
1712    }
1713
1714    Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor;
1715    Tick start = curTick + dmaReadDelay + factor;
1716    txDmaReadEvent.schedule(start);
1717    return true;
1718}
1719
1720void
1721NSGigE::txDmaReadDone()
1722{
1723    assert(txDmaState == dmaReading);
1724    txDmaReadCopy();
1725
1726    // If the receive state machine  has a pending DMA, let it go first
1727    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1728        rxKick();
1729
1730    txKick();
1731}
1732
1733void
1734NSGigE::txDmaWriteCopy()
1735{
1736    assert(txDmaState == dmaWriting);
1737
1738    physmem->dma_write(txDmaAddr, (uint8_t *)txDmaData, txDmaLen);
1739    txDmaState = dmaIdle;
1740
1741    DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n",
1742            txDmaAddr, txDmaLen);
1743    DDUMP(EthernetDMA, txDmaData, txDmaLen);
1744}
1745
1746bool
1747NSGigE::doTxDmaWrite()
1748{
1749    assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
1750    txDmaState = dmaWriting;
1751
1752    if (dmaInterface && !txDmaFree) {
1753        if (dmaInterface->busy())
1754            txDmaState = dmaWriteWaiting;
1755        else
1756            dmaInterface->doDMA(WriteInvalidate, txDmaAddr, txDmaLen, curTick,
1757                                &txDmaWriteEvent, true);
1758        return true;
1759    }
1760
1761    if (dmaWriteDelay == 0 && dmaWriteFactor == 0.0) {
1762        txDmaWriteCopy();
1763        return false;
1764    }
1765
1766    Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor;
1767    Tick start = curTick + dmaWriteDelay + factor;
1768    txDmaWriteEvent.schedule(start);
1769    return true;
1770}
1771
1772void
1773NSGigE::txDmaWriteDone()
1774{
1775    assert(txDmaState == dmaWriting);
1776    txDmaWriteCopy();
1777
1778    // If the receive state machine  has a pending DMA, let it go first
1779    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1780        rxKick();
1781
1782    txKick();
1783}
1784
1785void
1786NSGigE::txKick()
1787{
1788    DPRINTF(EthernetSM, "transmit kick state=%s\n", NsTxStateStrings[txState]);
1789
1790    if (txKickTick > curTick) {
1791        DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
1792                txKickTick);
1793
1794        return;
1795    }
1796
1797  next:
1798    switch(txDmaState) {
1799      case dmaReadWaiting:
1800        if (doTxDmaRead())
1801            goto exit;
1802        break;
1803      case dmaWriteWaiting:
1804        if (doTxDmaWrite())
1805            goto exit;
1806        break;
1807      default:
1808        break;
1809    }
1810
1811    switch (txState) {
1812      case txIdle:
1813        if (!txEnable) {
1814            DPRINTF(EthernetSM, "Transmit disabled.  Nothing to do.\n");
1815            goto exit;
1816        }
1817
1818        if (CTDD) {
1819            txState = txDescRefr;
1820
1821            txDmaAddr = regs.txdp & 0x3fffffff;
1822            txDmaData = &txDescCache + offsetof(ns_desc, link);
1823            txDmaLen = sizeof(txDescCache.link);
1824            txDmaFree = dmaDescFree;
1825
1826            descDmaReads++;
1827            descDmaRdBytes += txDmaLen;
1828
1829            if (doTxDmaRead())
1830                goto exit;
1831
1832        } else {
1833            txState = txDescRead;
1834
1835            txDmaAddr = regs.txdp & 0x3fffffff;
1836            txDmaData = &txDescCache;
1837            txDmaLen = sizeof(ns_desc);
1838            txDmaFree = dmaDescFree;
1839
1840            descDmaReads++;
1841            descDmaRdBytes += txDmaLen;
1842
1843            if (doTxDmaRead())
1844                goto exit;
1845        }
1846        break;
1847
1848      case txDescRefr:
1849        if (txDmaState != dmaIdle)
1850            goto exit;
1851
1852        txState = txAdvance;
1853        break;
1854
1855      case txDescRead:
1856        if (txDmaState != dmaIdle)
1857            goto exit;
1858
1859        DPRINTF(EthernetDesc,
1860                "txDescCache data:\n"
1861                "\tlink=%08x\n"
1862                "\tbufptr=%08x\n"
1863                "\tcmdsts=%08x\n"
1864                "\textsts=%08x\n",
1865                txDescCache.link, txDescCache.bufptr, txDescCache.cmdsts,
1866                txDescCache.extsts);
1867
1868        if (txDescCache.cmdsts & CMDSTS_OWN) {
1869            txState = txFifoBlock;
1870            txFragPtr = txDescCache.bufptr;
1871            txDescCnt = txDescCache.cmdsts & CMDSTS_LEN_MASK;
1872        } else {
1873            devIntrPost(ISR_TXIDLE);
1874            txState = txIdle;
1875            goto exit;
1876        }
1877        break;
1878
1879      case txFifoBlock:
1880        if (!txPacket) {
1881            DPRINTF(EthernetSM, "\n\n*****starting the tx of a new packet\n");
1882            txPacket = new EtherPacket;
1883            txPacket->data = new uint8_t[16384];
1884            txPacketBufPtr = txPacket->data;
1885        }
1886
1887        if (txDescCnt == 0) {
1888            DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");
1889            if (txDescCache.cmdsts & CMDSTS_MORE) {
1890                DPRINTF(EthernetSM, "there are more descriptors to come\n");
1891                txState = txDescWrite;
1892
1893                txDescCache.cmdsts &= ~CMDSTS_OWN;
1894
1895                txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts);
1896                txDmaAddr &= 0x3fffffff;
1897                txDmaData = &(txDescCache.cmdsts);
1898                txDmaLen = sizeof(txDescCache.cmdsts);
1899                txDmaFree = dmaDescFree;
1900
1901                if (doTxDmaWrite())
1902                    goto exit;
1903
1904            } else { /* this packet is totally done */
1905                DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
1906                /* deal with the the packet that just finished */
1907                if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
1908                    if (txDescCache.extsts & EXTSTS_UDPPKT) {
1909                        udpChecksum(txPacket, true);
1910                    } else if (txDescCache.extsts & EXTSTS_TCPPKT) {
1911                        tcpChecksum(txPacket, true);
1912                        txTCPChecksums++;
1913                    }
1914                    if (txDescCache.extsts & EXTSTS_IPPKT) {
1915                        ipChecksum(txPacket, true);
1916                        txIPChecksums++;
1917                    }
1918                }
1919
1920                txPacket->length = txPacketBufPtr - txPacket->data;
1921                // this is just because the receive can't handle a
1922                // packet bigger want to make sure
1923                assert(txPacket->length <= 1514);
1924                txFifo.push_back(txPacket);
1925
1926                /*
1927                 * this following section is not tqo spec, but
1928                 * functionally shouldn't be any different.  normally,
1929                 * the chip will wait til the transmit has occurred
1930                 * before writing back the descriptor because it has
1931                 * to wait to see that it was successfully transmitted
1932                 * to decide whether to set CMDSTS_OK or not.
1933                 * however, in the simulator since it is always
1934                 * successfully transmitted, and writing it exactly to
1935                 * spec would complicate the code, we just do it here
1936                 */
1937
1938                txDescCache.cmdsts &= ~CMDSTS_OWN;
1939                txDescCache.cmdsts |= CMDSTS_OK;
1940
1941                DPRINTF(EthernetDesc,
1942                        "txDesc writeback:\n\tcmdsts=%08x\n\textsts=%08x\n",
1943                        txDescCache.cmdsts, txDescCache.extsts);
1944
1945                txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts);
1946                txDmaAddr &= 0x3fffffff;
1947                txDmaData = &(txDescCache.cmdsts);
1948                txDmaLen = sizeof(txDescCache.cmdsts) +
1949                    sizeof(txDescCache.extsts);
1950                txDmaFree = dmaDescFree;
1951
1952                descDmaWrites++;
1953                descDmaWrBytes += txDmaLen;
1954
1955                transmit();
1956                txPacket = 0;
1957
1958                if (!txEnable) {
1959                    DPRINTF(EthernetSM, "halting TX state machine\n");
1960                    txState = txIdle;
1961                    goto exit;
1962                } else
1963                    txState = txAdvance;
1964
1965                if (doTxDmaWrite())
1966                    goto exit;
1967            }
1968        } else {
1969            DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
1970            if (txFifoAvail) {
1971                txState = txFragRead;
1972
1973                /*
1974                 * The number of bytes transferred is either whatever
1975                 * is left in the descriptor (txDescCnt), or if there
1976                 * is not enough room in the fifo, just whatever room
1977                 * is left in the fifo
1978                 */
1979                txXferLen = min<uint32_t>(txDescCnt, txFifoAvail);
1980
1981                txDmaAddr = txFragPtr & 0x3fffffff;
1982                txDmaData = txPacketBufPtr;
1983                txDmaLen = txXferLen;
1984                txDmaFree = dmaDataFree;
1985
1986                if (doTxDmaRead())
1987                    goto exit;
1988            } else {
1989                txState = txFifoBlock;
1990                transmit();
1991
1992                goto exit;
1993            }
1994
1995        }
1996        break;
1997
1998      case txFragRead:
1999        if (txDmaState != dmaIdle)
2000            goto exit;
2001
2002        txPacketBufPtr += txXferLen;
2003        txFragPtr += txXferLen;
2004        txDescCnt -= txXferLen;
2005        txFifoAvail -= txXferLen;
2006
2007        txState = txFifoBlock;
2008        break;
2009
2010      case txDescWrite:
2011        if (txDmaState != dmaIdle)
2012            goto exit;
2013
2014        if (txDescCache.cmdsts & CMDSTS_INTR)
2015            devIntrPost(ISR_TXDESC);
2016
2017        txState = txAdvance;
2018        break;
2019
2020      case txAdvance:
2021        if (txDescCache.link == 0) {
2022            devIntrPost(ISR_TXIDLE);
2023            txState = txIdle;
2024            goto exit;
2025        } else {
2026            txState = txDescRead;
2027            regs.txdp = txDescCache.link;
2028            CTDD = false;
2029
2030            txDmaAddr = txDescCache.link & 0x3fffffff;
2031            txDmaData = &txDescCache;
2032            txDmaLen = sizeof(ns_desc);
2033            txDmaFree = dmaDescFree;
2034
2035            if (doTxDmaRead())
2036                goto exit;
2037        }
2038        break;
2039
2040      default:
2041        panic("invalid state");
2042    }
2043
2044    DPRINTF(EthernetSM, "entering next tx state=%s\n",
2045            NsTxStateStrings[txState]);
2046
2047    goto next;
2048
2049  exit:
2050    /**
2051     * @todo do we want to schedule a future kick?
2052     */
2053    DPRINTF(EthernetSM, "tx state machine exited state=%s\n",
2054            NsTxStateStrings[txState]);
2055}
2056
2057void
2058NSGigE::transferDone()
2059{
2060    if (txFifo.empty())
2061        return;
2062
2063    if (txEvent.scheduled())
2064        txEvent.reschedule(curTick + 1);
2065    else
2066        txEvent.schedule(curTick + 1);
2067}
2068
2069bool
2070NSGigE::rxFilter(PacketPtr packet)
2071{
2072    bool drop = true;
2073    string type;
2074
2075    if (packet->IsUnicast()) {
2076        type = "unicast";
2077
2078        // If we're accepting all unicast addresses
2079        if (acceptUnicast)
2080            drop = false;
2081
2082        // If we make a perfect match
2083        if (acceptPerfect &&
2084            memcmp(rom.perfectMatch, packet->data, EADDR_LEN) == 0)
2085            drop = false;
2086
2087        eth_header *eth = (eth_header *) packet->data;
2088        if ((acceptArp) && (eth->type == 0x608))
2089            drop = false;
2090
2091    } else if (packet->IsBroadcast()) {
2092        type = "broadcast";
2093
2094        // if we're accepting broadcasts
2095        if (acceptBroadcast)
2096            drop = false;
2097
2098    } else if (packet->IsMulticast()) {
2099        type = "multicast";
2100
2101        // if we're accepting all multicasts
2102        if (acceptMulticast)
2103            drop = false;
2104
2105    } else {
2106        type = "unknown";
2107
2108        // oh well, punt on this one
2109    }
2110
2111    if (drop) {
2112        DPRINTF(Ethernet, "rxFilter drop\n");
2113        DDUMP(EthernetData, packet->data, packet->length);
2114    }
2115
2116    return drop;
2117}
2118
2119bool
2120NSGigE::recvPacket(PacketPtr packet)
2121{
2122    rxBytes += packet->length;
2123    rxPackets++;
2124
2125    DPRINTF(Ethernet, "\n\nReceiving packet from wire, rxFifoAvail=%d\n",
2126            maxRxFifoSize - rxFifoCnt);
2127
2128    if (!rxEnable) {
2129        DPRINTF(Ethernet, "receive disabled...packet dropped\n");
2130        interface->recvDone();
2131        return true;
2132    }
2133
2134    if (rxFilterEnable && rxFilter(packet)) {
2135        DPRINTF(Ethernet, "packet filtered...dropped\n");
2136        interface->recvDone();
2137        return true;
2138    }
2139
2140    if ((rxFifoCnt + packet->length) >= maxRxFifoSize) {
2141        DPRINTF(Ethernet,
2142                "packet will not fit in receive buffer...packet dropped\n");
2143        devIntrPost(ISR_RXORN);
2144        return false;
2145    }
2146
2147    rxFifo.push_back(packet);
2148    rxFifoCnt += packet->length;
2149    interface->recvDone();
2150
2151    rxKick();
2152    return true;
2153}
2154
2155/**
2156 * does a udp checksum.  if gen is true, then it generates it and puts
2157 * it in the right place else, it just checks what it calculates
2158 * against the value in the header in packet
2159 */
2160bool
2161NSGigE::udpChecksum(PacketPtr packet, bool gen)
2162{
2163    ip_header *ip = packet->getIpHdr();
2164    udp_header *hdr = packet->getUdpHdr(ip);
2165
2166    pseudo_header *pseudo = new pseudo_header;
2167
2168    pseudo->src_ip_addr = ip->src_ip_addr;
2169    pseudo->dest_ip_addr = ip->dest_ip_addr;
2170    pseudo->protocol = ip->protocol;
2171    pseudo->len = hdr->len;
2172
2173    uint16_t cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr,
2174                                  (uint32_t) hdr->len);
2175
2176    delete pseudo;
2177    if (gen)
2178        hdr->chksum = cksum;
2179    else
2180        if (cksum != 0)
2181            return false;
2182
2183    return true;
2184}
2185
2186bool
2187NSGigE::tcpChecksum(PacketPtr packet, bool gen)
2188{
2189    ip_header *ip = packet->getIpHdr();
2190    tcp_header *hdr = packet->getTcpHdr(ip);
2191
2192    uint16_t cksum;
2193    pseudo_header *pseudo = new pseudo_header;
2194    if (!gen) {
2195        pseudo->src_ip_addr = ip->src_ip_addr;
2196        pseudo->dest_ip_addr = ip->dest_ip_addr;
2197        pseudo->protocol = reverseEnd16(ip->protocol);
2198        pseudo->len = reverseEnd16(reverseEnd16(ip->dgram_len) -
2199                                   (ip->vers_len & 0xf)*4);
2200
2201        cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr,
2202                             (uint32_t) reverseEnd16(pseudo->len));
2203    } else {
2204        pseudo->src_ip_addr = 0;
2205        pseudo->dest_ip_addr = 0;
2206        pseudo->protocol = hdr->chksum;
2207        pseudo->len = 0;
2208        hdr->chksum = 0;
2209        cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr,
2210                             (uint32_t) (reverseEnd16(ip->dgram_len) -
2211                                         (ip->vers_len & 0xf)*4));
2212    }
2213
2214    delete pseudo;
2215    if (gen)
2216        hdr->chksum = cksum;
2217    else
2218        if (cksum != 0)
2219            return false;
2220
2221    return true;
2222}
2223
2224bool
2225NSGigE::ipChecksum(PacketPtr packet, bool gen)
2226{
2227    ip_header *hdr = packet->getIpHdr();
2228
2229    uint16_t cksum = checksumCalc(NULL, (uint16_t *) hdr,
2230                                  (hdr->vers_len & 0xf)*4);
2231
2232    if (gen) {
2233        DPRINTF(EthernetCksum, "generated checksum: %#x\n", cksum);
2234        hdr->hdr_chksum = cksum;
2235    }
2236    else
2237        if (cksum != 0)
2238            return false;
2239
2240    return true;
2241}
2242
2243uint16_t
2244NSGigE::checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len)
2245{
2246    uint32_t sum = 0;
2247
2248    uint16_t last_pad = 0;
2249    if (len & 1) {
2250        last_pad = buf[len/2] & 0xff;
2251        len--;
2252        sum += last_pad;
2253    }
2254
2255    if (pseudo) {
2256        sum = pseudo[0] + pseudo[1] + pseudo[2] +
2257            pseudo[3] + pseudo[4] + pseudo[5];
2258    }
2259
2260    for (int i=0; i < (len/2); ++i) {
2261        sum += buf[i];
2262    }
2263
2264    while (sum >> 16)
2265        sum = (sum >> 16) + (sum & 0xffff);
2266
2267    return ~sum;
2268}
2269
2270//=====================================================================
2271//
2272//
2273void
2274NSGigE::serialize(ostream &os)
2275{
2276    // Serialize the PciDev base class
2277    PciDev::serialize(os);
2278
2279    /*
2280     * Finalize any DMA events now.
2281     */
2282    if (rxDmaReadEvent.scheduled())
2283        rxDmaReadCopy();
2284    if (rxDmaWriteEvent.scheduled())
2285        rxDmaWriteCopy();
2286    if (txDmaReadEvent.scheduled())
2287        txDmaReadCopy();
2288    if (txDmaWriteEvent.scheduled())
2289        txDmaWriteCopy();
2290
2291    /*
2292     * Serialize the device registers
2293     */
2294    SERIALIZE_SCALAR(regs.command);
2295    SERIALIZE_SCALAR(regs.config);
2296    SERIALIZE_SCALAR(regs.mear);
2297    SERIALIZE_SCALAR(regs.ptscr);
2298    SERIALIZE_SCALAR(regs.isr);
2299    SERIALIZE_SCALAR(regs.imr);
2300    SERIALIZE_SCALAR(regs.ier);
2301    SERIALIZE_SCALAR(regs.ihr);
2302    SERIALIZE_SCALAR(regs.txdp);
2303    SERIALIZE_SCALAR(regs.txdp_hi);
2304    SERIALIZE_SCALAR(regs.txcfg);
2305    SERIALIZE_SCALAR(regs.gpior);
2306    SERIALIZE_SCALAR(regs.rxdp);
2307    SERIALIZE_SCALAR(regs.rxdp_hi);
2308    SERIALIZE_SCALAR(regs.rxcfg);
2309    SERIALIZE_SCALAR(regs.pqcr);
2310    SERIALIZE_SCALAR(regs.wcsr);
2311    SERIALIZE_SCALAR(regs.pcr);
2312    SERIALIZE_SCALAR(regs.rfcr);
2313    SERIALIZE_SCALAR(regs.rfdr);
2314    SERIALIZE_SCALAR(regs.srr);
2315    SERIALIZE_SCALAR(regs.mibc);
2316    SERIALIZE_SCALAR(regs.vrcr);
2317    SERIALIZE_SCALAR(regs.vtcr);
2318    SERIALIZE_SCALAR(regs.vdr);
2319    SERIALIZE_SCALAR(regs.ccsr);
2320    SERIALIZE_SCALAR(regs.tbicr);
2321    SERIALIZE_SCALAR(regs.tbisr);
2322    SERIALIZE_SCALAR(regs.tanar);
2323    SERIALIZE_SCALAR(regs.tanlpar);
2324    SERIALIZE_SCALAR(regs.taner);
2325    SERIALIZE_SCALAR(regs.tesr);
2326
2327    SERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN);
2328
2329    SERIALIZE_SCALAR(ioEnable);
2330
2331    /*
2332     * Serialize the data Fifos
2333     */
2334    int txNumPkts = txFifo.size();
2335    SERIALIZE_SCALAR(txNumPkts);
2336    int i = 0;
2337    pktiter_t end = txFifo.end();
2338    for (pktiter_t p = txFifo.begin(); p != end; ++p) {
2339        nameOut(os, csprintf("%s.txFifo%d", name(), i++));
2340        (*p)->serialize(os);
2341    }
2342
2343    int rxNumPkts = rxFifo.size();
2344    SERIALIZE_SCALAR(rxNumPkts);
2345    i = 0;
2346    end = rxFifo.end();
2347    for (pktiter_t p = rxFifo.begin(); p != end; ++p) {
2348        nameOut(os, csprintf("%s.rxFifo%d", name(), i++));
2349        (*p)->serialize(os);
2350    }
2351
2352    /*
2353     * Serialize the various helper variables
2354     */
2355    bool txPacketExists = txPacket;
2356    SERIALIZE_SCALAR(txPacketExists);
2357    if (txPacketExists) {
2358        nameOut(os, csprintf("%s.txPacket", name()));
2359        txPacket->serialize(os);
2360        uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
2361        SERIALIZE_SCALAR(txPktBufPtr);
2362    }
2363
2364    bool rxPacketExists = rxPacket;
2365    SERIALIZE_SCALAR(rxPacketExists);
2366    if (rxPacketExists) {
2367        nameOut(os, csprintf("%s.rxPacket", name()));
2368        rxPacket->serialize(os);
2369        uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
2370        SERIALIZE_SCALAR(rxPktBufPtr);
2371    }
2372
2373    SERIALIZE_SCALAR(txXferLen);
2374    SERIALIZE_SCALAR(rxXferLen);
2375
2376    /*
2377     * Serialize DescCaches
2378     */
2379    SERIALIZE_SCALAR(txDescCache.link);
2380    SERIALIZE_SCALAR(txDescCache.bufptr);
2381    SERIALIZE_SCALAR(txDescCache.cmdsts);
2382    SERIALIZE_SCALAR(txDescCache.extsts);
2383    SERIALIZE_SCALAR(rxDescCache.link);
2384    SERIALIZE_SCALAR(rxDescCache.bufptr);
2385    SERIALIZE_SCALAR(rxDescCache.cmdsts);
2386    SERIALIZE_SCALAR(rxDescCache.extsts);
2387
2388    /*
2389     * Serialize tx state machine
2390     */
2391    int txState = this->txState;
2392    SERIALIZE_SCALAR(txState);
2393    SERIALIZE_SCALAR(txEnable);
2394    SERIALIZE_SCALAR(CTDD);
2395    SERIALIZE_SCALAR(txFifoAvail);
2396    SERIALIZE_SCALAR(txFragPtr);
2397    SERIALIZE_SCALAR(txDescCnt);
2398    int txDmaState = this->txDmaState;
2399    SERIALIZE_SCALAR(txDmaState);
2400
2401    /*
2402     * Serialize rx state machine
2403     */
2404    int rxState = this->rxState;
2405    SERIALIZE_SCALAR(rxState);
2406    SERIALIZE_SCALAR(rxEnable);
2407    SERIALIZE_SCALAR(CRDD);
2408    SERIALIZE_SCALAR(rxPktBytes);
2409    SERIALIZE_SCALAR(rxFifoCnt);
2410    SERIALIZE_SCALAR(rxDescCnt);
2411    int rxDmaState = this->rxDmaState;
2412    SERIALIZE_SCALAR(rxDmaState);
2413
2414    SERIALIZE_SCALAR(extstsEnable);
2415
2416    /*
2417     * If there's a pending transmit, store the time so we can
2418     * reschedule it later
2419     */
2420    Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;
2421    SERIALIZE_SCALAR(transmitTick);
2422
2423    /*
2424     * receive address filter settings
2425     */
2426    SERIALIZE_SCALAR(rxFilterEnable);
2427    SERIALIZE_SCALAR(acceptBroadcast);
2428    SERIALIZE_SCALAR(acceptMulticast);
2429    SERIALIZE_SCALAR(acceptUnicast);
2430    SERIALIZE_SCALAR(acceptPerfect);
2431    SERIALIZE_SCALAR(acceptArp);
2432
2433    /*
2434     * Keep track of pending interrupt status.
2435     */
2436    SERIALIZE_SCALAR(intrTick);
2437    SERIALIZE_SCALAR(cpuPendingIntr);
2438    Tick intrEventTick = 0;
2439    if (intrEvent)
2440        intrEventTick = intrEvent->when();
2441    SERIALIZE_SCALAR(intrEventTick);
2442
2443}
2444
2445void
2446NSGigE::unserialize(Checkpoint *cp, const std::string &section)
2447{
2448    // Unserialize the PciDev base class
2449    PciDev::unserialize(cp, section);
2450
2451    UNSERIALIZE_SCALAR(regs.command);
2452    UNSERIALIZE_SCALAR(regs.config);
2453    UNSERIALIZE_SCALAR(regs.mear);
2454    UNSERIALIZE_SCALAR(regs.ptscr);
2455    UNSERIALIZE_SCALAR(regs.isr);
2456    UNSERIALIZE_SCALAR(regs.imr);
2457    UNSERIALIZE_SCALAR(regs.ier);
2458    UNSERIALIZE_SCALAR(regs.ihr);
2459    UNSERIALIZE_SCALAR(regs.txdp);
2460    UNSERIALIZE_SCALAR(regs.txdp_hi);
2461    UNSERIALIZE_SCALAR(regs.txcfg);
2462    UNSERIALIZE_SCALAR(regs.gpior);
2463    UNSERIALIZE_SCALAR(regs.rxdp);
2464    UNSERIALIZE_SCALAR(regs.rxdp_hi);
2465    UNSERIALIZE_SCALAR(regs.rxcfg);
2466    UNSERIALIZE_SCALAR(regs.pqcr);
2467    UNSERIALIZE_SCALAR(regs.wcsr);
2468    UNSERIALIZE_SCALAR(regs.pcr);
2469    UNSERIALIZE_SCALAR(regs.rfcr);
2470    UNSERIALIZE_SCALAR(regs.rfdr);
2471    UNSERIALIZE_SCALAR(regs.srr);
2472    UNSERIALIZE_SCALAR(regs.mibc);
2473    UNSERIALIZE_SCALAR(regs.vrcr);
2474    UNSERIALIZE_SCALAR(regs.vtcr);
2475    UNSERIALIZE_SCALAR(regs.vdr);
2476    UNSERIALIZE_SCALAR(regs.ccsr);
2477    UNSERIALIZE_SCALAR(regs.tbicr);
2478    UNSERIALIZE_SCALAR(regs.tbisr);
2479    UNSERIALIZE_SCALAR(regs.tanar);
2480    UNSERIALIZE_SCALAR(regs.tanlpar);
2481    UNSERIALIZE_SCALAR(regs.taner);
2482    UNSERIALIZE_SCALAR(regs.tesr);
2483
2484    UNSERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN);
2485
2486    UNSERIALIZE_SCALAR(ioEnable);
2487
2488    /*
2489     * unserialize the data fifos
2490     */
2491    int txNumPkts;
2492    UNSERIALIZE_SCALAR(txNumPkts);
2493    int i;
2494    for (i = 0; i < txNumPkts; ++i) {
2495        PacketPtr p = new EtherPacket;
2496        p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
2497        txFifo.push_back(p);
2498    }
2499
2500    int rxNumPkts;
2501    UNSERIALIZE_SCALAR(rxNumPkts);
2502    for (i = 0; i < rxNumPkts; ++i) {
2503        PacketPtr p = new EtherPacket;
2504        p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
2505        rxFifo.push_back(p);
2506    }
2507
2508    /*
2509     * unserialize the various helper variables
2510     */
2511    bool txPacketExists;
2512    UNSERIALIZE_SCALAR(txPacketExists);
2513    if (txPacketExists) {
2514        txPacket = new EtherPacket;
2515        txPacket->unserialize(cp, csprintf("%s.txPacket", section));
2516        uint32_t txPktBufPtr;
2517        UNSERIALIZE_SCALAR(txPktBufPtr);
2518        txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
2519    } else
2520        txPacket = 0;
2521
2522    bool rxPacketExists;
2523    UNSERIALIZE_SCALAR(rxPacketExists);
2524    rxPacket = 0;
2525    if (rxPacketExists) {
2526        rxPacket = new EtherPacket;
2527        rxPacket->unserialize(cp, csprintf("%s.rxPacket", section));
2528        uint32_t rxPktBufPtr;
2529        UNSERIALIZE_SCALAR(rxPktBufPtr);
2530        rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
2531    } else
2532        rxPacket = 0;
2533
2534    UNSERIALIZE_SCALAR(txXferLen);
2535    UNSERIALIZE_SCALAR(rxXferLen);
2536
2537    /*
2538     * Unserialize DescCaches
2539     */
2540    UNSERIALIZE_SCALAR(txDescCache.link);
2541    UNSERIALIZE_SCALAR(txDescCache.bufptr);
2542    UNSERIALIZE_SCALAR(txDescCache.cmdsts);
2543    UNSERIALIZE_SCALAR(txDescCache.extsts);
2544    UNSERIALIZE_SCALAR(rxDescCache.link);
2545    UNSERIALIZE_SCALAR(rxDescCache.bufptr);
2546    UNSERIALIZE_SCALAR(rxDescCache.cmdsts);
2547    UNSERIALIZE_SCALAR(rxDescCache.extsts);
2548
2549    /*
2550     * unserialize tx state machine
2551     */
2552    int txState;
2553    UNSERIALIZE_SCALAR(txState);
2554    this->txState = (TxState) txState;
2555    UNSERIALIZE_SCALAR(txEnable);
2556    UNSERIALIZE_SCALAR(CTDD);
2557    UNSERIALIZE_SCALAR(txFifoAvail);
2558    UNSERIALIZE_SCALAR(txFragPtr);
2559    UNSERIALIZE_SCALAR(txDescCnt);
2560    int txDmaState;
2561    UNSERIALIZE_SCALAR(txDmaState);
2562    this->txDmaState = (DmaState) txDmaState;
2563
2564    /*
2565     * unserialize rx state machine
2566     */
2567    int rxState;
2568    UNSERIALIZE_SCALAR(rxState);
2569    this->rxState = (RxState) rxState;
2570    UNSERIALIZE_SCALAR(rxEnable);
2571    UNSERIALIZE_SCALAR(CRDD);
2572    UNSERIALIZE_SCALAR(rxPktBytes);
2573    UNSERIALIZE_SCALAR(rxFifoCnt);
2574    UNSERIALIZE_SCALAR(rxDescCnt);
2575    int rxDmaState;
2576    UNSERIALIZE_SCALAR(rxDmaState);
2577    this->rxDmaState = (DmaState) rxDmaState;
2578
2579    UNSERIALIZE_SCALAR(extstsEnable);
2580
2581     /*
2582     * If there's a pending transmit, reschedule it now
2583     */
2584    Tick transmitTick;
2585    UNSERIALIZE_SCALAR(transmitTick);
2586    if (transmitTick)
2587        txEvent.schedule(curTick + transmitTick);
2588
2589    /*
2590     * unserialize receive address filter settings
2591     */
2592    UNSERIALIZE_SCALAR(rxFilterEnable);
2593    UNSERIALIZE_SCALAR(acceptBroadcast);
2594    UNSERIALIZE_SCALAR(acceptMulticast);
2595    UNSERIALIZE_SCALAR(acceptUnicast);
2596    UNSERIALIZE_SCALAR(acceptPerfect);
2597    UNSERIALIZE_SCALAR(acceptArp);
2598
2599    /*
2600     * Keep track of pending interrupt status.
2601     */
2602    UNSERIALIZE_SCALAR(intrTick);
2603    UNSERIALIZE_SCALAR(cpuPendingIntr);
2604    Tick intrEventTick;
2605    UNSERIALIZE_SCALAR(intrEventTick);
2606    if (intrEventTick) {
2607        intrEvent = new IntrEvent(this, true);
2608        intrEvent->schedule(intrEventTick);
2609    }
2610
2611    /*
2612     * re-add addrRanges to bus bridges
2613     */
2614    if (pioInterface) {
2615        pioInterface->addAddrRange(BARAddrs[0], BARAddrs[0] + BARSize[0] - 1);
2616        pioInterface->addAddrRange(BARAddrs[1], BARAddrs[1] + BARSize[1] - 1);
2617    }
2618}
2619
2620Tick
2621NSGigE::cacheAccess(MemReqPtr &req)
2622{
2623    DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n",
2624            req->paddr, req->paddr - addr);
2625    return curTick + pioLatency;
2626}
2627//=====================================================================
2628
2629
2630//********** helper functions******************************************
2631
2632uint16_t reverseEnd16(uint16_t num)
2633{
2634    uint16_t reverse = (num & 0xff)<<8;
2635    reverse += ((num & 0xff00) >> 8);
2636    return reverse;
2637}
2638
2639uint32_t reverseEnd32(uint32_t num)
2640{
2641    uint32_t reverse = (reverseEnd16(num & 0xffff)) << 16;
2642    reverse += reverseEnd16((uint16_t) ((num & 0xffff0000) >> 8));
2643    return reverse;
2644}
2645
2646
2647
2648//=====================================================================
2649
2650BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
2651
2652    SimObjectParam<EtherInt *> peer;
2653    SimObjectParam<NSGigE *> device;
2654
2655END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
2656
2657BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
2658
2659    INIT_PARAM_DFLT(peer, "peer interface", NULL),
2660    INIT_PARAM(device, "Ethernet device of this interface")
2661
2662END_INIT_SIM_OBJECT_PARAMS(NSGigEInt)
2663
2664CREATE_SIM_OBJECT(NSGigEInt)
2665{
2666    NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device);
2667
2668    EtherInt *p = (EtherInt *)peer;
2669    if (p) {
2670        dev_int->setPeer(p);
2671        p->setPeer(dev_int);
2672    }
2673
2674    return dev_int;
2675}
2676
2677REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt)
2678
2679
2680BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
2681
2682    Param<Tick> tx_delay;
2683    Param<Tick> rx_delay;
2684    SimObjectParam<IntrControl *> intr_ctrl;
2685    Param<Tick> intr_delay;
2686    SimObjectParam<MemoryController *> mmu;
2687    SimObjectParam<PhysicalMemory *> physmem;
2688    Param<bool> rx_filter;
2689    Param<string> hardware_address;
2690    SimObjectParam<Bus*> header_bus;
2691    SimObjectParam<Bus*> payload_bus;
2692    SimObjectParam<HierParams *> hier;
2693    Param<Tick> pio_latency;
2694    Param<bool> dma_desc_free;
2695    Param<bool> dma_data_free;
2696    Param<Tick> dma_read_delay;
2697    Param<Tick> dma_write_delay;
2698    Param<Tick> dma_read_factor;
2699    Param<Tick> dma_write_factor;
2700    SimObjectParam<PciConfigAll *> configspace;
2701    SimObjectParam<PciConfigData *> configdata;
2702    SimObjectParam<Tsunami *> tsunami;
2703    Param<uint32_t> pci_bus;
2704    Param<uint32_t> pci_dev;
2705    Param<uint32_t> pci_func;
2706    Param<uint32_t> tx_fifo_size;
2707    Param<uint32_t> rx_fifo_size;
2708
2709END_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
2710
2711BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
2712
2713    INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000),
2714    INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000),
2715    INIT_PARAM(intr_ctrl, "Interrupt Controller"),
2716    INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0),
2717    INIT_PARAM(mmu, "Memory Controller"),
2718    INIT_PARAM(physmem, "Physical Memory"),
2719    INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true),
2720    INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address",
2721                    "00:99:00:00:00:01"),
2722    INIT_PARAM_DFLT(header_bus, "The IO Bus to attach to for headers", NULL),
2723    INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL),
2724    INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams),
2725    INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
2726    INIT_PARAM_DFLT(dma_desc_free, "DMA of Descriptors is free", false),
2727    INIT_PARAM_DFLT(dma_data_free, "DMA of Data is free", false),
2728    INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0),
2729    INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0),
2730    INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0),
2731    INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0),
2732    INIT_PARAM(configspace, "PCI Configspace"),
2733    INIT_PARAM(configdata, "PCI Config data"),
2734    INIT_PARAM(tsunami, "Tsunami"),
2735    INIT_PARAM(pci_bus, "PCI bus"),
2736    INIT_PARAM(pci_dev, "PCI device number"),
2737    INIT_PARAM(pci_func, "PCI function code"),
2738    INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 131072),
2739    INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 131072)
2740
2741END_INIT_SIM_OBJECT_PARAMS(NSGigE)
2742
2743
2744CREATE_SIM_OBJECT(NSGigE)
2745{
2746    int eaddr[6];
2747    sscanf(((string)hardware_address).c_str(), "%x:%x:%x:%x:%x:%x",
2748           &eaddr[0], &eaddr[1], &eaddr[2], &eaddr[3], &eaddr[4], &eaddr[5]);
2749
2750    return new NSGigE(getInstanceName(), intr_ctrl, intr_delay,
2751                      physmem, tx_delay, rx_delay, mmu, hier, header_bus,
2752                      payload_bus, pio_latency, dma_desc_free, dma_data_free,
2753                      dma_read_delay, dma_write_delay, dma_read_factor,
2754                      dma_write_factor, configspace, configdata,
2755                      tsunami, pci_bus, pci_dev, pci_func, rx_filter, eaddr,
2756                      tx_fifo_size, rx_fifo_size);
2757}
2758
2759REGISTER_SIM_OBJECT("NSGigE", NSGigE)
2760