/* * Copyright (c) 2004-2005 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. */ #ifndef __DEV_SINIC_HH__ #define __DEV_SINIC_HH__ #include "base/inet.hh" #include "base/statistics.hh" #include "dev/etherint.hh" #include "dev/etherpkt.hh" #include "dev/io_device.hh" #include "dev/pcidev.hh" #include "dev/pktfifo.hh" #include "dev/sinicreg.hh" #include "sim/eventq.hh" namespace Sinic { class Interface; class Base : public PciDev { protected: bool rxEnable; bool txEnable; Tick clock; inline Tick cycles(int numCycles) const { return numCycles * clock; } protected: Tick intrDelay; Tick intrTick; bool cpuIntrEnable; bool cpuPendingIntr; void cpuIntrPost(Tick when); void cpuInterrupt(); void cpuIntrClear(); typedef EventWrapper IntrEvent; friend void IntrEvent::process(); IntrEvent *intrEvent; Interface *interface; bool cpuIntrPending() const; void cpuIntrAck() { cpuIntrClear(); } /** * Serialization stuff */ public: virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); /** * Construction/Destruction/Parameters */ public: struct Params : public PciDev::Params { Tick clock; Tick intr_delay; }; Base(Params *p); }; class Device : public Base { protected: /** Receive State Machine States */ enum RxState { rxIdle, rxFifoBlock, rxBeginCopy, rxCopy, rxCopyDone }; /** Transmit State Machine states */ enum TxState { txIdle, txFifoBlock, txBeginCopy, txCopy, txCopyDone }; /** device register file */ struct { uint32_t Config; // 0x00 uint32_t Command; // 0x04 uint32_t IntrStatus; // 0x08 uint32_t IntrMask; // 0x0c uint32_t RxMaxCopy; // 0x10 uint32_t TxMaxCopy; // 0x14 uint32_t RxMaxIntr; // 0x18 uint32_t VirtualCount; // 0x1c uint32_t RxFifoSize; // 0x20 uint32_t TxFifoSize; // 0x24 uint32_t RxFifoMark; // 0x28 uint32_t TxFifoMark; // 0x2c uint64_t RxData; // 0x30 uint64_t RxDone; // 0x38 uint64_t RxWait; // 0x40 uint64_t TxData; // 0x48 uint64_t TxDone; // 0x50 uint64_t TxWait; // 0x58 uint64_t HwAddr; // 0x60 } regs; struct VirtualReg { uint64_t RxData; uint64_t RxDone; uint64_t TxData; uint64_t TxDone; PacketFifo::iterator rxPacket; int rxPacketOffset; int rxPacketBytes; uint64_t rxDoneData; Counter rxUnique; Counter txUnique; VirtualReg() : RxData(0), RxDone(0), TxData(0), TxDone(0), rxPacketOffset(0), rxPacketBytes(0), rxDoneData(0) { } }; typedef std::vector VirtualRegs; typedef std::list VirtualList; Counter rxUnique; Counter txUnique; VirtualRegs virtualRegs; VirtualList rxList; VirtualList rxBusy; int rxActive; VirtualList txList; uint8_t ®Data8(Addr daddr) { return *((uint8_t *)®s + daddr); } uint32_t ®Data32(Addr daddr) { return *(uint32_t *)®Data8(daddr); } uint64_t ®Data64(Addr daddr) { return *(uint64_t *)®Data8(daddr); } protected: RxState rxState; PacketFifo rxFifo; PacketFifo::iterator rxFifoPtr; bool rxEmpty; bool rxLow; Addr rxDmaAddr; uint8_t *rxDmaData; int rxDmaLen; TxState txState; PacketFifo txFifo; bool txFull; EthPacketPtr txPacket; int txPacketOffset; int txPacketBytes; Addr txDmaAddr; uint8_t *txDmaData; int txDmaLen; protected: void reset(); void rxKick(); Tick rxKickTick; typedef EventWrapper RxKickEvent; friend void RxKickEvent::process(); void txKick(); Tick txKickTick; typedef EventWrapper TxKickEvent; friend void TxKickEvent::process(); /** * Retransmit event */ void transmit(); void txEventTransmit() { transmit(); if (txState == txFifoBlock) txKick(); } typedef EventWrapper TxEvent; friend void TxEvent::process(); TxEvent txEvent; void txDump() const; void rxDump() const; /** * receive address filter */ bool rxFilter(const EthPacketPtr &packet); /** * device configuration */ void changeConfig(uint32_t newconfig); void command(uint32_t command); /** * device ethernet interface */ public: bool recvPacket(EthPacketPtr packet); void transferDone(); void setInterface(Interface *i) { assert(!interface); interface = i; } /** * DMA parameters */ protected: void rxDmaDone(); friend class EventWrapper; EventWrapper rxDmaEvent; void txDmaDone(); friend class EventWrapper; EventWrapper txDmaEvent; Tick dmaReadDelay; Tick dmaReadFactor; Tick dmaWriteDelay; Tick dmaWriteFactor; /** * Interrupt management */ protected: void devIntrPost(uint32_t interrupts); void devIntrClear(uint32_t interrupts = Regs::Intr_All); void devIntrChangeMask(uint32_t newmask); /** * Memory Interface */ public: virtual Tick read(Packet *pkt); virtual Tick write(Packet *pkt); void prepareIO(int cpu, int index); void prepareRead(int cpu, int index); void prepareWrite(int cpu, int index); // Fault iprRead(Addr daddr, int cpu, uint64_t &result); /** * Statistics */ private: Stats::Scalar<> rxBytes; Stats::Formula rxBandwidth; Stats::Scalar<> rxPackets; Stats::Formula rxPacketRate; Stats::Scalar<> rxIpPackets; Stats::Scalar<> rxTcpPackets; Stats::Scalar<> rxUdpPackets; Stats::Scalar<> rxIpChecksums; Stats::Scalar<> rxTcpChecksums; Stats::Scalar<> rxUdpChecksums; Stats::Scalar<> txBytes; Stats::Formula txBandwidth; Stats::Formula totBandwidth; Stats::Formula totPackets; Stats::Formula totBytes; Stats::Formula totPacketRate; Stats::Scalar<> txPackets; Stats::Formula txPacketRate; Stats::Scalar<> txIpPackets; Stats::Scalar<> txTcpPackets; Stats::Scalar<> txUdpPackets; Stats::Scalar<> txIpChecksums; Stats::Scalar<> txTcpChecksums; Stats::Scalar<> txUdpChecksums; public: virtual void regStats(); /** * Serialization stuff */ public: virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); /** * Construction/Destruction/Parameters */ public: struct Params : public Base::Params { Tick tx_delay; Tick rx_delay; bool rx_filter; Net::EthAddr eaddr; uint32_t rx_max_copy; uint32_t tx_max_copy; uint32_t rx_max_intr; uint32_t rx_fifo_size; uint32_t tx_fifo_size; uint32_t rx_fifo_threshold; uint32_t rx_fifo_low_mark; uint32_t tx_fifo_high_mark; uint32_t tx_fifo_threshold; Tick dma_read_delay; Tick dma_read_factor; Tick dma_write_delay; Tick dma_write_factor; bool rx_thread; bool tx_thread; bool rss; uint32_t virtual_count; bool zero_copy; bool delay_copy; bool virtual_addr; }; protected: const Params *params() const { return (const Params *)_params; } public: Device(Params *params); ~Device(); }; /* * Ethernet Interface for an Ethernet Device */ class Interface : public EtherInt { private: Device *dev; public: Interface(const std::string &name, Device *d) : EtherInt(name), dev(d) { dev->setInterface(this); } virtual bool recvPacket(EthPacketPtr pkt) { return dev->recvPacket(pkt); } virtual void sendDone() { dev->transferDone(); } }; /* namespace Sinic */ } #endif // __DEV_SINIC_HH__