ns_gige.cc revision 5485
110037SARM gem5 Developers/*
210037SARM gem5 Developers * Copyright (c) 2004-2005 The Regents of The University of Michigan
314127Sgiacomo.travaglini@arm.com * All rights reserved.
410037SARM gem5 Developers *
510037SARM gem5 Developers * Redistribution and use in source and binary forms, with or without
610037SARM gem5 Developers * modification, are permitted provided that the following conditions are
710037SARM gem5 Developers * met: redistributions of source code must retain the above copyright
810037SARM gem5 Developers * notice, this list of conditions and the following disclaimer;
910037SARM gem5 Developers * redistributions in binary form must reproduce the above copyright
1010037SARM gem5 Developers * notice, this list of conditions and the following disclaimer in the
1110037SARM gem5 Developers * documentation and/or other materials provided with the distribution;
1210037SARM gem5 Developers * neither the name of the copyright holders nor the names of its
1310037SARM gem5 Developers * contributors may be used to endorse or promote products derived from
1410037SARM gem5 Developers * this software without specific prior written permission.
1510037SARM gem5 Developers *
1610037SARM gem5 Developers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1710037SARM gem5 Developers * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1810037SARM gem5 Developers * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1910037SARM gem5 Developers * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2010037SARM gem5 Developers * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2110037SARM gem5 Developers * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210037SARM gem5 Developers * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2310037SARM gem5 Developers * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2410037SARM gem5 Developers * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2510037SARM gem5 Developers * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2610037SARM gem5 Developers * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2710037SARM gem5 Developers *
2810037SARM gem5 Developers * Authors: Nathan Binkert
2910037SARM gem5 Developers *          Lisa Hsu
3010037SARM gem5 Developers */
3110037SARM gem5 Developers
3210037SARM gem5 Developers/** @file
3310037SARM gem5 Developers * Device module for modelling the National Semiconductor
3410037SARM gem5 Developers * DP83820 ethernet controller.  Does not support priority queueing
3510037SARM gem5 Developers */
3610037SARM gem5 Developers#include <deque>
3710037SARM gem5 Developers#include <string>
3810037SARM gem5 Developers
3910037SARM gem5 Developers#include "base/inet.hh"
4012538Sgiacomo.travaglini@arm.com#include "cpu/thread_context.hh"
4112538Sgiacomo.travaglini@arm.com#include "dev/etherlink.hh"
4212538Sgiacomo.travaglini@arm.com#include "dev/ns_gige.hh"
4312538Sgiacomo.travaglini@arm.com#include "dev/pciconfigall.hh"
4412538Sgiacomo.travaglini@arm.com#include "mem/packet.hh"
4512538Sgiacomo.travaglini@arm.com#include "mem/packet_access.hh"
4612538Sgiacomo.travaglini@arm.com#include "params/NSGigE.hh"
4712538Sgiacomo.travaglini@arm.com#include "sim/debug.hh"
4812616Sgabeblack@google.com#include "sim/host.hh"
4912538Sgiacomo.travaglini@arm.com#include "sim/system.hh"
5012538Sgiacomo.travaglini@arm.com
5112538Sgiacomo.travaglini@arm.comconst char *NsRxStateStrings[] =
5212538Sgiacomo.travaglini@arm.com{
5312538Sgiacomo.travaglini@arm.com    "rxIdle",
5412538Sgiacomo.travaglini@arm.com    "rxDescRefr",
5512538Sgiacomo.travaglini@arm.com    "rxDescRead",
5612538Sgiacomo.travaglini@arm.com    "rxFifoBlock",
5712538Sgiacomo.travaglini@arm.com    "rxFragWrite",
5812538Sgiacomo.travaglini@arm.com    "rxDescWrite",
5912538Sgiacomo.travaglini@arm.com    "rxAdvance"
6010037SARM gem5 Developers};
6110037SARM gem5 Developers
6210037SARM gem5 Developersconst char *NsTxStateStrings[] =
6310037SARM gem5 Developers{
6410037SARM gem5 Developers    "txIdle",
6510037SARM gem5 Developers    "txDescRefr",
6610037SARM gem5 Developers    "txDescRead",
6710037SARM gem5 Developers    "txFifoBlock",
6810037SARM gem5 Developers    "txFragRead",
6912616Sgabeblack@google.com    "txDescWrite",
7010037SARM gem5 Developers    "txAdvance"
7110037SARM gem5 Developers};
7210037SARM gem5 Developers
7310037SARM gem5 Developersconst char *NsDmaState[] =
7410184SCurtis.Dunham@arm.com{
7510037SARM gem5 Developers    "dmaIdle",
7610037SARM gem5 Developers    "dmaReading",
7710037SARM gem5 Developers    "dmaWriting",
7810037SARM gem5 Developers    "dmaReadWaiting",
7910037SARM gem5 Developers    "dmaWriteWaiting"
8010037SARM gem5 Developers};
8110037SARM gem5 Developers
8210037SARM gem5 Developersusing namespace std;
8310037SARM gem5 Developersusing namespace Net;
8410037SARM gem5 Developersusing namespace TheISA;
8510037SARM gem5 Developers
8610037SARM gem5 Developers///////////////////////////////////////////////////////////////////////
8710037SARM gem5 Developers//
8810037SARM gem5 Developers// NSGigE PCI Device
8910037SARM gem5 Developers//
9010037SARM gem5 DevelopersNSGigE::NSGigE(Params *p)
9110037SARM gem5 Developers    : EtherDevice(p), ioEnable(false),
9210037SARM gem5 Developers      txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size),
9310037SARM gem5 Developers      txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
9410037SARM gem5 Developers      txXferLen(0), rxXferLen(0), rxDmaFree(false), txDmaFree(false),
9512616Sgabeblack@google.com      clock(p->clock),
9610037SARM gem5 Developers      txState(txIdle), txEnable(false), CTDD(false), txHalt(false),
9710037SARM gem5 Developers      txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
9810037SARM gem5 Developers      rxEnable(false), CRDD(false), rxPktBytes(0), rxHalt(false),
9910037SARM gem5 Developers      rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false),
10010184SCurtis.Dunham@arm.com      eepromState(eepromStart), eepromClk(false), eepromBitsToRx(0),
10110037SARM gem5 Developers      eepromOpcode(0), eepromAddress(0), eepromData(0),
10210037SARM gem5 Developers      dmaReadDelay(p->dma_read_delay), dmaWriteDelay(p->dma_write_delay),
10310037SARM gem5 Developers      dmaReadFactor(p->dma_read_factor), dmaWriteFactor(p->dma_write_factor),
10410037SARM gem5 Developers      rxDmaData(NULL), rxDmaAddr(0), rxDmaLen(0),
10510037SARM gem5 Developers      txDmaData(NULL), txDmaAddr(0), txDmaLen(0),
10610037SARM gem5 Developers      rxDmaReadEvent(this), rxDmaWriteEvent(this),
10710037SARM gem5 Developers      txDmaReadEvent(this), txDmaWriteEvent(this),
10810037SARM gem5 Developers      dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free),
10910037SARM gem5 Developers      txDelay(p->tx_delay), rxDelay(p->rx_delay),
11010037SARM gem5 Developers      rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this),
11110037SARM gem5 Developers      txEvent(this), rxFilterEnable(p->rx_filter),
11214127Sgiacomo.travaglini@arm.com      acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false),
11314127Sgiacomo.travaglini@arm.com      acceptPerfect(false), acceptArp(false), multicastHashEnable(false),
11414127Sgiacomo.travaglini@arm.com      intrDelay(p->intr_delay), intrTick(0), cpuPendingIntr(false),
11514127Sgiacomo.travaglini@arm.com      intrEvent(0), interface(0)
11614127Sgiacomo.travaglini@arm.com{
11714127Sgiacomo.travaglini@arm.com
11814127Sgiacomo.travaglini@arm.com
11914127Sgiacomo.travaglini@arm.com    interface = new NSGigEInt(name() + ".int0", this);
12014127Sgiacomo.travaglini@arm.com
12114127Sgiacomo.travaglini@arm.com    regsReset();
12214127Sgiacomo.travaglini@arm.com    memcpy(&rom.perfectMatch, p->hardware_address.bytes(), ETH_ADDR_LEN);
12314127Sgiacomo.travaglini@arm.com
12414127Sgiacomo.travaglini@arm.com    memset(&rxDesc32, 0, sizeof(rxDesc32));
12514127Sgiacomo.travaglini@arm.com    memset(&txDesc32, 0, sizeof(txDesc32));
12614127Sgiacomo.travaglini@arm.com    memset(&rxDesc64, 0, sizeof(rxDesc64));
12714127Sgiacomo.travaglini@arm.com    memset(&txDesc64, 0, sizeof(txDesc64));
12814127Sgiacomo.travaglini@arm.com}
12914127Sgiacomo.travaglini@arm.com
13014127Sgiacomo.travaglini@arm.comNSGigE::~NSGigE()
13114127Sgiacomo.travaglini@arm.com{}
13214127Sgiacomo.travaglini@arm.com
13314127Sgiacomo.travaglini@arm.com/**
13414127Sgiacomo.travaglini@arm.com * This is to write to the PCI general configuration registers
13512280Sgiacomo.travaglini@arm.com */
13612280Sgiacomo.travaglini@arm.comTick
13712280Sgiacomo.travaglini@arm.comNSGigE::writeConfig(PacketPtr pkt)
13812280Sgiacomo.travaglini@arm.com{
13912280Sgiacomo.travaglini@arm.com    int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
14012280Sgiacomo.travaglini@arm.com    if (offset < PCI_DEVICE_SPECIFIC)
14112280Sgiacomo.travaglini@arm.com        PciDev::writeConfig(pkt);
14212280Sgiacomo.travaglini@arm.com    else
14312616Sgabeblack@google.com        panic("Device specific PCI config space not implemented!\n");
14412280Sgiacomo.travaglini@arm.com
14512280Sgiacomo.travaglini@arm.com    switch (offset) {
14612280Sgiacomo.travaglini@arm.com        // seems to work fine without all these PCI settings, but i
14712280Sgiacomo.travaglini@arm.com        // put in the IO to double check, an assertion will fail if we
14812280Sgiacomo.travaglini@arm.com        // need to properly implement it
14912280Sgiacomo.travaglini@arm.com      case PCI_COMMAND:
15012280Sgiacomo.travaglini@arm.com        if (config.data[offset] & PCI_CMD_IOSE)
15112280Sgiacomo.travaglini@arm.com            ioEnable = true;
15212280Sgiacomo.travaglini@arm.com        else
15312280Sgiacomo.travaglini@arm.com            ioEnable = false;
15412280Sgiacomo.travaglini@arm.com        break;
15512280Sgiacomo.travaglini@arm.com    }
15612280Sgiacomo.travaglini@arm.com
15712280Sgiacomo.travaglini@arm.com    return configDelay;
15812280Sgiacomo.travaglini@arm.com}
15912280Sgiacomo.travaglini@arm.com
16012280Sgiacomo.travaglini@arm.comEtherInt*
16112280Sgiacomo.travaglini@arm.comNSGigE::getEthPort(const std::string &if_name, int idx)
16212280Sgiacomo.travaglini@arm.com{
16312280Sgiacomo.travaglini@arm.com    if (if_name == "interface") {
16412280Sgiacomo.travaglini@arm.com       if (interface->getPeer())
16512280Sgiacomo.travaglini@arm.com           panic("interface already connected to\n");
16612280Sgiacomo.travaglini@arm.com       return interface;
16712616Sgabeblack@google.com    }
16812280Sgiacomo.travaglini@arm.com    return NULL;
16912280Sgiacomo.travaglini@arm.com}
17012280Sgiacomo.travaglini@arm.com
17112280Sgiacomo.travaglini@arm.com/**
17212280Sgiacomo.travaglini@arm.com * This reads the device registers, which are detailed in the NS83820
17312280Sgiacomo.travaglini@arm.com * spec sheet
17412280Sgiacomo.travaglini@arm.com */
17512280Sgiacomo.travaglini@arm.comTick
17612280Sgiacomo.travaglini@arm.comNSGigE::read(PacketPtr pkt)
17712280Sgiacomo.travaglini@arm.com{
17812280Sgiacomo.travaglini@arm.com    assert(ioEnable);
17912280Sgiacomo.travaglini@arm.com
18012280Sgiacomo.travaglini@arm.com    pkt->allocate();
18112280Sgiacomo.travaglini@arm.com
182    //The mask is to give you only the offset into the device register file
183    Addr daddr = pkt->getAddr() & 0xfff;
184    DPRINTF(EthernetPIO, "read  da=%#x pa=%#x size=%d\n",
185            daddr, pkt->getAddr(), pkt->getSize());
186
187
188    // there are some reserved registers, you can see ns_gige_reg.h and
189    // the spec sheet for details
190    if (daddr > LAST && daddr <=  RESERVED) {
191        panic("Accessing reserved register");
192    } else if (daddr > RESERVED && daddr <= 0x3FC) {
193        return readConfig(pkt);
194    } else if (daddr >= MIB_START && daddr <= MIB_END) {
195        // don't implement all the MIB's.  hopefully the kernel
196        // doesn't actually DEPEND upon their values
197        // MIB are just hardware stats keepers
198        pkt->set<uint32_t>(0);
199        pkt->makeAtomicResponse();
200        return pioDelay;
201    } else if (daddr > 0x3FC)
202        panic("Something is messed up!\n");
203
204    assert(pkt->getSize() == sizeof(uint32_t));
205        uint32_t &reg = *pkt->getPtr<uint32_t>();
206        uint16_t rfaddr;
207
208        switch (daddr) {
209          case CR:
210            reg = regs.command;
211            //these are supposed to be cleared on a read
212            reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR);
213            break;
214
215          case CFGR:
216            reg = regs.config;
217            break;
218
219          case MEAR:
220            reg = regs.mear;
221            break;
222
223          case PTSCR:
224            reg = regs.ptscr;
225            break;
226
227          case ISR:
228            reg = regs.isr;
229            devIntrClear(ISR_ALL);
230            break;
231
232          case IMR:
233            reg = regs.imr;
234            break;
235
236          case IER:
237            reg = regs.ier;
238            break;
239
240          case IHR:
241            reg = regs.ihr;
242            break;
243
244          case TXDP:
245            reg = regs.txdp;
246            break;
247
248          case TXDP_HI:
249            reg = regs.txdp_hi;
250            break;
251
252          case TX_CFG:
253            reg = regs.txcfg;
254            break;
255
256          case GPIOR:
257            reg = regs.gpior;
258            break;
259
260          case RXDP:
261            reg = regs.rxdp;
262            break;
263
264          case RXDP_HI:
265            reg = regs.rxdp_hi;
266            break;
267
268          case RX_CFG:
269            reg = regs.rxcfg;
270            break;
271
272          case PQCR:
273            reg = regs.pqcr;
274            break;
275
276          case WCSR:
277            reg = regs.wcsr;
278            break;
279
280          case PCR:
281            reg = regs.pcr;
282            break;
283
284            // see the spec sheet for how RFCR and RFDR work
285            // basically, you write to RFCR to tell the machine
286            // what you want to do next, then you act upon RFDR,
287            // and the device will be prepared b/c of what you
288            // wrote to RFCR
289          case RFCR:
290            reg = regs.rfcr;
291            break;
292
293          case RFDR:
294            rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
295            switch (rfaddr) {
296              // Read from perfect match ROM octets
297              case 0x000:
298                reg = rom.perfectMatch[1];
299                reg = reg << 8;
300                reg += rom.perfectMatch[0];
301                break;
302              case 0x002:
303                reg = rom.perfectMatch[3] << 8;
304                reg += rom.perfectMatch[2];
305                break;
306              case 0x004:
307                reg = rom.perfectMatch[5] << 8;
308                reg += rom.perfectMatch[4];
309                break;
310              default:
311                // Read filter hash table
312                if (rfaddr >= FHASH_ADDR &&
313                    rfaddr < FHASH_ADDR + FHASH_SIZE) {
314
315                    // Only word-aligned reads supported
316                    if (rfaddr % 2)
317                        panic("unaligned read from filter hash table!");
318
319                    reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8;
320                    reg += rom.filterHash[rfaddr - FHASH_ADDR];
321                    break;
322                }
323
324                panic("reading RFDR for something other than pattern"
325                      " matching or hashing! %#x\n", rfaddr);
326            }
327            break;
328
329          case SRR:
330            reg = regs.srr;
331            break;
332
333          case MIBC:
334            reg = regs.mibc;
335            reg &= ~(MIBC_MIBS | MIBC_ACLR);
336            break;
337
338          case VRCR:
339            reg = regs.vrcr;
340            break;
341
342          case VTCR:
343            reg = regs.vtcr;
344            break;
345
346          case VDR:
347            reg = regs.vdr;
348            break;
349
350          case CCSR:
351            reg = regs.ccsr;
352            break;
353
354          case TBICR:
355            reg = regs.tbicr;
356            break;
357
358          case TBISR:
359            reg = regs.tbisr;
360            break;
361
362          case TANAR:
363            reg = regs.tanar;
364            break;
365
366          case TANLPAR:
367            reg = regs.tanlpar;
368            break;
369
370          case TANER:
371            reg = regs.taner;
372            break;
373
374          case TESR:
375            reg = regs.tesr;
376            break;
377
378          case M5REG:
379            reg = 0;
380            if (params()->rx_thread)
381                reg |= M5REG_RX_THREAD;
382            if (params()->tx_thread)
383                reg |= M5REG_TX_THREAD;
384            if (params()->rss)
385                reg |= M5REG_RSS;
386            break;
387
388          default:
389            panic("reading unimplemented register: addr=%#x", daddr);
390        }
391
392        DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
393                daddr, reg, reg);
394
395    pkt->makeAtomicResponse();
396    return pioDelay;
397}
398
399Tick
400NSGigE::write(PacketPtr pkt)
401{
402    assert(ioEnable);
403
404    Addr daddr = pkt->getAddr() & 0xfff;
405    DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n",
406            daddr, pkt->getAddr(), pkt->getSize());
407
408    if (daddr > LAST && daddr <=  RESERVED) {
409        panic("Accessing reserved register");
410    } else if (daddr > RESERVED && daddr <= 0x3FC) {
411        return writeConfig(pkt);
412    } else if (daddr > 0x3FC)
413        panic("Something is messed up!\n");
414
415    if (pkt->getSize() == sizeof(uint32_t)) {
416        uint32_t reg = pkt->get<uint32_t>();
417        uint16_t rfaddr;
418
419        DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg);
420
421        switch (daddr) {
422          case CR:
423            regs.command = reg;
424            if (reg & CR_TXD) {
425                txEnable = false;
426            } else if (reg & CR_TXE) {
427                txEnable = true;
428
429                // the kernel is enabling the transmit machine
430                if (txState == txIdle)
431                    txKick();
432            }
433
434            if (reg & CR_RXD) {
435                rxEnable = false;
436            } else if (reg & CR_RXE) {
437                rxEnable = true;
438
439                if (rxState == rxIdle)
440                    rxKick();
441            }
442
443            if (reg & CR_TXR)
444                txReset();
445
446            if (reg & CR_RXR)
447                rxReset();
448
449            if (reg & CR_SWI)
450                devIntrPost(ISR_SWI);
451
452            if (reg & CR_RST) {
453                txReset();
454                rxReset();
455
456                regsReset();
457            }
458            break;
459
460          case CFGR:
461            if (reg & CFGR_LNKSTS ||
462                reg & CFGR_SPDSTS ||
463                reg & CFGR_DUPSTS ||
464                reg & CFGR_RESERVED ||
465                reg & CFGR_T64ADDR ||
466                reg & CFGR_PCI64_DET)
467
468            // First clear all writable bits
469            regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
470                                   CFGR_RESERVED | CFGR_T64ADDR |
471                                   CFGR_PCI64_DET;
472            // Now set the appropriate writable bits
473            regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
474                                   CFGR_RESERVED | CFGR_T64ADDR |
475                                   CFGR_PCI64_DET);
476
477// all these #if 0's are because i don't THINK the kernel needs to
478// have these implemented. if there is a problem relating to one of
479// these, you may need to add functionality in.
480            if (reg & CFGR_TBI_EN) ;
481            if (reg & CFGR_MODE_1000) ;
482
483            if (reg & CFGR_AUTO_1000)
484                panic("CFGR_AUTO_1000 not implemented!\n");
485
486            if (reg & CFGR_PINT_DUPSTS ||
487                reg & CFGR_PINT_LNKSTS ||
488                reg & CFGR_PINT_SPDSTS)
489                ;
490
491            if (reg & CFGR_TMRTEST) ;
492            if (reg & CFGR_MRM_DIS) ;
493            if (reg & CFGR_MWI_DIS) ;
494
495            if (reg & CFGR_T64ADDR) ;
496            // panic("CFGR_T64ADDR is read only register!\n");
497
498            if (reg & CFGR_PCI64_DET)
499                panic("CFGR_PCI64_DET is read only register!\n");
500
501            if (reg & CFGR_DATA64_EN) ;
502            if (reg & CFGR_M64ADDR) ;
503            if (reg & CFGR_PHY_RST) ;
504            if (reg & CFGR_PHY_DIS) ;
505
506            if (reg & CFGR_EXTSTS_EN)
507                extstsEnable = true;
508            else
509                extstsEnable = false;
510
511            if (reg & CFGR_REQALG) ;
512            if (reg & CFGR_SB) ;
513            if (reg & CFGR_POW) ;
514            if (reg & CFGR_EXD) ;
515            if (reg & CFGR_PESEL) ;
516            if (reg & CFGR_BROM_DIS) ;
517            if (reg & CFGR_EXT_125) ;
518            if (reg & CFGR_BEM) ;
519            break;
520
521          case MEAR:
522            // Clear writable bits
523            regs.mear &= MEAR_EEDO;
524            // Set appropriate writable bits
525            regs.mear |= reg & ~MEAR_EEDO;
526
527            // FreeBSD uses the EEPROM to read PMATCH (for the MAC address)
528            // even though it could get it through RFDR
529            if (reg & MEAR_EESEL) {
530                // Rising edge of clock
531                if (reg & MEAR_EECLK && !eepromClk)
532                    eepromKick();
533            }
534            else {
535                eepromState = eepromStart;
536                regs.mear &= ~MEAR_EEDI;
537            }
538
539            eepromClk = reg & MEAR_EECLK;
540
541            // since phy is completely faked, MEAR_MD* don't matter
542            if (reg & MEAR_MDIO) ;
543            if (reg & MEAR_MDDIR) ;
544            if (reg & MEAR_MDC) ;
545            break;
546
547          case PTSCR:
548            regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY);
549            // these control BISTs for various parts of chip - we
550            // don't care or do just fake that the BIST is done
551            if (reg & PTSCR_RBIST_EN)
552                regs.ptscr |= PTSCR_RBIST_DONE;
553            if (reg & PTSCR_EEBIST_EN)
554                regs.ptscr &= ~PTSCR_EEBIST_EN;
555            if (reg & PTSCR_EELOAD_EN)
556                regs.ptscr &= ~PTSCR_EELOAD_EN;
557            break;
558
559          case ISR: /* writing to the ISR has no effect */
560            panic("ISR is a read only register!\n");
561
562          case IMR:
563            regs.imr = reg;
564            devIntrChangeMask();
565            break;
566
567          case IER:
568            regs.ier = reg;
569            break;
570
571          case IHR:
572            regs.ihr = reg;
573            /* not going to implement real interrupt holdoff */
574            break;
575
576          case TXDP:
577            regs.txdp = (reg & 0xFFFFFFFC);
578            assert(txState == txIdle);
579            CTDD = false;
580            break;
581
582          case TXDP_HI:
583            regs.txdp_hi = reg;
584            break;
585
586          case TX_CFG:
587            regs.txcfg = reg;
588#if 0
589            if (reg & TX_CFG_CSI) ;
590            if (reg & TX_CFG_HBI) ;
591            if (reg & TX_CFG_MLB) ;
592            if (reg & TX_CFG_ATP) ;
593            if (reg & TX_CFG_ECRETRY) {
594                /*
595                 * this could easily be implemented, but considering
596                 * the network is just a fake pipe, wouldn't make
597                 * sense to do this
598                 */
599            }
600
601            if (reg & TX_CFG_BRST_DIS) ;
602#endif
603
604#if 0
605            /* we handle our own DMA, ignore the kernel's exhortations */
606            if (reg & TX_CFG_MXDMA) ;
607#endif
608
609            // also, we currently don't care about fill/drain
610            // thresholds though this may change in the future with
611            // more realistic networks or a driver which changes it
612            // according to feedback
613
614            break;
615
616          case GPIOR:
617            // Only write writable bits
618            regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
619                        | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN;
620            regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
621                                | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN);
622            /* these just control general purpose i/o pins, don't matter */
623            break;
624
625          case RXDP:
626            regs.rxdp = reg;
627            CRDD = false;
628            break;
629
630          case RXDP_HI:
631            regs.rxdp_hi = reg;
632            break;
633
634          case RX_CFG:
635            regs.rxcfg = reg;
636#if 0
637            if (reg & RX_CFG_AEP) ;
638            if (reg & RX_CFG_ARP) ;
639            if (reg & RX_CFG_STRIPCRC) ;
640            if (reg & RX_CFG_RX_RD) ;
641            if (reg & RX_CFG_ALP) ;
642            if (reg & RX_CFG_AIRL) ;
643
644            /* we handle our own DMA, ignore what kernel says about it */
645            if (reg & RX_CFG_MXDMA) ;
646
647            //also, we currently don't care about fill/drain thresholds
648            //though this may change in the future with more realistic
649            //networks or a driver which changes it according to feedback
650            if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ;
651#endif
652            break;
653
654          case PQCR:
655            /* there is no priority queueing used in the linux 2.6 driver */
656            regs.pqcr = reg;
657            break;
658
659          case WCSR:
660            /* not going to implement wake on LAN */
661            regs.wcsr = reg;
662            break;
663
664          case PCR:
665            /* not going to implement pause control */
666            regs.pcr = reg;
667            break;
668
669          case RFCR:
670            regs.rfcr = reg;
671
672            rxFilterEnable = (reg & RFCR_RFEN) ? true : false;
673            acceptBroadcast = (reg & RFCR_AAB) ? true : false;
674            acceptMulticast = (reg & RFCR_AAM) ? true : false;
675            acceptUnicast = (reg & RFCR_AAU) ? true : false;
676            acceptPerfect = (reg & RFCR_APM) ? true : false;
677            acceptArp = (reg & RFCR_AARP) ? true : false;
678            multicastHashEnable = (reg & RFCR_MHEN) ? true : false;
679
680#if 0
681            if (reg & RFCR_APAT)
682                panic("RFCR_APAT not implemented!\n");
683#endif
684            if (reg & RFCR_UHEN)
685                panic("Unicast hash filtering not used by drivers!\n");
686
687            if (reg & RFCR_ULM)
688                panic("RFCR_ULM not implemented!\n");
689
690            break;
691
692          case RFDR:
693            rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
694            switch (rfaddr) {
695              case 0x000:
696                rom.perfectMatch[0] = (uint8_t)reg;
697                rom.perfectMatch[1] = (uint8_t)(reg >> 8);
698                break;
699              case 0x002:
700                rom.perfectMatch[2] = (uint8_t)reg;
701                rom.perfectMatch[3] = (uint8_t)(reg >> 8);
702                break;
703              case 0x004:
704                rom.perfectMatch[4] = (uint8_t)reg;
705                rom.perfectMatch[5] = (uint8_t)(reg >> 8);
706                break;
707              default:
708
709                if (rfaddr >= FHASH_ADDR &&
710                    rfaddr < FHASH_ADDR + FHASH_SIZE) {
711
712                    // Only word-aligned writes supported
713                    if (rfaddr % 2)
714                        panic("unaligned write to filter hash table!");
715
716                    rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg;
717                    rom.filterHash[rfaddr - FHASH_ADDR + 1]
718                        = (uint8_t)(reg >> 8);
719                    break;
720                }
721                panic("writing RFDR for something other than pattern matching\
722                    or hashing! %#x\n", rfaddr);
723            }
724
725          case BRAR:
726            regs.brar = reg;
727            break;
728
729          case BRDR:
730            panic("the driver never uses BRDR, something is wrong!\n");
731
732          case SRR:
733            panic("SRR is read only register!\n");
734
735          case MIBC:
736            panic("the driver never uses MIBC, something is wrong!\n");
737
738          case VRCR:
739            regs.vrcr = reg;
740            break;
741
742          case VTCR:
743            regs.vtcr = reg;
744            break;
745
746          case VDR:
747            panic("the driver never uses VDR, something is wrong!\n");
748
749          case CCSR:
750            /* not going to implement clockrun stuff */
751            regs.ccsr = reg;
752            break;
753
754          case TBICR:
755            regs.tbicr = reg;
756            if (reg & TBICR_MR_LOOPBACK)
757                panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
758
759            if (reg & TBICR_MR_AN_ENABLE) {
760                regs.tanlpar = regs.tanar;
761                regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS);
762            }
763
764#if 0
765            if (reg & TBICR_MR_RESTART_AN) ;
766#endif
767
768            break;
769
770          case TBISR:
771            panic("TBISR is read only register!\n");
772
773          case TANAR:
774            // Only write the writable bits
775            regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED;
776            regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED);
777
778            // Pause capability unimplemented
779#if 0
780            if (reg & TANAR_PS2) ;
781            if (reg & TANAR_PS1) ;
782#endif
783
784            break;
785
786          case TANLPAR:
787            panic("this should only be written to by the fake phy!\n");
788
789          case TANER:
790            panic("TANER is read only register!\n");
791
792          case TESR:
793            regs.tesr = reg;
794            break;
795
796          default:
797            panic("invalid register access daddr=%#x", daddr);
798        }
799    } else {
800        panic("Invalid Request Size");
801    }
802    pkt->makeAtomicResponse();
803    return pioDelay;
804}
805
806void
807NSGigE::devIntrPost(uint32_t interrupts)
808{
809    if (interrupts & ISR_RESERVE)
810        panic("Cannot set a reserved interrupt");
811
812    if (interrupts & ISR_NOIMPL)
813        warn("interrupt not implemented %#x\n", interrupts);
814
815    interrupts &= ISR_IMPL;
816    regs.isr |= interrupts;
817
818    if (interrupts & regs.imr) {
819        if (interrupts & ISR_SWI) {
820            totalSwi++;
821        }
822        if (interrupts & ISR_RXIDLE) {
823            totalRxIdle++;
824        }
825        if (interrupts & ISR_RXOK) {
826            totalRxOk++;
827        }
828        if (interrupts & ISR_RXDESC) {
829            totalRxDesc++;
830        }
831        if (interrupts & ISR_TXOK) {
832            totalTxOk++;
833        }
834        if (interrupts & ISR_TXIDLE) {
835            totalTxIdle++;
836        }
837        if (interrupts & ISR_TXDESC) {
838            totalTxDesc++;
839        }
840        if (interrupts & ISR_RXORN) {
841            totalRxOrn++;
842        }
843    }
844
845    DPRINTF(EthernetIntr,
846            "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
847            interrupts, regs.isr, regs.imr);
848
849    if ((regs.isr & regs.imr)) {
850        Tick when = curTick;
851        if ((regs.isr & regs.imr & ISR_NODELAY) == 0)
852            when += intrDelay;
853        postedInterrupts++;
854        cpuIntrPost(when);
855    }
856}
857
858/* writing this interrupt counting stats inside this means that this function
859   is now limited to being used to clear all interrupts upon the kernel
860   reading isr and servicing.  just telling you in case you were thinking
861   of expanding use.
862*/
863void
864NSGigE::devIntrClear(uint32_t interrupts)
865{
866    if (interrupts & ISR_RESERVE)
867        panic("Cannot clear a reserved interrupt");
868
869    if (regs.isr & regs.imr & ISR_SWI) {
870        postedSwi++;
871    }
872    if (regs.isr & regs.imr & ISR_RXIDLE) {
873        postedRxIdle++;
874    }
875    if (regs.isr & regs.imr & ISR_RXOK) {
876        postedRxOk++;
877    }
878    if (regs.isr & regs.imr & ISR_RXDESC) {
879            postedRxDesc++;
880    }
881    if (regs.isr & regs.imr & ISR_TXOK) {
882        postedTxOk++;
883    }
884    if (regs.isr & regs.imr & ISR_TXIDLE) {
885        postedTxIdle++;
886    }
887    if (regs.isr & regs.imr & ISR_TXDESC) {
888        postedTxDesc++;
889    }
890    if (regs.isr & regs.imr & ISR_RXORN) {
891        postedRxOrn++;
892    }
893
894    interrupts &= ~ISR_NOIMPL;
895    regs.isr &= ~interrupts;
896
897    DPRINTF(EthernetIntr,
898            "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",
899            interrupts, regs.isr, regs.imr);
900
901    if (!(regs.isr & regs.imr))
902        cpuIntrClear();
903}
904
905void
906NSGigE::devIntrChangeMask()
907{
908    DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n",
909            regs.isr, regs.imr, regs.isr & regs.imr);
910
911    if (regs.isr & regs.imr)
912        cpuIntrPost(curTick);
913    else
914        cpuIntrClear();
915}
916
917void
918NSGigE::cpuIntrPost(Tick when)
919{
920    // If the interrupt you want to post is later than an interrupt
921    // already scheduled, just let it post in the coming one and don't
922    // schedule another.
923    // HOWEVER, must be sure that the scheduled intrTick is in the
924    // future (this was formerly the source of a bug)
925    /**
926     * @todo this warning should be removed and the intrTick code should
927     * be fixed.
928     */
929    assert(when >= curTick);
930    assert(intrTick >= curTick || intrTick == 0);
931    if (when > intrTick && intrTick != 0) {
932        DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
933                intrTick);
934        return;
935    }
936
937    intrTick = when;
938    if (intrTick < curTick) {
939        debug_break();
940        intrTick = curTick;
941    }
942
943    DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
944            intrTick);
945
946    if (intrEvent)
947        intrEvent->squash();
948    intrEvent = new IntrEvent(this, intrTick, true);
949}
950
951void
952NSGigE::cpuInterrupt()
953{
954    assert(intrTick == curTick);
955
956    // Whether or not there's a pending interrupt, we don't care about
957    // it anymore
958    intrEvent = 0;
959    intrTick = 0;
960
961    // Don't send an interrupt if there's already one
962    if (cpuPendingIntr) {
963        DPRINTF(EthernetIntr,
964                "would send an interrupt now, but there's already pending\n");
965    } else {
966        // Send interrupt
967        cpuPendingIntr = true;
968
969        DPRINTF(EthernetIntr, "posting interrupt\n");
970        intrPost();
971    }
972}
973
974void
975NSGigE::cpuIntrClear()
976{
977    if (!cpuPendingIntr)
978        return;
979
980    if (intrEvent) {
981        intrEvent->squash();
982        intrEvent = 0;
983    }
984
985    intrTick = 0;
986
987    cpuPendingIntr = false;
988
989    DPRINTF(EthernetIntr, "clearing interrupt\n");
990    intrClear();
991}
992
993bool
994NSGigE::cpuIntrPending() const
995{ return cpuPendingIntr; }
996
997void
998NSGigE::txReset()
999{
1000
1001    DPRINTF(Ethernet, "transmit reset\n");
1002
1003    CTDD = false;
1004    txEnable = false;;
1005    txFragPtr = 0;
1006    assert(txDescCnt == 0);
1007    txFifo.clear();
1008    txState = txIdle;
1009    assert(txDmaState == dmaIdle);
1010}
1011
1012void
1013NSGigE::rxReset()
1014{
1015    DPRINTF(Ethernet, "receive reset\n");
1016
1017    CRDD = false;
1018    assert(rxPktBytes == 0);
1019    rxEnable = false;
1020    rxFragPtr = 0;
1021    assert(rxDescCnt == 0);
1022    assert(rxDmaState == dmaIdle);
1023    rxFifo.clear();
1024    rxState = rxIdle;
1025}
1026
1027void
1028NSGigE::regsReset()
1029{
1030    memset(&regs, 0, sizeof(regs));
1031    regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000);
1032    regs.mear = 0x12;
1033    regs.txcfg = 0x120; // set drain threshold to 1024 bytes and
1034                        // fill threshold to 32 bytes
1035    regs.rxcfg = 0x4;   // set drain threshold to 16 bytes
1036    regs.srr = 0x0103;  // set the silicon revision to rev B or 0x103
1037    regs.mibc = MIBC_FRZ;
1038    regs.vdr = 0x81;    // set the vlan tag type to 802.1q
1039    regs.tesr = 0xc000; // TBI capable of both full and half duplex
1040    regs.brar = 0xffffffff;
1041
1042    extstsEnable = false;
1043    acceptBroadcast = false;
1044    acceptMulticast = false;
1045    acceptUnicast = false;
1046    acceptPerfect = false;
1047    acceptArp = false;
1048}
1049
1050bool
1051NSGigE::doRxDmaRead()
1052{
1053    assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
1054    rxDmaState = dmaReading;
1055
1056    if (dmaPending() || getState() != Running)
1057        rxDmaState = dmaReadWaiting;
1058    else
1059        dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData);
1060
1061    return true;
1062}
1063
1064void
1065NSGigE::rxDmaReadDone()
1066{
1067    assert(rxDmaState == dmaReading);
1068    rxDmaState = dmaIdle;
1069
1070    DPRINTF(EthernetDMA, "rx dma read  paddr=%#x len=%d\n",
1071            rxDmaAddr, rxDmaLen);
1072    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1073
1074    // If the transmit state machine has a pending DMA, let it go first
1075    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1076        txKick();
1077
1078    rxKick();
1079}
1080
1081bool
1082NSGigE::doRxDmaWrite()
1083{
1084    assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
1085    rxDmaState = dmaWriting;
1086
1087    if (dmaPending() || getState() != Running)
1088        rxDmaState = dmaWriteWaiting;
1089    else
1090        dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData);
1091    return true;
1092}
1093
1094void
1095NSGigE::rxDmaWriteDone()
1096{
1097    assert(rxDmaState == dmaWriting);
1098    rxDmaState = dmaIdle;
1099
1100    DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
1101            rxDmaAddr, rxDmaLen);
1102    DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1103
1104    // If the transmit state machine has a pending DMA, let it go first
1105    if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1106        txKick();
1107
1108    rxKick();
1109}
1110
1111void
1112NSGigE::rxKick()
1113{
1114    bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
1115
1116    DPRINTF(EthernetSM,
1117            "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n",
1118            NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32);
1119
1120    Addr link, bufptr;
1121    uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts;
1122    uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts;
1123
1124  next:
1125    if (clock) {
1126        if (rxKickTick > curTick) {
1127            DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
1128                    rxKickTick);
1129
1130            goto exit;
1131        }
1132
1133        // Go to the next state machine clock tick.
1134        rxKickTick = curTick + ticks(1);
1135    }
1136
1137    switch(rxDmaState) {
1138      case dmaReadWaiting:
1139        if (doRxDmaRead())
1140            goto exit;
1141        break;
1142      case dmaWriteWaiting:
1143        if (doRxDmaWrite())
1144            goto exit;
1145        break;
1146      default:
1147        break;
1148    }
1149
1150    link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link;
1151    bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr;
1152
1153    // see state machine from spec for details
1154    // the way this works is, if you finish work on one state and can
1155    // go directly to another, you do that through jumping to the
1156    // label "next".  however, if you have intermediate work, like DMA
1157    // so that you can't go to the next state yet, you go to exit and
1158    // exit the loop.  however, when the DMA is done it will trigger
1159    // an event and come back to this loop.
1160    switch (rxState) {
1161      case rxIdle:
1162        if (!rxEnable) {
1163            DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");
1164            goto exit;
1165        }
1166
1167        if (CRDD) {
1168            rxState = rxDescRefr;
1169
1170            rxDmaAddr = regs.rxdp & 0x3fffffff;
1171            rxDmaData =
1172                is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link;
1173            rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link);
1174            rxDmaFree = dmaDescFree;
1175
1176            descDmaReads++;
1177            descDmaRdBytes += rxDmaLen;
1178
1179            if (doRxDmaRead())
1180                goto exit;
1181        } else {
1182            rxState = rxDescRead;
1183
1184            rxDmaAddr = regs.rxdp & 0x3fffffff;
1185            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
1186            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1187            rxDmaFree = dmaDescFree;
1188
1189            descDmaReads++;
1190            descDmaRdBytes += rxDmaLen;
1191
1192            if (doRxDmaRead())
1193                goto exit;
1194        }
1195        break;
1196
1197      case rxDescRefr:
1198        if (rxDmaState != dmaIdle)
1199            goto exit;
1200
1201        rxState = rxAdvance;
1202        break;
1203
1204     case rxDescRead:
1205        if (rxDmaState != dmaIdle)
1206            goto exit;
1207
1208        DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n",
1209                regs.rxdp & 0x3fffffff);
1210        DPRINTF(EthernetDesc,
1211                "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
1212                link, bufptr, cmdsts, extsts);
1213
1214        if (cmdsts & CMDSTS_OWN) {
1215            devIntrPost(ISR_RXIDLE);
1216            rxState = rxIdle;
1217            goto exit;
1218        } else {
1219            rxState = rxFifoBlock;
1220            rxFragPtr = bufptr;
1221            rxDescCnt = cmdsts & CMDSTS_LEN_MASK;
1222        }
1223        break;
1224
1225      case rxFifoBlock:
1226        if (!rxPacket) {
1227            /**
1228             * @todo in reality, we should be able to start processing
1229             * the packet as it arrives, and not have to wait for the
1230             * full packet ot be in the receive fifo.
1231             */
1232            if (rxFifo.empty())
1233                goto exit;
1234
1235            DPRINTF(EthernetSM, "****processing receive of new packet****\n");
1236
1237            // If we don't have a packet, grab a new one from the fifo.
1238            rxPacket = rxFifo.front();
1239            rxPktBytes = rxPacket->length;
1240            rxPacketBufPtr = rxPacket->data;
1241
1242#if TRACING_ON
1243            if (DTRACE(Ethernet)) {
1244                IpPtr ip(rxPacket);
1245                if (ip) {
1246                    DPRINTF(Ethernet, "ID is %d\n", ip->id());
1247                    TcpPtr tcp(ip);
1248                    if (tcp) {
1249                        DPRINTF(Ethernet,
1250                                "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1251                                tcp->sport(), tcp->dport(), tcp->seq(),
1252                                tcp->ack());
1253                    }
1254                }
1255            }
1256#endif
1257
1258            // sanity check - i think the driver behaves like this
1259            assert(rxDescCnt >= rxPktBytes);
1260            rxFifo.pop();
1261        }
1262
1263
1264        // dont' need the && rxDescCnt > 0 if driver sanity check
1265        // above holds
1266        if (rxPktBytes > 0) {
1267            rxState = rxFragWrite;
1268            // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
1269            // check holds
1270            rxXferLen = rxPktBytes;
1271
1272            rxDmaAddr = rxFragPtr & 0x3fffffff;
1273            rxDmaData = rxPacketBufPtr;
1274            rxDmaLen = rxXferLen;
1275            rxDmaFree = dmaDataFree;
1276
1277            if (doRxDmaWrite())
1278                goto exit;
1279
1280        } else {
1281            rxState = rxDescWrite;
1282
1283            //if (rxPktBytes == 0) {  /* packet is done */
1284            assert(rxPktBytes == 0);
1285            DPRINTF(EthernetSM, "done with receiving packet\n");
1286
1287            cmdsts |= CMDSTS_OWN;
1288            cmdsts &= ~CMDSTS_MORE;
1289            cmdsts |= CMDSTS_OK;
1290            cmdsts &= 0xffff0000;
1291            cmdsts += rxPacket->length;   //i.e. set CMDSTS_SIZE
1292
1293#if 0
1294            /*
1295             * all the driver uses these are for its own stats keeping
1296             * which we don't care about, aren't necessary for
1297             * functionality and doing this would just slow us down.
1298             * if they end up using this in a later version for
1299             * functional purposes, just undef
1300             */
1301            if (rxFilterEnable) {
1302                cmdsts &= ~CMDSTS_DEST_MASK;
1303                const EthAddr &dst = rxFifoFront()->dst();
1304                if (dst->unicast())
1305                    cmdsts |= CMDSTS_DEST_SELF;
1306                if (dst->multicast())
1307                    cmdsts |= CMDSTS_DEST_MULTI;
1308                if (dst->broadcast())
1309                    cmdsts |= CMDSTS_DEST_MASK;
1310            }
1311#endif
1312
1313            IpPtr ip(rxPacket);
1314            if (extstsEnable && ip) {
1315                extsts |= EXTSTS_IPPKT;
1316                rxIpChecksums++;
1317                if (cksum(ip) != 0) {
1318                    DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
1319                    extsts |= EXTSTS_IPERR;
1320                }
1321                TcpPtr tcp(ip);
1322                UdpPtr udp(ip);
1323                if (tcp) {
1324                    extsts |= EXTSTS_TCPPKT;
1325                    rxTcpChecksums++;
1326                    if (cksum(tcp) != 0) {
1327                        DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
1328                        extsts |= EXTSTS_TCPERR;
1329
1330                    }
1331                } else if (udp) {
1332                    extsts |= EXTSTS_UDPPKT;
1333                    rxUdpChecksums++;
1334                    if (cksum(udp) != 0) {
1335                        DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
1336                        extsts |= EXTSTS_UDPERR;
1337                    }
1338                }
1339            }
1340            rxPacket = 0;
1341
1342            /*
1343             * the driver seems to always receive into desc buffers
1344             * of size 1514, so you never have a pkt that is split
1345             * into multiple descriptors on the receive side, so
1346             * i don't implement that case, hence the assert above.
1347             */
1348
1349            DPRINTF(EthernetDesc,
1350                    "rxDesc: addr=%08x writeback cmdsts extsts\n",
1351                    regs.rxdp & 0x3fffffff);
1352            DPRINTF(EthernetDesc,
1353                    "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
1354                    link, bufptr, cmdsts, extsts);
1355
1356            rxDmaAddr = regs.rxdp & 0x3fffffff;
1357            rxDmaData = &cmdsts;
1358            if (is64bit) {
1359                rxDmaAddr += offsetof(ns_desc64, cmdsts);
1360                rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts);
1361            } else {
1362                rxDmaAddr += offsetof(ns_desc32, cmdsts);
1363                rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts);
1364            }
1365            rxDmaFree = dmaDescFree;
1366
1367            descDmaWrites++;
1368            descDmaWrBytes += rxDmaLen;
1369
1370            if (doRxDmaWrite())
1371                goto exit;
1372        }
1373        break;
1374
1375      case rxFragWrite:
1376        if (rxDmaState != dmaIdle)
1377            goto exit;
1378
1379        rxPacketBufPtr += rxXferLen;
1380        rxFragPtr += rxXferLen;
1381        rxPktBytes -= rxXferLen;
1382
1383        rxState = rxFifoBlock;
1384        break;
1385
1386      case rxDescWrite:
1387        if (rxDmaState != dmaIdle)
1388            goto exit;
1389
1390        assert(cmdsts & CMDSTS_OWN);
1391
1392        assert(rxPacket == 0);
1393        devIntrPost(ISR_RXOK);
1394
1395        if (cmdsts & CMDSTS_INTR)
1396            devIntrPost(ISR_RXDESC);
1397
1398        if (!rxEnable) {
1399            DPRINTF(EthernetSM, "Halting the RX state machine\n");
1400            rxState = rxIdle;
1401            goto exit;
1402        } else
1403            rxState = rxAdvance;
1404        break;
1405
1406      case rxAdvance:
1407        if (link == 0) {
1408            devIntrPost(ISR_RXIDLE);
1409            rxState = rxIdle;
1410            CRDD = true;
1411            goto exit;
1412        } else {
1413            if (rxDmaState != dmaIdle)
1414                goto exit;
1415            rxState = rxDescRead;
1416            regs.rxdp = link;
1417            CRDD = false;
1418
1419            rxDmaAddr = regs.rxdp & 0x3fffffff;
1420            rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
1421            rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1422            rxDmaFree = dmaDescFree;
1423
1424            if (doRxDmaRead())
1425                goto exit;
1426        }
1427        break;
1428
1429      default:
1430        panic("Invalid rxState!");
1431    }
1432
1433    DPRINTF(EthernetSM, "entering next rxState=%s\n",
1434            NsRxStateStrings[rxState]);
1435    goto next;
1436
1437  exit:
1438    /**
1439     * @todo do we want to schedule a future kick?
1440     */
1441    DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
1442            NsRxStateStrings[rxState]);
1443
1444    if (clock && !rxKickEvent.scheduled())
1445        rxKickEvent.schedule(rxKickTick);
1446}
1447
1448void
1449NSGigE::transmit()
1450{
1451    if (txFifo.empty()) {
1452        DPRINTF(Ethernet, "nothing to transmit\n");
1453        return;
1454    }
1455
1456    DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",
1457            txFifo.size());
1458    if (interface->sendPacket(txFifo.front())) {
1459#if TRACING_ON
1460        if (DTRACE(Ethernet)) {
1461            IpPtr ip(txFifo.front());
1462            if (ip) {
1463                DPRINTF(Ethernet, "ID is %d\n", ip->id());
1464                TcpPtr tcp(ip);
1465                if (tcp) {
1466                    DPRINTF(Ethernet,
1467                            "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1468                            tcp->sport(), tcp->dport(), tcp->seq(),
1469                            tcp->ack());
1470                }
1471            }
1472        }
1473#endif
1474
1475        DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length);
1476        txBytes += txFifo.front()->length;
1477        txPackets++;
1478
1479        DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
1480                txFifo.avail());
1481        txFifo.pop();
1482
1483        /*
1484         * normally do a writeback of the descriptor here, and ONLY
1485         * after that is done, send this interrupt.  but since our
1486         * stuff never actually fails, just do this interrupt here,
1487         * otherwise the code has to stray from this nice format.
1488         * besides, it's functionally the same.
1489         */
1490        devIntrPost(ISR_TXOK);
1491    }
1492
1493   if (!txFifo.empty() && !txEvent.scheduled()) {
1494       DPRINTF(Ethernet, "reschedule transmit\n");
1495       txEvent.schedule(curTick + retryTime);
1496   }
1497}
1498
1499bool
1500NSGigE::doTxDmaRead()
1501{
1502    assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
1503    txDmaState = dmaReading;
1504
1505    if (dmaPending() || getState() != Running)
1506        txDmaState = dmaReadWaiting;
1507    else
1508        dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData);
1509
1510    return true;
1511}
1512
1513void
1514NSGigE::txDmaReadDone()
1515{
1516    assert(txDmaState == dmaReading);
1517    txDmaState = dmaIdle;
1518
1519    DPRINTF(EthernetDMA, "tx dma read  paddr=%#x len=%d\n",
1520            txDmaAddr, txDmaLen);
1521    DDUMP(EthernetDMA, txDmaData, txDmaLen);
1522
1523    // If the receive state machine  has a pending DMA, let it go first
1524    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1525        rxKick();
1526
1527    txKick();
1528}
1529
1530bool
1531NSGigE::doTxDmaWrite()
1532{
1533    assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
1534    txDmaState = dmaWriting;
1535
1536    if (dmaPending() || getState() != Running)
1537        txDmaState = dmaWriteWaiting;
1538    else
1539        dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData);
1540    return true;
1541}
1542
1543void
1544NSGigE::txDmaWriteDone()
1545{
1546    assert(txDmaState == dmaWriting);
1547    txDmaState = dmaIdle;
1548
1549    DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n",
1550            txDmaAddr, txDmaLen);
1551    DDUMP(EthernetDMA, txDmaData, txDmaLen);
1552
1553    // If the receive state machine  has a pending DMA, let it go first
1554    if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1555        rxKick();
1556
1557    txKick();
1558}
1559
1560void
1561NSGigE::txKick()
1562{
1563    bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
1564
1565    DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n",
1566            NsTxStateStrings[txState], is64bit ? 64 : 32);
1567
1568    Addr link, bufptr;
1569    uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts;
1570    uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts;
1571
1572  next:
1573    if (clock) {
1574        if (txKickTick > curTick) {
1575            DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
1576                    txKickTick);
1577            goto exit;
1578        }
1579
1580        // Go to the next state machine clock tick.
1581        txKickTick = curTick + ticks(1);
1582    }
1583
1584    switch(txDmaState) {
1585      case dmaReadWaiting:
1586        if (doTxDmaRead())
1587            goto exit;
1588        break;
1589      case dmaWriteWaiting:
1590        if (doTxDmaWrite())
1591            goto exit;
1592        break;
1593      default:
1594        break;
1595    }
1596
1597    link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link;
1598    bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr;
1599    switch (txState) {
1600      case txIdle:
1601        if (!txEnable) {
1602            DPRINTF(EthernetSM, "Transmit disabled.  Nothing to do.\n");
1603            goto exit;
1604        }
1605
1606        if (CTDD) {
1607            txState = txDescRefr;
1608
1609            txDmaAddr = regs.txdp & 0x3fffffff;
1610            txDmaData =
1611                is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link;
1612            txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link);
1613            txDmaFree = dmaDescFree;
1614
1615            descDmaReads++;
1616            descDmaRdBytes += txDmaLen;
1617
1618            if (doTxDmaRead())
1619                goto exit;
1620
1621        } else {
1622            txState = txDescRead;
1623
1624            txDmaAddr = regs.txdp & 0x3fffffff;
1625            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
1626            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
1627            txDmaFree = dmaDescFree;
1628
1629            descDmaReads++;
1630            descDmaRdBytes += txDmaLen;
1631
1632            if (doTxDmaRead())
1633                goto exit;
1634        }
1635        break;
1636
1637      case txDescRefr:
1638        if (txDmaState != dmaIdle)
1639            goto exit;
1640
1641        txState = txAdvance;
1642        break;
1643
1644      case txDescRead:
1645        if (txDmaState != dmaIdle)
1646            goto exit;
1647
1648        DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n",
1649                regs.txdp & 0x3fffffff);
1650        DPRINTF(EthernetDesc,
1651                "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n",
1652                link, bufptr, cmdsts, extsts);
1653
1654        if (cmdsts & CMDSTS_OWN) {
1655            txState = txFifoBlock;
1656            txFragPtr = bufptr;
1657            txDescCnt = cmdsts & CMDSTS_LEN_MASK;
1658        } else {
1659            devIntrPost(ISR_TXIDLE);
1660            txState = txIdle;
1661            goto exit;
1662        }
1663        break;
1664
1665      case txFifoBlock:
1666        if (!txPacket) {
1667            DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
1668            txPacket = new EthPacketData(16384);
1669            txPacketBufPtr = txPacket->data;
1670        }
1671
1672        if (txDescCnt == 0) {
1673            DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");
1674            if (cmdsts & CMDSTS_MORE) {
1675                DPRINTF(EthernetSM, "there are more descriptors to come\n");
1676                txState = txDescWrite;
1677
1678                cmdsts &= ~CMDSTS_OWN;
1679
1680                txDmaAddr = regs.txdp & 0x3fffffff;
1681                txDmaData = &cmdsts;
1682                if (is64bit) {
1683                    txDmaAddr += offsetof(ns_desc64, cmdsts);
1684                    txDmaLen = sizeof(txDesc64.cmdsts);
1685                } else {
1686                    txDmaAddr += offsetof(ns_desc32, cmdsts);
1687                    txDmaLen = sizeof(txDesc32.cmdsts);
1688                }
1689                txDmaFree = dmaDescFree;
1690
1691                if (doTxDmaWrite())
1692                    goto exit;
1693
1694            } else { /* this packet is totally done */
1695                DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
1696                /* deal with the the packet that just finished */
1697                if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
1698                    IpPtr ip(txPacket);
1699                    if (extsts & EXTSTS_UDPPKT) {
1700                        UdpPtr udp(ip);
1701                        if (udp) {
1702                            udp->sum(0);
1703                            udp->sum(cksum(udp));
1704                            txUdpChecksums++;
1705                        } else {
1706                            debug_break();
1707                            warn_once("UDPPKT set, but not UDP!\n");
1708                        }
1709                    } else if (extsts & EXTSTS_TCPPKT) {
1710                        TcpPtr tcp(ip);
1711                        if (tcp) {
1712                            tcp->sum(0);
1713                            tcp->sum(cksum(tcp));
1714                            txTcpChecksums++;
1715                        } else {
1716                            debug_break();
1717                            warn_once("TCPPKT set, but not UDP!\n");
1718                        }
1719                    }
1720                    if (extsts & EXTSTS_IPPKT) {
1721                        if (ip) {
1722                            ip->sum(0);
1723                            ip->sum(cksum(ip));
1724                            txIpChecksums++;
1725                        } else {
1726                            debug_break();
1727                            warn_once("IPPKT set, but not UDP!\n");
1728                        }
1729                    }
1730                }
1731
1732                txPacket->length = txPacketBufPtr - txPacket->data;
1733                // this is just because the receive can't handle a
1734                // packet bigger want to make sure
1735                if (txPacket->length > 1514)
1736                    panic("transmit packet too large, %s > 1514\n",
1737                          txPacket->length);
1738
1739#ifndef NDEBUG
1740                bool success =
1741#endif
1742                    txFifo.push(txPacket);
1743                assert(success);
1744
1745                /*
1746                 * this following section is not tqo spec, but
1747                 * functionally shouldn't be any different.  normally,
1748                 * the chip will wait til the transmit has occurred
1749                 * before writing back the descriptor because it has
1750                 * to wait to see that it was successfully transmitted
1751                 * to decide whether to set CMDSTS_OK or not.
1752                 * however, in the simulator since it is always
1753                 * successfully transmitted, and writing it exactly to
1754                 * spec would complicate the code, we just do it here
1755                 */
1756
1757                cmdsts &= ~CMDSTS_OWN;
1758                cmdsts |= CMDSTS_OK;
1759
1760                DPRINTF(EthernetDesc,
1761                        "txDesc writeback: cmdsts=%08x extsts=%08x\n",
1762                        cmdsts, extsts);
1763
1764                txDmaFree = dmaDescFree;
1765                txDmaAddr = regs.txdp & 0x3fffffff;
1766                txDmaData = &cmdsts;
1767                if (is64bit) {
1768                    txDmaAddr += offsetof(ns_desc64, cmdsts);
1769                    txDmaLen =
1770                        sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts);
1771                } else {
1772                    txDmaAddr += offsetof(ns_desc32, cmdsts);
1773                    txDmaLen =
1774                        sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts);
1775                }
1776
1777                descDmaWrites++;
1778                descDmaWrBytes += txDmaLen;
1779
1780                transmit();
1781                txPacket = 0;
1782
1783                if (!txEnable) {
1784                    DPRINTF(EthernetSM, "halting TX state machine\n");
1785                    txState = txIdle;
1786                    goto exit;
1787                } else
1788                    txState = txAdvance;
1789
1790                if (doTxDmaWrite())
1791                    goto exit;
1792            }
1793        } else {
1794            DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
1795            if (!txFifo.full()) {
1796                txState = txFragRead;
1797
1798                /*
1799                 * The number of bytes transferred is either whatever
1800                 * is left in the descriptor (txDescCnt), or if there
1801                 * is not enough room in the fifo, just whatever room
1802                 * is left in the fifo
1803                 */
1804                txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());
1805
1806                txDmaAddr = txFragPtr & 0x3fffffff;
1807                txDmaData = txPacketBufPtr;
1808                txDmaLen = txXferLen;
1809                txDmaFree = dmaDataFree;
1810
1811                if (doTxDmaRead())
1812                    goto exit;
1813            } else {
1814                txState = txFifoBlock;
1815                transmit();
1816
1817                goto exit;
1818            }
1819
1820        }
1821        break;
1822
1823      case txFragRead:
1824        if (txDmaState != dmaIdle)
1825            goto exit;
1826
1827        txPacketBufPtr += txXferLen;
1828        txFragPtr += txXferLen;
1829        txDescCnt -= txXferLen;
1830        txFifo.reserve(txXferLen);
1831
1832        txState = txFifoBlock;
1833        break;
1834
1835      case txDescWrite:
1836        if (txDmaState != dmaIdle)
1837            goto exit;
1838
1839        if (cmdsts & CMDSTS_INTR)
1840            devIntrPost(ISR_TXDESC);
1841
1842        if (!txEnable) {
1843            DPRINTF(EthernetSM, "halting TX state machine\n");
1844            txState = txIdle;
1845            goto exit;
1846        } else
1847            txState = txAdvance;
1848        break;
1849
1850      case txAdvance:
1851        if (link == 0) {
1852            devIntrPost(ISR_TXIDLE);
1853            txState = txIdle;
1854            goto exit;
1855        } else {
1856            if (txDmaState != dmaIdle)
1857                goto exit;
1858            txState = txDescRead;
1859            regs.txdp = link;
1860            CTDD = false;
1861
1862            txDmaAddr = link & 0x3fffffff;
1863            txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
1864            txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
1865            txDmaFree = dmaDescFree;
1866
1867            if (doTxDmaRead())
1868                goto exit;
1869        }
1870        break;
1871
1872      default:
1873        panic("invalid state");
1874    }
1875
1876    DPRINTF(EthernetSM, "entering next txState=%s\n",
1877            NsTxStateStrings[txState]);
1878    goto next;
1879
1880  exit:
1881    /**
1882     * @todo do we want to schedule a future kick?
1883     */
1884    DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
1885            NsTxStateStrings[txState]);
1886
1887    if (clock && !txKickEvent.scheduled())
1888        txKickEvent.schedule(txKickTick);
1889}
1890
1891/**
1892 * Advance the EEPROM state machine
1893 * Called on rising edge of EEPROM clock bit in MEAR
1894 */
1895void
1896NSGigE::eepromKick()
1897{
1898    switch (eepromState) {
1899
1900      case eepromStart:
1901
1902        // Wait for start bit
1903        if (regs.mear & MEAR_EEDI) {
1904            // Set up to get 2 opcode bits
1905            eepromState = eepromGetOpcode;
1906            eepromBitsToRx = 2;
1907            eepromOpcode = 0;
1908        }
1909        break;
1910
1911      case eepromGetOpcode:
1912        eepromOpcode <<= 1;
1913        eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0;
1914        --eepromBitsToRx;
1915
1916        // Done getting opcode
1917        if (eepromBitsToRx == 0) {
1918            if (eepromOpcode != EEPROM_READ)
1919                panic("only EEPROM reads are implemented!");
1920
1921            // Set up to get address
1922            eepromState = eepromGetAddress;
1923            eepromBitsToRx = 6;
1924            eepromAddress = 0;
1925        }
1926        break;
1927
1928      case eepromGetAddress:
1929        eepromAddress <<= 1;
1930        eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0;
1931        --eepromBitsToRx;
1932
1933        // Done getting address
1934        if (eepromBitsToRx == 0) {
1935
1936            if (eepromAddress >= EEPROM_SIZE)
1937                panic("EEPROM read access out of range!");
1938
1939            switch (eepromAddress) {
1940
1941              case EEPROM_PMATCH2_ADDR:
1942                eepromData = rom.perfectMatch[5];
1943                eepromData <<= 8;
1944                eepromData += rom.perfectMatch[4];
1945                break;
1946
1947              case EEPROM_PMATCH1_ADDR:
1948                eepromData = rom.perfectMatch[3];
1949                eepromData <<= 8;
1950                eepromData += rom.perfectMatch[2];
1951                break;
1952
1953              case EEPROM_PMATCH0_ADDR:
1954                eepromData = rom.perfectMatch[1];
1955                eepromData <<= 8;
1956                eepromData += rom.perfectMatch[0];
1957                break;
1958
1959              default:
1960                panic("FreeBSD driver only uses EEPROM to read PMATCH!");
1961            }
1962            // Set up to read data
1963            eepromState = eepromRead;
1964            eepromBitsToRx = 16;
1965
1966            // Clear data in bit
1967            regs.mear &= ~MEAR_EEDI;
1968        }
1969        break;
1970
1971      case eepromRead:
1972        // Clear Data Out bit
1973        regs.mear &= ~MEAR_EEDO;
1974        // Set bit to value of current EEPROM bit
1975        regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0;
1976
1977        eepromData <<= 1;
1978        --eepromBitsToRx;
1979
1980        // All done
1981        if (eepromBitsToRx == 0) {
1982            eepromState = eepromStart;
1983        }
1984        break;
1985
1986      default:
1987        panic("invalid EEPROM state");
1988    }
1989
1990}
1991
1992void
1993NSGigE::transferDone()
1994{
1995    if (txFifo.empty()) {
1996        DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
1997        return;
1998    }
1999
2000    DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
2001
2002    txEvent.reschedule(curTick + ticks(1), true);
2003}
2004
2005bool
2006NSGigE::rxFilter(const EthPacketPtr &packet)
2007{
2008    EthPtr eth = packet;
2009    bool drop = true;
2010    string type;
2011
2012    const EthAddr &dst = eth->dst();
2013    if (dst.unicast()) {
2014        // If we're accepting all unicast addresses
2015        if (acceptUnicast)
2016            drop = false;
2017
2018        // If we make a perfect match
2019        if (acceptPerfect && dst == rom.perfectMatch)
2020            drop = false;
2021
2022        if (acceptArp && eth->type() == ETH_TYPE_ARP)
2023            drop = false;
2024
2025    } else if (dst.broadcast()) {
2026        // if we're accepting broadcasts
2027        if (acceptBroadcast)
2028            drop = false;
2029
2030    } else if (dst.multicast()) {
2031        // if we're accepting all multicasts
2032        if (acceptMulticast)
2033            drop = false;
2034
2035        // Multicast hashing faked - all packets accepted
2036        if (multicastHashEnable)
2037            drop = false;
2038    }
2039
2040    if (drop) {
2041        DPRINTF(Ethernet, "rxFilter drop\n");
2042        DDUMP(EthernetData, packet->data, packet->length);
2043    }
2044
2045    return drop;
2046}
2047
2048bool
2049NSGigE::recvPacket(EthPacketPtr packet)
2050{
2051    rxBytes += packet->length;
2052    rxPackets++;
2053
2054    DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n",
2055            rxFifo.avail());
2056
2057    if (!rxEnable) {
2058        DPRINTF(Ethernet, "receive disabled...packet dropped\n");
2059        return true;
2060    }
2061
2062    if (!rxFilterEnable) {
2063        DPRINTF(Ethernet,
2064            "receive packet filtering disabled . . . packet dropped\n");
2065        return true;
2066    }
2067
2068    if (rxFilter(packet)) {
2069        DPRINTF(Ethernet, "packet filtered...dropped\n");
2070        return true;
2071    }
2072
2073    if (rxFifo.avail() < packet->length) {
2074#if TRACING_ON
2075        IpPtr ip(packet);
2076        TcpPtr tcp(ip);
2077        if (ip) {
2078            DPRINTF(Ethernet,
2079                    "packet won't fit in receive buffer...pkt ID %d dropped\n",
2080                    ip->id());
2081            if (tcp) {
2082                DPRINTF(Ethernet, "Seq=%d\n", tcp->seq());
2083            }
2084        }
2085#endif
2086        droppedPackets++;
2087        devIntrPost(ISR_RXORN);
2088        return false;
2089    }
2090
2091    rxFifo.push(packet);
2092
2093    rxKick();
2094    return true;
2095}
2096
2097
2098void
2099NSGigE::resume()
2100{
2101    SimObject::resume();
2102
2103    // During drain we could have left the state machines in a waiting state and
2104    // they wouldn't get out until some other event occured to kick them.
2105    // This way they'll get out immediately
2106    txKick();
2107    rxKick();
2108}
2109
2110
2111//=====================================================================
2112//
2113//
2114void
2115NSGigE::serialize(ostream &os)
2116{
2117    // Serialize the PciDev base class
2118    PciDev::serialize(os);
2119
2120    /*
2121     * Finalize any DMA events now.
2122     */
2123    // @todo will mem system save pending dma?
2124
2125    /*
2126     * Serialize the device registers
2127     */
2128    SERIALIZE_SCALAR(regs.command);
2129    SERIALIZE_SCALAR(regs.config);
2130    SERIALIZE_SCALAR(regs.mear);
2131    SERIALIZE_SCALAR(regs.ptscr);
2132    SERIALIZE_SCALAR(regs.isr);
2133    SERIALIZE_SCALAR(regs.imr);
2134    SERIALIZE_SCALAR(regs.ier);
2135    SERIALIZE_SCALAR(regs.ihr);
2136    SERIALIZE_SCALAR(regs.txdp);
2137    SERIALIZE_SCALAR(regs.txdp_hi);
2138    SERIALIZE_SCALAR(regs.txcfg);
2139    SERIALIZE_SCALAR(regs.gpior);
2140    SERIALIZE_SCALAR(regs.rxdp);
2141    SERIALIZE_SCALAR(regs.rxdp_hi);
2142    SERIALIZE_SCALAR(regs.rxcfg);
2143    SERIALIZE_SCALAR(regs.pqcr);
2144    SERIALIZE_SCALAR(regs.wcsr);
2145    SERIALIZE_SCALAR(regs.pcr);
2146    SERIALIZE_SCALAR(regs.rfcr);
2147    SERIALIZE_SCALAR(regs.rfdr);
2148    SERIALIZE_SCALAR(regs.brar);
2149    SERIALIZE_SCALAR(regs.brdr);
2150    SERIALIZE_SCALAR(regs.srr);
2151    SERIALIZE_SCALAR(regs.mibc);
2152    SERIALIZE_SCALAR(regs.vrcr);
2153    SERIALIZE_SCALAR(regs.vtcr);
2154    SERIALIZE_SCALAR(regs.vdr);
2155    SERIALIZE_SCALAR(regs.ccsr);
2156    SERIALIZE_SCALAR(regs.tbicr);
2157    SERIALIZE_SCALAR(regs.tbisr);
2158    SERIALIZE_SCALAR(regs.tanar);
2159    SERIALIZE_SCALAR(regs.tanlpar);
2160    SERIALIZE_SCALAR(regs.taner);
2161    SERIALIZE_SCALAR(regs.tesr);
2162
2163    SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
2164    SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2165
2166    SERIALIZE_SCALAR(ioEnable);
2167
2168    /*
2169     * Serialize the data Fifos
2170     */
2171    rxFifo.serialize("rxFifo", os);
2172    txFifo.serialize("txFifo", os);
2173
2174    /*
2175     * Serialize the various helper variables
2176     */
2177    bool txPacketExists = txPacket;
2178    SERIALIZE_SCALAR(txPacketExists);
2179    if (txPacketExists) {
2180        txPacket->length = txPacketBufPtr - txPacket->data;
2181        txPacket->serialize("txPacket", os);
2182        uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
2183        SERIALIZE_SCALAR(txPktBufPtr);
2184    }
2185
2186    bool rxPacketExists = rxPacket;
2187    SERIALIZE_SCALAR(rxPacketExists);
2188    if (rxPacketExists) {
2189        rxPacket->serialize("rxPacket", os);
2190        uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
2191        SERIALIZE_SCALAR(rxPktBufPtr);
2192    }
2193
2194    SERIALIZE_SCALAR(txXferLen);
2195    SERIALIZE_SCALAR(rxXferLen);
2196
2197    /*
2198     * Serialize Cached Descriptors
2199     */
2200    SERIALIZE_SCALAR(rxDesc64.link);
2201    SERIALIZE_SCALAR(rxDesc64.bufptr);
2202    SERIALIZE_SCALAR(rxDesc64.cmdsts);
2203    SERIALIZE_SCALAR(rxDesc64.extsts);
2204    SERIALIZE_SCALAR(txDesc64.link);
2205    SERIALIZE_SCALAR(txDesc64.bufptr);
2206    SERIALIZE_SCALAR(txDesc64.cmdsts);
2207    SERIALIZE_SCALAR(txDesc64.extsts);
2208    SERIALIZE_SCALAR(rxDesc32.link);
2209    SERIALIZE_SCALAR(rxDesc32.bufptr);
2210    SERIALIZE_SCALAR(rxDesc32.cmdsts);
2211    SERIALIZE_SCALAR(rxDesc32.extsts);
2212    SERIALIZE_SCALAR(txDesc32.link);
2213    SERIALIZE_SCALAR(txDesc32.bufptr);
2214    SERIALIZE_SCALAR(txDesc32.cmdsts);
2215    SERIALIZE_SCALAR(txDesc32.extsts);
2216    SERIALIZE_SCALAR(extstsEnable);
2217
2218    /*
2219     * Serialize tx state machine
2220     */
2221    int txState = this->txState;
2222    SERIALIZE_SCALAR(txState);
2223    SERIALIZE_SCALAR(txEnable);
2224    SERIALIZE_SCALAR(CTDD);
2225    SERIALIZE_SCALAR(txFragPtr);
2226    SERIALIZE_SCALAR(txDescCnt);
2227    int txDmaState = this->txDmaState;
2228    SERIALIZE_SCALAR(txDmaState);
2229    SERIALIZE_SCALAR(txKickTick);
2230
2231    /*
2232     * Serialize rx state machine
2233     */
2234    int rxState = this->rxState;
2235    SERIALIZE_SCALAR(rxState);
2236    SERIALIZE_SCALAR(rxEnable);
2237    SERIALIZE_SCALAR(CRDD);
2238    SERIALIZE_SCALAR(rxPktBytes);
2239    SERIALIZE_SCALAR(rxFragPtr);
2240    SERIALIZE_SCALAR(rxDescCnt);
2241    int rxDmaState = this->rxDmaState;
2242    SERIALIZE_SCALAR(rxDmaState);
2243    SERIALIZE_SCALAR(rxKickTick);
2244
2245    /*
2246     * Serialize EEPROM state machine
2247     */
2248    int eepromState = this->eepromState;
2249    SERIALIZE_SCALAR(eepromState);
2250    SERIALIZE_SCALAR(eepromClk);
2251    SERIALIZE_SCALAR(eepromBitsToRx);
2252    SERIALIZE_SCALAR(eepromOpcode);
2253    SERIALIZE_SCALAR(eepromAddress);
2254    SERIALIZE_SCALAR(eepromData);
2255
2256    /*
2257     * If there's a pending transmit, store the time so we can
2258     * reschedule it later
2259     */
2260    Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;
2261    SERIALIZE_SCALAR(transmitTick);
2262
2263    /*
2264     * receive address filter settings
2265     */
2266    SERIALIZE_SCALAR(rxFilterEnable);
2267    SERIALIZE_SCALAR(acceptBroadcast);
2268    SERIALIZE_SCALAR(acceptMulticast);
2269    SERIALIZE_SCALAR(acceptUnicast);
2270    SERIALIZE_SCALAR(acceptPerfect);
2271    SERIALIZE_SCALAR(acceptArp);
2272    SERIALIZE_SCALAR(multicastHashEnable);
2273
2274    /*
2275     * Keep track of pending interrupt status.
2276     */
2277    SERIALIZE_SCALAR(intrTick);
2278    SERIALIZE_SCALAR(cpuPendingIntr);
2279    Tick intrEventTick = 0;
2280    if (intrEvent)
2281        intrEventTick = intrEvent->when();
2282    SERIALIZE_SCALAR(intrEventTick);
2283
2284}
2285
2286void
2287NSGigE::unserialize(Checkpoint *cp, const std::string &section)
2288{
2289    // Unserialize the PciDev base class
2290    PciDev::unserialize(cp, section);
2291
2292    UNSERIALIZE_SCALAR(regs.command);
2293    UNSERIALIZE_SCALAR(regs.config);
2294    UNSERIALIZE_SCALAR(regs.mear);
2295    UNSERIALIZE_SCALAR(regs.ptscr);
2296    UNSERIALIZE_SCALAR(regs.isr);
2297    UNSERIALIZE_SCALAR(regs.imr);
2298    UNSERIALIZE_SCALAR(regs.ier);
2299    UNSERIALIZE_SCALAR(regs.ihr);
2300    UNSERIALIZE_SCALAR(regs.txdp);
2301    UNSERIALIZE_SCALAR(regs.txdp_hi);
2302    UNSERIALIZE_SCALAR(regs.txcfg);
2303    UNSERIALIZE_SCALAR(regs.gpior);
2304    UNSERIALIZE_SCALAR(regs.rxdp);
2305    UNSERIALIZE_SCALAR(regs.rxdp_hi);
2306    UNSERIALIZE_SCALAR(regs.rxcfg);
2307    UNSERIALIZE_SCALAR(regs.pqcr);
2308    UNSERIALIZE_SCALAR(regs.wcsr);
2309    UNSERIALIZE_SCALAR(regs.pcr);
2310    UNSERIALIZE_SCALAR(regs.rfcr);
2311    UNSERIALIZE_SCALAR(regs.rfdr);
2312    UNSERIALIZE_SCALAR(regs.brar);
2313    UNSERIALIZE_SCALAR(regs.brdr);
2314    UNSERIALIZE_SCALAR(regs.srr);
2315    UNSERIALIZE_SCALAR(regs.mibc);
2316    UNSERIALIZE_SCALAR(regs.vrcr);
2317    UNSERIALIZE_SCALAR(regs.vtcr);
2318    UNSERIALIZE_SCALAR(regs.vdr);
2319    UNSERIALIZE_SCALAR(regs.ccsr);
2320    UNSERIALIZE_SCALAR(regs.tbicr);
2321    UNSERIALIZE_SCALAR(regs.tbisr);
2322    UNSERIALIZE_SCALAR(regs.tanar);
2323    UNSERIALIZE_SCALAR(regs.tanlpar);
2324    UNSERIALIZE_SCALAR(regs.taner);
2325    UNSERIALIZE_SCALAR(regs.tesr);
2326
2327    UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
2328    UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2329
2330    UNSERIALIZE_SCALAR(ioEnable);
2331
2332    /*
2333     * unserialize the data fifos
2334     */
2335    rxFifo.unserialize("rxFifo", cp, section);
2336    txFifo.unserialize("txFifo", cp, section);
2337
2338    /*
2339     * unserialize the various helper variables
2340     */
2341    bool txPacketExists;
2342    UNSERIALIZE_SCALAR(txPacketExists);
2343    if (txPacketExists) {
2344        txPacket = new EthPacketData(16384);
2345        txPacket->unserialize("txPacket", cp, section);
2346        uint32_t txPktBufPtr;
2347        UNSERIALIZE_SCALAR(txPktBufPtr);
2348        txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
2349    } else
2350        txPacket = 0;
2351
2352    bool rxPacketExists;
2353    UNSERIALIZE_SCALAR(rxPacketExists);
2354    rxPacket = 0;
2355    if (rxPacketExists) {
2356        rxPacket = new EthPacketData(16384);
2357        rxPacket->unserialize("rxPacket", cp, section);
2358        uint32_t rxPktBufPtr;
2359        UNSERIALIZE_SCALAR(rxPktBufPtr);
2360        rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
2361    } else
2362        rxPacket = 0;
2363
2364    UNSERIALIZE_SCALAR(txXferLen);
2365    UNSERIALIZE_SCALAR(rxXferLen);
2366
2367    /*
2368     * Unserialize Cached Descriptors
2369     */
2370    UNSERIALIZE_SCALAR(rxDesc64.link);
2371    UNSERIALIZE_SCALAR(rxDesc64.bufptr);
2372    UNSERIALIZE_SCALAR(rxDesc64.cmdsts);
2373    UNSERIALIZE_SCALAR(rxDesc64.extsts);
2374    UNSERIALIZE_SCALAR(txDesc64.link);
2375    UNSERIALIZE_SCALAR(txDesc64.bufptr);
2376    UNSERIALIZE_SCALAR(txDesc64.cmdsts);
2377    UNSERIALIZE_SCALAR(txDesc64.extsts);
2378    UNSERIALIZE_SCALAR(rxDesc32.link);
2379    UNSERIALIZE_SCALAR(rxDesc32.bufptr);
2380    UNSERIALIZE_SCALAR(rxDesc32.cmdsts);
2381    UNSERIALIZE_SCALAR(rxDesc32.extsts);
2382    UNSERIALIZE_SCALAR(txDesc32.link);
2383    UNSERIALIZE_SCALAR(txDesc32.bufptr);
2384    UNSERIALIZE_SCALAR(txDesc32.cmdsts);
2385    UNSERIALIZE_SCALAR(txDesc32.extsts);
2386    UNSERIALIZE_SCALAR(extstsEnable);
2387
2388    /*
2389     * unserialize tx state machine
2390     */
2391    int txState;
2392    UNSERIALIZE_SCALAR(txState);
2393    this->txState = (TxState) txState;
2394    UNSERIALIZE_SCALAR(txEnable);
2395    UNSERIALIZE_SCALAR(CTDD);
2396    UNSERIALIZE_SCALAR(txFragPtr);
2397    UNSERIALIZE_SCALAR(txDescCnt);
2398    int txDmaState;
2399    UNSERIALIZE_SCALAR(txDmaState);
2400    this->txDmaState = (DmaState) txDmaState;
2401    UNSERIALIZE_SCALAR(txKickTick);
2402    if (txKickTick)
2403        txKickEvent.schedule(txKickTick);
2404
2405    /*
2406     * unserialize rx state machine
2407     */
2408    int rxState;
2409    UNSERIALIZE_SCALAR(rxState);
2410    this->rxState = (RxState) rxState;
2411    UNSERIALIZE_SCALAR(rxEnable);
2412    UNSERIALIZE_SCALAR(CRDD);
2413    UNSERIALIZE_SCALAR(rxPktBytes);
2414    UNSERIALIZE_SCALAR(rxFragPtr);
2415    UNSERIALIZE_SCALAR(rxDescCnt);
2416    int rxDmaState;
2417    UNSERIALIZE_SCALAR(rxDmaState);
2418    this->rxDmaState = (DmaState) rxDmaState;
2419    UNSERIALIZE_SCALAR(rxKickTick);
2420    if (rxKickTick)
2421        rxKickEvent.schedule(rxKickTick);
2422
2423    /*
2424     * Unserialize EEPROM state machine
2425     */
2426    int eepromState;
2427    UNSERIALIZE_SCALAR(eepromState);
2428    this->eepromState = (EEPROMState) eepromState;
2429    UNSERIALIZE_SCALAR(eepromClk);
2430    UNSERIALIZE_SCALAR(eepromBitsToRx);
2431    UNSERIALIZE_SCALAR(eepromOpcode);
2432    UNSERIALIZE_SCALAR(eepromAddress);
2433    UNSERIALIZE_SCALAR(eepromData);
2434
2435    /*
2436     * If there's a pending transmit, reschedule it now
2437     */
2438    Tick transmitTick;
2439    UNSERIALIZE_SCALAR(transmitTick);
2440    if (transmitTick)
2441        txEvent.schedule(curTick + transmitTick);
2442
2443    /*
2444     * unserialize receive address filter settings
2445     */
2446    UNSERIALIZE_SCALAR(rxFilterEnable);
2447    UNSERIALIZE_SCALAR(acceptBroadcast);
2448    UNSERIALIZE_SCALAR(acceptMulticast);
2449    UNSERIALIZE_SCALAR(acceptUnicast);
2450    UNSERIALIZE_SCALAR(acceptPerfect);
2451    UNSERIALIZE_SCALAR(acceptArp);
2452    UNSERIALIZE_SCALAR(multicastHashEnable);
2453
2454    /*
2455     * Keep track of pending interrupt status.
2456     */
2457    UNSERIALIZE_SCALAR(intrTick);
2458    UNSERIALIZE_SCALAR(cpuPendingIntr);
2459    Tick intrEventTick;
2460    UNSERIALIZE_SCALAR(intrEventTick);
2461    if (intrEventTick) {
2462        intrEvent = new IntrEvent(this, intrEventTick, true);
2463    }
2464}
2465
2466NSGigE *
2467NSGigEParams::create()
2468{
2469    return new NSGigE(this);
2470}
2471