PutPacket:
PUBLIC
ENTRY PROC [type, data1, data2, len:
CARD32 ← 0, pProc: SoftcardDataExch.PutProc] ~ {
h: Header;
done: CARD32 ← 0;
bufHead, bufTail: Block ← 0;
myLastWrittenPacket: Header ← GetLastWritten[data.myZone];
lastW: HeaderRec ← GetHeaderRec[data.myZone, myLastWrittenPacket];
prevSize: CARD32 ← lastW.size+(lastW.size MOD 2); -- round up to a word boundary
IF len>bufSize THEN Error; --oversized msg
h ← IF myLastWrittenPacket=maxHeaders-1 THEN 0 ELSE myLastWrittenPacket+1;
WHILE h=GetLastRed[data.hisZone]
DO
-- wait for a free header
Process.PauseMsec[ms: outputWaitingTime]
ENDLOOP;
bufHead ← IF lastW.b+prevSize>bufSize THEN lastW.b+prevSize-bufSize ELSE lastW.b+prevSize;
IF len>0
THEN {
bufTail ← IF bufHead+len>bufSize THEN bufHead+len-bufSize ELSE bufHead+len;
WHILE TouchSpace[data.myZone, GetLastRed[data.hisZone], myLastWrittenPacket, bufHead, bufTail]
DO
-- wait for some buffer space
Process.PauseMsec[ms: outputWaitingTime]
ENDLOOP;
};
PutHeaderRec[data.myZone, h, bufHead, len, type, data1, data2];
IF len>0
THEN {
DoAction:
PROC [ub: Basics.UnsafeBlock] ~ {
IF pProc#NIL THEN done ← done+pProc[ub];
};
IF bufHead<=bufTail
THEN {
realBase: CARD32 ← SoftcardBDVM.RealFromAddress[[data.myZone.a+buffer+bufHead/2]];
SoftcardBDVM.DoWithTranslation[realBase, len, DoAction]
}
ELSE {
realBase: CARD32 ← SoftcardBDVM.RealFromAddress[[data.myZone.a+buffer+bufHead/2]];
SoftcardBDVM.DoWithTranslation[realBase, bufSize-bufHead, DoAction];
realBase ← SoftcardBDVM.RealFromAddress[[data.myZone.a+buffer]];
SoftcardBDVM.DoWithTranslation[realBase, bufTail, DoAction];
};
};
PutLastWritten[data.myZone, h];
};
GetNextNonEmpty:
PROC [z: Zone, h, hl: Header]
RETURNS [findOne:
BOOLEAN, nh: Header] ~ {
size: CARD32 ← 0;
WHILE size=0
DO
IF h=maxHeaders-1 THEN h ← 0 ELSE h ← h+1;
size ← GetHeaderRec[z, h].size;
IF h=hl THEN RETURN[FALSE, 0];
ENDLOOP;
RETURN [TRUE, h];
};
TouchSpace:
PROC [z: Zone, h, hl: Header, head, tail: Block]
RETURNS[
OK:
BOOLEAN] ~ {
checks that [head..tail) does not overlap target, with special care of the circularity
target: Block;
nh: Header;
findOne: BOOLEAN;
IF h=hl THEN RETURN[FALSE];
[findOne, nh] ← GetNextNonEmpty[z, h, hl];
IF NOT findOne THEN RETURN[FALSE];
target ← GetHeaderRec[z, nh].b;
IF tail<target THEN RETURN [FALSE]
ELSE RETURN [ head>tail];
};