$SUBTITLE('KbdInt_all.plm - Last update 10/17/89 by JMR') $RESET (fDebug) /* PUBLIC interfaces exported by this module: BeepIo CmdKbd IntHKbd KbdErrInt KbdTxInt KbdRxInt WriteIBusEvent ResetIBus */ /* Type definitions used by this module: */ $SAVE NOLIST $SET(MouseDataType) $SET(PntDeviceDataType) $INCLUDE(:f1:CTOStypes.edf) $SET(KbdRC) $INCLUDE(:f1:RC.edf) $RESTORE $IF MF $INCLUDE(:f1:cdt.edf) $ENDIF $IF fDebug /********** Trace Stuff **********/ DECLARE fKbdTrace FlagType PUBLIC INITIAL (True) ,rgbKbdTraceBuffer (4098) byte public ,iKbdTraceBuffer word public initial (0) ,ModsKbdTraceBuffer literally 'and 0FFFh' ; $ENDIF /* EXTERNAL data imported by this module */ $IF NOT MF /* mouseData is a structure that may be accessed by the Mouse System Service when it is installed. The Mouse uses InitNetServer to get a pointer to NetServerData, which is defined in Sysgen.mdf. The structure NetServerData has a pointer to mouseData. */ DECLARE mouseData MouseDataType EXTERNAL; DECLARE fDebuggerEnabled FlagType EXTERNAL; DECLARE fDebuggerExecuting FlagType EXTERNAL; $ENDIF $SET(fBufOutOverflow) $SET(fBufInOverflow) $SET(fIntHLEDsActive) $SET(fWakeupPending) $SET(hardwareType) $SET(ibBufInPut) $SET(ibBufInTake) $SET(ibBufLEDsPut) $SET(ibBufLEDsTake) DECLARE (ibBufOutTake, ibBufOutPut) BYTE EXTERNAL; DECLARE lExchCli LITERALLY '16'; $SET(mBufOut) $SET(processorType) $SET(pIBusIDTable) $SET(rgbBufIn) $SET(rgbBufOut) $SET(rgbEventTypeBufIn) $SET(rgbBufLEDs) DECLARE maskiBufLED WORD EXTERNAL; $SET(rgMask) $SET(rqKbdWakeup) $SET(serviceExchKbd) DECLARE BeeperPortNGen WORD EXTERNAL; $SET(VidControl) $SAVE NOLIST $INCLUDE(:f1:CTOSexternal.edf) $RESTORE /* PUBLIC data exported by this module */ $IF MF DECLARE pUnencoded POINTER EXTERNAL; $ENDIF $SET(cInconsistency) $SET(cIoErrors) $SET(kbdControlReg) $SET(kbdDataReg) $SET(kbdClearInt) $SET(RxRdy) $SET(TxRdy) $SAVE NOLIST $INCLUDE(:f1:CTOSpublic.edf) $RESTORE /* EXTERNAL interfaces imported by this module: */ $SET(KPSend) $SET(SetDS) $SET(SetDSOsDGroup) $SAVE NOLIST $INCLUDE(:f1:CTOSinternal.edf) $RESTORE InputPlm:PROCEDURE(port) WORD EXTERNAL; DECLARE port WORD; END InputPlm; OutputPlm:PROCEDURE(port, value) EXTERNAL; DECLARE (port, value) WORD; END OutputPlm; CallProc:PROCEDURE(bCh, prgbEventCode, prgbCharCode, pbEntries, pfQueue, fReset, pProc) flagType EXTERNAL; DECLARE bCh BYTE ,prgbEventCode POINTER ,prgbCharCode POINTER ,pbEntries POINTER ,pfQueue POINTER ,fReset FLAG ,pProc POINTER ; END CallProc; /* ERROR codes used by this module */ $SAVE NOLIST $SET(KbdErc) $INCLUDE(:f1:erc.edf) $RESTORE /* IO addresses used by this module */ $SAVE NOLIST $INCLUDE(:f1:ioaddr.edf) $RESTORE DECLARE txEnable LITERALLY '27h' ,txDisable LITERALLY '26h' ,txIntEnable LITERALLY '2h' ,txIntReset LITERALLY '28h' ,uartReset LITERALLY '10h' /*mask for error-reset bit of 8251*/ ,errorReset LITERALLY '30h' /*mask for error-reset bit of 8274*/ ,saveCtlUart BYTE INITIAL (txDisable) ,ForceToCommandMode LITERALLY '82H' ,hardreset LITERALLY '40H' ,uartMode LITERALLY '4EH' ,enableUart LITERALLY '27H' ,wr1ChanB BYTE PUBLIC INITIAL(14h) ,rgbInit8251(6) BYTE INITIAL(ForceToCommandMode,ForceToCommandMode,ForceToCommandMode, hardReset,uartMode,enableUart) $IF 0 *** *** Unused variables for resetting kbd. Now handled by normal state machine. *** ,kbdReset LITERALLY '92H' /*For plugging in NGen kbd*/ ,lNormal LITERALLY '0' ,lRcvdFE LITERALLY '1' ,lRcvd1stID LITERALLY '2' ,lReset LITERALLY '3' ,bKbdState BYTE INITIAL(lNormal) /*State transition when 0FEh NOT received:*/ ,rgbNewState(*) BYTE DATA ( lNormal /*Normal*/ ,lRcvd1stID /*lRcvdFE*/ ,lReset /*lRcvd1stID*/ ,lNormal /*lReset*/ ) $ENDIF $IF MF ,c8251Busy WORD INITIAL(0) $ENDIF ; sc_GetIBusData: PROCEDURE(bIn, prgbEventCode, prgbCharCode, pbEntries, pfQueue, fReset) EXTERNAL; DECLARE bIn BYTE ,prgbEventCode POINTER ,prgbCharCode POINTER ,pbEntries POINTER ,pfQueue POINTER ,fReset FLAG ; END sc_GetIBusData; DECLARE /*Ring buffers*/ /* action-buffer in which interrupt-handler puts actions, and from which ProcessAction removes them. */ MOD$sBufIn LITERALLY 'AND (sBufIn-1)' /* Kbd-LED buffer, filled by CmdKbd and emptied by IntHKbd. */ ,MOD$sBufLED LITERALLY 'AND (maskiBufLed)' ; /* K b d I n t e r r u p t H a n d l e r */ $IF NOT MF DECLARE sKeyMap LITERALLY '16' /* = 128/8, the number of bytes to bitmap the up/down state of the keyboard */ ,keyMapOld (sKeyMap) BYTE INITIAL (0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0) ,keyMapNew (sKeyMap) BYTE INITIAL (0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0) ,iKeyNoKeys LITERALLY '40h' ; /************ Pnt Device Stuff ************/ DECLARE /* For GetIBusData */ fQueue FLAG PUBLIC /* TRUE => queue events */ ,rgbEventCode (10) BYTE PUBLIC ,rgbCharCode (10) BYTE PUBLIC ,bEntries BYTE PUBLIC ; /* Translate char to state table column. */ DECLARE bSoftReset LITERALLY '92h'; DECLARE bInboundDevice LITERALLY '0CEh'; DECLARE bOutboundPassThru LITERALLY '0CEh'; DECLARE bOutboundKbd LITERALLY '0DFh'; DECLARE bInboundDeviceOV LITERALLY '0CFh'; DECLARE bInboundKbd LITERALLY '0DFh'; DECLARE bSetInboundPass LITERALLY '0D0h'; DECLARE bIdSync LITERALLY '0FEh'; /* Translate char for VM103 controller firmware - this stuff may need to be part of the state machine !!!! DECLARE bNotifyMode LITERALLY '009h'; DECLARE bRemoteMode LITERALLY '00Ah'; DECLARE bSetBrightness LITERALLY '00Ch'; DECLARE bSetContrast LITERALLY '00Dh'; DECLARE bSetStepSize LITERALLY '00Bh'; DECLARE bSetThreshold LITERALLY '00Eh'; DECLARE bSetDelay LITERALLY '00Fh'; DECLARE bGetCheckSum LITERALLY '010h'; DECLARE bGetState LITERALLY '011h'; DECLARE bGetKeys LITERALLY '012h'; DECLARE bGetType LITERALLY '013h'; DECLARE bGetParam LITERALLY '014h'; */ /* Translate char for Notify mode on VM103 monitor controller */ DECLARE bVolumeUp LITERALLY '024h'; DECLARE bVolumeDown LITERALLY '025h'; DECLARE bBrightnessUp LITERALLY '026h'; DECLARE bBrightnessDown LITERALLY '027h'; DECLARE bContrastUp LITERALLY '028h'; DECLARE bContrastDown LITERALLY '029h'; DECLARE fVolumeUp BYTE PUBLIC INITIAL(FALSE); DECLARE fVolumeDown BYTE PUBLIC INITIAL(FALSE); DECLARE fBrightnessUp BYTE PUBLIC INITIAL(FALSE); DECLARE fBrightnessDown BYTE PUBLIC INITIAL(FALSE); DECLARE fContrastUp BYTE PUBLIC INITIAL(FALSE); DECLARE fContrastDown BYTE PUBLIC INITIAL(FALSE); DECLARE bErrorByte BYTE PUBLIC INITIAL(0); DECLARE cdefault BYTE PUBLIC INITIAL(0); DECLARE fErrorOccured BYTE PUBLIC INITIAL(FALSE); DECLARE fGotMon BYTE PUBLIC INITIAL(FALSE); DECLARE bGotMoncCE BYTE PUBLIC INITIAL(0); DECLARE cCase2 BYTE PUBLIC INITIAL(0); DECLARE cUpdatecCE BYTE PUBLIC INITIAL(0); DECLARE cSetInPass BYTE PUBLIC INITIAL(0); DECLARE cInccCEbyTwo BYTE PUBLIC INITIAL(0); /* Debug Contsants for GetMonitorData */ DECLARE cVolumeUp BYTE PUBLIC INITIAL(0); DECLARE cVolumeDown BYTE PUBLIC INITIAL(0); DECLARE cBrightnessUp BYTE PUBLIC INITIAL(0); DECLARE cBrightnessDown BYTE PUBLIC INITIAL(0); DECLARE cContrastUp BYTE PUBLIC INITIAL(0); DECLARE cContrastDown BYTE PUBLIC INITIAL(0); DECLARE cErrorOccured BYTE PUBLIC INITIAL(0); DECLARE cbOutBoundPassSent BYTE PUBLIC INITIAL(0); DECLARE cSentSoftReset BYTE PUBLIC INITIAL(0); DECLARE cSentOpenInBound BYTE PUBLIC INITIAL(0); DECLARE cCalledGetMonitorData BYTE PUBLIC INITIAL(0); DECLARE cCalledSetID BYTE PUBLIC INITIAL(0); /* Columns of state table (input byte types) */ DECLARE tychInboundKbd LITERALLY '0'; DECLARE tychInboundMouse LITERALLY '1'; DECLARE tychIdSync LITERALLY '2'; DECLARE tychInBoundMouseOV LITERALLY '3'; DECLARE tychOther LITERALLY '4'; DECLARE mptychCh(*) BYTE DATA(bInboundKbd, bInboundDevice, bIdSync, bInBoundDeviceOV); /* Rows of state table (states) */ DECLARE stIdSync LITERALLY '0'; DECLARE stIdSync1 LITERALLY '1'; DECLARE stDevEsc LITERALLY '2'; DECLARE stDevId LITERALLY '3'; DECLARE stDevice LITERALLY '4'; DECLARE stIdSync2 LITERALLY '5'; DECLARE stIdSync3 LITERALLY '6'; DECLARE stChg LITERALLY '7'; DECLARE StoredState WORD PUBLIC; DECLARE CEinState WORD PUBLIC; DECLARE CEnextState WORD PUBLIC; DECLARE cClearedcCE BYTE PUBLIC INITIAL(0); DECLARE stKbdCur BYTE PUBLIC INITIAL(stDevice) ,stNext WORD PUBLIC /* Next state */; /* complete state table word looks like: fClearcCE BIT 15 cFE: BITS 12-14 output this many FE bytes Case Index BITS 8 -11 stNext: BYTE */ DECLARE maskCFE LITERALLY '07000h'; DECLARE maskCaseIndex LITERALLY '0Fh'; DECLARE shCFe LITERALLY '12'; DECLARE maskClearcCE LITERALLY '8000h'; /* X states are same as state without X plus clear cCE before executing. */ DECLARE stIdSyncX LITERALLY '8000h'; DECLARE stIdSync1B LITERALLY '0401h'; DECLARE stDevEscOut LITERALLY '0302h'; DECLARE stDevOut LITERALLY '0304h'; DECLARE stChgOut1FE LITERALLY '1007h'; DECLARE stChgOut2FE LITERALLY '2007h'; DECLARE stDevIdCE LITERALLY '0203h'; DECLARE stDevIdCEX LITERALLY '8203h'; DECLARE stDevOutBX LITERALLY '8304h'; DECLARE stDevOutCE LITERALLY '0304h'; DECLARE stDevOut1FECE LITERALLY '1304h'; DECLARE stDevOut2FECE LITERALLY '2304h'; DECLARE stDevOut1FEB LITERALLY '1304h'; DECLARE stDevOut2FEB LITERALLY '2304h'; DECLARE stDevOutDF LITERALLY '0304h'; DECLARE stDevIdCF LITERALLY '0103h'; DECLARE stDevIdCFX LITERALLY '8103h'; DECLARE stDevSetId LITERALLY '0504h';/* This state is caused by device ID byte */ /* Event types THESE MUST GO INTO AN EDF FILE */ DECLARE lKbdEvent LITERALLY '20h' ,lmotionRecEvent LITERALLY '60h' ,lstDeviceButtons LITERALLY '80h' ; /* STATE TABLE - the 3 columns of zeros are to allow access in the table by using SHR's. The row names are as follows: Id states 0 stIdSync These two states absorb FEs, then record 1 stIdSync1 next two non-FE bytes as ID. Also allow DF to dev 0. Device states 2 stDevEsc Device chars always queued. Handler switches between this and stDevice. 3 stDevId Recognise first dev char FE means id sequence. Queue char, switch to stDevice unless FE - then stIdSync. 4 stDevice All chars queued until 1 DF (not 2) or >2 FEs. 5 stIdSync2 So device data may have FEs. These two states 6 stIdSync3 allow up to 2 FEs before switching to stIdSync. 7 stChange Allows DFDF in stDevice to mean one DF. Same as stDev except DF returns to stDevice. */ DECLARE mpstMptychstNext (*) WORD PUBLIC DATA ( /* DFh CEh FEh CFh Other */ stChg, stIdSync1B, stIdSync, stIdSync1B, stIdSync1B, 0,0,0, stDevSetId, stDevSetId, stDevSetId, stDevSetId, stDevSetId, 0,0,0, stDevEscOut, stDevEscOut, stDevEscOut,stDevEscOut, stDevEscOut,0,0,0, stChg, stDevIdCE, stIdSync, stDevIdCF, stDevOut, 0,0,0, stChg, stDevIdCE, stIdSync2, stDevIdCF, stDevOut, 0,0,0, stChgOut1FE, stDevOut1FECE, stIdSync3, stDevOut1FECE, stDevOut1FEB, 0,0,0, stChgOut2FE, stDevOut2FECE, stIdSync, stDevOut2FECE, stDevOut2FEB, 0,0,0, stDevOutDF, stDevIdCEX, stIdSyncX, stDevIdCFX, stDevOutBX, 0,0,0 ); /* Examples, XX is any non-protocol byte Kbd id XX XX FE ID ID XX Dev id XX XX CE FE ID ID DF XX Kbd id XX XX CE XX FE FE .. FE ID ID XX reset during device sequence Dev id XX XX CE XX FE FE .. FE ID ID DF XX Dev data XX XX CE XX XX FE XX DF XX Dev data XX XX CE XX DF DF XX DF XX Indeterminate case XX XX CE XX XX DF XX CE FE XX XX DF XX When keystrokes interrupt a device sequence, resuming the sequence may begin with FE. The spec says >2 FEs indicate ID sequence, but BULL uses only 1 FE to introduce ID. Currently only mouse has problem. */ DECLARE MoncCE WORD PUBLIC INITIAL(0); /* DEBUG GWH */ DECLARE cCE WORD INITIAL(0);/* Count number of CEs -> index device on iBus. */ DECLARE iBusIDTable BASED pIBusIDTable STRUCTURE( cId WORD ,idVid WORD /* Included in cId, but not in cCE. */ ,rgID(4) WORD ); DECLARE maskTwoPortDevice LITERALLY '20h'; DECLARE maskIdBoot LITERALLY '40h'; DECLARE maskNotIdBoot LITERALLY '0FFBFh'; DECLARE lNilId LITERALLY '0FFFFh'; DECLARE lAnyId LITERALLY '0FF00h'; DECLARE lNothingToReport LITERALLY '0A00h'; DECLARE lKbdId LITERALLY '4B0h'; DECLARE lAnyKbdId LITERALLY '0FFB0h'; DECLARE lMouseId LITERALLY '0C00h'; DECLARE lAnyMouseId LITERALLY '0FF00h'; DECLARE wID WORD, rgbID(2) BYTE AT(.wID); DECLARE rgIBusProc(10) STRUCTURE(wID WORD, pProc POINTER, userNum WORD) PUBLIC INITIAL(lAnyMouseId, @GetMouseData, 0 ,lAnyKbdId, @GetKbdData, 0 ,2030h, @GetMonitorData, 0 ,lNilId, 0, 0 ,lNilId, 0, 0 ,lNilId, 0, 0 ,lNilId, 0, 0 ,lNilId, 0, 0 ,lNilId, 0, 0 ,lNilId, 0, 0 ); DECLARE rgIBusqProc(10) STRUCTURE(wID WORD, qProc DWORD, userNum WORD) AT(.rgIBusProc); $ELSE DECLARE lKbdEvent LITERALLY '20h'; DECLARE rgIBusProc WORD PUBLIC;/* Dummy for KbdPros. */ $ENDIF $IF MF DECLARE fCliPortAvail FLAG EXTERNAL; $ENDIF /* K b d I n t e r r u p t H a n d l e r */ /* Interrupts from the keyboard UART arrive here after the OS level-4 handler decides it must be ours. Initialization of the UART can be found in module IniDev.asm; It is set up to be txDisabled, so no transmit interrupts will occur unless we want them. */ KbdErrInt: PROCEDURE REENTRANT PUBLIC; /************************************************************************** * Function: * Called by: * Calls: * Modifications: ************************************************************************** */ DECLARE (b,i,j) BYTE; cIoErrors = cIoErrors + 1; if (processorType = NewGen) then do; OUTPUT(KbdControlReg) = initUart6402; do j = 0 to 200; end; end; ELSE IF processorType <> cws186 THEN DO i = 0 to 5; OUTPUT(kbdControlReg) = rgbInit8251(i); DO j = 0 to 10; END; END; ELSE Call OutputPlm(KbdControlReg, errorReset); if (processorType = Newgen) then do; fIntHLEDsActive=FALSE; if (SHR(INWORD(KbdDataReg),8) AND rxRdy) <> 0 then do; b = Inputplm(KbdDataReg); output(KbdClearInt) = 1; end; end; else IF (LOW(InputPlm(KbdControlReg)) AND rxRdy) <> 0 THEN b = InputPlm(KbdDataReg); RETURN; END KbdErrInt; KbdTxInt: PROCEDURE REENTRANT PUBLIC; Declare st byte ,bStatus BYTE ,cRetry WORD ,cRetryMax LITERALLY '100' ; $IF MF IF NOT fCliPortAvail THEN RETURN; IF processorType = bCpType OR processorType = bTpType THEN DO; IF ibBufOutTake <> ibBufOutPut THEN DO; cRetry=0; bStatus=InputPlm(KbdControlReg); DO WHILE (bStatus AND txRdy) = 0 AND cRetry < cRetryMax; bStatus=InputPlm(KbdControlReg); cRetry=cRetry+1; END; IF cRetry = cRetryMax THEN DO; ibBufOutTake=ibBufOutPut; RETURN; END; IF (bStatus AND 78h) <> 0 THEN DO;/*errors*/ CALL OutputPlm(KbdControlReg,37h); /*reset and enable*/ CALL Time(10); END; CALL OutputPlm(KbdDataReg,rgbBufOut(ibBufOutTake)); ibBufOutTake=(ibBufOutTake+1) AND mBufOut; END; IF fBufOutOverFlow THEN DO; fBufOutOverFlow=FALSE; CALL KPSend(lExchCli, 0); END; END; $ELSE if processorType = NewGen then do; st = SHR(INWORD(KbdDataReg),8); OUTPUT(kbdControlReg)= initUart6402; end; else st = INPUT(KbdControlReg); IF (st AND txRdy) <>0 THEN IF fIntHLEDsActive THEN DO; IF ibBufLEDsTake=ibBufLEDsPut THEN DO; /*no more to send*/ fIntHLEDsActive=FALSE; IF ((processorType <> cws186) AND (processorType <> NewGen)) THEN saveCtlUart, OUTPUT(kbdControlReg) = txDisable; ELSE DO; if processorType <> Newgen then do; DISABLE; Call OutputPlm(KbdControlReg, txIntReset); Call OutputPlm(KbdControlReg, 1); wr1ChanB = wr1ChanB AND (NOT txIntEnable); Call OutputPlm(KbdControlReg, wr1ChanB); ENABLE; end; end; end; ELSE DO; OUTPUT(KbdDataReg) = rgbBufLEDs(ibBufLEDsTake); ibBufLEDsTake = (ibBufLEDsTake+1) MOD$sBufLED; END; RETURN; END; /*output*/ cInconsistency = cInconsistency+1; IF ((processorType <> cws186) AND (processorType <> NewGen)) THEN DO; fIntHLEDsActive=FALSE; saveCtlUart, OUTPUT(kbdControlReg) = txDisable; END; ELSE DO; DISABLE; if processorType = NewGen then do; OUTPUT(KbdControlReg)= initUart6402; fIntHLEDsActive=FALSE; end; else Call OutputPlm(KbdControlReg, txIntReset); if processorType <> NewGen then do; DISABLE; Call OutputPlm(KbdControlReg, 1); wr1ChanB = wr1ChanB AND (NOT txIntEnable); Call OutputPlm(KbdControlReg, wr1ChanB); ENABLE; end; /*processorType<>NewGen*/ END; RETURN; $ENDIF END KbdTxInt; EnqueueOut:PROCEDURE(bKey, bEvent) REENTRANT; DECLARE (bKey,bEvent) BYTE; IF ((ibBufInput + 1)MOD$sBufIn) <> ibBufInTake THEN DO; /* Record events */ rgbBufIn(ibBufInPut) = bKey; rgbEventTypeBufIn(ibBufInPut) = bEvent; ibBufInPut = (ibBufInPut + 1)MOD$sBufIn; END; ELSE fBufInOverflow = TRUE; END EnqueueOut; WakeUp:PROCEDURE; IF NOT fWakeUpPending THEN DO; fWakeUpPending = TRUE; CALL KpSend(ServiceExchKbd, @rqKbdWakeUp); END; END WakeUp; CharToKbdStream: PROCEDURE (bChar) REENTRANT PUBLIC; DECLARE bChar BYTE; $IF MF DECLARE mpChSbUnencoded BASED pUnencoded (256) STRUCTURE(cb BYTE, rgb(7) BYTE); DECLARE iStroke WORD; iStroke=0; DO WHILE iStroke < mpChSbUnencoded(bChar).cb; CALL EnqueueOut(mpChSbUnencoded(bChar).rgb(iStroke) ,lKbdEvent); iStroke=iStroke+1; END; CALL WakeUp; $ENDIF RETURN; END CharToKbdStream; $IF MF ResetIBus:PROCEDURE REENTRANT PUBLIC; RETURN; END ResetIBus; /* MF receives ASCII, must look up unencoded equivalent. */ KbdRxInt: PROCEDURE REENTRANT PUBLIC; IF NOT fCliPortAvail OR pUnencoded = 0 THEN RETURN; IF (LOW(InputPlm(KbdControlreg)) AND 78h) <> 0 THEN /*errors*/ CALL OutputPlm(KbdControlreg,37h); /*reset and enable*/ CALL CharToKbdStream(InputPlm(KbdDataReg)); END KbdRxInt; $ELSE DECLARE lReset LITERALLY 'TRUE', lNoReset LITERALLY 'FALSE'; SetId:PROCEDURE REENTRANT; /* SetId is called from case 5 in kbdrxint. The state machine has recognized the proper FE sequence and the first two non FE bytes are the device ID. Here the Id is stored in the IBusIdTable at position cCE - i.e. the postion of the ID in the table reflects the postion of the device in the IBus Stream. IBus ID table structure WORD number of entries WORD Video id WORD 1st device id, usually keyboard 4B0, cCE=0 WORD 2nd device id, cCE=1 etc. It is not certain what IBus position an ID corresponds to. If the id is inconsistent with the IBus so far, reset it. Id sequences will be resent starting from 0. */ DECLARE i WORD; cCalledSetid = cCalledSetid +1; IF wID <> lNothingToReport THEN DO; /* Set mouse data. Why doesn't GetIBusData do this? */ IF LOW(wID) = 0 THEN DO;/* Single-port non-kbd device. */ mouseData.bPntDeviceIdOne = LOW(wID); mouseData.bPntDeviceIdTwo = HIGH(wID); END; /* check if we got monitor id GWH */ IF wID = 02030h THEN DO; fGotMon = TRUE; bGotMoncCE = cCE; END; wID=wID AND maskNotIdBoot;/* Remove bitNonStandardBoot */ iBusIDTable.rgID(cCE)=wID; StoredState = StNext; /* Don't clear default ids (kbd,mouse) until more than kbd id received. */ IF cCE = 0 AND (wID AND maskTwoPortDevice) <> 0 THEN /* Kbd - leave list length alone - let mouse default exist. */ cdefault = cdefault +1; ELSE DO; /* Update the count of ID's in the table */ iBusIDTable.cID=cCE+2; cInccCEbytwo = cInccCEbyTwo + 1; END; CALL QueueIBusData(HIGH(wID), lReset); /* If id inconsistent reset iBus, set cCE=0. */ DO i=1 TO cCE;/* Only scan up to level of this id. */ /* If this device id already in table, reset. */ IF iBusIdTable.rgId(i-1) = wId /* If previous device not two-ported, reset. */ OR (iBusIdTable.rgId(i-1) AND maskTwoPortDevice) = 0 THEN DO; CALL ResetIBus; RETURN;/* Id sequence will start over from 0.*/ END; END; /* Allow inbound data from this device if it is two-ported. */ IF (wID AND maskTwoPortDevice) <> 0 THEN DO; i=cCE; /* If cCE = 1 then set device 0 outboundpassthru so device 1 will get the byte ETC.. */ DO WHILE i > 0; CALL CmdKBD(bOutboundPassThru); /* Send CE */ i=i-1; END; /* Start device accepting commands. Only the KBD should get soft reset.*/ IF wId = lanykbdid THEN DO; CALL CmdKBD(bSoftReset); /* Give 1 byte time for device to notice reset. */ CALL CmdKBD(bSoftReset); END; CALL CmdKBD(bSetInBoundPass); cSetInPass = cSetInPass +1; /* End of packet. */ /* */ IF cCE <> 0 THEN CALL CmdKBD(bOutboundKbd); /* send DF */ END; END; END SetId; ResetIBus:PROCEDURE REENTRANT PUBLIC; DECLARE st BYTE; /* Note that processes are disabled for the duration of these calls to Time. */ DISABLE; /* Reassert default ids for devices that may not send proper reset sequence. */ iBusIDTable.cId=3;/* Video, Kbd, Mouse. */ iBusIDTable.rgID(0)=lKbdId; iBusIDTable.rgID(1)=lMouseId; if processorType = Newgen then do; OUTPUT(IntMonFlopPort) = 1; /* Assert Kbd Hdw reset 2500 uS*/ CALL Time(25); OUTPUT(IntMonFlopPort) = 0; /* Deassert Kbd reset 2500 uS */ CALL Time(25); OUTPUT(IntMonFlopPort) = 1; /* Assert KBD Hdw reset 7500 uS */ CALL Time(75); OUTPUT(IntMonFlopPort) = 0; /* Deassert Kbd reset */ ENABLE; end; else do; /* Reset Keyboard */ st = INPUT(VidControl); Call Time(100); OUTPUT(VidControl) = st OR 8h; /* Assert Kbd hdw reset 2500uS */ CALL Time(65); OUTPUT(VidControl) = st; /* Deassert Kbd reset for 2500 uS */ CALL Time(65); OUTPUT(VidControl) = st OR 8h; /* Assert kbd hdw reset for 7500uS */ CALL Time(175); OUTPUT(VidControl) = st; /* unreset Kbd */ ENABLE; /* This enable should be moved */ end; cCE=0; /* Reset current keyboard state to 4 (stdevice) to start to look for ID's */ stKbdCur=stDevice; END ResetIBus; QueueIBusData:PROCEDURE(bCh,fReset) REENTRANT; DECLARE bCh BYTE; DECLARE fReset FLAG; DECLARE i WORD; DECLARE qIBusProc DWORD; DECLARE pIBusProc POINTER AT(.qIBusProc); /* cCE tells what device - Look up id in iBusIDTable, use appropriate pIBusProc. */ IF cCE+1 >= iBusIDTable.cId THEN RETURN; i=LENGTH(rgIBusProc); DO WHILE i > 0; i=i-1; IF rgIBusProc(i).wID = iBusIDTable.rgId(cCE) OR rgIBusProc(i).wID = (iBusIDTable.rgId(cCE) OR lAnyId) THEN DO; qIBusProc=rgIBusqProc(i).qProc; fQueue=FALSE; /* IBus handlers return flag fEscape. */ IF CallProc( bCh, @rgbEventCode, @rgbCharCode, @bEntries, @fQueue, fReset ,pIBusProc) THEN DO; stNext=stDevEscOut; stKbdCur=LOW(stNext); END; ELSE IF stKbdCur = stDevEsc THEN DO; stNext=stDevOut; stKbdCur=LOW(stNext); END; IF fQueue THEN GOTO QueueEntries; END; END; RETURN; QueueEntries: IF NOT fReset THEN DO; i = 0; DO WHILE ((i < bEntries) AND (NOT fBufInOverflow)); CALL EnqueueOut(rgbCharCode(i),rgbEventCode(i)); i = i + 1; END; CALL WakeUp; END; END QueueIBusData; GetMouseData: PROCEDURE(bIn, prgbEventCode, prgbCharCode, pbEntries, pfQueue, fReset) flagType REENTRANT PUBLIC; DECLARE bIn BYTE ,prgbEventCode POINTER ,prgbCharCode POINTER ,pbEntries POINTER ,pfQueue POINTER ,fReset FLAG ; CALL sc_GetIBusData(bIn, prgbEventCode, prgbCharCode, pbEntries, pfQueue, fReset); RETURN FALSE; END GetMouseData; GetKbdData: PROCEDURE(bIn, prgbEventCode, prgbCharCode, pbEntries, pfQueue, fReset) flagType REENTRANT PUBLIC; DECLARE bIn BYTE ,prgbEventCode POINTER ,prgbCharCode POINTER ,pbEntries POINTER ,pfQueue POINTER ,fReset FLAG ,iKey BYTE ,ibKeyMap BYTE ,iMask BYTE ,iMaskChange BYTE ; IF fReset THEN RETURN FALSE; /* * Actions are encoded by the kbd uP as sequences of iKeys which are * currently DOWN, terminated by an iKey with its high-order-bit ON. * Until we receive that iKey, we merely record which keys are down in * keyMapNew. * The special case of the-last-key-went-up is encoded as * iKey = iKeyNoKeys with high-order bit ON. */ iKey = bIn AND 07Fh; /* Mask stop bit */ /* Turn on bit(iKey) in the KeyMapNew */ ibKeyMap = SHR(iKey, 3); KeyMapNew(ibKeyMap) = KeyMapNew(ibKeyMap) OR rgMask(iKey AND 7); IF (iKey = iKeyNoKeys) OR fReset THEN CALL SETB(0, @KeyMapNew, sKeyMap); /* All keys up */ IF bIn > 07Fh THEN DO; /* Last byte from kbd */ DO ibKeyMap = 0 TO sKeyMap - 1; /* Compare all bytes in the keymaps for differences. */ IF KeyMapOld(ibKeyMap) <> KeyMapNew(ibKeyMap) THEN DO iMask = 0 TO 7; /* Something has changed */ iMaskChange = rgmask(iMask) AND (KeyMapOld(ibKeyMap) XOR KeyMapNew(ibKeyMap)); IF iMaskChange > 0 THEN DO; /* Changed bit */ iKey = SHL(ibKeyMap, 3) + iMask; CALL EnqueueOut(iKey OR /* High order bit = 0 if key went down, 1 if up */ SHL(iMaskChange AND KeyMapOld(ibKeyMap), 7 -iMask) ,lKbdEvent); END; /* A changed bit */ END; /* Something has changed */ END; /* Loop thru bytes in keymap */ CALL MOVB(@KeyMapNew, @KeyMapOld, sKeyMap); CALL SETB(0, @KeyMapNew, sKeyMap); CALL WakeUp; END; /* Last byte */ RETURN FALSE; END GetKbdData; GetMonitorData: PROCEDURE (bIn, prgbEventCode, prgbCharCode, pbEntries, pfQueue, fReset) flagType REENTRANT PUBLIC; /************************************************************************** xxxxxx **************************************************************************/ DECLARE bIn BYTE ,prgbEventCode POINTER ,prgbCharCode POINTER ,pbEntries POINTER ,pfQueue POINTER ,fReset FLAG ; /* DEBUG code added to see whats the first three characters getting here GWH */ MoncCE = cCE; cCalledGetMonitorData = cCalledGetMonitorData + 1; /* IF cCalledGetMonitorData = 1 THEN chMon1 = bIn; ELSE IF cCalledGetMonitorData = 2 THEN chMon2 = bIn; ELSE chMon3 = bIn; */ IF bIn = bVolumeUp THEN DO; fVolumeUp = TRUE; cVolumeUp = cVolumeUp +1; END; ELSE IF bIn = bVolumeUp THEN DO; fVolumeDown = TRUE; cVolumeDown = cVolumeDown + 1; END; ELSE IF bIn = bContrastUp THEN DO; fContrastUp = TRUE; cContrastUp = cContrastUp + 1; END; ELSE IF bIn = bContrastDown THEN DO; fContrastDown = TRUE; cContrastDown = cContrastDown + 1; END; ELSE IF bIn = bBrightnessUp THEN DO; fBrightnessUp = TRUE; cBrightNessUp = cBrightNessUp +1; END; ELSE IF bIn = bBrightnessDown THEN DO; fBrightnessDown = TRUE; cBrightnessUp = cBrightNessUp +1; END; ELSE /* ERROR Condition */ DO; fErrorOccured = TRUE; cErrorOccured = cErrorOccured +1; bErrorByte = bIn; END; RETURN FALSE; END GetMonitorData; KbdRxInt: PROCEDURE REENTRANT PUBLIC; /************************************************************************** * Function: * This is the interrupt routine for the IBus. * * Notes: * The IBus interrupt handler is now table driven. The current state * of the system combined with the input byte from the USART select the * next state. States that require identical processing, will have * equivalent values for their state words and thus can all be handled in * the same CASE. * Certain states such as StDevOut2FEB can cause more than one entry to * be input into rgbBufIn (and rgbEventTypeBufIn). To support this, * states that cause more than one entry (one of which is always FE) * must be preprocessed. ************************************************************************** */ DECLARE bIn BYTE ,erc WORD ,iCase BYTE ,i BYTE ; DECLARE tych WORD ,cFE BYTE /* Count of FE bytes */ ; bIn = INPUT(KbdDataReg); if (processorType = Newgen) then output(KbdClearInt) = 1; IF bIn = 0CEh THEN CEinState = StNext; /* Determine StNext depending on the incoming byte */ tych=FINDB(@mptychCh, bIn, SIZE(mptychCh)); IF tych = 0FFFFh THEN tych=tychOther; /* IF bIn = bInBoundMouse /* THEN tych = tychInBoundMouse; /* ELSE IF bIn = bInBoundMouseOV /* THEN tych = tychInBoundMouseOV; /* ELSE IF bIn = bInBoundKbd /* THEN tych = tychInBoundKbd; /* ELSE IF bIn = bIdSync /* THEN tych = tychIdSync; /* ELSE tych = tychOther; /**/ /* Get the next position in the state table. */ StNext = mpStMptychstNext(SHL(stKbdCur, 3) + tych); StKbdCur = LOW(StNext); IF bIn = 0CEh THEN CEnextState = StNext; /* After DF that terminates device data, clear device index cCE. */ IF (stNext AND maskClearcCE) <> 0 THEN DO; cCE=0; cClearedcCE = cClearedcCE +1; END; $IF fDebug /***** trace ******/ IF fKbdTrace THEN do; rgbKbdTraceBuffer(iKbdTraceBuffer) = stKbdCur; iKbdTraceBuffer = (iKbdTraceBuffer + 1) ModsKbdTraceBuffer; rgbKbdTraceBuffer(iKbdTraceBuffer) = bIn; iKbdTraceBuffer = (iKbdTraceBuffer + 1) ModsKbdTraceBuffer; end; $ENDIF /** Throw away all but keyboard keys if debugger is enabled **/ /* Bogus - this byte may drive us to kbd state. Must process all bytes. /* IF (fDebuggerEnabled OR fDebuggerExecuting) THEN /* IF (iBusIDTable.rgId(cCE) OR lAnyId) <> lAnyKbdId THEN RETURN; /**/ cFE = SHR(StNext and maskcFE, ShCFE); /* Number of FE bytes */ /* Preprocess FE bytes */ DO WHILE cFE > 0; CALL QueueIBusData(bIDSync,lNoReset); cFE = cFE - 1; END; /* Process the current state appropriately */ iCase = HIGH(StNext) AND maskCaseIndex; IF iCase > 4 THEN iCase = 5; /* THIS SHOULD NEVER HAPPEN */ DO CASE (iCase); DO; /* Case 0 */ END; DO; /* Case 1 */ /* Got a CF indicating switch to device but lost data (Reset) */ /* IF received from single-port device, treat as data. */ IF (iBusIDTable.rgID(cCE) AND maskTwoPortDevice) <> 0 THEN DO; /* Dual-port device, treat CF as protocol. */ IF cCE < iBusIDTable.cId-1 THEN cCE=cCE+1;/* id0=Vid, id1=Kbd */ CALL QueueIBusData(bIn,lReset); END; ELSE /* Single-port device */ CALL QueueIBusData(bIn,lNoReset); END; DO; /* Case 2 */ /* Got a CE indicating switch to device, perhaps "Nothing to report" from Kbd. */ /* IF received from single-port device, treat as data. */ cCase2 = cCase2+1; IF (iBusIDTable.rgID(cCE) AND maskTwoPortDevice) <> 0 THEN DO; /* Dual-port device, treat CE as protocol. */ IF cCE < iBusIDTable.cId-1 THEN DO; cCE=cCE+1;/* id0=Vid, id1=Kbd */ cUpdatecCE = cUpdatecCE; END; END; ELSE /* Single-port device */ CALL QueueIBusData(bIn,lNoReset); END; DO; /* Case 3 */ /* Handles all states that capture a byte from a device. */ CALL QueueIBusData(bIn,lNoReset); END; /* End Case 3 */ DO; /* Case 4 */ /* FE sequence ended, ID started. Record low byte of word ID. */ rgbID(0)=bIn; END; /* End Case 4 */ DO; /* Case 5 */ /* Device ID sequence complete. Record device. */ rgbID(1)=bIn; CALL SetId;/* uses cCE, wID and iBusIdTable. */ END; /* End Case 5 */ DO; /* Case 6 */ /* CALL Tell(.('Software error in KbdRxInt - invalid case index.')); */ END; /* End Case 6 */ END; /* End DO CASE */ RETURN; END KbdRxInt; $ENDIF IntHKbd: PROCEDURE REENTRANT PUBLIC; /************************************************************************** * Function: * Keyboard interrupts come in through here and are dispatched * based on whether an error has occurred or a character is * present. * Called by: * Calls: KbdRxInt, KbdTxInt, KbdErrInt * Modifications: ************************************************************************** */ DECLARE (bStatus, b, StatMask) BYTE ,erc WORD ; if processorType = Newgen then bStatus = SHR(INWORD(KbdDataReg),8); else bStatus = INPUT(kbdControlReg); if processorType = NewGen then StatMask = 1ch; else StatMask = 38h; IF 0 <> (bStatus AND StatMask) THEN DO; CALL KbdErrInt; /*parity, overrun, or framing*/ RETURN; END; IF (bStatus AND rxRdy) <> 0 THEN CALL KbdRxInt; /*input*/ ELSE CALL KbdTxInt; /*output*/ END IntHKbd; CmdKbd: PROCEDURE (b) PUBLIC REENTRANT; /************************************************************************** * Function: * This procedure is used to ouput commands to the keyboard. * Called by: KbdRxInt * Calls: * Modifications: ************************************************************************** */ DECLARE b BYTE; IF ((processorType <> cws186) AND (processorType <> NewGen)) THEN do; /* Put b in buffer and wake up interrupt handler if necessary */ IF ((ibBufLEDsPut+1) MOD$sBufLED) <> ibBufLEDsTake THEN do; rgbBufLEDs(ibBufLEDsPut) = b; ibBufLEDsPut = (ibBufLEDsPut+1) MOD$sBufLED; IF NOT fIntHLEDsActive THEN DO; fIntHLEDsActive = TRUE; OUTPUT(kbdControlReg) = txEnable; END; END; END; ELSE DO; /* Must be CWS or NewGen */ /* Output if transmitter is not active */ IF NOT fIntHLedsActive THEN DO; fIntHLEDsActive = TRUE; DISABLE; if processorType <> NewGen then do; Call OutputPlm(KbdControlReg, 1); wr1ChanB = wr1ChanB OR txIntEnable; Call OutputPlm(KbdControlReg, wr1ChanB); end; /*processorType<>NewGen*/ Call OutputPlm(KbdDataReg, b); ENABLE; END; ELSE IF ((ibBufLEDsPut+1) MOD$sBufLED) <> ibBufLEDsTake THEN DO; rgbBufLEDs(ibBufLEDsPut) = b; ibBufLEDsPut = (ibBufLEDsPut+1) MOD$sBufLED; END; END; RETURN; END CmdKbd; BeepIo:PROCEDURE(fOn) REENTRANT PUBLIC; DECLARE fOn Flag; IF fOn THEN OUTWORD(BeeperPortNGen) = (Inputplm(BeeperPortNGen) and BeeperOffNGen) OR BeeperOnNGen; ELSE /*Off*/ OUTWORD(BeeperPortNGen) = Inputplm(BeeperPortNGen) AND BeeperOffNGen; RETURN; END BeepIo; KbdErrIntCWS: PROCEDURE (lineNo) REENTRANT PUBLIC; DECLARE lineNo WORD; CALL KbdErrInt; END KbdErrIntCWS; KbdTxIntCWS: PROCEDURE (lineNo) REENTRANT PUBLIC; DECLARE lineNo WORD; CALL KbdTxInt; END KbdTxIntCWS; KbdRxIntCWS: PROCEDURE (lineNo) REENTRANT PUBLIC; DECLARE lineNo WORD; CALL KbdRxInt; END KbdRxIntCWS; WriteIBusEvent:PROCEDURE(pb, cb) ercType REENTRANT PUBLIC; DECLARE pb POINTER, cb WORD; DECLARE rgw BASED pb (1) WORD; DECLARE i WORD; DECLARE wDSUser WORD; wDsUser=SetDSOsDGroup; DO i=0 TO SHR(cb,1)-1; CALL EnqueueOut(HIGH(rgw(i)),LOW(rgw(i))); END; CALL WakeUp; CALL SetDS(wDsUser); RETURN ercOk; END WriteIBusEvent; $IF MF WriteIBusDevice:PROCEDURE(wId, pb, cb) ercType REENTRANT PUBLIC; DECLARE wId WORD; DECLARE pb POINTER, cb WORD; RETURN ercNotImplemented; END WriteIBusDevice; $ELSE NGen WriteIBusDevice:PROCEDURE(wId, pb, cb) ercType REENTRANT PUBLIC; DECLARE wId WORD; DECLARE pb POINTER, cb WORD; DECLARE rgb BASED pb (1) BYTE; DECLARE (i,iId) WORD; DECLARE wDSUser WORD; wDsUser=SetDSOsDGroup; DO iId=1 TO iBusIDTable.cId-1; IF wID = iBusIDTable.rgId(iId-1) OR wID = (iBusIDTable.rgId(iId-1) OR lAnyId) THEN DO; DO i=1 TO iId-1; CALL CmdKbd(bOutboundPassThru); END; i=0; DO WHILE i < cb; CALL CmdKbd(rgb(i)); i=i+1; END; /* End of packet. */ IF iId > 1 THEN CALL CmdKBD(bOutboundKbd); CALL SetDS(wDsUser); RETURN ercOk; END; END; CALL SetDS(wDsUser); RETURN ercIBusNoSuchId; END WriteIBusDevice; $ENDIF /* LOG 11/26/82 by JF: Use Optimize(3); Use V2SysLit for V2 Compiler Organize Includes; Use CrashIfErcNotOK 1/6/83 by JF: Use KPsend 5/2/83 by MO: Make module machine independent with run time checks 8/29/83 by JF: Add support for unplugging keyboard from a t1. Under 8.2, keyboard would remain reset and was unusable after plugging it back in. 10/19/83 by JA: Use $IF so CTOS SP shorter. 2/11/84 by JA: BeepIo moved here from KbdPros to shorten everybody. 2/15/84 by JA: NGen keyboard plug-in works for Aws. Also make state table. 10/17/84 by JF: add mouse stuff 3/1/85 by MO: add dummy routines for CWS kbd 4/2/85 by MO: add support for GWS 8/7/85 by KB: added formatting so can read tables etc. 2/27/86 by MS: throw away mouse input when in the debugger. 4/18/86 by FW: Support for 6402 uart on NewGen. 4/23/86 by KB: made tracing conditional compiled. 6/23/86 by DR: use NGenOffBeeper literal 7/1/86 JM/JA, increase kbd buffer to 64 bytes. 9/29/86 by DR: CTOS II 2.0 merge 11/10/86 JA remove CTOS.edf. 11/18/86 FW correct some Kbd problems with 286i. 6/24/87 JA EnqueueOut, WriteIBusEvent. 11/9/87 JA In/OutPutPlm ala 9.9. 11/25/87 JA IBus device support, Bull first client. 11/30/87 JA Remove stKbd, fold into stDevice. 12/4/87 JA Reset IBus when encounter inconsistent id. 12/9/87 JA mask wId bitNonStandardBoot. Soft reset twice for Bull kbd. 12/15/87 JA lNilId=0FFFFh. 12/16/87 JA don't clear iBusIdTable.cId until ids received. 12/17/87 JA add WriteIBusDevice. 1/13/88 JA invent KbdInt_MF with pUnencoded. CTOS 2.3 1/29/88 JA Make GetKbdData,GetMouseData return flag fEscape. 2/2/88 JA dummy rgIBusProc,ResetIBus for MF. 2/22/88 JA/AM treat CE or CF as data when received from 1-port device. fEscape no longer needed, but left in. Actually it doesn't work with >1 device, as DF may be received at any time. Also make rgbBufLeds a sysgen option. 3/4/88 JA ResetIBus set default kbd,mouse ids. 07/06/88 JM Do SRP 8251 stuff for transmit side. 12/4/88 JA ercNotImplemented WriteIBusDevice on Srp. 09/21/89 JMR wrote CharToKbdStream from KbdRxInt. 10/17/89 JMR made CharToKbdStream Stub for workstation dueto link errors. */