mirror of
https://github.com/livingcomputermuseum/ContrAlto.git
synced 2026-01-21 02:07:30 +00:00
Minor fixes for debugger interface and disassembler; started hooking Ethernet interface up to real host Ethernet (because MazeWar.)
This commit is contained in:
parent
30ed445764
commit
898abdc906
@ -185,6 +185,12 @@ namespace Contralto.CPU
|
||||
int c = (_output & 0x1) << 15;
|
||||
_output = (ushort)((_output >> 1) | c);
|
||||
}
|
||||
|
||||
if (_dns)
|
||||
{
|
||||
// Should never happen
|
||||
throw new InvalidOperationException("DNS on Rotate Right, not possible.");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@ -117,7 +117,7 @@ namespace Contralto.CPU
|
||||
// Dispatch to the appropriate device.
|
||||
// The Ethernet controller is the only common device that is documented
|
||||
// to have used STARTF, so we'll just go there directly; if other
|
||||
// hardware is discovered we'll put together a more flexible dispatch.
|
||||
// hardware is discovered to be worth emulating we'll put together a more flexible dispatch.
|
||||
//
|
||||
if (_busData < 4)
|
||||
{
|
||||
@ -186,9 +186,6 @@ namespace Contralto.CPU
|
||||
//
|
||||
// "...DNS also addresses R from (3-IR[3 - 4])..."
|
||||
//
|
||||
|
||||
// TODO: is S reg select impacted by this?
|
||||
//_srSelect =
|
||||
_rSelect = (_rSelect & 0xfffc) | ((((uint)_cpu._ir & 0x1800) >> 11) ^ 3);
|
||||
break;
|
||||
|
||||
|
||||
@ -27,6 +27,11 @@ namespace Contralto.CPU
|
||||
get { return (int)_taskType; }
|
||||
}
|
||||
|
||||
public TaskType TaskType
|
||||
{
|
||||
get { return _taskType; }
|
||||
}
|
||||
|
||||
public bool Wakeup
|
||||
{
|
||||
get { return _wakeup; }
|
||||
|
||||
@ -38,12 +38,12 @@ namespace Contralto.CPU
|
||||
break;
|
||||
|
||||
case BusSource.LoadR:
|
||||
source = "0 ";
|
||||
source = "L ";
|
||||
loadR = true;
|
||||
break;
|
||||
|
||||
case BusSource.None:
|
||||
source = "177777 ";
|
||||
source = "177777(no source) ";
|
||||
break;
|
||||
|
||||
case BusSource.TaskSpecific1:
|
||||
@ -289,7 +289,7 @@ namespace Contralto.CPU
|
||||
|
||||
default:
|
||||
loadS = false;
|
||||
return String.Format("BS{0}", Conversion.ToOctal((int)instruction.BS));
|
||||
return String.Format("BS {0}", Conversion.ToOctal((int)instruction.BS));
|
||||
}
|
||||
}
|
||||
|
||||
@ -301,7 +301,7 @@ namespace Contralto.CPU
|
||||
return DisassembleEmulatorSpecialFunction1(instruction);
|
||||
|
||||
default:
|
||||
return String.Format("F1{0}", Conversion.ToOctal((int)instruction.F1));
|
||||
return String.Format("F1 {0}", Conversion.ToOctal((int)instruction.F1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,7 +313,7 @@ namespace Contralto.CPU
|
||||
return DisassembleEmulatorSpecialFunction2(instruction);
|
||||
|
||||
default:
|
||||
return String.Format("F2{0}", Conversion.ToOctal((int)instruction.F2));
|
||||
return String.Format("F2 {0}", Conversion.ToOctal((int)instruction.F2));
|
||||
}
|
||||
}
|
||||
|
||||
@ -367,7 +367,7 @@ namespace Contralto.CPU
|
||||
return "STARTF ";
|
||||
|
||||
default:
|
||||
return String.Format("F1{0}", Conversion.ToOctal((int)ef1));
|
||||
return String.Format("F1 {0}", Conversion.ToOctal((int)ef1));
|
||||
}
|
||||
|
||||
}
|
||||
@ -400,7 +400,7 @@ namespace Contralto.CPU
|
||||
return "IDISP ";
|
||||
|
||||
default:
|
||||
return String.Format("F2{0}", Conversion.ToOctal((int)ef2));
|
||||
return String.Format("F2 {0}", Conversion.ToOctal((int)ef2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,10 +93,9 @@ namespace Contralto.CPU
|
||||
get { return _uCodeRam; }
|
||||
}
|
||||
|
||||
public static MicrocodeBank Bank
|
||||
{
|
||||
// Just return the Bank for the Emulator task for now
|
||||
get { return _microcodeBank[(int)TaskType.Emulator]; }
|
||||
public static MicrocodeBank GetBank(TaskType task)
|
||||
{
|
||||
return _microcodeBank[(int)task];
|
||||
}
|
||||
|
||||
public static void LoadControlRAMAddress(ushort address)
|
||||
|
||||
@ -52,6 +52,18 @@
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="PcapDotNet.Base">
|
||||
<HintPath>pcap\PcapDotNet.Base.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PcapDotNet.Core">
|
||||
<HintPath>pcap\PcapDotNet.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PcapDotNet.Core.Extensions">
|
||||
<HintPath>pcap\PcapDotNet.Core.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PcapDotNet.Packets">
|
||||
<HintPath>pcap\PcapDotNet.Packets.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
@ -108,6 +120,7 @@
|
||||
<Compile Include="IO\DiskController.cs" />
|
||||
<Compile Include="IO\DiabloPack.cs" />
|
||||
<Compile Include="IO\EthernetController.cs" />
|
||||
<Compile Include="IO\HostEthernet.cs" />
|
||||
<Compile Include="IO\Keyboard.cs" />
|
||||
<Compile Include="IO\Mouse.cs" />
|
||||
<Compile Include="Logging\Log.cs" />
|
||||
|
||||
4
Contralto/Debugger.Designer.cs
generated
4
Contralto/Debugger.Designer.cs
generated
@ -214,7 +214,7 @@
|
||||
this._rom0SourceViewer.Size = new System.Drawing.Size(582, 554);
|
||||
this._rom0SourceViewer.TabIndex = 1;
|
||||
this._rom0SourceViewer.TabStop = false;
|
||||
this._rom0SourceViewer.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.SourceViewCellClick);
|
||||
this._rom0SourceViewer.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.Rom0SourceViewCellClick);
|
||||
//
|
||||
// Breakpoint
|
||||
//
|
||||
@ -314,6 +314,7 @@
|
||||
this._rom1SourceViewer.Size = new System.Drawing.Size(582, 545);
|
||||
this._rom1SourceViewer.TabIndex = 2;
|
||||
this._rom1SourceViewer.TabStop = false;
|
||||
this._rom1SourceViewer.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.Rom1SourceViewCellClick);
|
||||
//
|
||||
// dataGridViewCheckBoxColumn1
|
||||
//
|
||||
@ -413,6 +414,7 @@
|
||||
this._ram0SourceViewer.Size = new System.Drawing.Size(582, 545);
|
||||
this._ram0SourceViewer.TabIndex = 2;
|
||||
this._ram0SourceViewer.TabStop = false;
|
||||
this._ram0SourceViewer.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.Ram0SourceViewCellClick);
|
||||
//
|
||||
// dataGridViewCheckBoxColumn2
|
||||
//
|
||||
|
||||
@ -25,7 +25,7 @@ namespace Contralto
|
||||
{
|
||||
_system = system;
|
||||
_controller = controller;
|
||||
_microcodeBreakpointEnabled = new bool[1024];
|
||||
_microcodeBreakpointEnabled = new bool[3,1024];
|
||||
_novaBreakpointEnabled = new bool[65536];
|
||||
|
||||
_controller.StepCallback += OnExecutionStep;
|
||||
@ -143,22 +143,24 @@ namespace Contralto
|
||||
|
||||
//
|
||||
// Select active tab based on current UCode bank
|
||||
switch (UCodeMemory.Bank)
|
||||
MicrocodeBank bank = UCodeMemory.GetBank(_system.CPU.CurrentTask.TaskType);
|
||||
|
||||
switch (bank)
|
||||
{
|
||||
case MicrocodeBank.ROM0:
|
||||
SourceTabs.TabIndex = 0;
|
||||
SourceTabs.SelectedIndex = 0;
|
||||
break;
|
||||
|
||||
case MicrocodeBank.ROM1:
|
||||
SourceTabs.TabIndex = 1;
|
||||
SourceTabs.SelectedIndex = 1;
|
||||
break;
|
||||
|
||||
case MicrocodeBank.RAM0:
|
||||
SourceTabs.TabIndex = 2;
|
||||
SourceTabs.SelectedIndex = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
RefreshMicrocodeDisassembly();
|
||||
RefreshMicrocodeDisassembly(_system.CPU.CurrentTask.MPC);
|
||||
|
||||
// Highlight the nova memory location corresponding to the emulator PC.
|
||||
// TODO: this should be configurable
|
||||
@ -197,25 +199,23 @@ namespace Contralto
|
||||
this.BringToFront();
|
||||
}
|
||||
|
||||
private void RefreshMicrocodeDisassembly()
|
||||
private void RefreshMicrocodeDisassembly(ushort address)
|
||||
{
|
||||
// Update non-ROM code listings, depending on the currently active tab
|
||||
switch (SourceTabs.SelectedIndex)
|
||||
{
|
||||
case 0:
|
||||
// Find the right source line and highlight it.
|
||||
HighlightMicrocodeSourceLine(_rom0SourceViewer, _system.CPU.CurrentTask.MPC);
|
||||
HighlightMicrocodeSourceLine(_rom0SourceViewer, address);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
SourceTabs.TabIndex = 1;
|
||||
HighlightMicrocodeSourceLine(_rom1SourceViewer, _system.CPU.CurrentTask.MPC);
|
||||
case 1:
|
||||
HighlightMicrocodeSourceLine(_rom1SourceViewer, address);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
SourceTabs.TabIndex = 2;
|
||||
RefreshMicrocodeDisassembly(MicrocodeBank.RAM0);
|
||||
HighlightMicrocodeSourceLine(_ram0SourceViewer, _system.CPU.CurrentTask.MPC);
|
||||
case 2:
|
||||
UpdateMicrocodeDisassembly(MicrocodeBank.RAM0);
|
||||
HighlightMicrocodeSourceLine(_ram0SourceViewer, address);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -272,21 +272,60 @@ namespace Contralto
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void SourceViewCellClick(object sender, DataGridViewCellEventArgs e)
|
||||
private void Rom0SourceViewCellClick(object sender, DataGridViewCellEventArgs e)
|
||||
{
|
||||
// Check for breakpoint column click.
|
||||
if (e.ColumnIndex == 0)
|
||||
{
|
||||
SetBreakpointFromCellClick(MicrocodeBank.ROM0, e.RowIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private void Rom1SourceViewCellClick(object sender, DataGridViewCellEventArgs e)
|
||||
{
|
||||
// Check for breakpoint column click.
|
||||
if (e.ColumnIndex == 0)
|
||||
{
|
||||
// See if this is a source line, if so check/uncheck the box
|
||||
// and set/unset a breakpoint for the line
|
||||
if (_rom0SourceViewer.Rows[e.RowIndex].Tag != null)
|
||||
{
|
||||
bool value = (bool)_rom0SourceViewer.Rows[e.RowIndex].Cells[0].Value;
|
||||
_rom0SourceViewer.Rows[e.RowIndex].Cells[0].Value = !value;
|
||||
SetBreakpointFromCellClick(MicrocodeBank.ROM1, e.RowIndex);
|
||||
}
|
||||
}
|
||||
|
||||
ModifyMicrocodeBreakpoint((UInt16)_rom0SourceViewer.Rows[e.RowIndex].Tag, !value);
|
||||
}
|
||||
private void Ram0SourceViewCellClick(object sender, DataGridViewCellEventArgs e)
|
||||
{
|
||||
// Check for breakpoint column click.
|
||||
if (e.ColumnIndex == 0)
|
||||
{
|
||||
SetBreakpointFromCellClick(MicrocodeBank.RAM0, e.RowIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetBreakpointFromCellClick(MicrocodeBank bank, int index)
|
||||
{
|
||||
DataGridView view = null;
|
||||
|
||||
switch(bank)
|
||||
{
|
||||
case MicrocodeBank.ROM0:
|
||||
view = _rom0SourceViewer;
|
||||
break;
|
||||
|
||||
case MicrocodeBank.ROM1:
|
||||
view = _rom1SourceViewer;
|
||||
break;
|
||||
|
||||
case MicrocodeBank.RAM0:
|
||||
view = _ram0SourceViewer;
|
||||
break;
|
||||
}
|
||||
|
||||
// See if this is a source line, if so check/uncheck the box
|
||||
// and set/unset a breakpoint for the line
|
||||
if (view.Rows[index].Tag != null)
|
||||
{
|
||||
bool value = (bool)view.Rows[index].Cells[0].Value;
|
||||
view.Rows[index].Cells[0].Value = !value;
|
||||
|
||||
ModifyMicrocodeBreakpoint(bank, (UInt16)view.Rows[index].Tag, !value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,7 +342,7 @@ namespace Contralto
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshMicrocodeDisassembly(MicrocodeBank bank)
|
||||
private void UpdateMicrocodeDisassembly(MicrocodeBank bank)
|
||||
{
|
||||
DataGridView view = null;
|
||||
uint[] uCode = null;
|
||||
@ -414,9 +453,9 @@ namespace Contralto
|
||||
|
||||
}
|
||||
|
||||
private void ModifyMicrocodeBreakpoint(UInt16 address, bool set)
|
||||
private void ModifyMicrocodeBreakpoint(MicrocodeBank bank, UInt16 address, bool set)
|
||||
{
|
||||
_microcodeBreakpointEnabled[address] = set;
|
||||
_microcodeBreakpointEnabled[(int)bank,address] = set;
|
||||
}
|
||||
|
||||
private bool GetNovaBreakpoint(UInt16 address)
|
||||
@ -629,7 +668,7 @@ namespace Contralto
|
||||
|
||||
private void OnTabChanged(object sender, EventArgs e)
|
||||
{
|
||||
RefreshMicrocodeDisassembly();
|
||||
RefreshMicrocodeDisassembly(_system.CPU.CurrentTask.MPC);
|
||||
}
|
||||
|
||||
private void Debugger_Load(object sender, EventArgs e)
|
||||
@ -647,7 +686,7 @@ namespace Contralto
|
||||
UInt16 address = Convert.ToUInt16(JumpToAddress.Text, 8);
|
||||
|
||||
// find the source address that matches this, if any.
|
||||
HighlightMicrocodeSourceLine(_rom0SourceViewer, address);
|
||||
RefreshMicrocodeDisassembly(address);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@ -768,7 +807,7 @@ namespace Contralto
|
||||
case ExecutionType.NextNovaInstruction:
|
||||
// See if we need to stop here
|
||||
if (_execAbort || // The Stop button was hit
|
||||
_microcodeBreakpointEnabled[_system.CPU.CurrentTask.MPC] || // A microcode breakpoint was hit
|
||||
_microcodeBreakpointEnabled[(int)UCodeMemory.GetBank(_system.CPU.CurrentTask.TaskType),_system.CPU.CurrentTask.MPC] || // A microcode breakpoint was hit
|
||||
(_execType == ExecutionType.NextTask &&
|
||||
_system.CPU.NextTask != null &&
|
||||
_system.CPU.NextTask != _system.CPU.CurrentTask) || // The next task was switched to
|
||||
@ -914,7 +953,7 @@ namespace Contralto
|
||||
|
||||
// Microcode Debugger breakpoints; one entry per address since we only need
|
||||
// to worry about a 10 bit address space, this is fast and uses little memory.
|
||||
private bool[] _microcodeBreakpointEnabled;
|
||||
private bool[,] _microcodeBreakpointEnabled;
|
||||
|
||||
// Nova Debugger breakpoints; same as above
|
||||
private bool[] _novaBreakpointEnabled;
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
using Contralto.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
@ -21,6 +22,8 @@ namespace Contralto.IO
|
||||
Reset();
|
||||
|
||||
_fifoWakeupEvent = new Event(_fifoTransmitDuration, null, FIFOCallback);
|
||||
|
||||
_hostEthernet = new HostEthernet(null);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
@ -208,7 +211,9 @@ namespace Contralto.IO
|
||||
|
||||
Log.Write(LogComponent.EthernetController, "Sending {0} words from fifo.", _fifo.Count);
|
||||
|
||||
// TODO: actually transmit data in FIFO rather than bit-bucketing it.
|
||||
// Copy FIFO to host ethernet output buffer
|
||||
_fifo.CopyTo(_outputData, _outputIndex);
|
||||
_outputIndex += _fifo.Count;
|
||||
_fifo.Clear();
|
||||
|
||||
if (!end)
|
||||
@ -224,6 +229,10 @@ namespace Contralto.IO
|
||||
|
||||
// Wakeup at end of transmission. ("OUTGONE Post wakeup.")
|
||||
_system.CPU.WakeupTask(TaskType.Ethernet);
|
||||
|
||||
// And actually tell the host ethernet interface to send the data.
|
||||
_hostEthernet.Send(_outputData, _outputIndex);
|
||||
_outputIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,6 +240,32 @@ namespace Contralto.IO
|
||||
{
|
||||
// TODO: pull next packet off host ethernet interface that's destined for the Alto, and start the
|
||||
// process of putting into the FIFO and generating wakeups for the microcode.
|
||||
_receiverWaiting = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the host ethernet interface receives a packet destined for us.
|
||||
/// TODO: determine the best behavior here; we could queue up a number of packets and let
|
||||
/// the emulated interface pull them off one by one, or we could only save one packet and discard
|
||||
/// any that arrive while the emulated interface is processing the current one.
|
||||
///
|
||||
/// The latter is probably more faithful to the intent, but the former might be more useful on
|
||||
/// busy Ethernets (though the bottom-level filter implemented by HostEthernet might take care
|
||||
/// of that already.)
|
||||
///
|
||||
/// For now, we just accept one at a time.
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
private void OnHostPacketReceived(MemoryStream data)
|
||||
{
|
||||
if (_incomingPacket == null)
|
||||
{
|
||||
_incomingPacket = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Drop.
|
||||
}
|
||||
}
|
||||
|
||||
private Queue<ushort> _fifo;
|
||||
@ -253,6 +288,16 @@ namespace Contralto.IO
|
||||
private ulong _fifoTransmitDuration = 87075; // ~87000 nsec to transmit 16 words at 3mbit, assuming no collision
|
||||
private Event _fifoWakeupEvent;
|
||||
|
||||
// The actual connection to a real Ethernet device on the host
|
||||
HostEthernet _hostEthernet;
|
||||
|
||||
// Buffer to hold outgoing data to the host ethernet
|
||||
ushort[] _outputData;
|
||||
int _outputIndex;
|
||||
|
||||
// Incoming data
|
||||
MemoryStream _incomingPacket;
|
||||
|
||||
private AltoSystem _system;
|
||||
}
|
||||
}
|
||||
|
||||
183
Contralto/IO/HostEthernet.cs
Normal file
183
Contralto/IO/HostEthernet.cs
Normal file
@ -0,0 +1,183 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using PcapDotNet.Base;
|
||||
using PcapDotNet.Core;
|
||||
using PcapDotNet.Core.Extensions;
|
||||
using PcapDotNet.Packets;
|
||||
using PcapDotNet.Packets.Ethernet;
|
||||
using System.IO;
|
||||
|
||||
namespace Contralto.IO
|
||||
{
|
||||
|
||||
public struct EthernetInterface
|
||||
{
|
||||
public EthernetInterface(string name, string description, MacAddress macAddress)
|
||||
{
|
||||
Name = name;
|
||||
Description = description;
|
||||
MacAddress = macAddress;
|
||||
}
|
||||
|
||||
public static List<EthernetInterface> EnumerateDevices()
|
||||
{
|
||||
List<EthernetInterface> interfaces = new List<EthernetInterface>();
|
||||
|
||||
foreach (LivePacketDevice device in LivePacketDevice.AllLocalMachine)
|
||||
{
|
||||
interfaces.Add(new EthernetInterface(device.Name, device.Description, device.GetMacAddress()));
|
||||
}
|
||||
|
||||
return interfaces;
|
||||
}
|
||||
|
||||
public string Name;
|
||||
public string Description;
|
||||
public MacAddress MacAddress;
|
||||
}
|
||||
|
||||
public delegate void ReceivePacketDelegate(MemoryStream data);
|
||||
|
||||
/// <summary>
|
||||
/// Implements the logic for encapsulating a 3mbit ethernet packet into a 10mb packet and sending it over an actual
|
||||
/// interface controlled by the host operating system.
|
||||
///
|
||||
/// This uses PCap.NET to do the dirty work.
|
||||
/// </summary>
|
||||
public class HostEthernet
|
||||
{
|
||||
public HostEthernet(EthernetInterface iface)
|
||||
{
|
||||
AttachInterface(iface);
|
||||
}
|
||||
|
||||
public void RegisterReceiveCallback(ReceivePacketDelegate callback)
|
||||
{
|
||||
_callback = callback;
|
||||
|
||||
// Now that we have a callback we can start receiving stuff.
|
||||
Open(false /* not promiscuous */, int.MaxValue);
|
||||
BeginReceive();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sends an array of bytes over the ethernet as a 3mbit packet encapsulated in a 10mbit packet.
|
||||
/// </summary>
|
||||
/// <param name="packet"></param>
|
||||
/// <param name="hostId"></param>
|
||||
public void Send(ushort[] packet, int length)
|
||||
{
|
||||
// Sanity check.
|
||||
if (length < 1)
|
||||
{
|
||||
throw new InvalidOperationException("Raw packet data must contain at least two bytes for addressing.");
|
||||
}
|
||||
|
||||
//
|
||||
// Do this annoying dance to stuff the ushorts into bytes because this is C#.
|
||||
//
|
||||
byte[] packetBytes = new byte[length * 2];
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
packetBytes[i * 2] = (byte)(packet[i] >> 8);
|
||||
packetBytes[i * 2 + 1] = (byte)packet[i];
|
||||
}
|
||||
|
||||
//
|
||||
// Grab the source and destination host addresses from the packet we're sending
|
||||
// and build 10mbit versions.
|
||||
//
|
||||
byte destinationHost = packetBytes[0];
|
||||
byte sourceHost = packetBytes[1];
|
||||
|
||||
MacAddress destinationMac = new MacAddress((UInt48)(_10mbitMACPrefix | destinationHost));
|
||||
MacAddress sourceMac = new MacAddress((UInt48)(_10mbitMACPrefix | sourceHost));
|
||||
|
||||
// Build the outgoing packet; place the source/dest addresses, type field and the raw data.
|
||||
EthernetLayer ethernetLayer = new EthernetLayer
|
||||
{
|
||||
Source = sourceMac,
|
||||
Destination = destinationMac,
|
||||
EtherType = (EthernetType)_3mbitFrameType,
|
||||
};
|
||||
|
||||
PayloadLayer payloadLayer = new PayloadLayer
|
||||
{
|
||||
Data = new Datagram(packetBytes),
|
||||
};
|
||||
|
||||
PacketBuilder builder = new PacketBuilder(ethernetLayer, payloadLayer);
|
||||
|
||||
// Send it over the 'net!
|
||||
_communicator.SendPacket(builder.Build(DateTime.Now));
|
||||
}
|
||||
|
||||
private void ReceiveCallback(Packet p)
|
||||
{
|
||||
//
|
||||
// Filter out packets intended for the emulator, forward them on, drop everything else.
|
||||
//
|
||||
if ((int)p.Ethernet.EtherType == _3mbitFrameType &&
|
||||
(p.Ethernet.Destination.ToValue() & 0xffffffffff00) == _10mbitMACPrefix )
|
||||
{
|
||||
_callback(p.Ethernet.Payload.ToMemoryStream());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not for us, discard the packet.
|
||||
}
|
||||
}
|
||||
|
||||
private void AttachInterface(EthernetInterface iface)
|
||||
{
|
||||
_interface = null;
|
||||
|
||||
// Find the specified device by name
|
||||
foreach (LivePacketDevice device in LivePacketDevice.AllLocalMachine)
|
||||
{
|
||||
if (device.Name == iface.Name && device.GetMacAddress() == iface.MacAddress)
|
||||
{
|
||||
_interface = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_interface == null)
|
||||
{
|
||||
throw new InvalidOperationException("Requested interface not found.");
|
||||
}
|
||||
}
|
||||
|
||||
private void Open(bool promiscuous, int timeout)
|
||||
{
|
||||
_communicator = _interface.Open(0xffff, promiscuous ? PacketDeviceOpenAttributes.Promiscuous : PacketDeviceOpenAttributes.None, timeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begin receiving packets, forever.
|
||||
/// </summary>
|
||||
private void BeginReceive()
|
||||
{
|
||||
_communicator.ReceivePackets(-1, ReceiveCallback);
|
||||
}
|
||||
|
||||
private LivePacketDevice _interface;
|
||||
private PacketCommunicator _communicator;
|
||||
private ReceivePacketDelegate _callback;
|
||||
|
||||
private const int _3mbitFrameType = 0xbeef; // easy to identify, ostensibly unused by anything of any import
|
||||
|
||||
/// <summary>
|
||||
/// On output, these bytes are prepended to the Alto's 3mbit (1 byte) address to form a full
|
||||
/// 6 byte Ethernet MAC.
|
||||
/// On input, ethernet frames are checked for this prefix
|
||||
/// </summary>
|
||||
private UInt48 _10mbitMACPrefix = 0x0000aa010200; // 00-00-AA is the old Xerox vendor code, used just to be cute.
|
||||
}
|
||||
}
|
||||
@ -257,10 +257,11 @@ namespace Contralto.Memory
|
||||
case 3:
|
||||
|
||||
// debug
|
||||
/*
|
||||
if (_memoryAddress == 0xfc90 || _memoryAddress == 0xfc91 || _memoryAddress == 0x151) // 176220 -- status word for disk
|
||||
{
|
||||
Logging.Log.Write(Logging.LogComponent.Debug, "++> Task {0} wrote {1} to {3} (was {2}).", _task, Conversion.ToOctal(data), Conversion.ToOctal(DebugReadWord(_task, _memoryAddress)), Conversion.ToOctal(_memoryAddress));
|
||||
}
|
||||
}*/
|
||||
|
||||
_memoryData = data; // Only really necessary to show in debugger
|
||||
// Start of doubleword write:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user