diff --git a/.gitignore b/.gitignore
index 7964536..96bd921 100644
--- a/.gitignore
+++ b/.gitignore
@@ -186,4 +186,8 @@ FakesAssemblies/
# LightSwitch generated files
GeneratedArtifacts/
_Pvt_Extensions/
-ModelManifest.xml
\ No newline at end of file
+ModelManifest.xml
+/PUP/.vs/IFS/v15/Server/sqlite3/db.lock
+/PUP/.vs/IFS/v15/Server/sqlite3/storage.ide
+/PUP/.vs/IFS/v15/Server/sqlite3/storage.ide-shm
+/PUP/.vs/IFS/v15/Server/sqlite3/storage.ide-wal
diff --git a/PUP/Conf/ifs.cfg b/PUP/Conf/ifs.cfg
index 25b2ce4..a890586 100644
--- a/PUP/Conf/ifs.cfg
+++ b/PUP/Conf/ifs.cfg
@@ -36,4 +36,4 @@ BOLDelay = 5000
# Debug settings
LogTypes = All
-LogComponents = Routing
+LogComponents = None
diff --git a/PUP/Entrypoint.cs b/PUP/Entrypoint.cs
index 716203f..175d292 100644
--- a/PUP/Entrypoint.cs
+++ b/PUP/Entrypoint.cs
@@ -85,7 +85,8 @@ namespace IFS
{
foreach (LivePacketDevice device in LivePacketDevice.AllLocalMachine)
{
- if (device.GetNetworkInterface().Name.ToLowerInvariant() == Configuration.InterfaceName.ToLowerInvariant())
+ if (device.GetNetworkInterface() != null &&
+ device.GetNetworkInterface().Name.ToLowerInvariant() == Configuration.InterfaceName.ToLowerInvariant())
{
Router.Instance.RegisterRAWInterface(device);
bFound = true;
diff --git a/PUP/IFS.csproj b/PUP/IFS.csproj
index f5a717f..6918367 100644
--- a/PUP/IFS.csproj
+++ b/PUP/IFS.csproj
@@ -139,7 +139,9 @@
PreserveNewest
-
+
+ PreserveNewest
+
PreserveNewest
diff --git a/PUP/MiscServicesProtocol.cs b/PUP/MiscServicesProtocol.cs
index d2363e7..5698802 100644
--- a/PUP/MiscServicesProtocol.cs
+++ b/PUP/MiscServicesProtocol.cs
@@ -113,7 +113,11 @@ namespace IFS
case PupType.MailCheckRequestLaurel:
SendMailCheckResponse(p);
- break;
+ break;
+
+ case PupType.MicrocodeRequest:
+ SendMicrocodeResponse(p);
+ break;
default:
Log.Write(LogComponent.MiscServices, String.Format("Unhandled misc. protocol {0}", p.Type));
@@ -427,6 +431,90 @@ namespace IFS
}
}
+ private void SendMicrocodeResponse(PUP p)
+ {
+ //
+ // The request PUP contains the file number in the lower-order 16-bits of the pup ID.
+ // Assuming the number is a valid bootfile, we start sending it to the client's port via EFTP.
+ //
+ ushort fileNumber = (ushort)p.ID;
+
+ Log.Write(LogType.Verbose, LogComponent.MiscServices, "Microcode request is for file {0}.", fileNumber);
+
+ FileStream microcodeFile = BootServer.GetStreamForNumber(fileNumber);
+
+ if (microcodeFile == null)
+ {
+ Log.Write(LogType.Warning, LogComponent.MiscServices, "Microcode file {0} does not exist or could not be opened.", fileNumber);
+ }
+ else
+ {
+ // Send the file. The MicrocodeReply protocol is extremely simple:
+ // Just send a sequence of MicrocodeReply PUPs containing the microcode data,
+ // there are no acks or flow control of any kind.
+ Log.Write(LogType.Warning, LogComponent.MiscServices, "Sending microcode file {0}.", fileNumber);
+ SendMicrocodeFile(p.SourcePort, microcodeFile);
+ }
+ }
+
+ private void SendMicrocodeFile(PUPPort sourcePort, Stream microcodeFile)
+ {
+ //
+ // "For version 1 of the protocol, a server willing to supply the data simply sends a sequence of packets
+ // of type MicrocodeReply as fast as it can. The high half of its pupID contains the version number(1)
+ // and the low half of the pupID contains the packet sequence number. After all the data packets
+ // have been sent, the server sends an empty (0 data bytes) packet for an end marker. There are no
+ // acknowledgments. This protocol is used by Dolphins and Dorados.
+ // Currently, the version 1 servers send packets containing 3 * n words of data. This constraint is imposed by the
+ // Rev L Dolphin EPROM microcode. I’d like to remove this restriction if I get a chance, so please don’t take
+ // advantage of it unless you need to.The Rev L Dolphin EPROM also requires the second word of the source
+ // socket to be 4. / HGM May - 80."
+ //
+
+ // TODO: this should happen in a worker thread.
+ //
+
+ //
+ // We send 192 words of data per PUP (3 * 64) in an attempt to make the Dolphin happy.
+ // We space these out a bit to give the D-machine time to keep up, we're much much faster than they are.
+ //
+ PUPPort localPort = new PUPPort(DirectoryServices.Instance.LocalHostAddress, 4);
+
+ byte[] buffer = new byte[384];
+ bool done = false;
+ uint id = 0;
+
+ while (!done)
+ {
+ int read = microcodeFile.Read(buffer, 0, buffer.Length);
+
+ if (read < buffer.Length)
+ {
+ done = true;
+ }
+
+ if (read > 0)
+ {
+ PUP microcodeReply = new PUP(PupType.MicrocodeReply, (id | 0x00010000), sourcePort, localPort, buffer);
+ Router.Instance.SendPup(microcodeReply);
+ }
+
+ // Pause a bit to give the D0 time to breathe.
+ System.Threading.Thread.Sleep(5);
+
+ id++;
+ }
+
+ //
+ // Send an empty packet to conclude the transfer.
+ //
+ PUP endReply = new PUP(PupType.MicrocodeReply, (id | 0x00010000), sourcePort, localPort, new byte[] { });
+ Router.Instance.SendPup(endReply);
+
+ Log.Write(LogType.Warning, LogComponent.MiscServices, "Microcode file sent.");
+
+ }
+
private struct BootDirectoryBlock
{
public ushort FileNumber;
diff --git a/PUP/PUP.cs b/PUP/PUP.cs
index 0e58528..f5f2aac 100644
--- a/PUP/PUP.cs
+++ b/PUP/PUP.cs
@@ -97,7 +97,11 @@ namespace IFS
// Gateway Information Protocol
GatewayInformationRequest = 128,
- GatewayInformationResponse = 129
+ GatewayInformationResponse = 129,
+
+ // D0 Microcode (handled by misc. services)
+ MicrocodeRequest = 180,
+ MicrocodeReply = 181,
}
public struct PUPPort
diff --git a/PUP/Transport/Ethernet.cs b/PUP/Transport/Ethernet.cs
index 3f30d0f..074a4b8 100644
--- a/PUP/Transport/Ethernet.cs
+++ b/PUP/Transport/Ethernet.cs
@@ -53,7 +53,7 @@ namespace IFS.Transport
_routerCallback = callback;
// Now that we have a callback we can start receiving stuff.
- Open(false /* not promiscuous */, int.MaxValue);
+ Open(false /* not promiscuous */, 0);
// Kick off the receiver thread, this will never return or exit.
Thread receiveThread = new Thread(new ThreadStart(BeginReceive));
@@ -207,7 +207,7 @@ namespace IFS.Transport
else
{
// Not a PUP, Discard the packet. We will not log this, so as to keep noise down.
- //Log.Write(LogLevel.DroppedPacket, "Not a PUP. Dropping.");
+ // Log.Write(LogType.Verbose, LogComponent.Ethernet, "Not a PUP (type 0x{0:x}. Dropping.", p.Ethernet.EtherType);
}
}
@@ -215,7 +215,7 @@ namespace IFS.Transport
{
_communicator = _interface.Open(
0xffff,
- promiscuous ? PacketDeviceOpenAttributes.Promiscuous | PacketDeviceOpenAttributes.NoCaptureLocal: PacketDeviceOpenAttributes.NoCaptureLocal,
+ promiscuous ? PacketDeviceOpenAttributes.Promiscuous : PacketDeviceOpenAttributes.None,
timeout);
_communicator.SetKernelMinimumBytesToCopy(1);