mirror of
https://github.com/livingcomputermuseum/ContrAlto.git
synced 2026-01-20 01:44:34 +00:00
185 lines
8.7 KiB
C#
185 lines
8.7 KiB
C#
using Contralto.IO;
|
|
using Contralto.Logging;
|
|
using System;
|
|
|
|
namespace Contralto.CPU
|
|
{
|
|
public partial class AltoCPU
|
|
{
|
|
/// <summary>
|
|
/// EthernetTask implements Ethernet-specific task function
|
|
/// </summary>
|
|
private sealed class EthernetTask : Task
|
|
{
|
|
public EthernetTask(AltoCPU cpu) : base(cpu)
|
|
{
|
|
_taskType = TaskType.Ethernet;
|
|
_wakeup = false;
|
|
|
|
_ethernetController = _cpu._system.EthernetController;
|
|
}
|
|
|
|
protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction)
|
|
{
|
|
// The Ethernet task only remains awake if there are pending data wakeups
|
|
if (_ethernetController.CountdownWakeup)
|
|
{
|
|
//
|
|
// The resulting [Countdown] wakeup is cleared when the Ether task next runs.
|
|
_ethernetController.CountdownWakeup = false;
|
|
_wakeup = false;
|
|
}
|
|
|
|
return base.ExecuteInstruction(instruction);
|
|
}
|
|
|
|
protected override ushort GetBusSource(int bs)
|
|
{
|
|
EthernetBusSource ebs = (EthernetBusSource)bs;
|
|
|
|
switch(ebs)
|
|
{
|
|
case EthernetBusSource.EIDFCT:
|
|
// Input Data Function. Gates the contents of the FIFO to BUS[0-15], and
|
|
// increments the read pointer at the end of the cycle.
|
|
return _ethernetController.ReadInputFifo(false /* increment read pointer */);
|
|
|
|
default:
|
|
throw new NotImplementedException(String.Format("Unimplemented Ethernet BS {0}", ebs));
|
|
}
|
|
}
|
|
|
|
protected override void ExecuteSpecialFunction1Early(MicroInstruction instruction)
|
|
{
|
|
EthernetF1 ef1 = (EthernetF1)instruction.F1;
|
|
switch (ef1)
|
|
{
|
|
case EthernetF1.EILFCT:
|
|
// Early: Input Look Function. Gates the contents of the FIFO to BUS[0-15] but does
|
|
// not increment the read pointer.
|
|
_busData &= _ethernetController.ReadInputFifo(true /* do not increment read pointer */);
|
|
break;
|
|
}
|
|
}
|
|
|
|
protected override void ExecuteSpecialFunction1(MicroInstruction instruction)
|
|
{
|
|
EthernetF1 ef1 = (EthernetF1)instruction.F1;
|
|
switch(ef1)
|
|
{
|
|
case EthernetF1.EILFCT:
|
|
// Nothing; handled in Early handler.
|
|
break;
|
|
|
|
case EthernetF1.EPFCT:
|
|
// Post Function. Gates interface status to BUS[8-15]. Resets the interface at
|
|
// the end of the cycle and removes wakeup for this task.
|
|
_busData &= _ethernetController.Status;
|
|
_ethernetController.ResetInterface();
|
|
_wakeup = false;
|
|
Log.Write(LogComponent.EthernetController, "EPFCT: Status {0}, bus now {1}",
|
|
Conversion.ToOctal(_ethernetController.Status),
|
|
Conversion.ToOctal(_busData));
|
|
break;
|
|
|
|
case EthernetF1.EWFCT:
|
|
// Countdown Wakeup Function. Sets a flip flop in the interface that will
|
|
// cause a wakeup to the Ether task on the next tick of SWAKMRT. This
|
|
// function must be issued in the instruction after a TASK. The resulting
|
|
// wakeup is cleared when the Ether task next runs.
|
|
Log.Write(LogComponent.EthernetController, "Enabling countdown wakeups.");
|
|
_ethernetController.CountdownWakeup = true;
|
|
break;
|
|
|
|
default:
|
|
throw new NotImplementedException(String.Format("Unimplemented Ethernet F1 {0}", ef1));
|
|
|
|
}
|
|
}
|
|
|
|
protected override void ExecuteSpecialFunction2(MicroInstruction instruction)
|
|
{
|
|
EthernetF2 ef2 = (EthernetF2)instruction.F2;
|
|
switch (ef2)
|
|
{
|
|
case EthernetF2.EODFCT:
|
|
// Output Data Function. Loads the FIFO from BUS[0-15], then increments the
|
|
// write pointer at the end of the cycle.
|
|
_ethernetController.WriteOutputFifo(_busData);
|
|
break;
|
|
|
|
case EthernetF2.EOSFCT:
|
|
// Output Start Function. Sets the OBusy flip flop in the interface, starting
|
|
// data wakeups to fill the FIFO for output. When the FIFO is full, or EEFct has
|
|
// been issued, the interface will wait for silence on the Ether and begin
|
|
// transmitting.
|
|
_ethernetController.StartOutput();
|
|
break;
|
|
|
|
case EthernetF2.ERBFCT:
|
|
// Reset Branch Function. This command dispatch function merges the ICMD
|
|
// and OCMD flip flops, into NEXT[6-7]. These flip flops are the means of
|
|
// communication between the emulator task and the Ethernet task. The
|
|
// emulator task sets them from BUS[14-15] with the STARTF function, causing
|
|
// the Ethernet task to wakeup, dispatch on them and then reset them with
|
|
// EPFCT.
|
|
Log.Write(LogComponent.EthernetController, "EBRBFCT: SIO is {0}.", _ethernetController.IOCMD);
|
|
_nextModifier |= (ushort)((_ethernetController.IOCMD << 2));
|
|
break;
|
|
|
|
case EthernetF2.EEFCT:
|
|
// End of transmission Function. This function is issued when all of the main
|
|
// memory output buffer has been transferred to the FIFO. EEFCT disables
|
|
// further data wakeups.
|
|
_ethernetController.EndTransmission();
|
|
break;
|
|
|
|
case EthernetF2.EBFCT:
|
|
// Branch Function. ORs a one into NEXT[7] if an input data late is detected,
|
|
// or an SIO with AC0[14:15] non-zero is issued, or if the transmitter or receiver
|
|
// goes done. ORs a one into NEXT[6] if a collision is detected.
|
|
|
|
if (_ethernetController.DataLate ||
|
|
_ethernetController.IOCMD != 0 ||
|
|
_ethernetController.OperationDone)
|
|
{
|
|
Log.Write(LogComponent.EthernetController, "EBFCT: DataLate {0} IOCMD {1} Done {2}", _ethernetController.DataLate, _ethernetController.IOCMD, _ethernetController.OperationDone);
|
|
_nextModifier |= 0x4;
|
|
}
|
|
|
|
if (_ethernetController.Collision)
|
|
{
|
|
Log.Write(LogComponent.EthernetController, "EBFCT: Collision");
|
|
_nextModifier |= 0x8;
|
|
}
|
|
break;
|
|
|
|
case EthernetF2.ECBFCT:
|
|
// Countdown Branch Function. ORs a one into NEXT[7] if the FIFO is not
|
|
// empty.
|
|
if (!_ethernetController.FIFOEmpty)
|
|
{
|
|
Log.Write(LogComponent.EthernetController, "ECBFCT: FIFO not empty");
|
|
_nextModifier |= 0x4;
|
|
}
|
|
break;
|
|
|
|
case EthernetF2.EISFCT:
|
|
// Input Start Function. Sets the IBusy flip flop in the interface, causing it to
|
|
// hunt for the beginning of a packet: silence on the Ether followed by a
|
|
// transition. When the interface has collected two words, it will begin
|
|
// generating data wakeups to the microcode.
|
|
_ethernetController.StartInput();
|
|
break;
|
|
|
|
default:
|
|
throw new NotImplementedException(String.Format("Unimplemented Ethernet F2 {0}", ef2));
|
|
|
|
}
|
|
}
|
|
|
|
private EthernetController _ethernetController;
|
|
}
|
|
}
|
|
}
|