public IxgbeDevice(string pciAddr, int rxQueues, int txQueues) : base(pciAddr, rxQueues, txQueues) { if (txQueues < 0 || txQueues > MaxQueues) { throw new ArgumentException(String.Format("Cannot configure {0} tx queues - limit is {1}", txQueues, MaxQueues)); } if (rxQueues < 0 || rxQueues > MaxQueues) { throw new ArgumentException(String.Format("Cannot configure {0} rx queues - limit is {1}", rxQueues, MaxQueues)); } DriverName = "ixy-ixgbe"; RxQueues = new IxgbeRxQueue[rxQueues]; TxQueues = new IxgbeTxQueue[txQueues]; PciController.RemoveDriver(pciAddr); PciController.EnableDma(pciAddr); try { //View accessor for mmapped file is automatically created PciMemMap = PciController.MapResource(pciAddr); } catch (Exception e) { Log.Error("FATAL: Could not map memory for device {0} - {1}", pciAddr, e.Message); Environment.Exit(1); } ResetAndInit(); }
private void InitRx() { //Disable RX while re-configuring ClearFlags(IxgbeDefs.RXCTRL, IxgbeDefs.RXCTRL_RXEN); //No DCB or VT, just a single 128kb packet buffer SetReg(IxgbeDefs.RXPBSIZE(0), IxgbeDefs.RXPBSIZE_128KB); for (uint i = 1; i < 8; i++) { SetReg(IxgbeDefs.RXPBSIZE(i), 0); } //Always enable CRC offloading SetFlags(IxgbeDefs.HLREG0, IxgbeDefs.HLREG0_RXCRCSTRP); SetFlags(IxgbeDefs.RDRXCTL, IxgbeDefs.RDRXCTL_CRCSTRIP); //Accept broadcast packets SetFlags(IxgbeDefs.FCTRL, IxgbeDefs.FCTRL_BAM); //Per queue config for (uint i = 0; i < RxQueues.Length; i++) { Log.Notice("Initializing rx queue {0}", i); //Enable advanced rx descriptors SetReg(IxgbeDefs.SRRCTL(i), (GetReg(IxgbeDefs.SRRCTL(i)) & ~IxgbeDefs.SRRCTL_DESCTYPE_MASK) | IxgbeDefs.SRRCTL_DESCTYPE_ADV_ONEBUF); //DROP_EN causes the NIC to drop packets if no descriptors are available instead of buffering them //A single overflowing queue can fill up the whole buffer and impact operations if not setting this SetFlags(IxgbeDefs.SRRCTL(i), IxgbeDefs.SRRCTL_DROP_EN); //Sec 7.1.9 - Set up descriptor ring int ringSizeBytes = NumRxQueueEntries * RxDescriptorSize; var dmaMem = MemoryHelper.AllocateDmaC((uint)ringSizeBytes, true); //TODO : The C version sets the allocated memory to -1 here SetReg(IxgbeDefs.RDBAL(i), (uint)(dmaMem.PhysicalAddress & 0xFFFFFFFFL)); SetReg(IxgbeDefs.RDBAH(i), (uint)(dmaMem.PhysicalAddress >> 32)); SetReg(IxgbeDefs.RDLEN(i), (uint)ringSizeBytes); Log.Notice("RX ring {0} physical address: {1}", i, dmaMem.PhysicalAddress); Log.Notice("RX ring {0} virtual address: {1}", i, dmaMem.VirtualAddress); //Set ring to empty SetReg(IxgbeDefs.RDH(i), 0); SetReg(IxgbeDefs.RDT(i), 0); var queue = new IxgbeRxQueue(NumRxQueueEntries); queue.Index = 0; queue.DescriptorsAddr = dmaMem.VirtualAddress; RxQueues[i] = queue; } //Section 4.6.7 - set some magic bits SetFlags(IxgbeDefs.CTRL_EXT, IxgbeDefs.CTRL_EXT_NS_DIS); //This flag probably refers to a broken feature: It's reserved and initialized as '1' but it must be '0' for (uint i = 0; i < RxQueues.Length; i++) { ClearFlags(IxgbeDefs.DCA_RXCTRL(i), 1 << 12); } //Start RX SetFlags(IxgbeDefs.RXCTRL, IxgbeDefs.RXCTRL_RXEN); }