/// <summary> /// Invoked on behalf of PHY whenever new data has been received. /// </summary> /// <param name="data">The data that was received.</param> void OnDataReceived(byte[] data) { data.ThrowIfNull("data"); var frame = Frame.Deserialize(data); WriteMac("Received an Ethernet frame."); // Compute checksum and compare to the one contained in the frame. var fcs = Frame.ComputeCheckSequence(frame); if (fcs != frame.CheckSequence) { WriteMac("Detected a bad frame check sequence, discarding."); return; } // Drop our own frames. if (frame.Source == MacAddress) { return; } // Examine the frame and see if it's for us; If not, discard it. if (frame.Destination != MacAddress && frame.Destination != broadcastAddress) { WriteMac("Recipient mismatch, discarding."); return; } //Extract the payload and hand it up to the Network layer. InterruptReason = Lan.Interrupt.DataReceived; Interrupt.RaiseEvent(this, new DataReceivedEventArgs(frame.Payload, frame.Type)); }
/// <summary> /// Invoked om behalf of PHY whenever a frame has been transmitted. /// </summary> void OnDataTransmitted() { WriteMac("Finished transmitting Ethernet frame."); // The idle period between two consecutive frames must at least be 96 // bittimes long as per IEEE 802.3 specification. emptyingFifo = sendFifo.Count != 0; // If the FIFO's not empty yet, issue another transmission. Otherwise // let the upper layer know we're ready for more data. if (sendFifo.Count > 0) { Simulation.Callback(interframeGapTime, EmptySendFifo); } else { Simulation.Callback(interframeGapTime, () => { InterruptReason = Lan.Interrupt.SendFifoEmpty; Interrupt.RaiseEvent(this, null); }); } }