DIRECTORY Ascii, Basics, GPIB, Process, RefText, Rope, XBus; GPIBImpl: CEDAR MONITOR IMPORTS Basics, Process, RefText, Rope, XBus EXPORTS GPIB = BEGIN OPEN Basics, Rope; controller: GPIB.DeviceAddr _ 0; statusWord: WORD _ 0000H; BusEND: WORD = LOOPHOLE[BITSHIFT[1, 13]]; SRQI: WORD = LOOPHOLE[BITSHIFT[1, 12]]; GPIBBaseAddr: LONG POINTER = LOOPHOLE[LONG[8000H]]; -- current setting for Multibus monitorStatusWord: BOOL _ TRUE; --for debugging swRegister: WORD _ statusWord; --for debugging smallBuf: NAT = 16; bigBuf: NAT = GPIB.maxReadBuffer; InitializeController: PUBLIC PROC RETURNS [open: BOOL] = { [] _ Init[]; open _ TRUE; }; FinalizeController: PUBLIC PROC = { SetIdle[] }; SRQAsserted: PUBLIC PROC RETURNS [asserted: BOOL] = { asserted _ FALSE; IF swRegister # 0 THEN { swRegister _ 0H; asserted _ TRUE; }; }; Command: PUBLIC PROC [sendMsg: Rope.ROPE] = { sendBuffer: REF TEXT _ RefText.ObtainScratch[bigBuf]; sendBuffer _ RefText.AppendRope[sendBuffer, sendMsg]; [] _ Cmd[sendBuffer]; RefText.ReleaseScratch[sendBuffer]; }; DevicesClear: PUBLIC PROC = { [] _ LCmd[LIST[GPIB.devicesClear, GPIB.UnListen]]}; GoToLocal: PUBLIC PROC = { [] _ LCmd[LIST[GPIB.goToLocal, GPIB.UnListen]]}; GroupExecuteTrigger: PUBLIC PROC = { [] _ LCmd[LIST[GPIB.groupExecuteTrigger, GPIB.UnListen]]}; InterfaceClear: PUBLIC PROC = {[] _ Clear[]}; LocalLockout: PUBLIC PROC = { [] _ LCmd[LIST[GPIB.localLockout, GPIB.UnListen]]}; RemoteEnable: PUBLIC PROC = {[] _ SetRemote[TRUE]}; SelectedDeviceClear: PUBLIC PROC [device: GPIB.DeviceAddr]= { [] _ LCmd[LIST[GPIB.UnListen, GetLAD[device], GPIB.selectedDeviceClear, GPIB.UnListen]]}; SelectedGoToLocal: PUBLIC PROC [device: GPIB.DeviceAddr] = { [] _ LCmd[LIST[GPIB.UnListen, GetLAD[device], GPIB.goToLocal, GPIB.UnListen]]}; SelectedExecuteTrigger: PUBLIC PROC [device: GPIB.DeviceAddr] = { [] _ LCmd[LIST[GPIB.UnListen, GetLAD[device],GPIB.groupExecuteTrigger,GPIB.UnListen]]}; SelectedGroupEnableTrigger: PUBLIC PROC [device: GPIB.DeviceAddr] = {ERROR}; SelectedRemoteEnable: PUBLIC PROC [device: GPIB.DeviceAddr] = { [] _ SetRemote[TRUE]; [] _ LCmd[LIST[GPIB.UnListen, GetLAD[device], GetTAD[device], GPIB.UnListen]]; }; ParallelPollConfigure: PUBLIC PROC [device: GPIB.DeviceAddr] = { [] _ LCmd[LIST[GPIB.UnListen, GPIB.parallelPollConfigure, GPIB.parallelPollEnable, GPIB.UnListen]]; }; ParallelPollUnconfigure: PUBLIC PROC = { [] _ LCmd[LIST[GPIB.UnListen, GPIB.parallelPollConfigure, GPIB.parallelPollDisable, GPIB.UnListen]]; }; SelectedParallelPollConfigure: PUBLIC PROC [device: GPIB.DeviceAddr] = { [] _ LCmd[LIST[GPIB.UnListen, GetLAD[device], GPIB.parallelPollConfigure, GPIB.parallelPollEnable, GPIB.UnListen]]; }; SelectedParallelPollUnconfigure: PUBLIC PROC [device: GPIB.DeviceAddr] = { [] _ LCmd[LIST[GPIB.UnListen, GetLAD[device], GPIB.parallelPollConfigure, GPIB.parallelPollDisable, GPIB.UnListen]]; }; PollDevice: PUBLIC PROC [device: GPIB.DeviceAddr, labels: GPIB.SRQLabels] = {ERROR}; SelectedReadSerialPoll: PUBLIC PROC [device: GPIB.DeviceAddr] RETURNS [statusByte: CHAR] = { [] _ LCmd[LIST[GPIB.UnListen, GPIB.serialPollEnable, GetTAD[device], GetLAD[controller]]]; [statusByte, ] _ DataByteRead[]; [] _ LCmd[LIST[GPIB.serialPollDisable, GPIB.UnTalk]]; }; ReadStatusByte: PUBLIC PROC [device: GPIB.DeviceAddr] RETURNS [char: CHAR] = { [] _ LCmd[LIST[GPIB.UnListen, GetTAD[device], GetLAD[controller]]]; [char, ] _ DataByteRead[! ABORTED => CONTINUE]; [] _ LCmd[LIST[GPIB.UnTalk]]; }; ReadDevice: PUBLIC PROC [device: GPIB.DeviceAddr, terminator: GPIB.Terminator _ EOI] RETURNS [recvMsg: Rope.ROPE] = { sendBuffer: REF TEXT _ RefText.ObtainScratch[smallBuf]; sendBuffer _ RefText.AppendChar[sendBuffer, GPIB.UnListen]; sendBuffer _ RefText.AppendChar[sendBuffer, GetTAD[device]]; sendBuffer _ RefText.AppendChar[sendBuffer, GetLAD[controller]]; [] _ Cmd[sendBuffer]; [recvMsg, ] _ DataRead[terminator ! ABORTED => CONTINUE]; sendBuffer.length _ 0; sendBuffer _ RefText.AppendChar[sendBuffer, GPIB.UnTalk]; [] _ Cmd[sendBuffer]; RefText.ReleaseScratch[sendBuffer]; }; ReadOnInterrupt: PUBLIC PROC [device: GPIB.DeviceAddr, recvMsg: Rope.ROPE, labels: GPIB.SRQLabels] = {ERROR}; WriteDevice: PUBLIC PROC [device: GPIB.DeviceAddr, sendMsg: Rope.ROPE] = { sendBuffer: REF TEXT _ RefText.ObtainScratch[smallBuf]; sendBuffer _ RefText.AppendChar[sendBuffer, GPIB.UnListen]; sendBuffer _ RefText.AppendChar[sendBuffer, GetLAD[device]]; sendBuffer _ RefText.AppendChar[sendBuffer, GetTAD[controller]]; [] _ Cmd[sendBuffer]; [] _ DataWrite[sendMsg ! ABORTED => CONTINUE]; sendBuffer.length _ 0; sendBuffer _ RefText.AppendChar[sendBuffer, GPIB.UnListen]; [] _ Cmd[sendBuffer]; RefText.ReleaseScratch[sendBuffer]; }; dev: GPIB.DeviceAddr; buffer: Rope.ROPE _ NIL; bufferEmptyCV, bufferFullCV: CONDITION; bufferEmpty: BOOL _ TRUE; WriteDeviceBuffered: PUBLIC ENTRY PROC [device: GPIB.DeviceAddr, sendMsg: Rope.ROPE, hold: BOOL] = { ENABLE UNWIND => NULL; UNTIL bufferEmpty DO WAIT bufferEmptyCV; ENDLOOP; dev _ device; buffer _ sendMsg; bufferEmpty _ FALSE; NOTIFY bufferFullCV; IF hold THEN UNTIL bufferEmpty DO WAIT bufferEmptyCV; ENDLOOP; }; BufferToDevice: ENTRY PROC = { ENABLE UNWIND => NULL; open: REF TEXT _ NEW[TEXT[smallBuf]]; close: REF TEXT _ NEW[TEXT[smallBuf]]; close _ RefText.AppendChar[close, GPIB.UnListen]; DO WHILE bufferEmpty DO WAIT bufferFullCV; ENDLOOP; open.length _ 0; open _ RefText.AppendChar[open, GPIB.UnListen]; open _ RefText.AppendChar[open, GetLAD[dev]]; open _ RefText.AppendChar[open, GetTAD[controller]]; [] _ Cmd[open]; [] _ DataWrite[buffer ! ABORTED => CONTINUE]; [] _ Cmd[close]; bufferEmpty _ TRUE; NOTIFY bufferEmptyCV; ENDLOOP; }; WriteDeviceInitial: PUBLIC ENTRY PROC [device: GPIB.DeviceAddr, sendMsg: Rope.ROPE] = BEGIN ENABLE UNWIND => NULL; sendBuffer: REF TEXT _ RefText.ObtainScratch[bigBuf]; sendBuffer _ RefText.AppendChar[sendBuffer, GPIB.UnListen]; sendBuffer _ RefText.AppendChar[sendBuffer, GetLAD[device]]; sendBuffer _ RefText.AppendChar[sendBuffer, GetTAD[controller]]; [] _ Cmd[sendBuffer]; sendBuffer.length _ 0; [] _ DataWrite[sendMsg, TRUE, FALSE ! ABORTED => CONTINUE]; RefText.ReleaseScratch[sendBuffer]; END; WriteDeviceContinued: PUBLIC ENTRY PROC [device: GPIB.DeviceAddr, sendMsg: Rope.ROPE, last: BOOL] = BEGIN ENABLE UNWIND => NULL; sendBuffer: REF TEXT _ RefText.ObtainScratch[bigBuf]; [] _ DataWrite[sendMsg, FALSE, last ! ABORTED => CONTINUE]; RefText.ReleaseScratch[sendBuffer]; END; IOWrite: PROCEDURE[add: LONG POINTER, data: WORD] = INLINE BEGIN XBus.WriteM[mBusAddr, Basics.HighHalf[LOOPHOLE[add]]]; XBus.WriteL[lBusAddr, Basics.LowHalf[LOOPHOLE[add]]]; XBus.WriteM[mBusCtl, 8508H]; XBus.WriteL[lBusOutData, data]; WHILE Basics.BITAND[XBus.ReadM[mBusCtl], 4] = 0 DO --check for XACK Process.CheckForAbort[]; ENDLOOP; END; IORead: PROCEDURE [add: LONG POINTER] RETURNS [data: WORD] = INLINE BEGIN XBus.WriteM[mBusAddr, Basics.HighHalf[LOOPHOLE[add]]]; XBus.WriteL[lBusAddr, Basics.LowHalf[LOOPHOLE[add]]]; XBus.WriteM[mBusCtl, 8604H]; XBus.WriteL[lBusOutData, 0]; WHILE Basics.BITAND[XBus.ReadM[mBusCtl], 4] = 0 DO --check for XACK Process.CheckForAbort[]; ENDLOOP; data _ XBus.ReadL[lBusInData] END; WriteDeviceBlock: PUBLIC ENTRY UNSAFE PROC [device: GPIB.DeviceAddr, lp: LONG POINTER, quadWordCnt: CARDINAL, last: BOOL] = TRUSTED BEGIN OPEN Basics; ENABLE UNWIND => NULL; dataWord: MACHINE DEPENDENT RECORD [a,b: CHAR] _ LOOPHOLE [lp^]; IF quadWordCnt < 1 THEN quadWordCnt _ 1; FOR i: CARDINAL IN [0 .. quadWordCnt-1) DO IOWrite[GPIBBaseAddr, LOOPHOLE[dataWord.a, CARDINAL]]; WHILE BITAND[IORead[LOOPHOLE[1+GPIBBaseAddr]], mask.D0] = 0 DO ENDLOOP; IOWrite[GPIBBaseAddr, LOOPHOLE[dataWord.b, CARDINAL]]; WHILE BITAND[IORead[LOOPHOLE[1+GPIBBaseAddr]], mask.D0] = 0 DO ENDLOOP; lp _ lp + 1; dataWord _ LOOPHOLE [lp^]; IOWrite[GPIBBaseAddr, LOOPHOLE[dataWord.a, CARDINAL]]; WHILE BITAND[IORead[LOOPHOLE[1+GPIBBaseAddr]], mask.D0] = 0 DO ENDLOOP; IOWrite[GPIBBaseAddr, LOOPHOLE[dataWord.b, CARDINAL]]; WHILE BITAND[IORead[LOOPHOLE[1+GPIBBaseAddr]], mask.D0] = 0 DO ENDLOOP; lp _ lp + 1; dataWord _ LOOPHOLE [lp^]; IOWrite[GPIBBaseAddr, LOOPHOLE[dataWord.a, CARDINAL]]; WHILE BITAND[IORead[LOOPHOLE[1+GPIBBaseAddr]], mask.D0] = 0 DO ENDLOOP; IOWrite[GPIBBaseAddr, LOOPHOLE[dataWord.b, CARDINAL]]; WHILE BITAND[IORead[LOOPHOLE[1+GPIBBaseAddr]], mask.D0] = 0 DO ENDLOOP; lp _ lp + 1; dataWord _ LOOPHOLE [lp^]; IOWrite[GPIBBaseAddr, LOOPHOLE[dataWord.a, CARDINAL]]; WHILE BITAND[IORead[LOOPHOLE[1+GPIBBaseAddr]], mask.D0] = 0 DO ENDLOOP; IOWrite[GPIBBaseAddr, LOOPHOLE[dataWord.b, CARDINAL]]; WHILE BITAND[IORead[LOOPHOLE[1+GPIBBaseAddr]], mask.D0] = 0 DO ENDLOOP; lp _ lp + 1; dataWord _ LOOPHOLE [lp^]; ENDLOOP; IOWrite[GPIBBaseAddr, LOOPHOLE[dataWord.a, CARDINAL]]; WHILE BITAND[IORead[LOOPHOLE[1+GPIBBaseAddr]], mask.D0] = 0 DO ENDLOOP; IOWrite[GPIBBaseAddr, LOOPHOLE[dataWord.b, CARDINAL]]; WHILE BITAND[IORead[LOOPHOLE[1+GPIBBaseAddr]], mask.D0] = 0 DO ENDLOOP; lp _ lp + 1; dataWord _ LOOPHOLE [lp^]; IOWrite[GPIBBaseAddr, LOOPHOLE[dataWord.a, CARDINAL]]; WHILE BITAND[IORead[LOOPHOLE[1+GPIBBaseAddr]], mask.D0] = 0 DO ENDLOOP; IOWrite[GPIBBaseAddr, LOOPHOLE[dataWord.b, CARDINAL]]; WHILE BITAND[IORead[LOOPHOLE[1+GPIBBaseAddr]], mask.D0] = 0 DO ENDLOOP; lp _ lp + 1; dataWord _ LOOPHOLE [lp^]; IOWrite[GPIBBaseAddr, LOOPHOLE[dataWord.a, CARDINAL]]; WHILE BITAND[IORead[LOOPHOLE[1+GPIBBaseAddr]], mask.D0] = 0 DO ENDLOOP; IOWrite[GPIBBaseAddr, LOOPHOLE[dataWord.b, CARDINAL]]; WHILE BITAND[IORead[LOOPHOLE[1+GPIBBaseAddr]], mask.D0] = 0 DO ENDLOOP; lp _ lp + 1; dataWord _ LOOPHOLE [lp^]; IOWrite[GPIBBaseAddr, LOOPHOLE[dataWord.a, CARDINAL]]; WHILE BITAND[IORead[LOOPHOLE[1+GPIBBaseAddr]], mask.D0] = 0 DO ENDLOOP; IF last THEN WriteReg[auxMode, sendEOI]; -- EOI with last byte IOWrite[GPIBBaseAddr, LOOPHOLE[dataWord.b, CARDINAL]]; WHILE BITAND[IORead[LOOPHOLE[1+GPIBBaseAddr]], mask.D0] = 0 DO ENDLOOP; END; WriteDMABlock: PUBLIC UNSAFE PROC [device: GPIB.DeviceAddr, multiBusAddress: LONG POINTER TO WORD, -- For Lupine -- byteCnt: CARDINAL, last: BOOL] = TRUSTED BEGIN i: INTEGER; bp: Basics.BytePair; md: MACHINE DEPENDENT RECORD [b1, b0, b3, b2: BYTE]; i _ 0 - LOOPHOLE[byteCnt, INTEGER]; byteCnt _ LOOPHOLE[i, CARDINAL]; bp _ LOOPHOLE[byteCnt]; WriteReg[byteCntLo, LOOPHOLE[bp.low]]; WriteReg[byteCntHi, LOOPHOLE[bp.high]]; md _ LOOPHOLE[multiBusAddress]; WriteReg[dmaAddr0, LOOPHOLE[md.b0]]; WriteReg[dmaAddr1, LOOPHOLE[md.b1]]; WriteReg[dmaAddr2, LOOPHOLE[md.b2]]; IF last THEN WriteReg[carryCycleFunc, sendEOI]; WriteReg[intrptMask1, LOOPHOLE[0]]; WriteReg[dmaControl1, LOOPHOLE[0Bh]]; -- ~MIE, *Burst, ~CBRE, SC, 22.4 to 25.6 timeout WriteReg[intrptMask2, LOOPHOLE[20H]]; WriteReg[dmaControl0, LOOPHOLE[(IF last THEN 052H ELSE 012H)]]; WriteReg[dmaControl0, LOOPHOLE[(IF last THEN 053H ELSE 013H)]]; END; CheckDMADone: PUBLIC PROC RETURNS [BOOL] = BEGIN foo: CARDINAL _ ReadRegL[dmaStatus]; foo _ Basics.BITAND[foo, 80h]; Process.CheckForAbort[]; RETURN [foo # 0]; END; GetLAD: PRIVATE PROC [device: GPIB.DeviceAddr] RETURNS [CHAR] = { IF device > 30 THEN ERROR; RETURN [LOOPHOLE[device+32]]; -- ASCII Listen address }; GetTAD: PRIVATE PROC [device: GPIB.DeviceAddr] RETURNS [CHAR] = { IF device > 30 THEN ERROR; RETURN [LOOPHOLE[device+64]]; -- ASCII Talk address }; BufferSW: PRIVATE PROC = { IF statusWord # 0 THEN swRegister _ statusWord; }; powerOn: CHAR = 000C; -- AUX-PON chipReset: CHAR = 002C; -- AUXCR sendEOI: CHAR = 006C; -- AUXSEOI takeAsynchControl: CHAR = 021C; -- AUXTCA goToStandby: CHAR = 020C; -- AUXGTS executeParaPoll: CHAR = 035C; -- AUX-EPP setIFC: CHAR = 036C; -- AUXSIFC clearIFC: CHAR = 026C; -- AUXCIFC setREN: CHAR = 037C; -- AUX-SREN clearREN: CHAR = 027C; -- AUXCREN ICR: CARDINAL = 000040B; -- Internal Counter Register PPR: CARDINAL = 000140B; -- Parallel Poll Register AUXRA: CARDINAL = 000200B; -- Aux Register A AUXRB: CARDINAL = 000240B; -- Aux Register B AUXRE: CARDINAL = 000300B; -- Aux Register E WRegister: TYPE = { -- WriteOnly cmdDataOut, -- cdor intrptMask1, -- imr1 intrptMask2, -- imr2 serialPollMode, -- spmr addressMode, -- admr auxMode, -- auxmr address, -- adr endOfStr, -- eosr byteCntLo, -- bcr lo byteCntHi, -- bcr hi dmaControl0, -- CR0 carryCycleFunc, -- ccfr dmaAddr0, -- acr0 dmaAddr1, -- acr1 dmaAddr2, -- acr2 dmaControl1 -- CR1 }; RRegister: TYPE = { -- ReadOnly dataIn, -- dir intrptStatus1, -- isr1 intrptStatus2, -- isr2 serialPollStatus, -- spsr addressStatus, -- adsr cmdPassThru, -- cptr address0, -- adr0 address1, -- adr1 byteCntLo, -- bcr lo byteCntHi, -- bcr hi dmaStatus, -- SR carryCycleFunc -- ccfr }; mask: RECORD [ DI: CARDINAL _ BITSHIFT[1, 0], -- Data In D0: CARDINAL _ BITSHIFT[1, 1], -- Data Out BusEND: CARDINAL _ BITSHIFT[1, 4], -- End CO: CARDINAL _ BITSHIFT[1, 3], -- Command Output SRQI: CARDINAL _ BITSHIFT[1, 6], -- Service Request Input DMAI: CARDINAL _ BITSHIFT[1, 4], -- DMA Input Enable DMAO: CARDINAL _ BITSHIFT[1, 5], -- DMA Output Enable ADMO: CARDINAL _ BITSHIFT[1, 0], -- Addr Mode bit 0 TRMO: CARDINAL _ BITSHIFT[1, 4], -- Transmit/Receive Mode bit 0 TRMI: CARDINAL _ BITSHIFT[1, 5], -- Transmit/Receive Mode bit 1 DL: CARDINAL _ BITSHIFT[1, 5], -- Disable Listener DT: CARDINAL _ BITSHIFT[1, 6], -- Disable Talker ARS: CARDINAL _ BITSHIFT[1, 7], -- Addr Reg Select PPU: CARDINAL _ BITSHIFT[1, 4] -- Para Poll Unconfigure ]; Init: PROC [] RETURNS [WORD] = { WriteReg[auxMode, chipReset]; -- NEC 7210 [] _ ReadReg[cmdPassThru]; -- clear registers by reading & trashing result [] _ ReadReg[intrptStatus1]; [] _ ReadReg[intrptStatus2]; WriteReg[intrptMask1, 0C]; -- disable all interrupts WriteReg[intrptMask2, 0C]; WriteReg[serialPollMode, 0C]; WriteReg[address, 0C]; -- set 796P TAD = 100B+100B (controller) WriteRegL[address, BITOR[mask.ARS, BITOR[mask.DT, mask.DL]]]; WriteRegL[addressMode, BITOR[mask.TRMI, BITOR[mask.TRMO, mask.ADMO]]]; WriteReg[endOfStr, 0C]; WriteReg[auxMode, clearIFC]; -- and by default enable system controller WriteRegL[auxMode, BITOR[ICR, 5]]; -- set internal counter register N = 5 WriteRegL[auxMode, BITOR[PPR, mask.PPU]]; -- parallel poll unconfigure WriteRegL[auxMode, BITOR[AUXRA, 0]]; WriteRegL[auxMode, BITOR[AUXRB, 0]]; WriteRegL[auxMode, BITOR[AUXRE, 0]]; WriteReg[auxMode, powerOn]; -- put chip online IF monitorStatusWord THEN { statusWord _ IF BITAND[ReadRegL[intrptStatus2], mask.SRQI] # 0 THEN SRQI ELSE 0; BufferSW[]; }; RETURN[statusWord]; }; SetIdle: PROC = { WriteReg[auxMode, chipReset]; [] _ ReadReg[cmdPassThru]; -- clear registers by reading & trashing result [] _ ReadReg[intrptStatus1]; [] _ ReadReg[intrptStatus2]; WriteReg[intrptMask1, 0C]; -- disable all interrupts WriteReg[intrptMask2, 0C]; WriteReg[serialPollMode, 0C]; WriteReg[address, 0C]; -- set 796P TAD = 100B+100B (controller) WriteRegL[address, BITOR[mask.ARS, BITOR[mask.DT, mask.DL]]]; WriteRegL[addressMode, BITOR[mask.TRMI, BITOR[mask.TRMO, mask.ADMO]]]; WriteReg[endOfStr, 0C]; WriteReg[auxMode, clearIFC]; -- and by default enable system controller WriteRegL[auxMode, BITOR[ICR, 5]]; -- set internal counter register N = 5 WriteRegL[auxMode, BITOR[PPR, mask.PPU]]; -- parallel poll unconfigure WriteRegL[auxMode, BITOR[AUXRA, 0]]; WriteRegL[auxMode, BITOR[AUXRB, 0]]; WriteRegL[auxMode, BITOR[AUXRE, 0]]; }; LCmd: PROC [chars: LIST OF CHAR] RETURNS [w: WORD] = { sendBuffer: REF TEXT _ RefText.ObtainScratch[smallBuf]; FOR l: LIST OF CHAR _ chars, l.rest WHILE l#NIL DO sendBuffer _ RefText.AppendChar[sendBuffer, l.first]; ENDLOOP; w _ Cmd[sendBuffer]; RefText.ReleaseScratch[sendBuffer]; }; Cmd: PROC [sendBuffer: REF TEXT] RETURNS [WORD] = { s: CARDINAL _ 0; WriteReg[auxMode, takeAsynchControl]; -- if on standby, go to controller active state FOR i: NAT IN [0..sendBuffer.length) DO s _ BITAND[s, BITNOT[mask.CO]]; -- clear saved copy of Command Output WriteReg[cmdDataOut, sendBuffer.text[i]]; -- output command WHILE BITAND[(s _ BITOR[s, ReadRegL[intrptStatus2]]), mask.CO] = 0 DO Process.CheckForAbort[]; -- escape route ENDLOOP; ENDLOOP; IF monitorStatusWord THEN { statusWord _ IF BITAND[s, mask.SRQI] # 0 THEN SRQI ELSE 0; BufferSW[]; }; RETURN[statusWord]; }; DataRead: PROC [terminateOn: GPIB.Terminator] RETURNS [ROPE, WORD] = { recBuffer: REF TEXT _ RefText.ObtainScratch[bigBuf]; s: CARDINAL _ 0; rope: Rope.ROPE _ NIL; [] _ ReadReg[dataIn]; -- krock to clear dataIn reg WriteReg[auxMode, goToStandby]; -- if controller active state, go to standby DO -- read unspecified number of bytes Process.CheckForAbort[]; WHILE BITAND[(s _ ReadRegL[intrptStatus1]), mask.DI] = 0 DO Process.CheckForAbort[]; ENDLOOP; recBuffer _ RefText.AppendChar[recBuffer, ReadReg[dataIn]]; -- store byte SELECT terminateOn FROM CR => IF recBuffer[recBuffer.length-1] = '\n THEN EXIT; LF => IF recBuffer[recBuffer.length-1] = '\l THEN EXIT; -- IEEE 728 string terminator ENDCASE => IF BITAND[s, mask.BusEND] # 0 THEN EXIT; -- EOI IF recBuffer.length = recBuffer.maxLength THEN { rope _ Rope.Concat[rope, Rope.FromRefText[recBuffer]]; recBuffer.length _ 0; }; ENDLOOP; rope _ Rope.Concat[rope, Rope.FromRefText[recBuffer]]; RefText.ReleaseScratch[recBuffer]; IF monitorStatusWord THEN { statusWord _ IF BITAND[s, mask.BusEND] # 0 THEN BusEND ELSE 0; statusWord _ BITOR[statusWord, IF BITAND[ReadRegL[intrptStatus2], mask.SRQI] # 0 THEN SRQI ELSE 0]; BufferSW[]; }; RETURN[rope, statusWord]; }; DataByteRead: PROC [] RETURNS [c: CHAR, w: WORD] = { s: CARDINAL _ 0; [] _ ReadReg[dataIn]; -- krock to clear dataIn reg WriteReg[auxMode, goToStandby]; -- if controller active state, go to standby Process.CheckForAbort[]; WHILE BITAND[(s _ ReadRegL[intrptStatus1]), mask.DI] = 0 DO Process.CheckForAbort[]; ENDLOOP; c _ ReadReg[dataIn]; -- store byte IF monitorStatusWord THEN { statusWord _ IF BITAND[s, mask.BusEND] # 0 THEN BusEND ELSE 0; statusWord _ BITOR[statusWord, IF BITAND[ReadRegL[intrptStatus2], mask.SRQI] # 0 THEN SRQI ELSE 0]; BufferSW[]; }; RETURN[c, statusWord]; }; mBusCtl: POINTER = LOOPHOLE[2]; lBusOutData: POINTER = LOOPHOLE[2]; lBusInData: POINTER = LOOPHOLE[2]; mBusAddr: POINTER = LOOPHOLE[3]; lBusAddr: POINTER = LOOPHOLE[3]; DataWrite: PROC [buffer: ROPE, init, last: BOOL _ TRUE] RETURNS [WORD] = { IF init THEN WriteReg[auxMode, goToStandby]; -- if controller active state, go to standby (data mode) buffer _ Rope.InlineFlatten[buffer]; FOR i: INT IN [0..Length[buffer]) DO XBus.WriteM[mBusAddr, Basics.HighHalf[LOOPHOLE[GPIBBaseAddr]]]; XBus.WriteL[lBusAddr, Basics.LowHalf[LOOPHOLE[GPIBBaseAddr]]]; XBus.WriteM[mBusCtl, 8508H]; XBus.WriteL[lBusOutData, LOOPHOLE[Rope.InlineFetch[buffer, i]]]; WHILE Basics.BITAND[XBus.ReadM[mBusCtl], 4] = 0 DO ENDLOOP; --XACK wait DO XBus.WriteM[mBusAddr, Basics.HighHalf[LOOPHOLE[1+GPIBBaseAddr]]]; XBus.WriteL[lBusAddr, Basics.LowHalf[LOOPHOLE[1+GPIBBaseAddr]]]; XBus.WriteM[mBusCtl, 8604H]; XBus.WriteL[lBusOutData, 0]; WHILE Basics.BITAND[XBus.ReadM[mBusCtl], 4] = 0 DO ENDLOOP; --XACK wait IF BITAND[XBus.ReadL[lBusInData], mask.D0] # 0 THEN EXIT; ENDLOOP; ENDLOOP; IF last THEN WriteReg[auxMode, sendEOI]; -- EOI with last byte IF monitorStatusWord THEN { statusWord _ (IF BITAND[ReadRegL[intrptStatus2], mask.SRQI] # 0 THEN SRQI ELSE 0); BufferSW[]; }; RETURN[statusWord]; }; Clear: PROC [] RETURNS [WORD] = { WriteReg[auxMode, setIFC]; Process.Pause[ticks: 10]; -- 40 ticks = 1mS WriteReg[auxMode, clearIFC]; IF monitorStatusWord THEN { statusWord _ (IF BITAND[ReadRegL[intrptStatus2], mask.SRQI] # 0 THEN SRQI ELSE 0); BufferSW[]; }; RETURN[statusWord]; }; SetRemote: PROC [set: BOOL] RETURNS [WORD] = { WriteReg[auxMode, (IF set THEN setREN ELSE clearREN)]; IF monitorStatusWord THEN { statusWord _ (IF BITAND[ReadRegL[intrptStatus2], mask.SRQI] # 0 THEN SRQI ELSE 0); BufferSW[]; }; RETURN[statusWord]; }; SetStandby: PROC [] RETURNS [WORD] = { WriteReg[auxMode, goToStandby]; IF monitorStatusWord THEN { statusWord _ (IF BITAND[ReadRegL[intrptStatus2], mask.SRQI] # 0 THEN SRQI ELSE 0); BufferSW[]; }; RETURN[statusWord]; }; SetCACS: PROC [] RETURNS [WORD] = { WriteReg[auxMode, takeAsynchControl]; IF monitorStatusWord THEN { statusWord _ (IF BITAND[ReadRegL[intrptStatus2], mask.SRQI] # 0 THEN SRQI ELSE 0); BufferSW[]; }; RETURN[statusWord]; }; Wait: PROC [for: WORD] = { WHILE (BITAND[GetStatus[], for] = 0) DO IF for = 0 THEN EXIT; Process.CheckForAbort[]; ENDLOOP; }; GetStatus: PROC RETURNS [WORD] = { RETURN[statusWord _ (IF BITAND[ReadRegL[intrptStatus2], mask.SRQI]#0 THEN SRQI ELSE 0)]; }; GetParaPoll: PROC [] RETURNS [ROPE, WORD] = { c: CHAR; WriteReg[auxMode, takeAsynchControl]; -- if standby, go to controller active state WriteReg[auxMode, executeParaPoll]; c _ ReadReg[cmdPassThru]; -- store the response byte IF monitorStatusWord THEN { statusWord _ (IF BITAND[ReadRegL[intrptStatus2], mask.SRQI] # 0 THEN SRQI ELSE 0); BufferSW[]; }; RETURN[Rope.FromChar[c], statusWord]; }; ReadReg: PRIVATE PROC [register: RRegister] RETURNS [char: CHAR] = { addr: NAT _ SELECT register FROM dataIn => 0, intrptStatus1 => 1, intrptStatus2 => 2, serialPollStatus => 3, addressStatus => 4, cmdPassThru => 5, address0 => 6, address1 => 7, byteCntLo => 8, byteCntHi => 9, dmaStatus => 0Ah, carryCycleFunc => 0Bh, ENDCASE => ERROR; word: WORD _ XBus.IORead[LOOPHOLE[addr+GPIBBaseAddr]]; char _ LOOPHOLE[LowByte[word]]; }; ReadRegL: PRIVATE PROC [register: RRegister] RETURNS [word: CARDINAL] = { addr: NAT _ SELECT register FROM dataIn => 0, intrptStatus1 => 1, intrptStatus2 => 2, serialPollStatus => 3, addressStatus => 4, cmdPassThru => 5, address0 => 6, address1 => 7, byteCntLo => 8, byteCntHi => 9, dmaStatus => 0Ah, carryCycleFunc => 0Bh, ENDCASE => ERROR; word _ XBus.IORead[LOOPHOLE[addr+GPIBBaseAddr]]; }; WriteReg: PRIVATE PROC [register: WRegister, dataByte: CHAR ] = { addr: NAT _ SELECT register FROM cmdDataOut => 0, intrptMask1 => 1, intrptMask2 => 2, serialPollMode => 3, addressMode => 4, auxMode => 5, address => 6, endOfStr => 7, byteCntLo => 8, byteCntHi => 9, dmaControl0 => 0Ah, carryCycleFunc => 0Bh, dmaAddr0 => 0Ch, dmaAddr1 => 0Dh, dmaAddr2 => 0Eh, dmaControl1 => 0Fh, ENDCASE => ERROR; XBus.IOWrite[LOOPHOLE[addr+GPIBBaseAddr], LOOPHOLE[dataByte]]; }; WriteRegL: PRIVATE PROC [register: WRegister, dataWord: CARDINAL ] = { addr: NAT _ SELECT register FROM cmdDataOut => 0, intrptMask1 => 1, intrptMask2 => 2, serialPollMode => 3, addressMode => 4, auxMode => 5, address => 6, endOfStr => 7, byteCntLo => 8, byteCntHi => 9, dmaControl0 => 0Ah, carryCycleFunc => 0Bh, dmaAddr0 => 0Ch, dmaAddr1 => 0Dh, dmaAddr2 => 0Eh, dmaControl1 => 0Fh, ENDCASE => ERROR; XBus.IOWrite[LOOPHOLE[addr+GPIBBaseAddr], dataWord]; }; TRUSTED {Process.Detach[FORK BufferToDevice[]]}; END... of NatInstrGPIBDriver.mesa ’GPIBImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Last edited by Neil Gunther, November 5, 1985 4:55:51 pm PST Last Edited by: Gasbarro April 24, 1986 11:37:59 am PST Tim Diebert: April 23, 1986 5:14:47 pm PST Globals for Level 1 Globals for Level 2 (GPIB-796P interface) *** Level 1: Implementation of GPIB.mesa *** Universal commands (all devices whether addressed or not) Selected Device Commands (only those devices addressed) Explicit Polling Routines Read Specific Devices for efficiency, don't do any allocates here... for efficiency, don't do do any allocates here... Printer Functions (see Tim Diebert) Private Procedures *** Level 2: Board-specific Procedures *** NEC 7210 M a s k s a n d R e g i s t e r s Auxiliary Controller Commands Nat. Instr. mnemonic Control Masks for Hidden Registers Nat. Instr. mnemonic Controller Register Definitions Nat. Instr. mnemonic G P I B - 7 9 6 P F u n c t i o n s disable secondary addressing return controller to idle state or somesuch. disable secondary addressing ships the global "sendBuffer" wait for Command Output flag BITOR-ed to preserve SRQI Read unspecified number of bytes of data from the GPIB-796P interface into buffer. In addition to I/O complete, the read operation terminates on detection of EOI. Prior to beginning the read the interface is placed in the controller standby state. No handshake holdoffs are used so care must be exercised when taking control (i.e., asserting ATN) following DataRead. Prior to calling DataRead, the intended devices as well as the interface board itself must be addressed by calling Cmd. wait for Data In flag Read one byte of data from the GPIB-796P interface into buffer. In addition to I/O complete, the read operation terminates on detection of EOI. Prior to beginning the read the interface is placed in the controller standby state. No handshake holdoffs are used so care must be exercised when taking control (i.e., asserting ATN) following DataRead. Prior to calling DataRead, the intended devices as well as the interface board itself must be addressed by calling Cmd. wait for Data In flag Write data bytes from buffer to the GPIB-796P. The write operation terminates only on I/O complete. By default, EOI is always sent along with the last byte. Prior to beginning the write the interface is placed in the controller standby state. Prior to calling DataWrite, the intended devices, as well as the interface board itself, must be addressed by calling Cmd. Process.CheckForAbort[]; --leave this out for speed, in for debugging Process.CheckForAbort[]; --leave this out for speed, in for debugging Send IFC for at least 100 microseconds(4 ticks). Clear must be called prior to the first call to Cmd in order to initialize the bus and enable the interface to leave the controller idle state. Go to the controller standby state (Data mode) from the controller active state, i.e., deassert ATN. Return to the controller active state (Command mode) from the controller standby state, i.e., assert ATN. Note that in order to enter the controller active state from the controller idle state, Clear must be called. Check or wait for a GPIB event to occur. The mask argument is a bit vector corresponding to the status bit vector. It has a bit set for each condition which can terminate the wait. If the mask is 0 then no condition is waited on and the current status is simply returned. Note that since the hardware SRQI bit is volatile it will only be reported once for each occurrence of SRQ. If another function has returned the SRQI status bit, then a call to Wait with a mask containing SRQI will never return. Update GPIB status information. Conduct a parallel poll and return the byte in buf. Prior to conducting the poll the interface is placed in the controller active state. P r i v a t e R e g i s t e r O p e r a t i o n s Initialization Ê!^˜Jšœ ™ šœ Ïmœ7™EJšœ<™Kšœžœ žœ˜6Kš žœžœžœ žœžœ˜GKšžœ˜—K˜š£ œžœžœžœ žœžœžœžœžœ¡œ žœžœžœž˜¢Kš œžœžœž œžœžœ˜UKšœžœ žœ˜#Kšœ žœžœ˜ Kšœžœ ˜Kšœžœ ˜&Kšœžœ ˜'Kšœžœ˜Kšœžœ ˜$Kšœžœ ˜$Kšœžœ ˜$Kšžœžœ#˜/Kšœžœ˜#Kšœžœ ¡0˜XKšœžœ˜%Kš œž œžœžœžœ ˜?Kš œž œžœžœžœ ˜?Kšž˜—K˜š £ œžœžœžœžœž˜0Kšœžœ˜$Kšœ žœ ˜K˜Kšžœ ˜Kšžœ˜—K˜J˜—Jš ™™š £œžœžœ žœ žœžœ˜AJšžœ žœžœ˜Jšžœžœ¡œ˜6J˜—J˜š £œžœžœ žœ žœžœ˜AJšžœ žœžœ˜Jšžœžœ¡˜3J˜J˜—š£œžœžœ˜Jšžœžœ˜/J˜J˜—J˜J˜—Jš¢*™*™JšÏb¢1™4J˜Jš œ ™5Jšœ žœ ¡ ˜(Jšœžœ ¡ ˜'Jšœžœ ¡ ˜(Jšœžœ ¡ ˜-Jšœžœ ¡ ˜)Jšœžœ ¡ ˜/Jšœ žœ ¡ ˜'Jšœžœ ¡ ˜)Jšœžœ ¡ ˜)šœžœ ¡ ˜(J˜—J˜Jš "œ ™9Jšžœžœ¡Ðci¡˜Jšœ˜Jšœžœ˜@šžœžœžœ˜3JšœF™FJšžœ¡ ˜—šž˜Jšœ&žœ˜AJšœ%žœ˜@Jšœ˜Jšœ˜šžœžœžœ˜3JšœF™FJšžœ¡ ˜—Kšžœžœ&žœžœ˜9Kšžœ˜—Jšžœ˜ —Jšžœžœ¡§¡˜Ašžœžœ˜Jš œžœžœžœžœžœžœ˜RJšœ ˜ J˜—Jšžœ ˜J˜—J˜Jš£œžœžœžœ˜!šœžœ»™ÃJšœ"˜"Jšœ¡˜.J˜šžœžœ˜Jš œžœžœžœžœžœžœ˜RJšœ ˜ J˜—Jšžœ ˜J˜—J˜š £ œžœžœžœžœ˜.Jšœžœžœžœ ˜8šžœžœ ˜#Jš œžœžœžœžœžœžœ˜RJšœ ˜ J˜—Jšžœ ˜J˜—J˜Jš£ œžœžœžœ˜&šœ`žœ™dJ˜ šžœžœ˜Jš œžœžœžœžœžœžœ˜RJšœ ˜ J˜—Jšžœ ˜J˜—J˜Jš£œžœžœžœ˜#šœežœp™ØJšœ%˜%šžœžœ˜Jš œžœžœžœžœžœžœ˜RJšœ ˜ J˜—Jšžœ ˜J˜—J˜Jš£œžœžœ˜š œžœžœGžœ)žœ8žœ™ÿšžœžœžœ˜(Jšœžœ žœžœ˜Jšœ˜Jšžœ˜—J˜J˜—š£ œžœžœžœ˜"Jšœžœ™Jšžœžœžœžœžœžœžœ˜XJ˜J˜—Jš £ œžœžœžœžœ˜.™ŽJšœžœ˜Jšœ)¡-˜VJ˜'Jšœ¡˜9šžœžœ˜Jš œžœžœžœžœžœžœ˜RJšœ ˜ J˜—Jšžœ˜%J˜J˜JšÐnzÑbnz¨©¨©™;J˜š £œžœžœžœžœ˜Dšœžœžœ ž˜ K˜K˜K˜K˜K˜K˜K˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœžœ˜—Kšœžœžœ˜6Kšœžœ˜J˜—J˜š £œžœžœžœžœ˜Išœžœžœ ž˜ K˜K˜K˜K˜K˜K˜K˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœžœ˜—Kšœžœ˜0J˜—J˜š£œžœžœ"žœ˜Dšœžœžœ ž˜ K˜K˜K˜K˜K˜K˜K˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœžœ˜—Kšœ žœžœ ˜>J˜—J˜š£ œžœžœ"žœ˜Išœžœžœ ž˜ K˜K˜K˜K˜K˜K˜K˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšžœžœ˜—Kšœ žœ˜4J˜—J˜—Jš©™™Jšžœžœ˜0—J˜JšžœÏi˜!J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜J˜—…—[Œ