diff options
Diffstat (limited to 'dev/ns_gige.hh')
-rw-r--r-- | dev/ns_gige.hh | 403 |
1 files changed, 403 insertions, 0 deletions
diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh new file mode 100644 index 000000000..eaece2551 --- /dev/null +++ b/dev/ns_gige.hh @@ -0,0 +1,403 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* @file + * Device module for modelling the National Semiconductor + * DP83820 ethernet controller + */ + +#ifndef __NS_GIGE_HH__ +#define __NS_GIGE_HH__ + +#include "dev/dma.hh" +#include "dev/etherint.hh" +#include "dev/etherpkt.hh" +#include "sim/eventq.hh" +#include "dev/ns_gige_reg.h" +#include "base/statistics.hh" +#include "dev/pcidev.hh" +#include "dev/tsunami.hh" +#include "dev/pciconfigall.hh" + +/** defined by the NS83820 data sheet */ +#define MAX_TX_FIFO_SIZE 8192 +#define MAX_RX_FIFO_SIZE 32768 + +/** length of ethernet address in bytes */ +#define EADDR_LEN 6 + +/** Transmit State Machine states */ +enum tx_state { txIdle, txDescRefr, txDescRead, txFifoBlock, txFragRead, + txDescWrite }; + +/** Receive State Machine States */ +enum rx_state { rxIdle, rxDescRefr, rxDescRead, rxFifoBlock, rxFragWrite, + rxDescWrite, rxAdvance }; + +/** + * Ethernet device registers + */ +struct dp_regs { + uint32_t command; + uint32_t config; + uint32_t mear; + uint32_t ptscr; + uint32_t isr; + uint32_t imr; + uint32_t ier; + uint32_t ihr; + uint32_t txdp; + uint32_t txdp_hi; + uint32_t txcfg; + uint32_t gpior; + uint32_t rxdp; + uint32_t rxdp_hi; + uint32_t rxcfg; + uint32_t pqcr; + uint32_t wcsr; + uint32_t pcr; + uint32_t rfcr; + uint32_t rfdr; + uint32_t srr; + uint32_t mibc; + uint32_t vrcr; + uint32_t vtcr; + uint32_t vdr; + uint32_t ccsr; + uint32_t tbicr; + uint32_t tbisr; + uint32_t tanar; + uint32_t tanlpar; + uint32_t taner; + uint32_t tesr; + + /** for perfect match memory. the linux driver doesn't use any other ROM */ + uint8_t perfectMatch[EADDR_LEN]; + + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); +}; + +/** an enum indicating direction, transmit or receive, used as a param for + some fns */ +enum dir_t { tx, rx }; + +class DmaEngine; +class IntrControl; +class EtherDevInt; +class PhysicalMemory; + +/** + * NS DP82830 Ethernet device model + */ +class EtherDev : public PciDev, public DmaHolder +{ + private: + /** pointer to the chipset */ + Tsunami *tsunami; + + protected: + Addr addr; + Addr mask; + + /** device register file */ + dp_regs regs; + + /*** BASIC STRUCTURES FOR TX/RX ***/ + /* Data FIFOs */ + typedef std::deque<PacketPtr> pktbuf_t; + typedef pktbuf_t::iterator pktiter_t; + pktbuf_t txFifo; + pktbuf_t rxFifo; + + /** for the tx side, to track addrs to write updated cmdsts to */ + typedef std::deque<uint32_t> txdpbuf_t; /* ASSUME32 */ + txdpbuf_t descAddrFifo; + + /** various helper vars */ + uint32_t txPacketLen; + uint8_t *txPacketBufPtr; + uint8_t *rxPacketBufPtr; + uint8_t *rxDescBufPtr; + uint32_t fragLen; + uint32_t rxCopied; + + /** DescCaches */ + ns_desc txDescCache; + ns_desc rxDescCache; + + /* tx State Machine */ + tx_state txState; + /** Current Transmit Descriptor Done */ + bool CTDD; + uint32_t txFifoCnt; /* amt of data in the txDataFifo in bytes (logical) */ + uint32_t txFifoAvail; /* current amt of free space in txDataFifo in byes */ + bool txHalt; + bool txPacketFlag; /* when set, indicates not working on a new packet */ + Addr txFragPtr; /* ptr to the next byte in the current fragment */ + uint32_t txDescCnt; /* count of bytes remaining in the current descriptor */ + + /** rx State Machine */ + rx_state rxState; + bool CRDD; /* Current Receive Descriptor Done */ + uint32_t rxPktBytes; /* num of bytes in the current packet being drained + from rxDataFifo */ + uint32_t rxFifoCnt; /* number of bytes in the rxFifo */ + bool rxHalt; + bool rxPacketFlag; /* when set, indicates not working on a new packet */ + Addr rxFragPtr; /* ptr to the next byte in current fragment */ + uint32_t rxDescCnt; /* count of bytes remaining in the current descriptor */ + + bool extstsEnable; + uint32_t maxTxBurst; + uint32_t maxRxBurst; + + PhysicalMemory *physmem; + + protected: + /** + * Receive dma for descriptors done callback + */ + class RxDescDone : public DmaCallback + { + public: + EtherDev *ethernet; + + public: + RxDescDone(EtherDev *e); + std::string name() const; + virtual void process(); + }; + + /** + * Receive dma done callback + */ + class RxDone : public DmaCallback + { + public: + EtherDev *ethernet; + + public: + RxDone(EtherDev *e); + std::string name() const; + virtual void process(); + }; + + /** + * Transmit dma for descriptors done callback + */ + class TxDescDone : public DmaCallback + { + public: + EtherDev *ethernet; + + public: + TxDescDone(EtherDev *e); + std::string name() const; + virtual void process(); + }; + + /* + * Transmit dma done callback + */ + class TxDone : public DmaCallback + { + public: + EtherDev *ethernet; + PacketPtr packet; + + public: + TxDone(EtherDev *e); + std::string name() const; + virtual void process(); + }; + + friend class TxDescDone; + friend class TxDone; + friend class RxDescDone; + friend class RxDone; + + RxDescDone rxDescDoneCB; + RxDone rxDoneCB; + TxDescDone txDescDoneCB; + TxDone txDoneCB; + + DmaEngine *dma; + DmaRequest readRequest; + DmaRequest writeRequest; + DmaRequest readDescRequest; + DmaRequest writeDescRequest; + PacketPtr rxPacket; + DmaPhys readPhys; + DmaPhys writePhys; + DmaPhys readDescPhys; + DmaPhys writeDescPhys; + + EtherDevInt *interface; + + protected: + IntrControl *intctrl; + Tick txDelay; + Tick rxDelay; + + void txReset(); + void rxReset(); + void regsReset() { + memset(®s, 0, sizeof(regs)); + regs.mear = 0x12; + regs.isr = 0x00608000; + regs.txcfg = 0x120; + regs.rxcfg = 0x4; + regs.srr = 0x0103; + regs.mibc = 0x2; + regs.vdr = 0x81; + regs.tesr = 0xc000; + } + + void txKick(); + void rxKick(); + + /* + * Retransmit event + */ + class TxEvent : public Event + { + protected: + EtherDev *dev; + + public: + TxEvent(EtherDev *_dev) + : Event(&mainEventQueue), dev(_dev) {} + void process() { dev->transmit(); } + virtual const char *description() { return "retransmit"; } + }; + friend class TxEvent; + TxEvent txEvent; + void transmit(); + + + void txDescDone(); + void rxDescDone(); + void txDone(PacketPtr packet); + void rxDone(); + + void txDump() const; + void rxDump() const; + + void devIntrPost(uint32_t interrupts); + void devIntrClear(uint32_t interrupts); + void devIntrChangeMask(); + + bool cpuPendingIntr; + void cpuIntrPost(); + void cpuIntrClear(); + + bool rxFilterEnable; + bool rxFilter(PacketPtr packet); + bool acceptBroadcast; + bool acceptMulticast; + bool acceptUnicast; + bool acceptPerfect; + bool acceptArp; + + bool udpChecksum(PacketPtr packet, bool gen); + bool tcpChecksum(PacketPtr packet, bool gen); + bool ipChecksum(PacketPtr packet, bool gen); + uint16_t checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len); + + public: + EtherDev(const std::string &name, DmaEngine *de, bool use_interface, + IntrControl *i, MemoryController *mmu, PhysicalMemory *pmem, + PCIConfigAll *cf, PciConfigData *cd, Tsunami *t, uint32_t bus, + uint32_t dev, uint32_t func, bool rx_filter, const int eaddr[6], + Tick tx_delay, Tick rx_delay, Addr addr, Addr mask); + ~EtherDev(); + + virtual void WriteConfig(int offset, int size, uint32_t data); + virtual void ReadConfig(int offset, int size, uint8_t *data); + + + + Fault read(MemReqPtr req, uint8_t *data); + Fault write(MemReqPtr req, const uint8_t *data); + + bool cpuIntrPending() const; + void cpuIntrAck() { cpuIntrClear(); } + + bool recvPacket(PacketPtr packet); + void transferDone(); + + void setInterface(EtherDevInt *i) { assert(!interface); interface = i; } + + virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); + + virtual DmaRequest *find_dmareq(uint32_t &id) { + if (id == 0) + return(&readRequest); + else if (id == 1) + return(&writeRequest); + else + return(NULL); + } + + public: + void regStats(); + + private: + Statistics::Scalar<> txBytes; + Statistics::Scalar<> rxBytes; + Statistics::Scalar<> txPackets; + Statistics::Scalar<> rxPackets; + Statistics::Formula txBandwidth; + Statistics::Formula rxBandwidth; + Statistics::Formula txPacketRate; + Statistics::Formula rxPacketRate; + + void readOneDesc(dir_t dir, uint32_t len = sizeof(ns_desc)); + void readOneFrag(); + void writeOneFrag(); +}; + +/* + * Ethernet Interface for an Ethernet Device + */ +class EtherDevInt : public EtherInt +{ + private: + EtherDev *dev; + + public: + EtherDevInt(const std::string &name, EtherDev *d) + : EtherInt(name), dev(d) { dev->setInterface(this); } + + virtual bool recvPacket(PacketPtr &pkt) { return dev->recvPacket(pkt); } + virtual void sendDone() { dev->transferDone(); } +}; + +#endif // __NS_GIGE_HH__ |