<> <> <> <> <> <<>> <> <<>> DIRECTORY Basics USING [UnsafeBlock], Process USING [Abort, Detach, PauseMsec, Milliseconds, InvalidProcess], SoftcardBDVM, SoftcardDataExch, SoftcardUtil; SoftcardDataExchImpl: CEDAR MONITOR IMPORTS Process, SoftcardBDVM, SoftcardUtil EXPORTS SoftcardDataExch ~ BEGIN <> Address: TYPE ~ SoftcardUtil.Address; Block: TYPE ~ CARD32; -- local pointer to Block buffer Header: TYPE ~ CARD32; -- local pointer to HeaderRec; HeaderRec: TYPE ~ RECORD [ b: Block, size: CARD32, type: CARD32, data1: CARD32, data2: CARD32 ]; Zone: TYPE ~ Address; bufSize: CARD32 = 31096; maxHeaders: CARD32 = 32; <> <> <> <> <> <> <<];>> lastWritten: CARD32 = 0; lastRed: CARD32 = lastWritten+2; headers: CARD32 = lastRed+2; buffer: CARD32 = headers+SIZE[HeaderRec]*maxHeaders; --324 zoneSize: CARD32 = buffer+bufSize/2; backDoorAddress: Address _ [1E2400h]; BiZone: TYPE ~ RECORD[hisZone, myZone: Zone]; data: BiZone _ [backDoorAddress, [backDoorAddress.a+zoneSize]]; watchingProcess: PROCESS _ NIL; <> Error: ERROR ~ CODE; FillZones: PROC [w: UNSPECIFIED _ 0] ~ TRUSTED { SoftcardUtil.FillZones[backDoorAddress, 2*zoneSize]; }; Restart: PUBLIC PROC ~ TRUSTED { IF watchingProcess#NIL THEN Process.Abort[watchingProcess ! Process.InvalidProcess => CONTINUE]; FillZones[0]; watchingProcess _ FORK WatchPacketsIn[]; Process.Detach[watchingProcess]; }; GetLastRed: PROC [zone: Zone] RETURNS [h: Header] ~ TRUSTED INLINE { RETURN[SoftcardUtil.GetCard32[[zone.a+lastRed]]]; }; GetLastWritten: PROC [zone: Zone] RETURNS [h: Header] ~ TRUSTED INLINE { RETURN[SoftcardUtil.GetCard32[[zone.a+lastWritten]]]; }; PutLastRed: PROC [zone: Zone, h: Header] ~ TRUSTED INLINE { SoftcardUtil.PutCard32[[zone.a+lastRed], h]; }; PutLastWritten: PROC [zone: Zone, h: Header] ~ TRUSTED INLINE { SoftcardUtil.PutCard32[[zone.a+lastWritten], h]; }; GetHeaderRec: PROC [zone: Zone, h: Header] RETURNS [hr: HeaderRec] ~ TRUSTED { base: CARD32 _ zone.a+headers+SIZE[HeaderRec]*h; hr.b _ SoftcardUtil.GetCard32[[base]]; hr.size _ SoftcardUtil.GetCard32[[base+2]]; hr.type _ SoftcardUtil.GetCard32[[base+4]]; hr.data1 _ SoftcardUtil.GetCard32[[base+6]]; hr.data2 _ SoftcardUtil.GetCard32[[base+8]]; }; PutHeaderRec: PROC [zone: Zone, h: Header, b: Block, len, type, data1, data2: CARD32] ~ TRUSTED { base: CARD32 _ zone.a+headers+SIZE[HeaderRec]*h; SoftcardUtil.PutCard32[[base], b]; SoftcardUtil.PutCard32[[base+2], len]; SoftcardUtil.PutCard32[[base+4], type]; SoftcardUtil.PutCard32[[base+6], data1]; SoftcardUtil.PutCard32[[base+8], data2]; }; <> outputWaitingTime: Process.Milliseconds _ 1; --ms 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] ~ { <> 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 tailtail]; }; <> inputWaitingTime: Process.Milliseconds _ 1; --ms WatchPacketsIn: PUBLIC PROC ~ { <> DO proc: SoftcardDataExch.ActionProc; hVal: HeaderRec; myLastRedPacket: Header _ GetLastRed[data.myZone]; h: Header _ IF myLastRedPacket=maxHeaders-1 THEN 0 ELSE myLastRedPacket+1; WHILE GetLastWritten[data.hisZone]=myLastRedPacket DO Process.PauseMsec[ms: inputWaitingTime] ENDLOOP; hVal _ GetHeaderRec[data.hisZone, h]; proc _ GetRegProc[hVal.type]; IF hVal.size #0 THEN { DoAction: PROC [ub: Basics.UnsafeBlock] ~ { IF proc#NIL THEN proc[ub, hVal.type, hVal.data1, hVal.data2]; }; bufHead: Block _ hVal.b; bufTail: Block _ IF bufHead+hVal.size>bufSize THEN bufHead+hVal.size-bufSize ELSE bufHead+hVal.size; IF bufHead<=bufTail THEN { realBase: CARD32 _ SoftcardBDVM.RealFromAddress[[data.hisZone.a+buffer+bufHead/2]]; SoftcardBDVM.DoWithTranslation[realBase, hVal.size, DoAction]; } ELSE { realBase: CARD32 _ SoftcardBDVM.RealFromAddress[[data.hisZone.a+buffer+bufHead/2]]; SoftcardBDVM.DoWithTranslation[realBase, bufSize-bufHead, DoAction]; realBase _ SoftcardBDVM.RealFromAddress[[data.hisZone.a+buffer]]; SoftcardBDVM.DoWithTranslation[realBase, bufTail, DoAction]; }; } ELSE IF proc#NIL THEN proc[[], hVal.type, hVal.data1, hVal.data2]; PutLastRed[data.myZone, h]; ENDLOOP; }; <<>> typeMask: CARD32 = 31; registration: ARRAY [0..typeMask] OF SoftcardDataExch.ActionProc; GetRegProc: PROC [type: CARD32] RETURNS [a: SoftcardDataExch.ActionProc] ~ { <<Description of the procedure.>> a _ registration[type]; }; Register: PUBLIC PROC [type: CARD32, proc: SoftcardDataExch.ActionProc] ~ { registration[type] _ proc; }; END.