172 lines
5.6 KiB
Plaintext
172 lines
5.6 KiB
Plaintext
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// File: TulipDeviceChannel.sg
|
|
//
|
|
|
|
using Microsoft.SingSharp;
|
|
|
|
using Microsoft.Singularity.Channels;
|
|
using Microsoft.Singularity.Io;
|
|
using Microsoft.Singularity.Io.Net;
|
|
using Microsoft.Singularity.Directory;
|
|
using Microsoft.Singularity.V1.Services;
|
|
|
|
using System;
|
|
using System.Threading;
|
|
|
|
namespace Microsoft.Singularity.Drivers.Network.Tulip
|
|
{
|
|
internal class TulipDeviceChannel
|
|
{
|
|
Tulip! device;
|
|
TRef<NicDeviceContract.Exp:Start> channel;
|
|
|
|
private TulipDeviceChannel(
|
|
Tulip! theDevice,
|
|
[Claims] NicDeviceContract.Exp:Start! channel
|
|
)
|
|
ensures this.channel != null;
|
|
{
|
|
this.device = theDevice;
|
|
this.channel = new TRef<NicDeviceContract.Exp:Start>(channel);
|
|
base();
|
|
}
|
|
|
|
private bool IoRunningMessageLoop(NicDeviceContract.Exp! ep)
|
|
{
|
|
device.StartIo();
|
|
|
|
for (;;) {
|
|
switch receive {
|
|
case ep.GiveRxPacketsToDevice(rxFifo):
|
|
device.ReceivePackets(rxFifo);
|
|
device.GetReceivedPackets(rxFifo);
|
|
ep.SendTakeRxPacketsFromDevice(rxFifo);
|
|
break;
|
|
|
|
case ep.GiveTxPacketsToDevice(txFifo):
|
|
device.TransmitPackets(txFifo);
|
|
device.GetTransmittedPackets(txFifo);
|
|
ep.SendTakeTxPacketsFromDevice(txFifo);
|
|
break;
|
|
|
|
case ep.StopIO():
|
|
device.StopIo();
|
|
return true;
|
|
|
|
case ep.ChannelClosed():
|
|
device.StopIo();
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private bool IoConfigureMessagePump(NicDeviceContract.Exp! ep)
|
|
{
|
|
Tracing.Log(Tracing.Debug,
|
|
"Tulip entered {0} state", ep.CurrentState());
|
|
|
|
for (;;) {
|
|
switch receive{
|
|
case ep.RegisterForEvents(eventExp):
|
|
ep.SendSuccess();
|
|
eventExp.SendSuccess();
|
|
device.SetEventRelay(
|
|
new TulipEventRelay(eventExp)
|
|
);
|
|
break;
|
|
|
|
case ep.SetChecksumProperties(checksumSupport):
|
|
if (checksumSupport == ChecksumSupport.None) {
|
|
ep.SendSuccess();
|
|
}
|
|
else {
|
|
ep.SendUnsupportedChecksumProperties();
|
|
}
|
|
break;
|
|
|
|
case ep.StartIO():
|
|
ep.SendAckStartIO();
|
|
return IoRunningMessageLoop(ep);
|
|
|
|
case ep.ChannelClosed():
|
|
return false;
|
|
|
|
case unsatisfiable:
|
|
DebugStub.Break();
|
|
break;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private void GetDeviceProperties(NicDeviceProperties*! in ExHeap ndp)
|
|
{
|
|
expose (ndp) {
|
|
delete ndp->DriverName;
|
|
ndp->DriverName = Bitter.FromString2(device.Name);
|
|
|
|
delete ndp->DriverVersion;
|
|
ndp->DriverVersion = Bitter.FromString2(device.Version);
|
|
|
|
ndp->MacType = MacType.Ethernet;
|
|
delete ndp->MacAddress;
|
|
ndp->MacAddress =
|
|
Bitter.FromByteArray(device.HardwareAddressBytes);
|
|
|
|
ndp->ChecksumSupport = ChecksumSupport.None;
|
|
ndp->MtuBytes = Tulip.MtuBytes;
|
|
ndp->MaxRxFragmentsPerPacket = Tulip.MaxRxFragmentsPerPacket;
|
|
ndp->MaxTxFragmentsPerPacket = Tulip.MaxTxFragmentsPerPacket;
|
|
ndp->MaxRxPacketsInDevice = Tulip.MaxRxPackets;
|
|
ndp->MaxTxPacketsInDevice = Tulip.MaxTxPackets;
|
|
}
|
|
}
|
|
|
|
private void ReadyMessagePump()
|
|
requires this.channel != null;
|
|
{
|
|
NicDeviceContract.Exp! ep = channel.Acquire();
|
|
channel = null;
|
|
|
|
assert ep.InState(NicDeviceContract.Start.Value);
|
|
ep.SendSuccess();
|
|
assert ep.InState(NicDeviceContract.READY.Value);
|
|
|
|
try {
|
|
NicDeviceProperties*! in ExHeap ndp;
|
|
ep.RecvGetDeviceProperties(out ndp);
|
|
GetDeviceProperties(ndp);
|
|
ep.SendDeviceProperties(ndp);
|
|
|
|
ep.RecvConfigureIO();
|
|
ep.SendAckConfigureIO();
|
|
IoConfigureMessagePump(ep);
|
|
}
|
|
catch (Exception e) {
|
|
DebugStub.Print("Caught exception: {0}\n",
|
|
__arglist(e.ToString()));
|
|
}
|
|
finally
|
|
{
|
|
delete ep;
|
|
}
|
|
}
|
|
|
|
internal static bool
|
|
CreateThread(Tulip! tulip, [Claims] NicDeviceContract.Exp:Start! ep)
|
|
{
|
|
TulipDeviceChannel tdc = new TulipDeviceChannel(tulip, ep);
|
|
Thread thread = new Thread(new ThreadStart(tdc.ReadyMessagePump));
|
|
thread.Start();
|
|
return true;
|
|
}
|
|
}
|
|
}
|