private void TransmitLoop(CancellationToken token) { while (true) { byte[] buffer = null; if (stream == null) { return; } try { buffer = LibC.ReadDataWithTimeout(stream.Handle, MTU, 1000, () => token.IsCancellationRequested); } catch (ArgumentException) { // stream was closed return; } catch (ObjectDisposedException) { return; } if (token.IsCancellationRequested) { return; } if (buffer == null || buffer.Length == 0) { continue; } var ethernetFrame = EthernetFrame.CreateEthernetFrameWithCRC(buffer); FrameReady?.Invoke(ethernetFrame); } }
private async Task ReadPacketAsync() { var buffer = new byte[Mtu]; while (!cts.IsCancellationRequested) { try { if (await deviceFile.ReadAsync(buffer, 0, buffer.Length, cts.Token) > 0) { var frame = EthernetFrame.CreateEthernetFrameWithCRC(buffer); Link.TransmitFrameFromInterface(frame); this.NoisyLog("Frame of length {0} received from host.", frame.Bytes.Length); } } catch (IOException) { if (networkInterface.OperationalStatus != OperationalStatus.Up) { this.NoisyLog("I/O exception while interface is not up, waiting {0}s.", Misc.NormalizeDecimal(GracePeriod.TotalSeconds)); // probably the interface is not opened yet await Task.Delay(GracePeriod); } else { throw; } } } }
private void transmitFrame() { var td = new transmitDescriptor(machine.SystemBus); td.Fetch(transmitDescriptorBase | transmitDescriptorOffset); if (!td.Enable) { return; //if decriptor is disabled there is nothing to send (just return) } var packetBytes = machine.SystemBus.ReadBytes((long)td.PacketAddress, (int)td.Length); var packet = EthernetFrame.CreateEthernetFrameWithCRC(packetBytes); if (Link.IsConnected) { this.Log(LogLevel.Info, "Sending packet length {0}", packet.Bytes.Length); this.Log(LogLevel.Info, "Packet address = 0x{0:X}", td.PacketAddress); Link.TransmitFrameFromInterface(packet); } registers.Status |= 1u << 3; if (td.Wrap) { transmitDescriptorOffset = 0; } else { if (transmitDescriptorOffset != 0x3f8) { transmitDescriptorOffset += 8; } else { transmitDescriptorOffset = 0; } } if (td.InterruptEnable && ((registers.Control & (1u << 2)) != 0)) { //if interrupts enabled registers.Status |= 1u << 3; //transmitter interrupt bit this.IRQ.Set(); this.IRQ.Unset(); } td.Enable = false; td.Wrap = false; td.InterruptEnable = false; td.Length = 0; td.UnderrunError = false; td.AttemptLimitError = false; td.WriteBack(); }
private void TransmitPacket() { var packetSize = transmitBufferEnd - transmitBufferStart; // -1 for the per packet control byte, but transmitBufferEnd points to the last byte of the packet var data = new byte[packetSize]; Array.Copy(ethernetBuffer, transmitBufferStart + 1, data, 0, packetSize); var frame = EthernetFrame.CreateEthernetFrameWithCRC(data); // status vector is not implemented yet this.Log(LogLevel.Debug, "Sending frame {0}.", frame); Link.TransmitFrameFromInterface(frame); transmitPacketInterrupt.Value = true; RefreshInterruptStatus(); }
public void WriteDataBulk(USBPacket packet) { if (packet.data == null) { return; } byte[] packetToSend; if (packet.data[5] != 64) { packetToSend = new byte[packet.data.Length - 8]; Array.Copy(packet.data, 8, packetToSend, 0, packetToSend.Length); } else { packetToSend = new byte[packet.data.Length - 12]; Array.Copy(packet.data, 12, packetToSend, 0, packetToSend.Length); if ((packetToSend[14] & 0xF0) == 0x40) //IP packet { ushort cksum; IPHeaderLength = (ushort)((packetToSend[14] & 0x0F) * 4); if (packetToSend[23] == 0x06) // TCP packet { IPpacket tcpPacket = new IPpacket(IPHeaderLength, IPpacket.PacketType.TCP); tcpPacket.ReadFromBuffer(packetToSend); cksum = tcpPacket.GetChecksum(); cksum -= 1; packetToSend[MACHeaderLegth + IPHeaderLength + 16] = (byte)((cksum >> 8) & 0xFF); packetToSend[MACHeaderLegth + IPHeaderLength + 17] = (byte)((cksum) & 0xFF); } else if (packetToSend[23] == 0x11) // UDP packet { IPpacket udpPacket = new IPpacket(IPHeaderLength, IPpacket.PacketType.UDP); udpPacket.ReadFromBuffer(packetToSend); cksum = udpPacket.GetChecksum(); cksum -= 1; packetToSend[MACHeaderLegth + IPHeaderLength + 6] = (byte)((cksum >> 8) & 0xFF); packetToSend[MACHeaderLegth + IPHeaderLength + 7] = (byte)((cksum) & 0xFF); } } } var frame = EthernetFrame.CreateEthernetFrameWithCRC(packetToSend); FrameReady?.Invoke(frame); }
public byte Transmit() { lock (lockObj) { int len; byte whichPacket; if ((transmitControl & TransmitEnabled) == 0) { return(0); } if (txFifo.Count == 0) { return(0); } while (txFifo.Count > 0) { whichPacket = txFifo.Dequeue(); var currentBuffer = memoryBuffer[whichPacket]; len = currentBuffer.Data[2]; len |= currentBuffer.Data[3] << 8; len -= 6; byte [] indata = new byte[len]; for (int j = 0; j < len; j++) { indata[j] = currentBuffer.Data[j + 4]; } if ((control & ControlAutorelease) != 0) { currentBuffer.IsAllocated = false; } else { sentFifo.Enqueue((byte)whichPacket); } var frame = EthernetFrame.CreateEthernetFrameWithCRC(indata); Link.TransmitFrameFromInterface(frame); } Update(); return(0); } }
private void SendFrames() { this.Log(LogLevel.Noisy, "Sending frame"); var transmitDescriptor = new TxDescriptor(machine.SystemBus); var packetData = new List <byte>(); transmitDescriptor.Fetch(dmaTransmitDescriptorListAddress); while (!transmitDescriptor.IsUsed) { transmitDescriptor.IsUsed = true; this.Log(LogLevel.Noisy, "GOING TO READ FROM {0:X}, len={1}", transmitDescriptor.Address1, transmitDescriptor.Buffer1Length); packetData.AddRange(machine.SystemBus.ReadBytes(transmitDescriptor.Address1, transmitDescriptor.Buffer1Length)); if (!transmitDescriptor.IsNextDescriptorChained) { packetData.AddRange(machine.SystemBus.ReadBytes(transmitDescriptor.Address2, transmitDescriptor.Buffer2Length)); } transmitDescriptor.WriteBack(); if (transmitDescriptor.IsEndOfRing) { dmaTransmitDescriptorListAddress = dmaTransmitDescriptorListAddressBegin; } else if (transmitDescriptor.IsNextDescriptorChained) { dmaTransmitDescriptorListAddress = transmitDescriptor.Address2; } else { dmaTransmitDescriptorListAddress += 8; } if (transmitDescriptor.IsLast) { this.Log(LogLevel.Noisy, "Sending frame of {0} bytes.", packetData.Count); if (Link.IsConnected) { var frame = EthernetFrame.CreateEthernetFrameWithoutCRC(packetData.ToArray()); if (transmitDescriptor.ChecksumInstertionControl > 0) { this.Log(LogLevel.Noisy, "Calculating checksum (mode {0}).", transmitDescriptor.ChecksumInstertionControl); if (transmitDescriptor.ChecksumInstertionControl == 1) { //IP only frame.FillWithChecksums(supportedEtherChecksums, null); } else { //IP and payload frame.FillWithChecksums(supportedEtherChecksums, supportedIPChecksums); } } this.Log(LogLevel.Debug, Misc.DumpPacket(frame, true, machine)); packetSent = true; //We recreate the EthernetFrame because the CRC should be appended after creating inner checksums. var frameWithCrc = EthernetFrame.CreateEthernetFrameWithCRC(frame.Bytes); Link.TransmitFrameFromInterface(frameWithCrc); } } transmitDescriptor.Fetch(dmaTransmitDescriptorListAddress); } //set TransmitBufferUnavailable dmaStatus |= TransmitBufferUnavailableStatus; if ((dmaInterruptEnable & (StartStopTransmission)) == 0) { IRQ.Set(); } this.Log(LogLevel.Noisy, "Frame sent."); }
private void SendFrames() { lock (sync) { txBufferDescriptor txBD = new txBufferDescriptor(machine.SystemBus); bool interrupt = false; List <byte> packet = new List <byte>(); txBD.Fetch(registers.TxQueueBaseAddr); while (!txBD.Used) { while (!txBD.Last) { packet.AddRange(machine.SystemBus.ReadBytes(txBD.Word0, txBD.Length)); txBD.Used = true; txBD.WriteBack(); if (txBD.Wrap) { registers.TxQueueBaseAddr = txBufferBase; } else { registers.TxQueueBaseAddr += 8; } txBD.Fetch(registers.TxQueueBaseAddr); } interrupt = false; txBD.Used = true; packet.AddRange(machine.SystemBus.ReadBytes(txBD.Word0, txBD.Length)); if ((registers.DMAConfig & 1u << 11) != 0) //if checksum offload enable { if ((packet[14] & 0xF0) == 0x40) //IP packet { ushort cksum; IPHeaderLength = (ushort)((packet[14] & 0x0F) * 4); if (packet[23] == 0x06) // TCP packet { IPpacket tcpPacket = new IPpacket(IPHeaderLength, IPpacket.PacketType.TCP); tcpPacket.ReadFromBuffer(packet.ToArray()); cksum = tcpPacket.GetChecksum(); cksum -= 1; packet[MACHeaderLegth + IPHeaderLength + 16] = (byte)((cksum >> 8) & 0xFF); packet[MACHeaderLegth + IPHeaderLength + 17] = (byte)((cksum) & 0xFF); } else if (packet[23] == 0x11) // UDP packet { IPpacket udpPacket = new IPpacket(IPHeaderLength, IPpacket.PacketType.UDP); udpPacket.ReadFromBuffer(packet.ToArray()); cksum = udpPacket.GetChecksum(); cksum -= 1; packet[MACHeaderLegth + IPHeaderLength + 6] = (byte)((cksum >> 8) & 0xFF); packet[MACHeaderLegth + IPHeaderLength + 7] = (byte)((cksum) & 0xFF); } } } if (Link.IsConnected) { EthernetFrame frame; if (!txBD.NoCRC) { frame = EthernetFrame.CreateEthernetFrameWithCRC(packet.ToArray()); } else { frame = EthernetFrame.CreateEthernetFrameWithoutCRC(packet.ToArray()); } this.Log(LogLevel.Noisy, "Sending packet length {0}", packet.ToArray().Length); Link.TransmitFrameFromInterface(frame); } txBD.WriteBack(); if (txBD.Wrap) { registers.TxQueueBaseAddr = txBufferBase; } else { registers.TxQueueBaseAddr += 8; } registers.TxStatus |= 1u << 5; //tx complete txBD.Fetch(registers.TxQueueBaseAddr); if (txBD.Used) { registers.TxStatus |= 0x01; if ((registers.InterruptMask & (1u << 3)) == 0) { registers.InterruptStatus |= 1u << 3; interrupt = true; } } if ((registers.InterruptMask & (1u << 7)) == 0) { registers.InterruptStatus |= 1u << 7; interrupt = true; } if (interrupt) { IRQ.Set(); } } } }