DMA Send and Receive Pseudocode - Complete SINTRAN Analysis
DMA Send Operation (HOINT - Transmitter Interrupt)
Complete Transmitter Interrupt Handler (Line 104034)
SUBR HOINT % Line 104033 - Transmitter interrupt
INTEGER TMR:=0 % Timer register
INTEGER HASTAT % Hardware status storage
INTEGER ACTSW % Activity switch
INTEGER TELL:=0 % Interrupt counter
INTEGER DUIN:=0 % Retry counter (dummy interrupts)
INTEGER SNDAC:=0 % AC field of buffer to transmit
INTEGER ARRAY BUFF0(BUFSIZ) % Frame data logging
INTEGER ARRAY BUFF1(BUFSIZ) % Device number logging
INTEGER ARRAY BUFF2(BUFSIZ) % Device status logging
INTEGER CMODI % Communication mode
HOINT:
% Step 1: Reset timer
0=:TMR % Reset timer
% Step 2: Read transmitter status - IOX+12
T:=HDEV+RTTS; *EXR ST % READ TRANSMITTER TRANSFER STATUS
A=:HASTAT % Store status in HASTAT variable
% Step 3: Check if unexpected interrupt
IF T:=ACTSW = 0 THEN % Device not active?
MIN DUIN; P+0; CALL WT12 FI % Increment retry counter (DUIN)
% Step 4: Mark device inactive
0=: ACTSW % Clear activity switch
% Step 5: Turn off RQTS if X.21 mode
IF CMODI = 40 THEN % X.21 mode?
T:=HDEV+WTTC; *EXR ST % IOX+13 - Turn off RQTS signal
FI
% Step 6: Increment interrupt counter for logging
GO HNOTRA % Patch for trace (if enabled)
MIN TELL; P+0 % Increment interrupt counter
TELL /\ TELMA=:TELL % Wrap counter (TELMA = BUFSIZ-1)
% Step 7: Log transmission data for debugging
A:=SNDAC % Get first word in transmitted frame
X:=TELL; *1BANK
A=:BUFF0(X); *2BANK % Log first word in frame
HDEV; *1BANK
A=:BUFF1(X); *2BANK % Log device number (HDEV)
HASTAT; *1BANK
A=:BUFF2(X); *2BANK % Log device status (HASTAT)
HNOTRA: % Trace patch entry point
X:=OMSG % Get current message pointer
% Step 8: **CRITICAL SUCCESS/ERROR CHECK**
IF A/\ "SILFO+TXUND" = 0 THEN % Line 104102 - Check for success
% SUCCESS PATH:
% SILFO = 0x8000 (bit 15) = Illegal format
% TXUND = 0x0002 (bit 1) = Transmitter underrun
% Combined mask = 0x8002
% If (HASTAT & 0x8002) == 0, transmission was successful
XRETRY=:RTDYN; A:=0; CALL SADTS % No retry needed, clear error
ELSE
% ERROR PATH:
% Either Illegal format OR Transmitter underrun occurred
A:=HASTAT; CALL SADTS; CALL DRERR % Handle error, may retry
A:=EUND % Set underrun error code
FI
% Step 9: Complete transmission
0=:DCBX; GO FAR BACKX % Clear current DCB, return to message handler
RBUS
DMA Receive Operation (HIINT - Receiver Interrupt)
Complete Receiver Interrupt Handler (Line 104436)
SUBR HIINT % Line 104436 - Receiver interrupt
INTEGER HASTAT % Hardware status storage
INTEGER ACTSW % Activity switch
INTEGER STPCNT % Stop counter
INTEGER TELL:=0 % Interrupt counter
INTEGER T9:=0 % Dummy interrupt counter
INTEGER T1:=0, T2:=0 % Temp variables for list copying
INTEGER LISTP, LIINT % DMA list pointers
INTEGER ARRAY BUFF1(BUFSIZ) % Device number logging
INTEGER ARRAY BUFF2(BUFSIZ) % Device status logging
INTEGER ARRAY BUFF3(11) % List keys when stopped
INTEGER ARRAY POINTER P0BUFF:=BUFF0 % Frame data pointer
HIINT:
% Step 1: Read receiver status - IOX+10
T:=HDEV+RRTS; *EXR ST % READ RECEIVER TRANSFER STATUS
A=:HASTAT % Store status in HASTAT variable
% Step 2: Check if unexpected interrupt
IF T:=ACTSW = 0 THEN % Not expecting data?
MIN T9; P+0; GO OUT1 FI % Increment dummy interrupt counter, exit
% Step 3: **X.21 ERROR PROCESSING**
IF A/\ HX21M >< 0 THEN % X.21 error bits (13-14)?
% HX21M = 0x6000 = bits 13-14 = X.21 modem status
T:=2000; X:=LIINT+T; T:=X.LKEY % Get DMA list key
A\/ LIINT.LKEY=:X.LKEY % Save error status in list
IF A BIT HX21S THEN % X.21 clear indication?
% HX21S = 0x000E = bits 1-3 = X.21 receiver state
HASTAT BONE BLDON=:HASTAT % Set block done bit
LIINT.LKEY BONE XBLDN=:X.LKEY % Set XBLDN to terminate
FI
FI
% Step 4: **LIST EMPTY PROCESSING - CRITICAL**
IF HASTAT/\"EMTY" >< 0 THEN % List empty (bit 11)?
% EMTY = 0x0800 = bit 11 = List Empty
% This STOPS the receiver completely!
0=:ACTSW % Stop device
MIN STPCNT % Increment stop counter (STPCNT)
P+0 % Skip return
% Save DMA list state when stopped for debugging
LISTP=:T1; 0=:T2
DO WHILE T1.LKEY >< "NLP" % Copy DMA list keys
X:=T2; *1BANK
A=:BUFF3(X); *2BANK % Save list key
MIN T2; 0/\0; T1+4=:T1
OD
FI
MORE: % Main receive processing loop
% Step 5: **BLOCK PROCESSING - CRITICAL**
A:=2000; X:=LIINT+A; X.LKEY % Get current list entry
A:=LIINT.LKEY=:D % Store key in D register
IF A NBIT XBLDN THEN % No more filled blocks (BlockEnd=0)?
% XBLDN = 0x0008 = bit 3 = Block done
% If BlockEnd NOT set, no more blocks to process
IF A = "ERB" THEN GO FAR ZSTARC FI % If empty, enable receiver
GO FAR OUT1 % Exit processing
FI
% Step 6: Log received data for debugging
GO HNOTRA % Trace patch
MIN TELL; P+0 % Increment interrupt counter
TELL /\ TELMA=:TELL=:X % Wrap counter, use as index
HDEV; *1BANK
A=:BUFF1(X); *2BANK % Log device number
HASTAT; *1BANK
A=:BUFF2(X); *2BANK % Log device status (HASTAT)
% Step 7: Get frame data
T:=LIINT.LMEM1; X:=X.LMEM2; *AC@3 LDATX % Get memory pointers
X:=TELL; *1BANK
A=:P0BUFF(X); *2BANK % Log first word of received frame
HNOTRA: % Trace patch entry point
% Step 8: Get received message information
X:=LIINT; A:=2000; X+A; X.DLSTS % Get DMA list status
A:=LIINT.LBYTC+DISP1=:T % Get received message size
% Step 9: Find corresponding DCB (Data Control Block)
CALL XMPAT % Find DCB from DCB list
X=:L; A:=LIINT.LKEY=:D; 0=:X.LKEY; 0=:X.LMEM2; X:=L
% Step 10: **FRAME STATUS PROCESSING**
IF A /\ "LMASK" = 3 THEN % Good frame received?
A:=0; CALL SCRET; CALL SADTS % Success - clear error, store status
ELSE
% Frame error processing
IF A BIT HX21S THEN EX21 ELSE EINP FI % X.21 or input error
CALL SCRET % Set return code
A:=D; CALL SADTS; A\/DSTAT=:DSTAT % Store status, update error flags
HDERC+1=:HDERC % Increment error counter
FI
% Step 11: Send message back to user
X-BHEAD; CALL OCHAIN % Queue message for user
% Step 12: Move to next DMA list entry
LIINT+4=:LIINT % Advance to next list entry
A+2000; A.LKEY % Check next entry
IF LIINT.LKEY=NLP THEN % End of list?
LISTP=:LIINT % Reset to start of list
FI
GO FAR HDSTA % Check for more messages
OUT1: % Exit sequence
% Step 13: **RECEIVER CONTROL UPDATE**
A:="1734"\/MAINT/\HXDOK % Calculate control value
% 1734 (octal) = 1244 decimal = 0x04DC
T:=HDEV+WRTC; * EXR ST % IOX+11 - Write receiver control
GO FAR HDSTA % Check for more messages
RBUS
Additional Registers Read After RRTS/RTTS
After RTTS Read (Line 104053):
% Additional register operations in transmitter interrupt:
T:=HDEV+WTTC; *EXR ST % IOX+13 - Turn off RQTS
After RRTS Read (Line 104321):
% Additional register operations in receiver interrupt:
T:=HDEV+WRTC; * EXR ST % IOX+11 - Update receiver control
Critical Status Bit Analysis
What SINTRAN Cares About After RTTS Read:
- SILFO (0x8000, bit 15) - Illegal format error
- TXUND (0x0002, bit 1) - Transmitter underrun error
- Combined check: (HASTAT & 0x8002) == 0 means SUCCESS
- If error bits set: Increment retry counter, may retransmit
What SINTRAN Cares About After RRTS Read:
- HX21M (0x6000, bits 13-14) - X.21 modem error status
- HX21S (0x000E, bits 1-3) - X.21 receiver state bits
- EMTY (0x0800, bit 11) - List empty (STOPS receiver completely)
- XBLDN (0x0008, bit 3) - Block done (more blocks available)
- LMASK bits - Frame validation mask
DMA Setup Operations - Complete WDCR/RDCR Usage
1. Transmitter DMA Start (XHMST - Line 103705):
SUBR XHMST % Start transmitter DMA
XHMST: LIINT+DPITPHYS; % Calculate physical DMA list address
XXHMST:T:=HDEV+WDMA; *IOF; EXR ST % IOX+15 - Write DMA address (least significant)
% DMA Command: Start Transmitter + Command Value
A:=2000\/D; T+"WDCR-WDMA"; *EXR ST % IOX+17 - Write DMA command + trigger
% 2000 (octal) = 1024 decimal = 0x400 = Start transmitter DMA
% Verify DMA Status
T+"RDCR-WDCR"; X:=-20;*EXR ST % IOX+16 - Read DMA status
CALL LTOUT; *JAF *-2; ION % Link timeout with 20 count timeout
% Enable Transmission
1134+CMODI; T:=HDEV+WTTC; *EXR ST % IOX+13 - Write transmitter control
% 1134 (octal) = 604 decimal = 0x25C = DMA transmit enable + mode
1 =: ACTSW % Mark device active
OMSG =: DCBX % Set current DCB
RBUS
2. Receiver DMA Start (ZSTARC - Line 104270):
SUBR ZSTARC % Start receiver DMA
ZSTARC: IF ACTSW = 0 THEN % Device not active?
% Clear receiver state
HXDOK/\MAINT; T:=HDEV+WRTC; *EXR ST % IOX+11 - Clear old garbage
% Set DMA Address
% ADD DPITPHYS TO GET PHYSICAL ADDRESS
LIINT+DPITPHYS; T:=HDEV+WDMA; *EXR ST % IOX+15 - Write DMA address
% DMA Command: Start Receiver
A:=1001; T+"WDCR-WDMA"; *EXR ST % IOX+17 - Write DMA command + trigger
% 1001 (octal) = 513 decimal = 0x201 = Start receiver DMA
% Verify DMA Status
T+"RDCR-WDCR"; X:=-10; *EXR ST % IOX+16 - Read DMA status
CALL LTOUT; *JAF *-2 % Link timeout with 10 count timeout
1=:ACTSW % Mark device active
FI
RBUS
3. Initialization DMA Setup (Line 105121):
SUBR HDSIN_DMA_INIT % HDLC initialization DMA setup
% Set DMA Address for Initialization
A:=XINITA+DPITPHYS; T:=HDEV+WDMA; *IOF; EXR ST % IOX+15 - Write init DMA address
% DMA Command: Initialize
401; T+"WDCR-WDMA";*EXR ST % IOX+17 - Write DMA command + trigger
% 401 (octal) = 257 decimal = 0x101 = Initialize DMA
% Verify DMA Status
T+"RDCR-WDCR"; X:=-10;*EXR ST % IOX+16 - Read DMA status
CALL LTOUT; * JAF *-2 % Link timeout with 10 count timeout
RBUS
4. X.21 DMA Operations (Line 110754):
SUBR X21_DMA_SETUP % X.21 HDLC DMA setup
% Clear DMA
T:=X2DHD+XWDCR; *EXR ST % IOX+17 - Clear DMA command register
% Wait for DMA Ready
X:=-30; T:=X2DHD+XRDCR; *EXR ST % IOX+16 - Read DMA status with timeout
*JPC TODMA; JAF *-2 % Jump on timeout, retry with 30 count
% Initialize X.21 DMA
A:=X2DUI.XINITA+DPITPHYS % Calculate physical address
T:=X2DHD+XWDMA; *IOF; EXR ST % IOX+15 - Write DMA address
401; T+"XWDCR-XWDMA"; *EXR ST % IOX+17 - Write DMA command (401 octal)
% Verify X.21 DMA Status
X:=-30; T+"XRDCR-XWDCR"; *EXR ST % IOX+16 - Read status with 30 timeout
*JPC TODMA; JAF *-2 % Jump on timeout
% Start X.21 Receiver
X.LIINT+DPITPHYS; T:=X2DHD+XWDMA; *EXR ST % IOX+15 - Set receiver DMA address
A:=1001; T+"XWDCR-XWDMA"; *EXR ST % IOX+17 - Start receiver (1001 octal)
X:=-30; T+"XRDCR-XWDCR"; *EXR ST % IOX+16 - Verify with 30 timeout
*JPC TODMA; JAF *-2
RBUS
5. DMA Clear Operation (Line 104747):
SUBR SMCLEAR_DMA % Clear DMA during shutdown
SMCLEAR: T:=HDEV+WTCR; A:=2; *EXR ST % IOX+7 - Send EOM to avoid issues
* TRR 10; IOF % Clear cache
A:=100; T:=HDEV+WRTC; *EXR ST % IOX+11 - Clear receiver
A:=140; *EXR ST % IOX+11 - Set maintenance mode
T+"WDCR-WRTC";*EXR ST; ION % IOX+17 - Clear DMA command register
RBUS
WDCR Command Values Analysis
DMA Command Values Used:
% Transmitter Commands:
2000 (octal) = 1024 decimal = 0x400 % Start transmitter DMA
% Receiver Commands:
1001 (octal) = 513 decimal = 0x201 % Start receiver DMA
% Initialization Commands:
401 (octal) = 257 decimal = 0x101 % Initialize DMA
% Clear Commands:
0 (written implicitly) % Clear/stop DMA
RDCR Status Check Pattern
Standard DMA Verification Sequence:
% Pattern used throughout SINTRAN:
T+"RDCR-WDCR"; X:=-timeout; *EXR ST % IOX+16 - Read DMA status
CALL LTOUT; *JAF *-2 % Link timeout, retry if timeout
% Where timeout is:
% -10 = 10 count timeout (receiver)
% -20 = 20 count timeout (transmitter)
% -30 = 30 count timeout (X.21)
Key Insights
- SINTRAN does NOT check DMAModuleRequest bit - it relies on success/error bits
- Transmitter success =
(HASTAT & 0x8002) == 0 (no SILFO or TXUND)
- Receiver stops if EMTY (ListEmpty) bit set - critical for emulator
- Block processing continues only if XBLDN (BlockEnd) bit set
- Multiple status registers updated after main status read (WTTC, WRTC)