Livt packages
Livt.Net
Version 1.4.1
Ethernet, IPv4, TCP, UDP, ARP, TFTP, and Telnet networking components for Livt hardware.
Published files (163)
src/drivers/ethernetlite/EthernetLiteTransmitter.lvt
namespace Livt.Net.Drivers.EthernetLite
using Livt.Net
enum EthernetLiteTransmitState
{
Idle
Borrowed
Terminal
}
/**
* Owns submission/completion metadata and borrows a statically bound source.
* The driver alone reads pending bytes and publishes terminal outcomes.
* No copy is required when the application already owns prepared packet storage.
*/
component EthernetLiteTransmitter<S: IPacketData, MAX_LENGTH: int = 1514> : IFrameTransmitter
{
static assert MAX_LENGTH >= 60 && MAX_LENGTH <= 1514, "TX length must fit a standard EthernetLite frame"
const LENGTH_BITS: int = Bits.RequiredFor(MAX_LENGTH)
// Prepared source remains owned by its caller and stable during a borrow.
source: S
phase: EthernetLiteTransmitState
length: logic[LENGTH_BITS]
ready: bool
failed: bool
outcome: FrameTransmitOutcome
/**
* Binds prepared data. Admission remains disabled until MAC initialization succeeds.
*/
new(source: S)
{
this.source = source
}
/**
* Composer-supplied Ethernet padding must bring frames to at least 60 bytes.
*/
override fn GetMinimumFrameLength() int
{
return 60
}
/**
* Reports the configured device frame limit, excluding FCS.
*/
override fn GetMaximumFrameLength() int
{
return MAX_LENGTH
}
/**
* Device transmission cannot be cancelled through this driver.
*/
override fn SupportsCancellation() bool
{
return false
}
/**
* Keeps the source borrowed through terminal device acceptance or failure.
*/
override fn IsSourceBorrowed() bool
{
return this.phase == EthernetLiteTransmitState.Borrowed
}
/**
* Borrows a prepared frame; acceptance is not delivery.
*/
override fn TrySubmit() FrameLinkResult
{
if (this.phase != EthernetLiteTransmitState.Idle) {
return FrameLinkResult.Busy
}
if (this.failed) {
return FrameLinkResult.DeviceFailure
}
if (!this.ready) {
return FrameLinkResult.NotReady
}
if (!this.source.IsReady()) {
return FrameLinkResult.Invalid
}
var size = this.source.GetAvailableLength()
if (size <= 0) {
return FrameLinkResult.Invalid
}
if (size < 60 || size > MAX_LENGTH) {
return FrameLinkResult.Unsupported
}
this.length = size as logic[LENGTH_BITS]
this.phase = EthernetLiteTransmitState.Borrowed
return FrameLinkResult.Accepted
}
/**
* Unsupported cancellation preserves a pending borrow.
*/
override fn TryCancel() FrameLinkResult
{
if (!this.IsSourceBorrowed()) {
return FrameLinkResult.Invalid
}
return FrameLinkResult.Unsupported
}
/**
* Reads the stable terminal result without clearing it.
*/
override fn TryGetCompletion(outcome: out FrameTransmitOutcome) FrameLinkResult
{
outcome = FrameTransmitOutcome.DeviceFailure
if (this.phase != EthernetLiteTransmitState.Terminal) {
return FrameLinkResult.NotReady
}
outcome = this.outcome
return FrameLinkResult.Success
}
/**
* Acknowledges the result and permits the next admission when initialized.
*/
override fn TryAcknowledgeCompletion() FrameLinkResult
{
if (this.phase != EthernetLiteTransmitState.Terminal) {
return FrameLinkResult.NotReady
}
this.phase = EthernetLiteTransmitState.Idle
this.length = 0
return FrameLinkResult.Success
}
/**
* Driver-only initialization/recovery status, independent of a latched completion.
*/
public fn SetDeviceReady(ready: bool, failed: bool)
{
this.ready = ready
this.failed = failed
}
/**
* Driver-only byte count for the current borrow.
*/
public fn GetPendingLength() int
{
return (this.length as uint) as int
}
/**
* Driver-only bounded source read; failure does not release ownership itself.
*/
public fn TryReadPending(index: int, value: out byte) PacketDataResult
{
value = 0x00
if (!this.IsSourceBorrowed()) {
return PacketDataResult.NotReady
}
if (index < 0 || index >= ((this.length as uint) as int)) {
return PacketDataResult.Invalid
}
var octet: byte = 0x00
var result = this.source.TryRead(index, octet)
value = octet
return result
}
/**
* Driver-only terminal transition, after all local source reads have stopped.
*/
public fn Complete(outcome: FrameTransmitOutcome)
{
if (!this.IsSourceBorrowed()) {
return
}
this.outcome = outcome
this.phase = EthernetLiteTransmitState.Terminal
}
}