-- File: RS232CDriverB.mesa -- LastEdited: 7-Jan-82 14:57:16 By: Danielson -- This is the Object Monitor for RS232C ChannelStatus records DIRECTORY Process USING [SetTimeout], RS232C USING [ AutoRecognitionOutcome, CompletionHandle, DeviceStatus, LineType, OperationClass, Parameter, PhysicalRecordHandle, TransferStatus, UnimplementedFeature], RS232CFace USING [ AutoRecognitionWait, AbortInput, AbortOutput, AbortStatus, DeviceStatus, Get, GetStatus, Put, ResetLine, SendBreak, SetParameters, StatusWait, TransferStatus, TransferWait, TransmitNow], RS232CInternal USING [ asynchronousDefaults, autoRecognitionDefaults, bitSynchronousDefaults, byteSynchronousDefaults, ChannelStatusHandle]; RS232CDriverB: MONITOR LOCKS channel USING channel: ChannelHandle IMPORTS Process, RS232C, RS232CFace EXPORTS RS232C, RS232CInternal = BEGIN ChannelHandle: PUBLIC TYPE = RS232CInternal.ChannelStatusHandle; ChannelSuspended: PUBLIC ERROR = CODE; InvalidParameter: PUBLIC ERROR = CODE; SendBreakIllegal: PUBLIC ERROR = CODE; aMoment: CONDITION; ConvertFaceToChannelTransferStatus: ARRAY RS232CFace.TransferStatus OF RS232C.TransferStatus = [ success, dataLost, deviceError, frameTimeout, checksumError, parityError, asynchFramingError, invalidChar, invalidFrame, aborted, disaster]; AutoRecognitionWait: PUBLIC PROCEDURE [channel: ChannelHandle] RETURNS [outcome: RS232C.AutoRecognitionOutcome] = BEGIN IF channel.otherSuspended THEN ERROR ChannelSuspended; outcome ← RS232CFace.AutoRecognitionWait[channel.face]; END; DecrementStatusWaitCount: PRIVATE ENTRY PROCEDURE [channel: ChannelHandle] = BEGIN ENABLE UNWIND => NULL; -- Required in order to release monitor lock channel.statusWaitCount ← channel.statusWaitCount - 1; END; DeleteChannel: PUBLIC ENTRY PROCEDURE [channel: ChannelHandle] = BEGIN ENABLE UNWIND => NULL; -- Required in order to release monitor lock channel.inputSuspended ← channel.outputSuspended ← channel.otherSuspended ← TRUE; RS232CFace.AbortOutput[channel.face]; RS232CFace.AbortInput[channel.face]; RS232CFace.AbortStatus[channel.face]; --This will complete calls to RS232CFace.StatusWait, --and consequently, calls to RS232C.StatusWait as well. channel.parameterRecord.dataTerminalReady ← FALSE; IF RS232CFace.SetParameters[channel.face, @channel.parameterRecord] # success THEN ERROR; -- This should be logged as a system error; UNTIL channel.statusWaitCount = 0 DO WAIT aMoment; ENDLOOP; -- This guaranteees that Delete has completed. END; Get: PUBLIC ENTRY PROCEDURE [ channel: ChannelHandle, rec: RS232C.PhysicalRecordHandle] RETURNS [RS232C.CompletionHandle] = BEGIN ENABLE UNWIND => NULL; IF channel.inputSuspended THEN ERROR ChannelSuspended; RETURN[RS232CFace.Get[channel.face, rec]]; END; GetStatus: PUBLIC PROCEDURE [channel: ChannelHandle] RETURNS [stat: RS232C.DeviceStatus] = BEGIN faceStat: RS232CFace.DeviceStatus; IF channel.otherSuspended THEN ERROR ChannelSuspended; faceStat ← RS232CFace.GetStatus[channel.face]; RETURN[ [ FALSE, faceStat.dataLost, faceStat.breakDetected, faceStat.clearToSend, faceStat.dataSetReady, faceStat.carrierDetect, faceStat.ringHeard, faceStat.ringIndicator, faceStat.deviceError]]; END; IncrementStatusWaitCount: PRIVATE ENTRY PROCEDURE [channel: ChannelHandle] = BEGIN ENABLE UNWIND => NULL; -- Required in order to release monitor lock channel.statusWaitCount ← channel.statusWaitCount + 1; END; Put: PUBLIC ENTRY PROCEDURE [ channel: ChannelHandle, rec: RS232C.PhysicalRecordHandle] RETURNS [RS232C.CompletionHandle] = BEGIN ENABLE UNWIND => NULL; IF channel.outputSuspended THEN ERROR ChannelSuspended; RETURN[RS232CFace.Put[channel.face, rec]] END; Restart: PUBLIC ENTRY PROCEDURE [ channel: ChannelHandle, class: RS232C.OperationClass] = BEGIN ENABLE UNWIND => NULL; -- Required in order to release monitor lock SELECT class FROM input => channel.inputSuspended ← FALSE; output => channel.outputSuspended ← FALSE; other => channel.otherSuspended ← FALSE; all => channel.inputSuspended ← channel.inputSuspended ← channel.otherSuspended ← FALSE; ENDCASE => ERROR; -- This should be logged as a system error. END; SendBreak: PUBLIC PROCEDURE [channel: ChannelHandle] = BEGIN IF channel.outputSuspended THEN ERROR ChannelSuspended; IF channel.parameterRecord.lineType = byteSynchronous THEN ERROR SendBreakIllegal; RS232CFace.SendBreak[channel.face]; END; SetLineType: PUBLIC ENTRY PROCEDURE [ channel: ChannelHandle, lineType: RS232C.LineType] = BEGIN ENABLE UNWIND => NULL; -- Required in order to release monitor lock holdDataTerminalReady: BOOLEAN; holdDataTerminalReady ← channel.parameterRecord.dataTerminalReady; channel.parameterRecord ← SELECT lineType FROM bitSynchronous => RS232CInternal.bitSynchronousDefaults, byteSynchronous => RS232CInternal.byteSynchronousDefaults, asynchronous => RS232CInternal.asynchronousDefaults, autoRecognition => RS232CInternal.autoRecognitionDefaults, ENDCASE => ERROR; -- This should be logged as a system error. channel.parameterRecord.dataTerminalReady ← holdDataTerminalReady; -- This will prevent disconnect, if DTR had been set prior to this call IF RS232CFace.ResetLine[channel.face, @channel.parameterRecord] # success THEN ERROR RS232C.UnimplementedFeature; END; SetParameter: PUBLIC ENTRY PROCEDURE [ channel: ChannelHandle, parameter: RS232C.Parameter] = BEGIN ENABLE UNWIND => NULL; -- Required in order to release monitor lock WITH parameter SELECT FROM charLength => channel.parameterRecord.charLength ← charLength; correspondent => channel.parameterRecord.correspondent ← correspondent; dataTerminalReady => channel.parameterRecord.dataTerminalReady ← dataTerminalReady; frameTimeout => channel.parameterRecord.frameTimeout ← frameTimeout; latchBitClear => BEGIN IF latchBitClearMask.dataLost THEN channel.parameterRecord.resetDataLost ← TRUE; IF latchBitClearMask.breakDetected THEN channel.parameterRecord.resetBreakDetected ← TRUE; IF latchBitClearMask.ringHeard THEN channel.parameterRecord.resetRingHeard ← TRUE; END; lineSpeed => channel.parameterRecord.lineSpeed ← lineSpeed; parity => channel.parameterRecord.parity ← parity; requestToSend => channel.parameterRecord.requestToSend ← requestToSend; stopBits => channel.parameterRecord.stopBits ← stopBits; syncChar => channel.parameterRecord.syncChar ← syncChar; syncCount => channel.parameterRecord.syncCount ← syncCount; ENDCASE => ERROR InvalidParameter; IF RS232CFace.SetParameters[channel.face, @channel.parameterRecord] # success THEN ERROR RS232C.UnimplementedFeature; -- for next call to SetParameters, make certain that latched bits -- don't get cleared again channel.parameterRecord.resetDataLost ← channel.parameterRecord.resetBreakDetected ← channel.parameterRecord.resetRingHeard ← FALSE; END; StatusWait: PUBLIC PROCEDURE [ channel: ChannelHandle, stat: RS232C.DeviceStatus] RETURNS [newstat: RS232C.DeviceStatus] = BEGIN faceStat: RS232CFace.DeviceStatus; -- Note that the deletion of the channel subsequent to the call -- to StatusWait will cause StatusWait to return normally. IF channel.otherSuspended THEN ERROR ChannelSuspended; stat.statusAborted ← FALSE; IncrementStatusWaitCount[channel]; DO --until newstat#stat faceStat ← RS232CFace.StatusWait[ channel.face, [ stat.dataLost, stat.breakDetected, stat.clearToSend, stat.dataSetReady, stat.carrierDetect, stat.ringHeard, stat.ringIndicator, stat.deviceError]]; newstat ← [ channel.otherSuspended, faceStat.dataLost, faceStat.breakDetected, faceStat.clearToSend, faceStat.dataSetReady, faceStat.carrierDetect, faceStat.ringHeard, faceStat.ringIndicator, faceStat.deviceError]; IF newstat # stat THEN EXIT; ENDLOOP; DecrementStatusWaitCount[channel]; RETURN; END; Suspend: PUBLIC ENTRY PROCEDURE [ channel: ChannelHandle, class: RS232C.OperationClass] = BEGIN ENABLE UNWIND => NULL; -- Required in order to release monitor lock IF class = input OR class = all THEN BEGIN channel.inputSuspended ← TRUE; RS232CFace.AbortInput[channel.face]; END; IF class = output OR class = all THEN BEGIN channel.outputSuspended ← TRUE; RS232CFace.AbortOutput[channel.face]; END; IF class = other OR class = all THEN BEGIN channel.otherSuspended ← TRUE; UNTIL channel.statusWaitCount = 0 DO RS232CFace.AbortStatus[channel.face]; WAIT aMoment; ENDLOOP; END; END; TransferWait: PUBLIC PROCEDURE [ channel: ChannelHandle, event: RS232C.CompletionHandle] RETURNS [byteCount: CARDINAL, status: RS232C.TransferStatus] = BEGIN faceStatus: RS232CFace.TransferStatus; [byteCount, faceStatus] ← RS232CFace.TransferWait[channel.face, event]; status ← ConvertFaceToChannelTransferStatus[faceStatus]; RETURN; END; TransmitNow: PUBLIC PROCEDURE [ channel: ChannelHandle, event: RS232C.CompletionHandle] RETURNS [byteCount: CARDINAL, status: RS232C.TransferStatus] = BEGIN faceStatus: RS232CFace.TransferStatus; [byteCount, faceStatus] ← RS232CFace.TransmitNow[channel.face, event]; status ← ConvertFaceToChannelTransferStatus[faceStatus]; RETURN; END; -- MAIN PROGRAM -- Process.SetTimeout[@aMoment, 1]; END. -- RS232CDriverB LOG Time: May 23, 1980 12:01 PM By: Victor Schwartz Action: Pre-Amargosa log entries deleted. Time: May 23, 1980 12:01 PM By: Victor Schwartz Action: Start of modifications to handle multiple RS232C Channels. Time: June 20, 1980 2:45 PM By: Victor Schwartz Action: Change semantics of Suspend/Restart. Remove Abort. Time: August 4, 1980 2:53 PM By: Victor Schwartz Action: Use Heap, rather than RS232CHeap to allocate storage. Time: January 20, 1981 3:54 PM By: Danielson Action: Changes required to support deviceError bit in deviceStatus. Time: 3-Aug-81 18:23:06 By: Danielson Action: Pescadero changes for new RS232CFace interface. Time: 19-Aug-81 16:41:09 By: Danielson Action: Made Get and Put be entries and changed Suspend code to catch races between Get/Put and Suspend. Time: 14-Oct-81 19:13:38 By: Danielson Action: Ignore suspend on SetParameter and SetLineType