Trailing-Edge
-
PDP-10 Archives
-
BB-PBDED-BB_1990
-
10,7/unsmon/xtcser.mac
There are 9 other files named xtcser.mac in the archive. Click here to see a list.
TITLE XTCSER - DA28 SERVICE ROUTINE AND XTTSK. UUO PROCESSOR - V163
SUBTTL DONALD LEWINE/DAL/RCR/TAH/KR/RDH/KR 17-APR-90
SEARCH F,S
$RELOC ;RELOCATE
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1974,1975,1976,1977,1978,1979,1980,1984,1986,1988,1990.
;ALL RIGHTS RESERVED.
.CPYRT<1974,1990>
XP VXTCSR,163 ;PUT VERSION NUMBER IN STORAGE MAP AND GLOB
XTCSER::ENTRY XTCSER ;LOAD XTCSER IF NEEDED FROM LIBRARY
SUBTTL REVISION HISTORY
COMMENT \ ;;; REVISION HISTORY
V064 FIX INPUT BUFFER SIZE CHECK & ADD NEW EP MODES
V065 ADD FTFRC CONDITIONAL, FIX HUNG DEVICE RECOVERY (RDYCHK)
V066 ADD HISTORY TABLE TO TRACE DA28C TRANSACTIONS
V067 ADD ADDITION ERROR RECOVERY & FIX TTY RESET ON GET
V070 CORRECT OUTPUT OF WFO ETC. AND ADD MESSAGE ACK
ADD XTGRB AND XTRET SUB-FUNCTIONS TO XTTSK. UUO
V071 FIRST ROUND MODS FOR 5.07/6.01
V072 FIX BUFFER LOOK AHEAD CODE IN INPUT/OUTPUT
V073 VARIOUS FIXES + RE-WRITE OF UNIT INTERLOCK LOGIC
V074 USE WORD COUNT SUPPLIED BY USER AND NOT THE BUFFER SIZE
ON OUTPUT UUO'S. MOREOVER IGNORE EMPTY BUFFERS
V075 REMOVE A RACE CONDITION BETWEEN RECCLS CODE AND RFI OUTPUT
V076 USE DEVIOS INSTEAD OF S AT UUO LEVEL
V077 LAST BUFFER WAS LOST DUE TO WRONG END OF FILE LOGIC
V100 THE USE OF S CAUSES THE GLOBAL PIOMOD TO RETURN THE WRONG
IOMODE. USE A GLOBAL PIOMOD INSTEAD
V101 THE XTGRB FUNCTION SHOULD REMOVE A DEVICE FROM THE CONSO
SKIP CHAIN AS ELSEWHISE REAL TIME USE OF THE DA28 WILL
CAUSE PROBLEMS WHENEVER A DEVICE ON THE SAME PI CHANNEL
IS BEING USED
V102 ANY XTGRB CONDITION SHOULD FAIL AS LONG AS THE CONTROLLER
HAS NOT BEEN RETURNED
V103 XTCOUT USED THE WRONG LOGIC FOR EMPTY BUFFERS
V104 TTY I/O NO LONGER ALLOWED A USER TO LOG IN ON A DA28 TERMINAL
AS UNNECESSARY WAKES WERE BEING DONE
V105 CLEAR XMIT STATUS BITS ON AN INIT SO A DDB CAN BE REUSED WITHOUT
DELETING IT
V106 IF AN EP WANTS TO KNOW WHETHER A PROCESS ON THE DECSYSTEM-10
IS SLOW OR THAT THE DECSYSTEM-10 HAS BEEN RELOADED IT HAS NO
TOOL. MOREOVER IT CANNOT COMMUNICATE ITS OPINION ON THE STATE OF
AFFAIRS. THEREFORE INTRODUCE A RESTART STATUS (SF=7), WHICH
IS SENT BY THE EP TO THE DECSYSTEM-10 AND STATES THE EP'S OPINION
0 IS DOWN;-1 IS UP. THIS INFO IS IN THE LAST 16 BITS OF A CTL WORD
THE -10 WILL RESPOND BY SENDING ITS STATUS. THIS WILL ABORT -10 JOBS
IF THE EP HAS PROBLEMS
V107 A RECEIVED REJECT SHOULD CLEAR IOACT IN DEVIOS TO PREVENT HUNG DEVICES
V110 STOP USING BITS IN RIGHT HALF OF DEVIOS AND REPLACE THIS BY LOGIC
TO RETURN AN OLD FASHIONED S
V111 DUMP MODE AND BUFFERED MODE NEED A DIFFERENT IO(D)END BIT
V112 STOP USING DEVIOS FOR ALL PROTOCOL STATUS BITS AND USE
A PROTOCOL STATUS WORD
V113 STOP CLOBBERING S IN XOSYNC AND XISYNC ROUTINE
V114 REDO ALL THE GETCTL AND XMT PROTOCOL LOGIC IN SUCH A WAY
THAT STOPCODE KNF SHOULD BE IMPOSSIBLE
V115 UNDO EDIT 105 AND USE THE RELEASE UUO TO RESET THE PROTOCOL STATUS
MOREOVER SEND A RESTART TASK MESSAGE
V116 ONLY DO A WAKE OF A .C0JOB IF XTCSER HAS DONE A HIBER FOR IT
V117 SEVERAL RETURNS WERE MADE BY XTCSER FOR XTTSK UUO'S
WHICH SHOULD HAVE BEEN JRSTS TO AN ERROR CODE GENERATOR
V120 NEEDLESS RESCHEDULING WAS DONE OF UUO CODE USE A COROUTINE ME-
CHANISM TO RUN UUO CODE ONLY WHEN AN EVENT NEEDED TO EXIT TO THE
UUO CODE OCCURRED
V121 IN LOGICAL MODE 11 THE BUFFER SIZE WAS LIMITED TO THE SIZE OF THE
MONITOR BUFFER. THIS RESTRICTION SEEMS UNNECESSARY
V122 BUFFERED AND DUMP MODE I/O USE DIFFERENT CODE FOR MANY PURPOSES
REDO I/O SO BUFFERED MODE IS A SPECIAL CASE OF DUMP MODE I/O
V123 MAKE DEVICES ALWAYS IO ACTIVE EVEN IN THE RFI RFO STATUS, THIS
WILL CAUSE FAST RESPONSES TO BENEFIT
V124 DO NOT FORCE UNITS OFFLINE AT IOGO TIME AS REMOTES CAN USE THE RESTART
STATUS TO DETECT PROBLEMS
V125 ADD MORE DATA TO GET CHARACTERISTICS FUNCTION OF XTTSK UUO
V126 HUNG LOGIC IS WRONG YOU ONLY SHOULD CLEAR THE DA28C WHEN
THE DDB USING THE DA28C IS THE HANGING ONE
V127 A WAKE UUO WAKING A .C0JOB DOING I/O TO OR FROM A TASK DDB
CAN RESULT IN I/O ERRORS
V130 USERS RELIED FORMERLY ON WAKES DONE BY XTCSER TO HIBER UNTIL
AN EVENT HAPPENED.
V132 INCLUDES UNDOCUMENTED BUG FIXES
V7132 IS 132 MODIFIED TO RUN ON KL-10 FOR 6.02
V135 INCLUDES UPDATE TO DDB STRUCTURE FOR 6.03
V7135 INCLUDES FIXES TO RUN ON KL-10 FOR 6.03, ALSO ADDS
NEW DEBUGGING FEATURE (EXECUTION TRACE)
V141 CONVERT TO SMP (7.01), REMOVE FTKA10 ETC.
V142 PICK UP FIXES FROM KR'S CODE, ETC. RESTORE POPJ IN
OUT UUO CODE SO OUTPUT WORKS. SEND A RESTART-10 TO ALL SMALL
COMPUTERS AT SYSINI TIME (SO FIRST PROGGIE THAT TRIES TO
TALK TO SMALL COMPUTER DOESN'T GET "OPR ACTION REQUESTED).
DON'T FLUSH CACHE ON CONTROL-WORD I/O FOR KL-10 (USE NIFTY
OUCHE ROUTINE INSTEAD) - SEEMS TO PROVIDE 10% BETTER THROUGH-
PUT AND 10% LESS KL LOAD AT THE SAME TIME.
V7136 Includes bug fix in SYNC$, HIBER call change for 6.03A, startup patch
and addition of documentation (6.03A only)
V143 Makes 7136 changes to 7.01 version (142)
V155 Move code from LINKDB to a new routine called XTCLNK.
\
SUBTTL TABLE OF CONTENTS
; TABLE OF CONTENTS FOR XTCSER
;
;
; SECTION PAGE
; 1. REVISION HISTORY.......................................... 1
; 2. TABLE OF CONTENTS......................................... 5
; 3. DEFINITIONS
; 3.1 PARAMETERS AND FEATURE TESTS...................... 9
; 3.2 BIT DEFINITIONS................................... 11
; 3.3 MACRO DEFINITIONS................................. 12
; 3.4 CONTROL WORD FUNCTION CODES....................... 13
; 3.5 I/O STATUS BITS................................... 14
; 3.6 KDB LAYOUT........................................ 15
; 3.7 UDB LAYOUT........................................ 16
; 3.8 DDB LAYOUT........................................ 17
; 4. CONSTANTS
; 4.1 BYTE POINTERS..................................... 19
; 4.2 I/O DISPATCH TABLE................................ 20
; 5. TIMER ROUTINES............................................ 21
; 6. XTTSK. UUO
; 6.1 SUB-FUNCTION DISPATCH TABLE....................... 22
; 6.2 UUO ENTRY......................................... 23
; 6.3 XT.RDR, XT.RDS, XT.SCH, XT.DEL.................... 24
; 6.4 XT.IDN............................................ 25
; 6.5 XT.MMD............................................ 26
; 6.6 XTWAKF............................................ 26
; 6.7 XT.GCH, XTSTAT.................................... 27
; 6.8 XT.ATB............................................ 28
; 6.9 SEND CLOSE INFO................................... 29
; 6.10 SPECIAL UNIT FUNCTIONS XTFRCL, XTLDXL, XTDSTL..... 30
; 6.11 XTGRB, XTRET MAINTENANCE FUNCTIONS................ 31
; 7. XTTSK. SUBROUTINES
; 7.1 DELETE AN XTC DDB................................. 32
; 7.2 XTCDEV, XTCIOS.................................... 33
; 7.3 FNDxxx SEARCH ROUTINES............................ 34
; 8. INITIALIZATION AT SYSINI TIME............................. 35
; 9. INPUT UUO
; 9.1 DUMP MODE......................................... 37
; 9.2 BUFFERED MODE..................................... 38
; 10. OUTPUT UUO
; 10.1 DUMP MODE......................................... 39
; 10.2 BUFFERED MODE..................................... 40
; 11. I/O UUO SUBROUTINES
; 11.1 INSET, OUTSET, PSACT, MAKACT...................... 42
; 11.2 IFDMP, XTCBTL, ZAPACT, XTCIPM, XFRRST, SETIPM..... 42
; 11.3 DMPSET, SETIOW, NXTIOW............................ 43
; 11.4 SBINIO............................................ 44
; 11.5 MPIOWD............................................ 45
; 11.6 RDYCHK............................................ 46
; 12. CLOSE AND RELEAS UUOS..................................... 47
; 13. INTERRUPT SERVICE
; 13.1 XTCINT, CLRERR, SETSCN............................ 48
; 13.2 REMINT, DOINP..................................... 48
; 13.3 UNIINT............................................ 49
; 13.4 RECUCW............................................ 49
; 13.5 CHKPRC, CHKWAK.................................... 50
; 13.6 DDBINT, IOREDY, BUFDON, DDBRST.................... 51
; 13.7 FINDDB, FINUNI.................................... 52
; 14. ERROR ROUTINES
; 14.1 UNIERR, DWNUNI.................................... 53
; 14.2 CHKCER, DDBERR, NXTERR............................ 54
; 15. DEBUGGING CODE
; 15.1 CONSOLE CONTROL WORD TRACE........................ 55
; 15.2 EXECUTION TRACE................................... 56
; 16. RECEIVE CONTROL WORDS
; 16.1 ATTRIBUTE BYTE.................................... 57
; 16.2 CLOSE............................................. 58
; 16.3 REJECT............................................ 59
; 16.4 READY FOR INPUT................................... 60
; 16.5 WAITING FOR INPUT................................. 61
; 16.6 WAITING FOR OUTPUT................................ 62
; 16.7 RESTART........................................... 63
; 16.8 DEAD-START........................................ 64
; 16.9 TTY FUNCTION...................................... 65
; 16.10 TTY SUBROUTINES................................... 66
; 16.11 DA28 SCHEDULING SUBROUTINES....................... 67
; 17. TTY FUNCTION SCNSER INTERFACE............................. 68
; 18. TRANSMITTERS OF CONTROL WORDS............................. 69
; 19. MAKE CONTROL WORDS
; 19.1 MAKxxx............................................ 70
; 19.2 FINISH UP COMMON CODE............................. 71
; 19.3 SUBROUTINES ADDSIZ, GETMOD, CHKMOD................ 72
; 19.4 SETACS............................................ 73
; 19.5 RING BUFFER CONTROL WORD TRACE.................... 74
; 19.6 SENDW............................................. 75
; 19.7 WAIT ROUTINES..................................... 76
; 19.8 ROUTINES TO GET ACCESS TO DA28 HARDWARE........... 77
; 20. DATA TRANSFER BEGIN
; 20.1 STOUTP, STINPT.................................... 78
; 20.2 D28XCW TO START CONTROL WORD...................... 79
; 20.3 SETUP SUBROUTINES SETKON, D28CLR, FRCOFL.......... 80
; 21. COROUTINE SUPPORT ROUTINES $COROUT, SYNC$, CPOPJx......... 81
; 22. SLEEP AND WAKE ROUTINES................................... 82
; 23. EVENT COUNTERS............................................ 83
; DEFINE the documentation macros
; The documentation of XTCSER's internals is normally extracted with
;RUNOFF; if the user sets the symbol LSTPLM to any value he will
;also see the RUNOFF input in the assembly listing.
DEFINE PLM <IFNDEF LSTPLM,<XLIST>>
DEFINE MLP <IFNDEF LSTPLM,<LIST>>
PLM
;+
;.autoparagraph.flag index.flag capital.lower case
;.page size 60,70
;.title ^^XCTSER\\ ^Program ^Logic ^Manual
;^^
;####
;.br;###
;.skip 5
;.center
;Program Logic Manual
;.skip 2
;.center
;XTCSER
;.skip 2
;.center
;6.03A Version 7136
;.center
;7.01 Version 143
;.skip 2
;.center
;Kalman Reti
;.skip 19
;Copyright (C) 1979 by Digital Equipment Corporation, Maynard, Massachusetts
;.skip
;This software is furnished under a license and may be used and copied
;only in accordance with the terms of such license and with the
;inclusion of the above copyright notice. This software or any other
;copies thereof may not be provided or otherwise made available to any
;other person. No title to and ownership of the software is hereby
;transferred.
;.skip;The information in this software is subject to change without notice
;and should not be construed as a commitment by Digital Equipment
;Corporation.
;.skip;Digital assumes no responsibility for the use or reliability of its
;software on equipment which is not supplied by Digital.
;.page;.subtitle Table of Contents
;.nofill.nojustify;^^
;1 Introduction
;##1.1 Scope of this Document.....................................1-1
;##1.2 Purpose and Major Functions of XTCSER......................1-1
;##1.3 XTCSER Protocol............................................1-2
;##1.3.1 Data Transfer Protocol...................................1-3
;##1.3.2 Protocol not associated with data transfer...............1-4
;##1.3.2.1 TTY function control words.............................1-4
;##1.3.2.2 Reject control words...................................1-5
;##1.3.2.3 Ack control word.......................................1-5
;##1.3.2.4 Close control word.....................................1-6
;##1.3.2.5 Attribute byte control words...........................1-6
;##1.3.2.6 Restart control words..................................1-6
;##1.3.2.7 Dead start protocol word...............................1-8
;2 Data Structures
;##2.1 Feature Test Switches and Parameters.......................2-1
;##2.2 Data Blocks................................................2-3
;##2.2.1 Controller Data Block....................................2-3
;##2.2.1.1 Detailed Description...................................2-4
;##2.2.1.2 KDB Layout.............................................2-6
;##2.2.2 Unit Data Block..........................................2-8
;##2.2.2.1 Detailed Description...................................2-8
;##2.2.2.2 UDB Layout.............................................2-10
;##2.2.3 Device Data Block........................................2-10
;##2.2.3.1 Detailed Description...................................2-11
;##2.2.3.2 DDB Layout.............................................2-14
;##2.3 Other Data Structures......................................2-16
;3 Code Description
;##3.1 Periodic Routines..........................................3-2
;##3.1.1 XTCHNG...................................................3-2
;##3.1.2 XTCSEC...................................................3-2
;##3.2 XTTSK. UUO Processing......................................3-3
;##3.2.1 Functions................................................3-4
;##3.3 Initialization code........................................3-7
;##3.4 Input/Output Routines......................................3-7
;##3.4.1 Co-routine Mechanism.....................................3-8
;##3.4.2 Input UUO................................................3-10
;##3.4.2.1 Detailed Logic.........................................3-11
;##3.4.3 Output UUO Processing....................................3-13
;##3.5 Interrupt Service..........................................3-15
;##3.5.1 XTCINT...................................................3-15
;##3.5.2 DDBIO....................................................3-16
;##3.5.3 RECUCW...................................................3-17
;##3.6 Send Control Words.........................................3-19
;4 Debugging Aids
;##4.1 XTDUMP.....................................................4-1
;##4.2 Console and Execution Trace................................4-2
;##4.2.1 Console Trace of protocol words..........................4-2
;##4.2.2 Execution Trace..........................................4-3
;.fill.justify;\\
;.page;.chapter Introduction
;^^
;.hl 1 Scope of this Document
;^^
; This document is intended to give the background information
;necessary for the reader to be able to follow and/or modify
;the XTCSER software. It assumes a knowledge of the TOPS-10
;monitor and also of the DA28 hardware.
;.hl 1 Purpose and Major Functions of XTCSER
;^^
; The DA28 hardware provides an high-speed half-duplex data path
;between a DECsystem-10 and up to 16 "small computers" (PDP-8s,
;PDP-11s or PDP-15s). The XTCSER software supports this hardware
;in such a way as to provide:
;.list;.le;the most comprehensive functionality for the user,
;namely any number of bi-directional data links to any number of small
;computers
;.le;an interface that is compatible with other I/O devices and hence
;usable from high-level languages such as FORTRAN
;.end list
;It accomplishes these goals by giving the user the ability to create
;a "device" which is in reality merely a representation for a single
;"conversation" between a program in the DECsystem-10 and a
;program in the small computer. Once the user has created this "device"
;he may use only the standard I/O calls to read and write data from/to the
;small computer. If he wishes a greater degree of control or flexiblity, he
;also has some extra monitor calls available to perform operations which
;are not analogous to those for any other I/O device.
;Therefore the main functions of XTCSER are:
;.list;.le;to implement a new CALLI (XTTSK.) to perform the control and
;extra I/O functions necessary to communicate with the small computers
;.le;to implement the normal I/O UUO's (IN, OUT, CLOSE, RELEAS) for
;the XTCSER "devices"
;.le;to handle the interrupts from the DA28 hardware in such a
;way as to allow multiple I/O operations on a single
;small computer, as well as multiple operations to several
;small computers, simultaneously.
;.end list
;These functions correspond to the three major divisions of the
;code, as well as the three major parts of this manual.
;.HL 1 XTCSER Protocol
;^^
; To implement the above-mentioned goals requires that the DECsystem-10
;and the small computer with which it is communicating exchange some control
;information about what type of data transfer is to take place; at the
;very minimum this information includes:
;.list
;.le;the desired direction of the data transfer (from -10 to small computer or vice versa)
;.le;the intended receiver process (because more than one set of pairs of tasks
;may be communicating at the same time)
;.le;the number of words to be transferred
;.le;the DA28 hardware mode of the forthcoming transfer
;.end list
;Only after both processors agree on all this information can they
;correctly set up the DA28 hardware to actually perform the transfer.
; Additional information is also necessary to ensure orderly
;termination of data communication between two processes:
;.list
;.le;notification that one process no longer intends to transmit
;data (end-of-file)
;.le;notification if a task aborts or is terminated (so that the other
;side doesn't try to communicate with a non-existent or unintended program)
;.le;notification that the operating system of the other
;computer has been restarted
;.end list
;Even more data exchange is useful to inform the other computer
;if it sends incorrect or conflicting information and
;to make certain functions more efficient.
; XTCSER conveys this information to the small computer through a
;protocol of 1-word data transfers called control words.
;There are four control words for data transfer information and
;synchronization (RFI, RFO, WFI and WFO) and six other control
;word types (some with various sub-functions) to transfer the
;rest of the control information.
;The small computer wishing to talk to XTCSER
;must adhere to the rules of this protocol (although it may not necessarily
;have to implement all the functions -- some apply only to features
;which are optional).
;.hl 2 Data Transfer Protocol
;^^
; The data transfer protocol consists of the four control words
;RFI (ready for input), RFO (ready for output), WFO (waiting for
;output) and WFI (waiting for input). In the normal case each
;processor transmits either RFI or RFO as soon as the user task
;issues an input or output request (respectively). Either
;one may come first, depending upon which process is ready to do
;I/O first. If the two processes both send RFI or both send RFO,
;both get an appropriate error return to their I/O requests.
; Once the two processors have agreed to the direction of transfer
;via the exchange of RFI/RFO, then the sending processor must get
;ready to actually transfer the data (e.g. perhaps swap in the job,
;map the user's buffer, do any conversion necessary, etc.).
;Then the sending processor sends a WFO control word, which
;means it is all set to transfer data. This control word contains
;the mode and length of the transfer. The receiving processor
;checks the mode and length; if they are unacceptable it may respond
;with either a "reject blocksize" or a "reject data mode" control
;word. If they are both acceptable, it responds with a WFI to indicate
;that it expects a data block of the size and mode specified in the
;WFO as the next transfer. The sending computer must then immediately
;transfer the data.
; This protocol exchange may be depicted as below:
;.nofill;.nojustify;.skip
;030550/ 400001,,000220 637570,,200020 _<-- A0 RFI (1)
;030552/ 000001,,000220 677573,,600020 --_> A0 RFO (1)
;030554/ 000001,,000221 777573,,600020 --_> A0 WFO (1)
;030556/ 400001,,000221 737570,,200020 _<-- A0 WFI (1)
;030560/ 200001,,000221 777777,,000000 _> D
;.fill;.justify;.skip
;(The above is an excerpt from the output of XTDUMP which
;displays the contents of a large circular buffer in XTCSER
;used to record protocol word transfers. For a detailed explanation
;of what all the fields mean, see Chapter 4.)
; The small computer interface may shorten this protocol when it
;is receiving input from the DECsystem-10 by sending WFO instead of
;RFO. XTCSER assumes that the stronger protocol word (WFO) implies
;the weaker (RFO). Such a data transfer might look like this:
;.nofill;.nojustify;.skip
;031270/ 400001,,000002 777764,,200020 _<-- A0 WFO (1)
;031272/ 000001,,000201 737767,,600020 --_> A0 WFI (1)
;031274/ 600001,,000201 777777,,000000 _< D
;.fill;.justify;.skip
;The LIP11M driver for the DA28 under RSX11M uses this shortened
;form of the protocol when transferring data to the DECsystem-10.
; It is absolutely essential for proper operation of the protocol
;that nothing but the data to be transferred appear on the DA28
;after a WFI has been transmitted; data messages are wholly transparent,
;can contain whatever they want (even something that looks like
;a protocol word) and are therefore only identified by their
;association with the RFI, RFO, WFO and WFI control words which
;precede them.
;.hl 2 Protocol not associated with data transfer
;^^
; The other defined control words deal either with exceptional
;situations or permit a more efficient transfer of small amounts of
;specialized data. Some of the protocol described below
;is no longer used, and exists merely to remain compatible with
;older implementations. We shall describe all the other control
;words briefly -- for more detail see the descriptions of the
;routines which actually use them.
;.hl 3 TTY function control words
;^^
;There are five TTY control words which allow a data path through
;the DA28 which behaves like a terminal line. These functions were used on
;the RSX11-D implementation of LIPS to provide a controlling terminal
;line to the DECsystem-10 via the MCR terminal and could only be used
;by a privileged task named CONTAS. They are not implemented at all
;on the RSX11M version of the LIPS driver.
; The five protocol words are:
;.list
;.le;"TTY get" which the small computer sends to request a line
;from the DA28 pool (receiving either a "TTY ack" or a "TTY nak"
;depending upon whether a line was available or not)
;.le;"TTY char" control word which contains a character
;which the destination processor should consider as input on the
;"terminal" line.
;(This will receive a "TTY nak" control word if the line number
;specified in the task ID field is not an XTCSER line.)
;.le;"TTY ack" (also called "TTY more") used by the -10 to acknowledge a successful "TTY get"
;request and by the small computer to acknowledge receipt of a "TTY char"
;message from the -10. (Note that only the small computer uses this
;message to answer a "TTY char"; when the DECsystem-10 receives
;a "TTY char" it doesn't send anything in response.)
;.le;"TTY nak" (also called "TTY reject") used to inform the destination processor that
;the source processor detected some illegality or that the "TTY get"
;request could not be satisfied.
;.le;"TTY delete" which the small computer sends to the -10 to
;relinquish the use of the specified DA28 "terminal" line.
;.end list
;.hl 3 Reject control words
;^^
;There are eight control words which signal errors of some kind. They are:
;.list
;.le;"reject no task" -- sent in response to any control word
;whose task identification does not match that of a currently active
;task.
;.le;"reject hung" (historical) -- used in previous implementations
;if the task in the small computer was present but couldn't be
;started. Never sent by LIP11M.
;.le;"reject function" -- sent whenever a control word with
;an illegal function or sub-function code is received.
;.le;"reject improper mode" (historical) -- sets the IOIMPM error bit
;if received by the -10. Never sent by LIP11M.
;.le;"reject improper data mode" -- sent instead of WFI if the intended data
;recipient doesn't like the data mode specified in WFO (this
;means that the two programs are not agreeing on data mode).
;The only data mode supported in LIP11M is "binary", i.e. 16-bit
;words packed as 16-bit bytes on the -10.
;.le;"reject blocksize" -- sent instead of WFI if the intended data
;recipient doesn't specify the same or greater blocksize as the sender.
;Sets IOBKTL (block too large) error on the -10 side.
;.le;"reject data error" (historical) -- sets IODTER (data error) on -10
;side; never sent by LIP11M.
;.le;"reject operation error" -- sent only by the -10 when
;it detects that the protocol has been violated (such as
;both sides trying to output to the same task).
;.end list
;.hl 3 Ack control word
;^^
;This is an historical control word, never sent by LIP11M.
;If the -10 should receive this, it would set the status
;bit IO.ACK in DEVIOS.
;.hl 3 Close control word
;^^
;This control word has a single valid sub-function which makes the
;"close EOF" control word. This signals normal shutdown of
;communications between two processes.
;.hl 3 Attribute byte control words
;^^
;These four control words are also historical. They were used by
;the RSX11-D implementation of LIPS, and are not sent by LIP11M. Their
;purpose was to provide a single 8-bit packet of information
;that was maintained in the -10 but could be interrogated and/or
;modified by either the -10 program or the small computer program.
;The same effect could be obtained by tranferring data messages
;according to some higher-level protocol known to the two tasks; however,
;this would require more overhead to transfer the data.
; The attribute byte control words are:
;.list
;.le;"query attribute byte" -- sent from the small computer to the -10
;to request the latter to send the attribute byte via a "transmit
;attribute byte" control word.
;.le;"transmit attribute byte" -- sent either as response to "query attribute
;byte" control word, or if user on -10 issues XTTSK. function to
;manipulate attribute bytes with the sub-function "send attribute
;byte". Includes the attribute byte in the supplementary information field
;of the control word.
;.le;"OR attribute byte" (also called "set attribute byte" ) --
;this control word allows the small computer
;to turn on bits in the attribute byte individually. The contents of
;the supplementary information field are ORed into the attribute stored in the
;DDB.
;.le;"AND attribute byte" (also called "clear attribute byte") --
;this control word allows the small computer to
;selectively turn off bits in the attribute byte. The bit mask given
;in the supplementary information field of the control word is
;complemented and ANDed with the attribute byte stored in
;the DDB.
;.end list
;.hl 3 Restart control words
;^^
;The restart control words inform the destination processor
;that something in the source processor has restarted, either
;a single user task or the whole operating system (i.e. all user
;tasks that were there before have gone away). The functions are:
;.list
;.le;"restart 16-bit small computer" (also known as "restart -11") --
;sent from an -11 to the -10 to indicate that its entire operating
;system has restarted. This will give errors to any -10 jobs currently
;doing I/O over the DA28. This is also a pre-requisite for considering the
;small computer ready if the -10 has been restarted or after the
;unit has been forced off-line.
;.le;"restart 18-bit small computer" (also known as "restart -15") --
;same as previous except from a PDP-15.
;.le;"restart 12-bit small computer" (also known as "restart -8") --
;same as previous except from a PDP-8.
;.le;"restart remote processor" -- (historical and never sent by
;LIP11M) sent to restart all "units" within a "REP". The task ID
;field was originally made up of two parts, a REP and a unit; this was to allow
;a single program to multiplex functions by using the high order
;part (the REP) to route data to the program, and the lower order part
;(the unit) to let the program know which sub-stream the
;data was for. This protocol word restarts all tasks on the -10 whose
;REP field matches that passed in the control word.
;This is not useful now since LIP11M uses the concatenation
;of the REP and unit fields as a single, unique task ID.
;.le;"restart release" (also known as "restart -10") -- this
;control word is sent from the -10 to the small computer either
;at SYSINI time or whenever it does the first I/O request after
;the small computer has been off-line. The small computer should
;respond with a "restart -11, -15 or -8" (whichever is appropriate)
;which will inform XTCSER that the small computer is alive. This
;message is illegal from the small computer, and results in a
;"reject operation error" control word response.
;.le;"restart task" -- this control word is the most common restart
;control word, and informs the destination processor that the
;task whose task-ID is given in the control word is no longer the
;same as before (it has been either halted, run anew, etc.).
;.le;"restart status" -- (historical, never sent by LIP11M) this
;control word is sent only from the small computer to the -10
;and contains a 0 or 1 in the supplementary information
;field to indicate that the small computer has restarted
;all the tasks communicating over the DA28 or that the
;small computer wants information only, respectively. The -10
;will respond with a "restart status" containing its opinion of the
;state of the small computer (0=down, -1=up) and also,
;if the small computer had sent a 0, perform the same functions as
;if it had received a "restart -11, -15 or -8".
;.end list
;.hl 3 Dead start protocol word
;^^
;This is an historical control word, used (I believe) in conjunction
;with the JAM XTTSK. function to bootstrap a small computer. LIP11M
;never sends it. Upon its receipt, XTCSER copies the entire
;control word into the cell XUBDST in the unit
;control block and wakes the associated job.
;.page.chapter Data Structures
;^^
; By data structures this document refers not only to the collection of
;data on which XTCSER operates and by which it controls its execution
;(for the most part contained in the various data blocks) but also to
;the symbols and parameters which control its assembly. Their
;descriptions will follow the order in which they are defined in
;XTCSER, which is not always the same as one would
;choose were one trying to organize the information logically.
;.hl 1 Feature Test Switches and Parameters
;^^
; XTCSER has several feature test switches which govern the code
;being generated. Most are for compatibility with old versions of
;XTCSER. It also has some parameters which govern its execution.
;Both type of symbol definition are briefly summarized below:
;.list
;.le;FTCMPx -- compatibility switches. There are four of these; all
;use the value of 0 to indicate that the "new" feature is enabled and
;the value of non-zero to indicate that the "new" feature is disabled
;(i.e. that we are trying to be compatible with older versions of XTCSER).
;They are:
;.list
;.le;FTCMP0 -- 0 means add word count to RFI/RFO/WFI; formerly it was
;only included in WFO
;.le;FTCMP1 -- 0 means to generate a "restart task"
;control word on a RELEAS UUO.
;.le;FTCMP2 -- 0 means to set IOBKTL error bit in dump mode I/O when
;a data transfer from the small computer is too short.
;.le;FTCMP3 -- 0 means do no extraneous wakes. The previous versions of
;XTCSER would wake the job whenever an interrupt occurred, and user
;applications had come to depend upon this behavior.
;.end list
;.le;DA28Y -- this feature test assembles code for the long-line driver
;option available on the DA28. However, I do not think
;that this will work correctly.
;.le;MX11BF -- this parameter defines the size of the monitor buffer used
;to copy data when the transfer is in "image binary" mode, i.e. 16-bit words
;right justified in each halfword. This mode is not used
;by LIP11M, so the setting of this parameter is not usually
;necessary. If it is changed, it must also be changed in
;COMDEV (the symbols are globals so that LINK will detect mismatched
;values).
;.le;_.DBLEN -- this is the length of the in-core circular buffer used
;to trace protocol words. It is this buffer that XTDUMP reads; it
;is recommended that this feature remain on at all times, as the extra
;overhead is minimal and the benefits in tracking down what has
;gone wrong are enormous. To completely disable the control
;word tracing feature one must set this symbol equal to zero.
;.le;LIVE -- this is a feature test for generating debugging code; if
;LIVE is non-zero, then we are running a "live" i.e. non-debugging
;XTCSER. If LIVE=0, then two debugging features are
;enabled:
;.list;.le;a trace of protocol words on the CTY
;.le;another circular buffer trace, but this time of routines executed
;within XTCSER (called the "execution trace").
;.end list
;.le;FTETR -- this feature controls assembly of the execution
;trace code. If it is non-zero, each NULL macro in the source
;becomes a two-word skippable call to the execution tracer
;routine ETRACE.
;ETRACE will only trace the execution PC if the high order bit
;of the ETRFLG word is on; if the next lower order bit is on, it will
;inhibit wraparound. Any call to ETRACE can be patched to
;be a call to ETRCON or ETRCOF instead, with the effect of setting
;or clearing the high order bit in ETRFLG (thus enabling or disabling tracing).
;The default value for FTETR is -1 if LIVE=0.
;.le;FTFRC -- if non-zero the SYSINI time initialization code
;will force all units off-line. An XTTSK. function will have to be
;executed by some program to put them on-line again. This is an old
;feature for which I can think of no use.
;.le;_.IOLEN -- the value of this parameter defines the number
;IOWD slots reserved in the DDB. XTCSER will copy I/O words from the
;user's list (in dump mode only) into the DDB until the DDB is full, then
;execute them. At the end of the data transfer, if there are more
;it will repeat the process. This may cause more interrupts on the
;DA28 if the next IOWD was a continuation of the previous one.
;.le;ACCTIM -- this parameter is the number of seconds a job is "pseudo"
;active, which means that it is active but not for immediate
;data transfer.
;Once this time has expired without completion of the transfer, the
;job is made inactive (more precisely, IOACT is cleared) so
;that it may be swapped. When the final protocol steps preceding
;the data transfer have finally completed it is made active again.
;.le;QLPCNT -- this parameter is the number of times UUO level should
;loop waiting for interrupt level to complete its tasks before HIBERing.
;The normal setting is 0; the advantage of a non-zero setting is that
;if the small computer is very fast, at the expense of some small
;amount of looping in the monitor we can save the overhead associated
;with a HIBER and a subsequent WAKE.
;.end list
;In addition to these there are the normal TOPS-10 monitor feature
;test switches (such as FTKL, etc.).
;-
MLP
COMMENT &
THIS VERSION IS INCOMPATIBLE WITH PREVIOUS VERSIONS OF XTCSER UNLESS
SOME SPECIAL COMPATIBILITY FEATURE SWITCHES ARE TURNED ON. ALL
KNOWN INCOMPATIBILITIES ARE LISTED BELOW:
1 RFI, RFO AND WFI PROTOCOL WORDS CONTAIN THE NEGATIVE WORD COUNT OF THE
I/O DATA TRANSFER WHEN THEY ARE SENT ON ISSUING A IN OR OUT UUO.
PREVIOUSLY THE WORD COUNT FIELD WAS ZERO.
COMPATIBLITY SWITCH: FTCMP0=1 GENERATE A ZERO COUNT FIELD
2 WHEN A RELEASE UUO IS EXECUTED A RESTART TASK PROTOCOL WORD IS TRANS-
MITTED TO THE EP. THIS ENABLES A TASK ON AN EP TO DETERMINE WHETHER IT
CAN COMMUNICATE WITH THE 10 WITHOUT WAITING (THIS IS EQUIVALENT TO A
DISCONNECT VALID UNTIL THE FIRST RFI OR RFO).
COMPATIBILITY SWITCH: FTCMP1=1 DO NOT GENERATE A RESTART TASK WORD
3 IF THE TRANSFER TO OR FROM AN EP IS ENDED PREMATURELY AND DUMP MODE
I/O IS USED THEN THE IOBKTL ERROR BIT WILL BE SET. FORMERLY THIS
CONDITION WAS IGNORED AND THE I/O WAS TREATED AS COMPLETED.
COMPATIBLITY SWITCH: FTCMP2=1 SET NO ERROR FLAG
4 THE DA28C IS ASSUMED TO BE AT ECO LEVEL 3. IF THE ECO LEVEL
IS LOWER THEN RESTART THE DA28C SCANNER AT THE NEXT UNIT AT LABEL
CLRERR.
COMPATIBILITY SWITCH: NONE
5 PREVIOUSLY MANY UNNECESSARY WAKES WERE DONE BY XTCSER SOME USERS
HAVE USED THIS FACT AS AN IMPLICIT WAKE FOR XTCSER ACTIVITY.
ANY .C0JOB RELYING ON THIS FACT WILL WITHOUT REDEFINITION OF FTCMP3
GO INTO AN INFINITE HIBER. A BETTER SOLUTION SEEMS TO BE THE USE
OF THE XT.WAK XTTSK SUBFUNCTION, WHICH ALLOWS THE SPECIFICATION OF
A ONE TIME EVENT FLAG FOR WHICH A WAKE WILL BE DONE. THIS FUNCTION
IS CONTROLLED BY FTCMP3 = 0
COMPATIBILITY SWITCH FTCMP3=1 ;DO EXTRANEOUS WAKES
6 IF THE DA28-C IS BEFORE ECO LEVEL 7 (REV D) THEN THE SWITCH ECO7 SHOULD
BE SET 0 SO THAT THE SETKON ROUTINE WILL NOT RE-SELECT THE SMALL
COMPUTER UNLESS THE UNIT IS CHANGING.
AS HIBERNATES ARE DONE BY XTCSER WHEN SYNCHRONIZATION WITH
AN EP HAS TO BE OBTAINED, IT SEEMS LIKELY THAT A REDUCTION IN THE
NUMBER OF HIBER CALLS MIGHT REDUCE THE OVERHEAD.
FOR THAT PURPOSE THE PARAMETER QLPCNT HAS BEEN DEFINED.
BELOW THE RESULTS FOR A LIPS IMPLEMENTATION UNDER RSX11D ARE GIVEN,
IT SHOULD BE NOTED THAT FOR CERTAIN SYSTEMS A ZERO VALUE MIGHT BE THE
BEST CHOICE.
PERFORMANCE MEASUREMENT WITH A LIPS SYSTEM RUNNING 4 TASKS
COMMUNICATING WITH 4 PDP10 JOBS SHOWED THAT:
1 IF THE LIPS DRIVER DOES NOT TRACE THEN
PER 14 I/O UUO'S 4 HIBERS ARE DONE WITH QLPCNT=40
PER 14 I/O UUO'S 7 HIBERS ARE DONE WITHOUT ANY DELAY IN SYNC$
SO AT THE EXPENSE OF 14*(32+3)=490 INSTRUCTIONS
3 CALLS TO HIBERS AND ASSOCIATED WAKJOB CALLS ARE SAVED,APPR.
165 INSTRUCTIONS (LESS THAN 500 MUSEC)
ANY CHOICE OF QLPCNT LOWER THAN 40 IS A LOSS IN CPU TIME.
THE DELAY COUNT IN WTQEMP IS ALSO MAXIMAL AT A VALUE OF 40.
VALUES LESS MAKE NO SENSE AND HIGHER VALUES DO NOT IMPROVE.
2 IF THE LIPS DRIVER TRACES THEN QLPCNT SHOULD BE AT LEAST 100
ALL THIS APPLIES TO A SYSTEM LOADED WITH 5 JOBS OF WHICH 3 ARE
SWAPPING.
NOTE THAT HIBERS DO NOT NEED TO RESULT IN A SCHEDULER CALL.
THE LOAD MAY SIGNIFICANTLY INFLUENCE THE DA28C THRUPUT.
VARYING PARAMETERS WITH FILDDT AND MEASURING OF THRUPUT
WILL BE REQUIRED.
&
SUBTTL DEFINITIONS -- PARAMETERS AND FEATURE TESTS
;ASSEMBLY PARAMETERS
;COMPATIBILITY SWITCHES:
NDL FTCMP0,0 ;ADD - COUNT TO RFI/RFO/WFI WORDS
;FOR INPUT AND OUTPUT UUO'S
NDL FTCMP1,0 ;GENERATE A RESTART TASK WORD
;ON A RELEASE UUO
NDL FTCMP2,0 ;SET IOBKTL ERROR BIT FOR DUMP MODE
;I/O WHEN A TRANSFER IS TOO SHORT
NDL FTCMP3,0 ;DO NO EXTRANEOUS WAKES
NDL DA28Y,0 ;LONG LINE DRIVER
NDL ECO7,0 ;DA28-C IS PRE-ECO 7 (REV D) LEVEL
;THE PARAMETER MX11BF DEFINES THE MAXIUM NUMBER
; OF PDP-10 WORDS WHICH CAN BE TRANSFERED TO A PDP-11 IN THE
; "PDP-11 BINARY" (REALLY "IMAGE-BINARY") MODE.
XP MX11BF,^D129 ;MAXIMUM -11 BUFFER SIZE IN IMAGE-BINARY
NDL MAXBSZ,<MX11BF/3>*2 ;SIZE OF MONITOR BUFFER
ND .DBLEN,400 ;DEFINE TO BE .NE. 0 FOR RING BUFFER FEATURE
NDL LIVE,-1 ;MAKE ZERO FOR DEBUG TRACING
;SW LH 40 disables Receive CW trace
;SW LH 10 disables Xmit XW trace
;.TRCF RH 1 disables receive CW trace
;.TRCF RH 4 disables Xmit CW trace
XP FTFRC,0 ;0 TO NOR FORCE UNITS OFF-LINE IN ONCE
NDL .IOLEN,4 ;FOR EFFICIENT DUMP MODE I/O
NDL ACTTIM,2 ;PSEUDO ACTIVE TIME
NDL QLPCNT,0 ;NUMBER OF TRIES BEFORE SLEEPING
IFE LIVE <
NDL FTETR,-1 ;default is execution trace enabled
NDL ENMENT,4000 ;default number of entries in ex. trace table
>;end IFE LIVE
;Define dummy trace macros
DEFINE NULL <> ;default is to do nothing
DEFINE TRCON <> ;"
DEFINE TRCOF <> ;"
IFE LIVE <
IFN FTETR < ;if execution trace enabled
DEFINE NULL (arg) <
IFB <arg> <
PUSHJ P,ETRACE ;trace execution
SKIPA ;to handle skips before instruction
>;end IFB <arg>
>;end DEFINE NULL
DEFINE TRCON < ;turns on software trace enable bit
PUSHJ P,ETRCON ;turn on
SKIPA ;handle prior skips
>;end DEFINE TRCON
DEFINE TRCOF <
PUSHJ P,ETRCOF
SKIPA
>;end DEFINE TRCOF
>;end IFN FTETR
>;end IFE LIVE
; SYMBOL CONVENTIONS:
; SYMBOLS BEGINNING XKB ARE WORDS IN CONTROLLER DATA BLOCK
; SYMBOLS BEGINNING XK. ARE BITS IN CONTROLLER DATA BLOCK
; SYMBOLS BEGINNING XUB ARE WORDS IN UNIT DATA BLOCK
; SYMBOLS BEGINNING XU. ARE BITS IN UNIT DATA BLOCK
; SYMBOLS BEGINNING DVX ARE DDB LOCATIONS UNIQUE TO XTCSER
; SYMBOLS BEGINNING XT. ARE BITS IN DDB
; SYMBOLS BEGINNING XS. ARE DA28C STATUS REGISTER BITS
; SYMBOLS BEGINNING XC. ARE DA28C COMMAND REGISTER BITS
; SYMBOLS BEGINNING DVY ARE BYTE POINTERS INTO THE DDB
; SYMBOLS BEGINNING CTY ARE BYTE POINTERS TO CONROL WORD IN P1
; SYMBOLS BEGINNING XUY ARE BYTE POINTERS INTO UDB
;AC USAGE:
;S) DEVIOS WORD FROM DDB
;P) PUSH DOWN POINTER
;J) USER JOB NUMBER
;R) LOW SEGMENT RELOCATION
;F) POINTER TO THE DDB
;U) POINTER TO THE UNIT DATA BLOCK
;T1 TO T4) TEMPS
;M) USER ARG LIST POINTER
;W) CONTROLLER DATA BLOCK ADDRESS
;P1 TO P4 PRESERVED
SUBTTL DEFINITIONS -- BIT DEFINITIONS
;BITS IN CONI/CONO DAS WORD
XS.UNI==17B21 ;UNIT NUMBER
XS.ETM==1B22 ;ENABLE TEST MODE
XS.EVP==1B23 ;EVEN PARITY
XS.FRC==1B24 ;FORCE
XS.ENL==1B24 ;ENABLE LEFT
XS.ENR==1B25 ;ENABLE RIGHT
XS.CLR==1B25 ;CLEAR DAC
XS.NRD==1B26 ;*NOT READY
XS.ETI==1B27 ;ENABLE TIMER INTERRUPT
XS.TER==1B28 ;*TIMER ERROR
XS.REM==1B29 ;*REMOTE ERROR
XS.PAR==1B30 ;*PARITY ERROR
XS.CON==1B31 ;*CONNECT ERROR
XS.NXM==1B32 ;*NXM ERROR
XS.PIA==7B35 ;PRIORITY INTERRUPT ASSIGNMENT
;BITS IN CONI/CONO DAC WORD
XC.DRD==000040 ;LEFT HAND BIT UNIT IS NOT READY
XC.ERR==1B18 ;*ERROR
XC.SCN==1B19 ;SCAN
XC.TST==1B20 ;TEST
XC.FST==1B21 ;FAST TRANSFER
XC.MOD==3B23 ;MODE
XC.MEM==1B24 ;MEMORY (OPPOSED TO IO BUS)
XC.CON==1B25 ;CONNECT
XC.OUT==1B26 ;DIRECTION (XC.OUT=1 FOR OUTPUT)
XC.SRQ==1B27 ;*SELECT REQUEST
XC.ERI==1B28 ;ENABLE REMOTE INTERRUPT
XC.RMI==1B29 ;*REMOTE INTERRUPT
XC.EOT==1B30 ;*EOT
XC.BSY==1B31 ;BUSY
XC.DUN==1B32 ;*DONE
XC.FT==1B33 ;READ FEATURES
XC.JAM==1B34 ;JAM
;MAGIC SHIFTS
UNILSH==^D36-^L<XS.UNI>-4 ;AMOUNT TO SHIFT UNIT FOR CONO DAS
MODLSH==^D36-^L<XC.MOD>-2 ;AMOUNT TO SHIFT XC.MOD FOR CONO
CNTLSH==^D22 ;SHIFT TO POSITION WORD COUNT
;DATA PACKING MODES
DM.IMI==0B23 ;IMAGE MODE
DM.ASC==1B23 ;ASCII
DM.PKI==2B23 ;PACKED IMAGE
DM.BIN==3B23 ;BINARY
;HARDWARE MODES
MD.IMI==0 ;IMAGE MODE
MD.ASC==1 ;ASCII MODE
MD.PKI==2 ;PACKED IMAGE
MD.BIN==3 ;BINARY MODE
;MACRO TO GENERATE THE WORD COUNT
DEFINE WC(X),<-<<X>_4>>
;DEFINE FUNCTION WORD FIELDS
PR.UIS==4 ;UNIT ID SIZE
PR.TIS==^D8 ;TASK ID FIELD SIZE
PR.TIM==1_PR.TIS-1 ;TASK ID MASK
PR.UIM==<1_PR.UIS-1>_PR.TIS ;UNIT ID MASK
SUBTTL DEFINITIONS -- MACRO DEFINITIONS
;MACRO DEFINITIONS
;MACRO COROUT STARTS A COROUTINE SHARED BETWEEN UUO AND
;INTERRUPT LEVEL. THIS MACRO IS VALID ON BOTH LEVELS AS IT
;IS A NOOP ON INTERRUPT LEVEL.
;NOTE THAT IN ORDER TO PREVENT THE USE OF STACKS IN THE DDB
;ALL INVOCATIONS HAVE TO EXIT AT THE LEVEL OF THE COROUT
;APPEARANCE
DEFINE COROUT(MASK)
< MOVE T1,[ MASK ] ;;GET EVENT FLAGS
PUSHJ P,$COROUT
>
;MACROS TO RETURN FROM AN UNKNOWN LEVEL TO THE JOB UUO LEVEL
;RETURNS ARE TO THE CALLER OF THE SHARED CODE
DEFINE $CPOPJ ;NORMAL RETURN
< PJRST CPOPJ$
>
DEFINE $POPJ1 ;SKIP RETURN
< PJRST CPOJ1$
>
DEFINE $POPJ2 ;DOUBLE SKIP RETURN
< PJRST CPOJ2$
>
;MACRO TO SYNC ON ANY LEVEL WITH INTERRUPT EVENTS
;AND TO WAIT FOR MASK BITS IN DEVIOS
;NOTE THAT THERE IS NO RACE CONDITION!!
DEFINE $SYNC(MASK)
< MOVE T1,[ MASK ]
PUSHJ P,SYNC$ ;RETURN HERE
>
;SEND VALUE GO TO XMT ' VALUE AND SEND OUT RESULT
;SEND RESULT AND WAIT IF W EQUALS WAIT
DEFINE SEND(V)
< PUSHJ P,MAK'V ;GET CONTROL WORD IN P1
PUSHJ P,SENDW ;THEN WAIT
> ;END O F SEND
;DELAYY IS A MACRO TO DELAY FOR DA28YS IT USES ACC TO COUNT DOWN A WAIT COUNT
DEFINE DELAYY(ACC)
< IFN DA28Y,<
MOVSI ACC,-20 ;;DELAY COUNT
AOBJN ACC,. ;;WAIT HERE
> > ;END OF DELAYY
SUBTTL DEFINITIONS -- CONTROL WORD FUNCTION CODES
;FUNCTION CODE DEFINITIONS
FN.TTY==01 ;TTY CONTROL
SF.TTC==01 ;TTY CHAR IN SFI
SF.TTM==02 ;MORE
SF.TTG==03 ;GET A TTY
SF.TTN==04 ;NO TTY AVAIL
SF.TTR==05 ;RETURN A TTY LINE
FN.REJ==02 ;REJECT
SF.NOT==01 ;EXTERNAL TASK DOES NOT EXIST
SF.HNG==02 ;EXTERNAL TASK IS HUNG
SF.FNE==03 ;FUNCTION ERROR
SF.IMP==04 ;IMPROPER MODE
SF.IDM==05 ;IMPROPER DATA MODE
SF.BTL==06 ;BLOCK TOO LARGE
SF.DTE==07 ;DATA ERROR
SF.OPE==10 ;OPERATION ERROR
FN.ACK==03 ;ACKNOWLEDGE MSG RECEIPT
SF.ACK==00 ;UNUSED
FN.CLS==04 ;CLOSE
SF.EOF==1 ;END OF FILE
FN.ATB==05 ;MANIPULATE ATTRIBUTE BYTE
SF.QAB==01 ;QUERY ATTRIBUTE BYTE
SF.XAB==02 ;XMT ATTRIBUTE BYTE
SF.OAB==03 ;"OR" ATTRIBUTE BYTE
SF.AAB==04 ;"AND" ATTRIBUTE BYTE
FN.RST==06 ;RESTART
SF.6BP==01 ;16 BIT PROCESSOR (PDP-11)
SF.8BP==02 ;18 BIT PROCESSOR (PDP-15)
SF.2BP==03 ;12 BIT PROCESSOR (PDP-8, PDP-12)
SF.RRP==04 ;RESTART REMOTE PROCESSOR
SF.REL==05 ;RELEASE
SF.RTK==06 ;RESTART TASK
SF.RST==07 ;RESTART STATUS
FN.DST==07 ;DEAD-START
FN.RFI==14 ;READY FOR INPUT
SF.RFI==00 ;UNUSED
FN.RFO==15 ;READY FOR OUTPUT
SF.RFO==00 ;UNUSED
FN.WFI==16 ;WAITING FOR INPUT
SF.WFI==00 ;UNUSED
FN.WFO==17 ;WAITING FOR OUTPUT
SF.WFO==0 ;WFO NO SUBCODE
SUBTTL DEFINITIONS -- I/O STATUS BITS
;IO STATUS BITS IN LH(DVXPST)
IOXXCW=(1B0) ;A CONTROL WORD IS IN THE SEND PIPE LINE
IOXRFI==(1B1) ;READY FOR INPUT HAS BEEN SENT
IOXRFO==(1B2) ;READY FOR OUTPUT HAS BEEN SENT
IOXWFI==(1B3) ;WAITING FOR INPUT HAS BEEN SENT
IOXWFO==(1B4) ;WAITING FOR OUTPUT HAS BEEN SENT
IORRFI==(1B5) ;THE EXTERNAL TASK IS READY FOR INPUT
IORRFO==(1B6) ;THE EXTERNAL TASK IS READY FOR OUTPUT
IORWFI==(1B7) ;THE EXTERNAL TASK IS WAITING FOR INPUT
IORWFO==(1B8) ;THE EXTERNAL TASK IS WAITING FOR OUTPUT
;BITS USED IN LEFT HALF OF S
;THERE IS IMPORTANT DIFFERENCE BETWEEN BITS HIBTSK
;AND WAKTSK. HIBTSK IS USED ALWAYS WHEN A DDB PROCESS HIBERS
;WHEN USED ALONE IT MEANS THAT IT WAITS FOR AN EVENT. WAKTSK
;IS SET TO ENABLE A PROCESS TO WAIT FOR THE EMPTYING OF ALL
;OUTPUT REQUESTS.
WAKTSK==(1B8) ;JOB WAITS FOR AN EMPTY SEND Q
HIBTSK==(1B9) ;SITS IN LEFT HALF!!
FRSTIN==(1B10) ;INPUTS SET THIS WHEN STARTED
;JOB WAITS FOR A WAKE
;BITS TURNED ON FOR USER PROGRAMS IN S
;ON A STATZ STATO OR GETSTS UUO
;NEVER USE THEM IN DEVIOS(F)!!
IO.RFI==1B24 ;EXTERNAL TASK SENT AN RFI
IO.RFO==1B25 ;EXTERNAL TASK SENT AN RFO
IO.WFI==1B26 ;EXTERNAL TASK IS IN INPUT WAIT
IO.WFO==1B27 ;EXTERNAL TASK IS IN OUTPUT WAIT
IO.BYP==1B28 ;PROTOCOL BYPASS
IO.ACK==1B29 ;MSG ACK (UGH)
;BITS USED TO CLEAR TRANSFER INFO
ANYACT==IOXWFI!IOXWFO!IORWFI
LHCLR==IOXRFI!IOXRFO!IOXWFI!IOXWFO!IORRFI!IORRFO!IORWFO!IORWFI!HIBTSK!FRSTIN
;BITS USED TO DO TEST ON STATUS
RHERR==IOBKTL!IODTER!IODERR!IOIMPM ;ERROR BITS
RHSTOP==RHERR!IODEND ;END OF FILE
PLM
;+
;.lm 0
;.hl 1 Data Blocks
;^^
; XTCSER has three main data blocks -- the controller data
;block (KDB) which gives information specific to a DA28C as a whole,
;the unit data block (UBD) which gives information specific to a
;single small processor on a DA28C and the DDB which contains all
;the standard DDB fields plus the DA28 information about the
;state of a single conversation through the DA28 unit. These blocks
;are all chained together, and are hierarchical:
;.lm+10
;.nofill.nojustify
;.skip 2
;##################KDB
;####UDB-----------! !-------------UDB
;DDB-! !--DDB#################DDB--! !--DDB
;.skip
;.fill.justify
;.lm-10
;(The fact that the blocks in the above illustration have only
;two lower level blocks connected is an artifact of the primitive
;graphics scheme and does not represent any XTCSER restriction.)
;The following sections will describe each block in greater
;detail.
;-
MLP
SUBTTL DEFINITIONS -- KDB LAYOUT
COMMENT &
The following code is copied from COMDEV where the interrupt
start and KDB are actually defined. This is for information only;
to see what is actually generated one must check in COMDEV.
XP MX11BF,^D129 ;MAXIMUM PDP-11 IMAGE BINARY BUFFER SIZE
DEFINE XTCDEF (X),<
IFNDEF XT'X'S,<XT'X'S==420+X*10>
IFNDEF XT'X'C,<XT'X'C==424+X*10>
XP XKBSKP,400450
XT'X'INT:: CONSO XT'X'C,XKBSKP ;EXTERNAL PROCESSOR INTERRUPT?
JRST .-1 ;NO, GO DOWN THE SKIP CHAIN
JSR XT'X'SAV## ;SAVE ALL THE AC'S
PUSHJ P,SAVE4## ; ..
JSP W,XTCINT## ;CALL XTCSER
XP XTCCHN,XT'X'CHN##
DEFINE XTLNK (A) <
IFN A-XTCN,<
XKBKDB::!EXP XKB'A' ;LINK TO NEXT KDB
>
IFE A-XTCN,<
XKBKDB::!EXP 0 ;NO MORE KDB'S
>
>
XP XKBINT,<XT'X'INT-.>
Z=X+1
XKB'X:: PHASE 0 ;BEGIN CONTROLLER DATA BLOCK
XKBNAM::!XWD 'EPA'+X,0 ;EP NAME
XTLNK \Z ;LINK TO NEXT KDB
XKBUDB::!BLOCK 21 ;SPACE FOR LINKS TO UDBS
XTSCNO::!CONO XT'X'S,(T1)
XTCCNO::!CONO XT'X'C,(T1)
XTSCNI::!CONI XT'X'S,T1
XTCCNI::!CONI XT'X'C,T1
XTSDTI::!DATAI XT'X'S,T1
XTCDTI::!DATAI XT'X'C,T1
XTCDTO::!DATAO XT'X'C,T1
XTSDTO::!DATAO XT'X'S,T2
XTCBSY::!CONSZ XT'X'C,20
XKBLOK::!EXP -1 ;INTERLOCK
XKBDDB::!BLOCK 1 ;POINTER TO DDB WAITING FOR INTRPT
XKBIUN::!BLOCK 1 ;POINTER TO UDB WAITING FOR INTERRUPT
XKBDAC::!BLOCK 1 ;INFO FROM LAST CONI DAC
XKBDAS::!BLOCK 1 ;INFO FROM LAST CONI DAS
XKBTIM::!BLOCK 1 ;COUNTER FOR TIMEOUT
XKBIOW::!BLOCK 1 ;IOWD FOR DAC OR PNTR TO IOLIST
XKBCUR::!BLOCK 1 ;CUR PNTR TO IOLIST (KI10 ONLY)
XKBGRB::!Z ;0 IF FREE 1 IF GRABBING
;CONTROL -1 IF GRABBED
XKBPAC::!BLOCK 1 ;# OF PSEUDO ACTIVE DDB'S ON THIS
; CONTROLLER
XKBREQ::!BLOCK 1 ;OLDEST JOB # REQUESTING USE OF UDB
XKBMBF::!BLOCK <MX11BF*3>/2 ;MONITOR BUFFER
DEPHASE
>
&;end of excerpt from COMDEV
PLM
;+
;.lm 0
;.hl 2 Controller Data Block
;^^
;.subtitle Controller Data Block
; This block contains data specific to a single DA28C; normally
;XTCSER addresses it via register W.
;Foremost among its contents are the CONO/CONI/DATAO/DATAI words, which contain
;the appropriate forms of those instructions for each DA28C.
;This enables the code to merely XCT the instruction at a specific
;offset into the KDB.
; Also in the KDB are pointers to each of the unit data blocks (UDBs),
;one for each small computer (with a spare 0 word at then end to terminate
;the list); the monitor buffer used for reading and writing data if
;information has to be reformatted in the user buffer; the words
;controlling access to the DA28C hardware either for total use (e.g.#by
;diagnostics) or in normal data transfer (for example between
;segments of a data transfer) and a few words to keep track of the
;current unit using the DA28C, where to continue processing on an
;interrupt, etc.
; The controller data block is defined and built in COMDEV; a copy of
;the code is included in XTCSER as a comment. There is a small
;amount of code generated as a prefix to each controller data
;block; this code includes the actual skip chain
;tests. If the test succeeds (i.e. this controller is wanting to
;interrupt) it saves the registers and does a JSR W,XTCINT to
;go to XTCSER's common interrupt handling code. Since this instruction
;immediately precedes the controller data block, this has the effect
;of loading W (the register used in XTCSER to hold the KDB address)
;correctly.
;.hl 3 Detailed Description
;^^
;The following lists all the fields of the KDB and explains
;(briefly) their uses.
;.list
;.le;XKBNAM -- this cell contains the name of the controller in
;SIXBIT. These names are EPA for the first DA28C, EPB for
;the second, etc. This naming convention is analogous to the naming
;of disk controllers (DPA, DPB ...) and lets the unit number refer to
;the small computer on the DA28C (EPA0 is the first computer, EPA1 the
;next, and so forth).
;.le;XKBUDB -- this is the start of a 17(8) word block; each cell
;contains the address of the corresponding UDB (i.e. XKBUDB+0 has the
;UDB address for small computer 0, XKBUDB+1 has the UDB address for
;small computer 1, etc.). The UDB's are built at system startup time;
;their number depends upon the scan limit setting in the DA28C (a
;strap option). This allows one to add more small computers (or
;delete them) without having to rebuild the monitor.
;A final 0 word ensures that even if there are all 16 small computers on a
;DA28C our scan for units will still terminate.
;.le;XTdCNo --these are several words which contain the
;appropriate CONI/CONI words for the DA28C. Each DA28C responds
;to two device codes, called DAS (for DA status) and DAC (for DA
;control). For the first DA28C these correspond to codes
;420 and 424 respectively. Each subsequent DA28C will have different
;I/O codes assigned (they are again a strap option of the hardware).
;XTdCNo (where "d" is S for DAS and C for DAC and "o" is I for
;CONI and O for CONO) words in the KDB contain the appropriate
;I/O instruction to set or read the bits using T1. This allows XTCSER
;(who always points to the KDB with register W) to do an
;.indent 20;.sk;XCT XTCCNO_#_#(W) (for example)
;.sk;to set the bits in the control register for whichever DA28C
;it is working with.
;.le;XTdDTo -- four words similar to the above but containing DATAI/DATAO DAC/DAS instructions.
;All use T1, except the DATAO DAS (XTSDTO) which uses T2 (because
;a single subroutine wants arguments for both a DATAO DAS and a CONO DAC).
;.le;XTCBSY -- contains a CONSZ DAC,20 (which tests the busy
;bit).
;.le;XKBLOK -- this is the controller interlock word. This is -1
;if anything can be started on the controller, and 0 if "locked". This
;happens, for example, between the time XTCSER receives a remote interrupt
;(a small computer wants to send something) and therefore starts a
;read from the small computer and the time that the done interrupt
;occurs signalling the completion of that read. The routine D28GET sets
;this word to 0 when it gives a success return to the caller.
;This word is necessary because once we have set up a DMA read or
;write on the DA28C hardware we do not want to start up another (say
;a write of a control word for some other process) until we have
;received the done interrupt for the current one.
;.le;XKBDDB -- this word contains 0 or the address of the DDB doing
;data I/O. XTCINT checks this word and if non-zero goes to tag
;DDBINT instead of to UNIINT. The routine DDBIO stores F
;(the register which holds the DDB address) in this cell every time it starts
;a new IOWD. The routine IOREDY clears this when all IOWDs have been
;processed.
;.le;XKBIUN -- this word has the address of the UCB for which the next
;done interrupt is intended in the RH, and if the transfer is associated
;with a DDB, the DDB address in the LH. The only interrupt for
;which neither XKBDDB nor XKBIUN has a value is a select request (REMINT).
;All done interrupts require that either XKBDDB or XKBIUN (but not both)
;record who set up the transfer that is currently finishing.
;.le;XKBDAC -- on every interrupt, the result of the CONI DAC is stored here.
;.le;XKBDAS -- on every interrupt the result of the CONI DAS is
;stored here.
;.le;XKBTIM, XKBIOW, XKBCUR -- no longer used.
;.le;XKBGRB -- a flag word for the XTTSK. grab function. Diagnostics
;"grab" the controller (as may user programs that want to do direct
;I/O [perhaps a bootstrap loader]) which means that the DA28C is
;removed from the skip chain and therefore from XTCSER's ken.
;This word is 0 if the controller is not grabbed, 1 when we are in the
;process of grabbing the controller, and -1 if the controller is grabbed.
;.le;XKBPAC -- this is a count of all the pseudo-active DDB's on this
;controller. It is there primarily to catch errors involving mismatched
;calls to make a job pseudo active and to make it no longer
;pseudo active.
;.le;XKBREQ -- this contains 0 or the job number of the first
;job requesting to grab the controller. If the controller is busy
;at the instant that a program wishes to grab it, the XTTSK. grab
;subfunction checks this cell. If there is already a request here
;it merely goes to sleep and tries again later. If there is no
;request here, it stores the job number of the requestor in this cell.
;When the next interrupt routine exits via SCNQUE, the fact
;that this cell is non-zero will force the DA28C to be cleared and
;the job to be awakened.
;.le;XKBMBF -- this is the monitor buffer for reading and writing to
;the DA28 if we have to transform the data for the user. This only
;occurs with "image-binary" mode, which is not supported with LIP11M.
;The length of this section depends on the parameter MX11BF
;(see above).
;.end list!KDB
;.hl 3 KDB Layout
;^^
;A pictorial representation of the controller data block would be:
;.test page 56
;.nofill.nojustify.skip 2
; +-------------------------------------------------------+
; XKBNAM ! controller name in SIXBIT (e.g. EPA) !
; !-------------------------------------------------------!
; XKBUDB ! address of first UDB (PDP-11 #0) or 0 !
; ! address of second UDB (PDP-11 #1) or 0 !
; _\ ... _\
; ! address of last UDB (PDP-11 #17) or 0 !
; ! 0 (to terminate list) !
; !-------------------------------------------------------!
; XTSCNO ! CONO DAS,0(T1) !
; !-------------------------------------------------------!
; XTCCNO ! CONO DAC,0(T1) !
; !-------------------------------------------------------!
; XTSCNI ! CONI DAS,T1 !
; !-------------------------------------------------------!
; XTCCNI ! CONI DAC,T1 !
; !-------------------------------------------------------!
; XTSDTI ! DATAI DAS,T1 !
; !-------------------------------------------------------!
; XTCDTI ! DATAI DAC,T1 !
; !-------------------------------------------------------!
; XTCDTO ! DATAO DAC,T1 !
; !-------------------------------------------------------!
; XTSDTO ! DATAO DAS,T2 !
; !-------------------------------------------------------!
; XTCBSY ! CONSZ DAC,20 (busy bit) !
; !-------------------------------------------------------!
; XKBLOK ! controller lock (0=in use, -1 free) !
; !-------------------------------------------------------!
; XKBDDB ! DDB waiting for I/O interrupt or 0 !
; !-------------------------------------------------------!
; XKBIUN ! DDB addr or 0 ! UDB waiting for done !
; !-------------------------------------------------------!
; XKBDAC ! data from last CONI DAC !
; !-------------------------------------------------------!
; XKBDAS ! data from last CONI DAS !
; !-------------------------------------------------------!
; XKBTIM ! counter for timeout (obsolete) !
; !-------------------------------------------------------!
; XKBIOW ! IOWD or pointer to IOLIST (obsolete) !
; !-------------------------------------------------------!
; XKBCUR ! pointer to current IOWD (obsolete) !
; !-------------------------------------------------------!
; XKBGRB ! 0=not grabbed, 1=grabbing, -1=grabbed !
; !-------------------------------------------------------!
; XKBPAC ! no. of pseudo active DDBs on controller !
; !-------------------------------------------------------!
; XKBREQ ! 0 or job number of first job grabbing controller !
; !-------------------------------------------------------!
; XKBMBF ! monitor buffer !
; _\ ... _\
; ! _<MX11BF*3_>/2 words long !
; +-------------------------------------------------------+
;.fill.justify.skip
;-
MLP
SUBTTL DEFINITIONS -- UDB LAYOUT
XTCUDB::PHASE 0 ;PROTOTYPE UDB
XUBNAM::!SIXBIT /EP/ ;UNIT NAME
XUBKDB::!
XUBDDB::!XWD 0,0 ;DDB LIST,,KDB
XUBUNO::!BLOCK 1 ;UNIT NUMBER
XUBUNI::!XWD 0,0 ;RESERVED,,NEXT UDB
XUBRCW::!BLOCK 1 ;RECEIVED CONTROL WORD
XUBXCW::!BLOCK 1 ;CONROL WORD TO SEND
XUBQUE::!BLOCK 1 ;START OF A WORK Q OF 4 WORD BLOCKS
XUBIPC::!BLOCK 1 ;INTERRUPT EVENT PC
XUBLOK::!BLOCK 1 ;INTERLOCK FOR UNIT (CONTAINS DDB ADDRS)
XUBRDY::!BLOCK 1 ;=0 IF WE ARE WAITING FOR A RESTART
;=-1 IF WE GOT A RESTART
XUBDST::!BLOCK 1 ;DEAD-START INFO
XUBEND::!BLOCK 1 ;END OF WORK LIST
XUBPAC:!BLOCK 1 ;NUMBER OF PSEUDO ACTIVE TASKS FOR UNIT
XUBSIZ==:.
DEPHASE
RELOC XTCUDB ;DO NOT NEED PROTOTYPE
PLM
;+
;.lm 0
;.hl 2 Unit Data Block
;^^
;.subtitle Unit Data Block
; The unit data block (UDB, addressed via register U) contains the information
;which pertains to a particular small computer interface on the
;DA28C. This includes the unit name, the last protocol words sent
;and received, the PC with which to continue when we receive a done interrupt
;for a unit, information about whether the small computer is alive or not
;and a queue of control words to send for this unit that are
;not associated with a DDB. Normal control word traffic is handled in
;the DDB, but there are control words (rejects, TTY functions, etc.)
;which must be sent to the small computer even if no normal data
;traffic is present.
;.hl 3 Detailed Description
;^^
;The following is a list of all the UDB fields:
;.list
;.le;XUBNAM -- this contains the unit name in SIXBIT.
;For example, the first unit on the first DA28C would be EPA0,
;the next EPA1, etc.
;.le;XUBKDB, XUBDDB -- both symbols refer to the same word.
;The LH contains the address of the first DDB on this
;unit. The right half contains the address of the KDB for this DA28C.
;.le;XUBUNO -- this word contains the unit number in binary form.
;It is useful for shifting into the CODE position of the DA28C
;status register.
;.le;XUBUNI -- the LH is reserved, the RH contains the
;address of the next UDB on this KDB.
;.le;XUBRCW -- this is the cell into which we read control words
;from the small computer. The DMA transfer set up at REMINT after
;we find out the small computer wishes to send us something does
;a one-word transfer into this location.
;.le;XUBXCW -- this is were we put the control word which we
;wish to send to the small computer; the DMA transfer
;to write the control word does a one-word transfer from here.
;.le;XUBQUE -- this contains either 0 or the address of the first in
;a queue of work requests for the unit. These work requests are
;gotten from free core (in routine D28WNF) and are 4 words long.
;The contents of an entry is:
;.skip
;.lm+20;0##control word to send
;.br;1##job number
;.br;2##unused
;.br;3##address of next work request or 0.
;.lm-20
;.sk
;When SCNQUE gets control after an interrupt has
;occurred it checks this queue. If it finds an entry, it goes to
;PHS2N0 which sets up XUBIPC to be XDNXU0 and then sends the control
;word. The done interrupt gets us to XDNXU0 which wakes the
;job, frees the work request block and starts another queued request
;(if there is one).
;.le;XUBIPC -- this word contains the routine which is to process
;the done interrupt for a unit (i.e. a control word was sent or
;received). The routine UNIINT dispatches to the address
;contained in this cell. The possible place to dispatch
;are:
;.list;.le;RECUCW -- here after we have set up to read a control
;word at REMINT.
;.le;XDNDDB -- here if we have sent a control word for a DDB.
;.le;XDNXUB -- here if we have sent a control word not for a DDB and
;the controller was not busy. In this case we did not have to
;queue anything.
;.le;XDNXU0 -- here if we sent a control word from the XUBQUE queue.
;We have to have a different routine because it must wake the job and
;throw away the queue entry 4-word block.
;.end list
;.le;XUBLOK -- this cell contains the address of the DDB for which
;we are "locking" the unit. This has to take place between the sending
;of WFI and doing input -- even if we have control words queued to go
;to this unit (either for other DDB's or in the unit queue) we had
;better not start anything between these points.
;This cell is set to the contents of F at XDNDDB. When
;the small computer decides to respond, we get a select request
;interrupt and go to REMINT; this routine checks XUBLOK and if
;it is non-zero goes to DOINP to start up the data transfer.
;.le;XUBRDY -- this cell contains XTCSER's opinion of the state of
;the small computer. If it is 0 we have not yet seen a "restart -8, -11 or -15"
;control word since 1) TOPS-10 came up or 2) the unit had been set offline
;for some reason. In this case we believe it is down; RDYCHK will attempt
;to send it a "restart -10" control word, but in any case wait until
;the receipt of a "restart -8, -11 or -15" has set this
;to -1.
;.le;XUBDST -- if the small computer sends a dead start control word
;to XTCSER it is copied here. The program can use an XTTSK. function
;to retrieve the information.
;.le;XUBEND -- this cell contains the address of the last 4-word
;block in the XUBQUE queue. This is so that we may easily append a
;new entry to the queue.
;.le;XUBPAC -- this cell contains a count of the number of DDB's on this
;unit that are pseudo active. Its usage is similar to that of XKBPAC,
;namely to catch any unmatched "make pseudo active" and "unmake pseudo active" calls.
;.end list!UDB
;.hl 3 UDB Layout
;^^
;The following is a pictorial representation of the UDB:
;.test page 30
;.nofill.nojustify.skip
; +-------------------------------------------------------+
; XUBNAM ! unit name in SIXBIT (EPA0) !
; !-------------------------------------------------------!
; XUBKDB ! ! !
; XUBDDB ! addr of 1st DDB on unit ! addr of KDB !
; !-------------------------------------------------------!
; XUBUNO ! unit number !
; !-------------------------------------------------------!
; XUBUNI ! reserved ! addr of next UDB on KDB !
; !-------------------------------------------------------!
; XUBRCW ! received control word !
; !-------------------------------------------------------!
; XUBXCW ! control word to send !
; !-------------------------------------------------------!
; XUBQUE ! addr of start of work queue !
; !-------------------------------------------------------!
; XUBIPC ! PC to continue with after done interrupt !
; !-------------------------------------------------------!
; XUBLOK ! 0 or addr of DDB using this unit !
; !-------------------------------------------------------!
; XUBRDY ! 0=waiting restart, -1=have gotten restart !
; !-------------------------------------------------------!
; XUBDST ! dead start control word !
; !-------------------------------------------------------!
; XUBEND ! addr of end of XUBQUE list !
; !-------------------------------------------------------!
; XUBPAC ! no. of pseudo active DDB's on unit !
; +-------------------------------------------------------+
;.fill.justify.skip
;-
MLP
SUBTTL DEFINITIONS -- DDB LAYOUT
XT1DDB==:0 ;DUMMY OUT UNWANTED DDB'S
XT2DDB==:0
XT3DDB==:0
$LOW
XT0DDB::
XTCDDB: PHASE 0
SIXBIT // ;(0) DEVNAM
XWD 6*HUNGST,41 ;(1) DEVCHR
0 ;(2) DEVIOS
XWD 0,XTCDSP ;(3) DEVSER
XWD 1003,115403 ;(4) DEVMOD
0 ;(5) DEVLOG
0 ;(6) DEVBUF
0 ;(7) DEVIAD
0 ;(10) DEVOAD
0 ;(11) DEVSTS
XWD <.TYXTC*.TYEST>!DEPLEN,DEPEVM ;(12) DEVSTA
0 ;(13) DEVXTR
0 ;(14) DEVEVM
0 ;(15) DEVPSI
0 ;(16) DEVESE
0 ;(17) DEVHCW
0 ;(20) DEVCPU
0 ;(21) DEVISN
0 ;(22) DEVDRV
0 ;(23) DEVJOB
;END OF STANDARD DDB DEFINITIONS, NEXT ARE THE XTCSER-SPECIFIC WORDS
;IN THE DDB.
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
DVXUDB:!0 ;XWD DDB LIST,UDB
DVXDSC:!0 ;DVXDSC
;FORMAT OF DVXDSC:
XT.PRM==400000 ;DDB DOES NOT DISSAPPEAR AT LOGOUT
;BITS 16-23 ARE ATTRIBUTES BYTE
;BITS 24-35 ARE TASK ID
DVXMOD:!BYTE (4)0,0,0,0,0,0,0,0,10 ;MODE CORRESPONDENCE
BYTE (4)11,0,13,14,0,0,17
DVXFZR:! ;FIRST LOCATION ZEROED
DVXCTL:!0 ;LAST CONTROL WORD RECEIVED FROM TASK
DVXXCW:!BLOCK 1 ;LAST CONTROL WORD SENT, OR
; SEND THIS CONTROL WORD
DVXST4:!BLOCK 1 ;SAVE PROTOCOL WORD HERE DURING XIOWAT CALL
DVXQUE:!BLOCK 1 ;FUNCTION TO PERFORM WHEN
; CONTROLLER IS IDLE
DVXIPC:!BLOCK 1 ;WHERE TO GO WHEN AN
; INTERRUPT HAPPENS
DVXPRC:!BLOCK 1 ;RETURN ADDRESS OF COROUTINE
DVXCOR:!BLOCK 1 ;ADDRESS OF INTERRUPT COROUTINE
DVXMSK:!BLOCK 1 ;EVENT FLAGS FOR INTERRUPT CODE
DVXRFI:!BLOCK 1 ;WORD COUNT SENT BY REMOTE IN RFI
DVXWFO:!XWD 0,0 ;LH - DATA MODE REC FROM TASK
; RH - WORD COUNT REC FROM TASK
; ALWAYS STORED POSITIVE.
DVXBSZ:!BLOCK 1 ;SIZE OF INPUT AREA OR OF OUTPUT AREA
DVXIWA:!BLOCK 1 ;ADDRESS OF NEXT DUMP MODE IOWD
DVXLLM:!BLOCK 1 ;FIRST OF TWO TEMPS FOR DUMP MODE
DVXULM:!BLOCK 1 ;SECOND OF TWO TEMPS FOR DUMP MODE
DVXCUR:!BLOCK 1 ;ADDRESS IN DVXIWD LIST
DVXIWD:!BLOCK .IOLEN-1 ;IOWD FOR DUMP MODE IO
DVXILS:!BLOCK 1 ;LAST WORD OF IOWD LIST
DVXPAC:!BLOCK 1 ;PSEUDO ACTIVE LOCATION
DVXPST:!BLOCK 1 ;PROTOCOL STATUS
DVXWAK:!BLOCK 1 ;SET OF WAKE EVENTS
DVXLZR:! ;LAST LOCATION ZEROED
DEPHASE
XTCDDW==.-XTCDDB
$HIGH ;BACK TO HIGH SEGMENT
PLM
;+
;.lm 0
;.hl 2 Device Data Block
;^^
;.subtitle Device Data Block
; The device data block (DDB, addressed via register F) is the central collection of information
;for all I/O devices in TOPS-10. It includes information that all
;devices have in common; this part is called the "standard" DDB, and
;the symbolic names for the offsets have the form "DEVxxx". XTCSER
;needs additional information to correctly handle each conversation over
;the DA28 between a program on the DECsystem-10 and a process in the
;small computer; rather than invent a new data structure it simply added
;an extension to the DDB (which is not unique -- other devices
;in the monitor have done the same).
; The types of data in this DDB extension include: information
;about the state of the protocol between the -10 and the small computer,
;the IOWDs used to transfer data between the user buffer and the
;small computer, the last control word read or written on behalf
;of this DDB and the size and mode information
;from previously received control words.
;The DDB's point to the UDB of the unit that they are on, and all
;DDB's on a particular unit are also chained together. Also,
;DDB's waiting to transfer protocol words may be chained together in
;a queue waiting for the DA28 hardware to become free.
;.hl 3 Detailed Description
;^^
;The following is a field-by-field description of the DDB extension:
;.list
;.le;DVXUDB -- the LH contains the address of the next DDB on this
;unit, the RH contains the address of this unit's UDB. These fields
;are initialized when the DDB is built by the XT.IDN sub-function
;of the XTTSK. UUO.
;The DDB chain is used in FNDTSK, FNDDDB and FINUNI to
;look at only the DDB's on a specific unit. I/O UUO's in which only
;the DDB is known (such as CLOSE) use the RH to get the pointer to
;the UDB.
;.le;DVXDSC -- this word contains three distinct fields. The sign bit is the
;bit that flags a DDB as permanent (XT.PRM). Bits 16-23 are the
;attribute byte and bits 24-35 are the task ID. The latter is
;conveyed in the protocol words and serves to link a task on the
;small computer with a DDB on the DECsystem-10.
;.le;DVXMOD -- this word and the following represent the mapping
;between the software modes that the user specifies when opening
;I/O devices (e.g. 17 = dump mode, 0 = ASCII mode) and the
;hardware mode that the DA28 will use in transferring data for that
;device. These two words consist of 16(10) 4 bit bytes, the first
;corresponding to mode 0, the next to 1 and so on. The actual
;hardware mode values may be changed by an XTTSK. UUO sub-function.
;.le;DVXCTL, DVXXCW -- both symbols refer to the same word. The
;symbol DVXCTL is used to refer to the last control word received
;from the small computer. The routine RECUCW copies the
;control word from the KDB into this word if the task ID is found to match
;that of a DDB. The word is also used to store the control word we
;have built to send to the small computer (DVXXCW);
;PHS2F in the SENDW routine stores the control word in this cell.
;.le;DVXST4 -- this word is used to save the protocol word (built
;in T4, hence the name) in the DDB over the call to D28WTF (which
;puts its caller's PC in DVXQUE and returns).
;.le;DVXQUE -- this cell contains the PC at which to continue after
;a control word queued in the DDB is ready to be sent.
;If the SENDW code decides that it has no other protocol words to
;send for this DDB but that the DA28 is busy for some other process,
;it calls D28WTF, which POPs the caller's PC into DVXQUE, then returns
;to previous caller. At some subsequent done interrupt, SCNQUE notices
;that DVXQUE for the DDB is non-zero, and jumps to the address
;contained in DVXQUE to continue processing.
;.le;DVXIPC -- no longer used by XTCSER; presumably fulfilled the
;function of XUBIPC in a previous version.
;.le;DVXPRC -- this word contains the PC of the co-routine caller.
;The eventual exit (via $CPOPJ or $CPOPJ1) of the co-routine
;will be to this address or this address plus 1. The only co-routine
;callers are INPCOM and OUTCOM, the common parts of the IN(PUT) UUO
;and OUT(PUT) UUO processing routines. The $COROUT routine (invoked at the
;beginning of both co-routines, XISYNC and XOSYNC) merely
;takes this PC from the stack and stores it in DVXPRC.
;.le;DVXCOR -- this is the other word used in the co-routine mechanism.
;The SYNC$ routine stores its caller PC in DVXCOR if it doesn't have
;a match of bits on DVXMSK. Then whenever there is an interrupt, the
;routine CHKPRC will notice that DVXCOR is non-zero (i.e. a co-routine
;is running) and dispatch to it at interrupt level to accomplish the
;next piece of the synchronization process. In this case, SYNC$ was
;called the first time at UUO level and is therefore HIBERing. When
;interrupt level executes the $CPOPJ or $CPOPJ1 code this latter will
;clear DVXCOR (to indicate that the co-routine is no longer running), increment DVXPRC (if $CPOPJ1) and then call WAKJOB to cause the HIBER
;to finish. The rest of the SYNC$ UUO level call will notice that
;DVXCOR is zero, and then return to the PC in DVXPRC.
;.le;DVXMSK -- these are the DEVIOS bits upon which to continue processing the
;co-routine. They are set by the SYNC$ code and tested by
;CHKPRC.
;.le;DVXRFI -- the RH of this word contains the positive word
;count extracted from the last RFI received.
;.le;DVXWFO -- the LF of this word contains the mode and the RH contains the word count, both extracted from
;the last WFO received.
;.le;DVXBSZ -- this word contains the user buffer size (or the
;size of the dump-mode transfer if in dump mode) in the RH. It is
;compared with the size in DVXWFO to decide whether or not
;to set IOBKTL or shorten the "user" requested length.
;.le;DVXIWA -- in dump mode, this has the address of the next user
;IOWD to process (by calling NXCMR). The routine DMPSET fills
;up the IOWD space in the DDB by calling COMCHK the first time and
;then NXCMR for subsequent I/O words. These words return the IOWD as well
;as (in M) the address of the next user IOWD to process (or 0).
;This M is stored here. If we have transferred all the IOWDs
;in the DDB and DVXIWA is still non-zero, interrupt level calls DMPSET again
;to fill more IOWDs into the DDB so it can continue the transfer.
;.le;DVXLLM -- this is the user virtual address lower limit (as
;returned by COMCHK).
;.le;DVXULM -- this is the user virtual address upper limit (as
;returned by COMCHK).
;.le;DVXCUR -- this is the address within the DDB IOWD area of the
;next IOWD to transfer over the DA28. Initially set to DVXIWD.
;.le;DVXIWD -- this is the start of the IOWD space in the
;DDB. There are .IOLEN-1 words set aside here in which to put user
;virtual address IOWDs so the MPIOWD can convert them to
;hardware IOWDs. This space is used so the dump mode and buffered
;mode can have common I/O handling code -- buffered mode and
;dump mode simply fill in the IOWDs here, and the rest of the code
;has only one source for them.
;.le;DVXILS -- this is the cell for the last IOWD. It has a tag
;merely to make it easier to check when we have filled up the
;DDB IOWD space.
;.le;DVXPAC -- this is a count of the number of seconds remaining for
;the DDB to be "pseudo-active". Normally a DDB is made I/O active (by
;setting IOACT in DEVIOS) only when a transfer to or from the
;user address space is in process. This is because being I/O active
;prevents a job from being moved in memory or swapped out. For
;high performance XTCSER makes a job I/O active at the beginning
;of I/O processing in anticipation that the small computer will
;respond quickly to the control words and transfer data. This may
;not be the case, however, and so this state is called a "pseudo-active"
;state because we are active only on the hope of imminent transfer,
;not on the actuality. XTCSEC once a second code decrements
;DVXPAC for all DDB's; if the value reaches 0 (i.e. the pseudo active
;time has expired) IOACT is cleared and the job can now be swapped.
;Just before data transfer really takes place the job is made active
;again.
;This cell is initialized in PSACT to the value of the parameter
;ACTTIM (currently 2).
;.le;DVXPST -- this cell contains the current protocol status bits.
;There are bits for the receipt and transmission of all the data-oriented
;protocol words. Most of the RECxxx routines merely set the
;IORxxx bit in this word, and the done interrupt on sending a control
;word for data transfer sets the IOXxxx bit.
;.le;DVXWAK -- these are the user-requested wake bits. There is a
;sub-function of the XTTSK. UUO which allows the user to test the
;current DEVIOS bits for the DDB against a mask. If none of the
;bits are on, this mask is copied into DVXWAK. Whenever one of these
;bits is subsequently set, a WAKJOB call
;will be done for the user job, so the combination XTTSK, HIBER UUOs
;can have the same effect as if one had new hiber-condition bits for
;XTCSER.
;.end list!DVX
;.hl 3 DDB Layout
;^^
;The following is a pictorial representation of the XTCSER
;extensions to the DDB:
;.test page 52
;.nofill.nojustify.skip
; +-------------------------------------------------------+
; DVXUDB ! link to next DDB on UDB ! addr of UDB !
; !-------------------------------------------------------!
; DVXDSC !prm! reserved ! attr byte ! task ID !
; !-------------------------------------------------------!
; DVXMOD ! first word of mode correspondence bits !
; !-------------------------------------------------------!
; ! second word of mode correspondence bits !
; !-------------------------------------------------------!
; DVXCTL ! last control word received for this DDB !
; DVXXCW ! or next control word to send for this DDB !
; !-------------------------------------------------------!
; DVXST4 ! saved control word if we have to wait for old one !
; !-------------------------------------------------------!
; DVXQUE ! PC to continue with if DDB had to be queued or 0 !
; !-------------------------------------------------------!
; DVXIPC ! PC to continue on done interrupt (obsolete) !
; !-------------------------------------------------------!
; DVXPRC ! co-routine caller PC !
; !-------------------------------------------------------!
; DVXCOR ! 0 or PC to continue co-routine !
; !-------------------------------------------------------!
; DVXMSK ! mask bits to wake up co-routine !
; !-------------------------------------------------------!
; DVXRFI ! positive count from last RFI received !
; !-------------------------------------------------------!
; DVXWFO ! data mode from WFO ! word count from WFO !
; !-------------------------------------------------------!
; DVXBSZ ! reserved ! buffer size !
; !-------------------------------------------------------!
; DVXIWA ! address of next user IOWD to process in dump mode !
; !-------------------------------------------------------!
; DVXLLM ! user dump mode lower limit (COMCHK) !
; !-------------------------------------------------------!
; DVXULM ! user dump mode upper limit (COMCHK) !
; !-------------------------------------------------------!
; DVXCUR ! address of next IOWD for DA28 transfer !
; !-------------------------------------------------------!
; DVXIWD ! first IOWD for DA28 transfer !
; _\ ... _\
; ! next to last IOWD for DA28 transfer !
; !-------------------------------------------------------!
; DVXILS ! last IOWD for DA28 transfer !
; !-------------------------------------------------------!
; DVXPAC ! timer for how long DDB has been pseudo active !
; !-------------------------------------------------------!
; DVXPST ! protocol status bits !
; !-------------------------------------------------------!
; DVXWAK ! user-requested wake bits !
; +-------------------------------------------------------+
;.fill.justify.skip
;-
MLP
SUBTTL CONSTANTS -- BYTE POINTERS
DVYTAT: POINT 8,DVXDSC(F),23 ;ATTRIBUTE BYTE
DVYTID: POINT 12,DVXDSC(F),35 ;TASK ID
DVYMFC: POINT 4,DVXCTL(F),3 ;RECEIVED MAJOR FUNCTION CODE
DVYXMF: POINT 4,DVXXCW(F),3 ;XMITTED MAJOR FUNCTION CODE
DVYFSC: POINT 4,DVXCTL(F),7 ;FUNCTION SUB CODE
DVYSFI: POINT 8,DVXCTL(F),15 ;SUPP. FUNCTION INFORMATION
DVYMOD: POINT 4,DVXCTL(F),19 ;DATA PACKING MODE
DVYUNI: POINT PR.UIS,DVXCTL(F),23 ;UNIT
DVYTIF: POINT 12,DVXCTL(F),31 ;TASK ID FIELD(COMBINED UNIT AND TASK ID)
DVYWDC: POINT 12,DVXCTL(F),15 ;WORD COUNT IN WFO
DVYIOM: POINT 4,DVXBSZ(F),3 ;I/O MODE
DVYHWM: POINT 4,DVXBSZ(F),7 ;HARDWARE MODE
CTYMFC: POINT 4,T4,3 ;MAJOR FUNCTION CODE
CTYFSC: POINT 4,T4,7 ;FUNCTION SUB CODE
CTYSFI: POINT 8,T4,15 ;SUPP. FUNCTION INFORMATION
CTYMOD: POINT 4,T4,19 ;DATA PACKING MODE
CTYUNI: POINT PR.UIS,T4,23 ;UNIT
CTYTIF: POINT 12,T4,31 ;TASK ID FIELD(COMBINED UNIT AND TASK ID)
XUYMFC: POINT 4,XUBRCW(U),3 ;MAJOR FUNCTION CODE
XUYFSC: POINT 4,XUBRCW(U),7 ;FUNCTION SUB CODE
XUYSFI: POINT 8,XUBRCW(U),15 ;SUPP. FUNCTION INFORMATION
XUYMOD: POINT 4,XUBRCW(U),19 ;DATA PACKING MODE
XUYUNI: POINT PR.UIS,XUBRCW(U),23 ;UNIT
XUYTIF: POINT 12,XUBRCW(U),31 ;TASK ID FIELD(COMBINED UNIT AND TASK ID)
PIOMOD: POINT 4,DEVIOS(F),35 ;I/O STATUS
PLM
;+
;.lm 0
;.hl 1 Other Data Structures
;^^
; There are a few other pieces of the "data structures" which
;I will not describe in detail but wish to mention.
;.list
;.le;There are a group of cells whose names look like DVYxxx, CTYxxx,
;or XUYxxx which are byte pointers for subfields (mostly within
;control words) of cells in the data structures described above.
;There is no need to enumerate them here as their function is
;obvious from the listing.
;.le;There is a dispatch table with the tag XTCDSP. This is
;the I/O dispatch table used by UUOCON to call a device service
;routine to perform specific functions. Each XTCSER DDB has the address
;of this dispatch table in it (in the RH of the DEVSER word).
;It is via this mechanism that the code to support I/O functions is
;executed. Note that there are separate entries in the dispatch
;table for dump mode and normal buffered mode I/O.
;Also note that there are negative displacements off the
;dispatch table address.
; There are two other entries into the XTCSER code: the CALLI dispatch
;table has an external symbol (XTUUO) as the service routine for
;the XTTSK. UUO and CLOCK1 has a call to XTCSEC for once a second processing.
;(If there are no XTCSER devices, XTCSEC is equated to
;CPOPJ in COMDEV.)
;.end list
;-
MLP
SUBTTL CONSTANTS -- I/O DISPATCH TABLE
POPJ P, ;*-5 DEVICE OFFLINE?
POPJ P, ;*-4 EXTENDED SOFTWARE ERROR STATUS
JRST REGSIZ## ;*-3 RETURN BUFFER SIZE
JRST XTCINI ;*-2 INITIALIZATION
JRST XTCHNG ;*-1 HUNG DEVICE
XTCDSP::JRST XTCREL ;(00) RELEASE THE TASK IS RESTART
JRST XTCLSO ;(01) CLOSE OUTPUT
JRST XTCOUT ;(02) BUFFERED OUTPUT
JRST XTCIN ;(03) BUFFERED INPUT
;END OF SHORT DISPATCH TABLE
JRST CPOPJ1## ;(04) ENTER
JRST CPOPJ1## ;(05) LOOKUP
JRST XTCDOU ;(06) DUMP MODE OUTPUT
JRST XTCDIN ;(07) DUMP MODE INPUT
POPJ P, ;(10) SETO
POPJ P, ;(11) SETI
POPJ P, ;(12) GETF
JRST CPOPJ1## ;(13) RENAME
JRST XTCLSI ;(14) CLOSE INPUT
POPJ P, ;(15) UTPCLR
POPJ P, ;(16) MTAPE
SUBTTL TIMER ROUTINES
XTCHNG: NULL
PUSHJ P,SETACS ;SET UP THE ACCS
PUSHJ P,ZAPACT ;CLEAN UP PSEUDO ACTIVE ACCOUNTING
SETZM DVXQUE(F) ;NO MORE REQUESTS
CONO PI,PI.OFF ;NO INTERRUPTS
SKIPN T1,XKBDDB##(W) ;IS THERE ANY ONE USING IT
HLRZ T1,XKBIUN##(U) ;DDB ADDRESS IF THERE IS ONE
JUMPE T1,NODHNG ;DA28C IS NOT BUSY
CAME T1,F ;ARE WE STUCK?
JRST NODHNG ;(NO) ANOTHER ONE MAYBE
MOVEI T1,XS.CLR ;CLEAR THE
XCT XTSCNO##(W) ;COMMAND REGISTER
SETZ T1, ;READY TO DISCONNECT
XCT XTCCNO##(W) ;DO IT
SETZM XKBDDB##(W) ;YES: ZAP EVERYTHING AND FREE CTL
SETZM XKBIUN##(W)
CONO PI,PI.ON ;WE CAN HEAR AGAIN
PJRST SCNQUE ;AND FIND WORK
NODHNG: NULL
CAMN F,XUBLOK(U) ;ARE WE LOCKING IT
SETZM XUBLOK(U) ;NO LONGER
PJRST ONPOPJ##
;XTCSEC CHECK IF PSEUDOACTIVE TASKS HAVE RUN OUT OF TIME
;CALLED ONCE A SECOND
XTCSEC::NULL
PUSHJ P,SAVE1## ;SAVE P1 RETURN RESTORES IT
PUSH P,W ;SAVE ACCS
PUSH P,U ;USED
PUSH P,F ;IN THIS CODE
MOVEI W,XKB0## ;CONTROL BLOCK NUMBER 1
LPKDB: SKIPN XKBPAC##(W) ;ANY PSEUDO ACTIVE UNITS?
JRST NXTKDB ;GET THE NEXT KDB
MOVEI P1,XKBUDB##(W) ;ADDRESS OF FIRST UDB
LPUDB: MOVE U,(P1) ;GET NEXT KDB
JUMPE U,NXTKDB ;NEXT CONTROL
SKIPN XUBPAC(U) ;ANY ACTIVITY?
JRST NXTUDB ;NOPE GET THE NEXT ONE
HLRZ F,XUBDDB(U) ;ADDRESS OF FIRST DDB
LPDDB: JUMPE F,NXTUDB ;FORGET IT
HRRZ T1,DVXPAC(F) ;GET THE PSEUDO TIME
JUMPE T1,NXTDDB ;UNINTERESTING
SOJG T1,NXTDD0 ;STILL TIME ON THE ACCOUNT
AOS PSZERO ;ACCOUNT THE LOSS
PUSHJ P,ZAPACT ;DO ALL THE ACCOUNTING
JRST NXTDDB ;GET THE NEXT DDB
NXTDD0: NULL
HRRM T1,DVXPAC(F) ;UPDATE THE ACCOUNT
NXTDDB: HLRZ F,DVXUDB(F) ;GET THE NEXT DDB
JRST LPDDB ;AND LOOP TILL DONE
NXTUDB: AOJA P1,LPUDB ;GET NEXT UDB
NXTKDB: HRRZ W,XKBKDB##(W) ;GET THE NEXT CONTROL ADDRESS
JUMPN W,LPKDB ;AND LOOP AGAIN
POP P,F ;GET REGISTERS BACK
POP P,U
POP P,W
POPJ P,
PLM
;+
;.chapter Code Description
;^^
;.subtitle Introduction
; This chapter will describe most of the routines in XTCSER briefly.
;No attempt is made to be exhaustive and therefore it is recommended
;that this section be read with a listing available.
; The routines in XTCSER fall into three large groups, with a
;few little ones left over. The groups are 1) routines to process
;the XTTSK. UUO (which has numerous sub-functions), 2) routines to
;process the I/O UUOs (IN, OUT, CLOSE, RELEAS) and 3) routines to
;handle the DA28 interrupts and to continue the process of completing
;the I/O operations started by the second group. Naturally this
;document will also have such major divisions.
; The code in XTCSER follows this outline to a large extent, but there
;are several routines that are out of place. Because this manual
;is imbedded in the code, the descriptions of these routines will
;similarly seem to defy logic.
; All of the code in XTCSER uses the following register convention:
;.list
;.le;S -- DEVIOS word from DDB
;.le;P -- stack pointer
;.le;J -- user job number
;.le;R -- low segment relocation (JBTADR value)
;.le;F -- address of DDB
;.le;U -- address of UDB
;.le;W -- address of KDB
;.end list
;.hl 1 Periodic Routines
;^^
;.subtitle Periodic Routines
; XTCSER has only two periodic routines -- XTCHNG and XTCSEC. The
;former is called by UUOCON if it detects that a device has been
;I/O active for more than its hung time (6 seconds in the case of
;the XTCSER DDB). The latter is called from CLOCK1 once a second
;to allow XTCSER to time the pseudo active state of a DDB.
;.hl 2 XTCHNG
;^^
;.subtitle XTCHNG
; When a device is hung, the monitor gives a message to the
;timesharing user; however, it calls the device service
;routine to clear out the device. Therefore XTCHNG's responsibilities are:
;.list
;.le;to take the device out of I/O active state so that it can be swapped
;.le;to clean up any information it was keeping about the device
;.le;to free any resources that the device was using (i.e. the
;DA28.
;.end list
;So the XTCHNG logic is:
;.list
;.le;set up all the ACs (U, W, S, J and R) based on F
;.le;zero DVXQUE so that interrupt level call of SCNQUE doesn't try to
;continue processing for the DDB
;.le;turn off PI's and check if this unit and this DDB were waiting for
;a done interrupt ([LH XKBIUN=F and RH=U] or XKBDDB=F) and if so,
;clear out the DA28 hardware, clear out the controller flags (XKBDDB, XKBIUN),
;allow interrupts again and exit via SCNQUE to do work on DA28 for
;some other DDB or unit.
;.le;or, if we had been waiting for an I/O transfer for this DDB (XUBLOK=F), clear lock and exit allowing interrupts.
;.end list
;.hl 2 XTCSEC
;^^
;.subtitle XTCSEC
; This routine makes all DDB's that have been pseudo-active
;for more than ACTTIM seconds no longer so. Its logic is:
;.list
;.le;save some registers and point W to first KDB
;.le;LPKDB -- if this KDB has 0 pseudo-active DDB's, go to NXTKDB; else point U to its first UDB
;.le;LPUDB -- if no more UDB's (U=0) go to NXTKDB; else if no pseudo-active
;DDB's on this UDB go to NXTUDB; else point to first DDB on unit
;.le;LPDDB -- if no more DDB's (F=0) go to NXTUDB
;.le;if DVXPAC is zero, go to NXTDDB; else decrement
;DVXPAC. If that goes to zero call ZAPACT to clear I/O active
;state and increment counter of times we've done this (PSZERO).
;.le;NXTDDB -- point to next DDB and go to LPDDB
;.le;NXTUDB -- point to next UDB slot and go to LPUDB
;.le;NXTKDB -- get pointer to next KDB and if non-zero go to LPKDB; else
;restore registers and exit.
;.end list
;Note that the logic of this routine goes to the next KDB as
;soon as it finds a 0 UDB slot in the current KDB; this means
;that if there exist small computers, say, on units 0 and 3 only
;the UDB's for units 1 and 2 must be built (they are marked offline).
;-
MLP
SUBTTL XTTSK. UUO -- SUB-FUNCTION DISPATCH TABLE
SALL
XT.DDB==400000 ;A DDB IS REQUIRED (SIGN BIT)
XT.PRV==200000 ;JOB HAS TO BE PRIVILIGED
XT.NUM==200 ;FACTOR TO MOVE ARG NUMBER IN PROPER PLACE
DEFINE X(A,B),<XX A,B,0> ;NO DDB NO PRIV
DEFINE XF(A,B),<XX A,B,XT.DDB> ;A DDB IS NEEDED
DEFINE XPR(A,B),<XX A,B,XT.PRV> ;PRIVILIGE NEEDE
DEFINE XFP(A,B),<XX A,B,<XT.DDB+XT.PRV>> ;PRIV & DDB
DEFINE XX(A,B,C),<C+<A*XT.NUM>,,B>
CUSDEF==.-FUNTAB
X 0,CPOPJ## ;PLACE FOR USER TO PATCH A FUNCTION
FUNTAB: X 0,CPOPJ## ;INVALID FUNCTION
XF 2,XTRDR ;(01) SEND READY TO RECEIVE
XF 2,XTRDS ;(02) SEND READY TO SEND
X 4,XTIDN ;(03) IDENTIFY A TASK
XF 2,XTMMD ;(04) MODE MODIFICATION
XF 3,XTGCH ;(05) GET CHARACTERISTICS
X 2,CPOPJ## ;(06) SET CHARACTERISTICS
XF 3,XTATB ;(07) ATTRIBUTE BYTE DIDDLE
XF 2,XTDEL ;(10) DELETE A TASK
XPR 2,XTLDX ;(11) LOAD EXTERNAL PROCESSOR (JAM)
XF 3,XTCLS ;(12) SEND CLOSE
XPR 2,XTFRC ;(13) FORCE UNIT OFF-LINE
XPR 2,XTDST ;(14) GET DEAD-START INFO
XPR 2,XTGRB ;(15) GRAB CONTROLLER & RETURN TO USER (SCANNER OFF)
XPR 2,XTRET ;(16) RESTART SCANNER & UNLOCK CTL
X 2,XTSTAT ;(17) GETSTATISTICS
IFE FTCMP3,<
XF 3,XTWAKF ;(20) WAKE ON EVENTS
> ;END OF FTCMP3=0
IFN FTCMP3,<
X 0,CPOPJ## ;(20) ILLEGAL
> ;END OF FTCMP3 .NEQ. 0
DECDEF==.-FUNTAB-1
PLM
;+
;.lm 0
;.hl 1 XTTSK. UUO Processing
;^^
;.subtitle XTTSK. UUO
; Roughly a quarter of the code in XTCSER is to process
;XTTSK. UUO functions.
;There are 16 XTTSK.#sub-functions; UUOCON enters the code at the
;tag XTUUO: which then uses the dispatch table FUNTAB
;to validate some of the arguments and find the address of
;the subroutine to actually perform the requested function.
;The register in an XTTSK. call contains "length of block,,addr of block".
;The first word of the argument block contains the function code; the
;next generally contains either a DDB name or channel number (if the function
;requires a DDB) or the SIXBIT controller or unit name (if the
;function pertains only to a controller or unit).
; All the routines use the standard GETWDU and PUTWDU to retrieve argument
;block words and to store results into the argument block. They also
;use the standard ECODx routines to return an error code in the
;user-register and cause an unsuccessful return (non-skip).
; A number of the XTTSK.#UUO functions can have an arbitrarily
;long list of arguments, that is they loop getting new arguments
;to operate on until there are no more. For example, XTWAKF allows
;a list of:
;.sk;#########function
;.br;#########DDB name
;.br;#########bits
;.br;#########DDB name 2
;.br;#########bits 2
;.br;############.
;.br;############.
;.br;############.
;.skip;for as many DDB/bits pairs as you want. The current
;status will be returned in each of the "bits" words.
;.hl 2 Functions
;^^
;.subtitle XTTSK. Functions
; The legal functions of the XTTSK. UUO are given
;in the FUNTAB table. This table consists of words with the LH
;containing requirements for the sub-function and the RH containing the address of the
;routine to perform the function.
;The requirements halfword consists of two bits XT.PRV (needs privileges) and XT.DDB (needs
;a DDB) along with minimum number of arguments that this function takes.
;Negative displacements off FUNTAB are for customer defined XTTSK.
;functions and positive offsets are for DEC-defined
;functions.
; XTCSER defines four macros to
;make setting of all the combinations of privilege bits easier --
;1) X (no DDB, no PRV); 2) XF (DDB, no PRV); 3) XPR (no DDB, PRV) and 4) XFP (DDB, PRV).
; FUNTAB has the following entries:
;.list
;.le;displacement -1 -- a spare for the purpose of allowing a
;customer to patch in his own XTTSK. function. Currently has
;no requirement bits, 0 arguments and executes CPOPJ.
;.le;0 -- illegal, goes to CPOPJ.
;.le;1 (XTRDR, needs F, 2 arguments) -- send an RFI to the
;small computer to signal readiness to do input.
;.le;2 (XTRDS, needs F, 2 arguments) -- send an RFO to the
;small computer to signal readiness to do output.
;.le;3 (XTIDN, 4 arguments) -- create a DDB (mnemonic refers to "identify a task").
;This function dynamically builds an XTCSER DDB. It can have any
;name (as long as it is unique within the system) and can be
;thought of as a link between the program doing I/O to it on the
;DECsystem-10 and a particular task on the small computer (as
;identified by the Task ID parameter that the creator of the
;DDB must supply). If the creator is privileged, he may mark
;the DDB as permanent (i.e.#must be explicitly deleted by another
;XTTSK.#UUO function). Many installations therefore use
;a privileged program running under the startup command file (OPR.ATO) to create DDB's named mnemonically by their
;purpose which will remain there as long as the system is up.
;.le;4 (XTMMD, needs F, 2 arguments) -- the "modify mode" subfunction
;allows the caller to change the mapping between software modes (the
;low order four bits of DEVIOS) and DA28 hardware modes (by
;changing the contents of the two DVXMOD words in the DDB).
;Thus the user may run existing programs in conjunction with the
;DA28 devices and ensure that they will work correctly no matter
;what data mode they were designed to use.
;.le;5 (XTGCH, needs F, min 3 arguments) -- the sub-function "get characteristics" various pieces of information about the
;XTCSER DDB to the user. It requires a minimum of three arguments, but
;up to 8 words of data (starting with the 3rd word of the argument list)
;if the list is long enough. The words are:
;.list
;.le;DVXCTL(F)
;.le;DEVSTS(F)
;.le;DEVIOS(F) plus the special XTCSER protocol bits
;.le;DVXDSC(F)
;.le;DEVMOD(F)
;.le;DEVCHR(F)
;.le;DVXPST(F) (where the special XTCSER protocol bits actually come from)
;.le;DVXXCW (which is now the same as DVXCTL)
;.end list
;.le;6 (not implemented, goes to CPOPJ) -- "set characteristics" was planned but never implemented.
;.le;7 (XTATB, needs F, 2 arguments) -- the sub-function "manipulate attribute byte" allows the user to:
;.list
;.le;set a new attribute byte
;.le;read the current attribute byte stored in the DDB
;.le;ANDCAM (i.e. clear) bits in the attribute byte
;.le;AND bits in the attribute bytes
;.le;OR bits into the attribute byte
;.le;send the current attribute byte to the small computer.
;.end list
;See the description of the protocol above for the functions the
;small computer can perform on the attribute byte.
;These functions are not usable with LIP11M.
;.le;10 (XTDEL, needs F, 2 arguments) -- the "delete DDB"
;function destroys an XTCSER DDB (even if the permanent bit is
;set). Normal (i.e. single user) DDB's need not be deleted in this manner because they are destroyed
;when they are deassigned (logout does this as well).
;.le;11 (XTLDX, needs privileges, 2 arguments) -- this function allows
;the privileged user to "jam" the small computer to a specific
;starting address (usually switch or strap selectable in the
;small computer DA28 interface). Another function (performed if
;the argument word has a right half of -1) is to force all
;the units on a specific controller on-line.
;.le;12 (XTCLS, needs F, 3 arguments) -- the function "send close eof"
;sends the "close eof" protocol word
;to the specified task on the small computer.
;This is equivalent to doing a CLOSE UUO if one has output some data,
;but is necessary if one wants to merely send an EOF (and
;nothing else) to the small processor because UUOCON never calls
;the device service routine (in this case XTCSER) if
;the user issues an OPEN immediately followed by a CLOSE.
;.le;13 (XTFRC, needs privileges) -- the function "force a unit off-line"
;causes the DA28C to force the unit offline. This might be useful
;if the small computer is misbehaving. To talk to the small computer
;again one must set the unit on-line with another XTTSK. function.
;When forcing the unit off-line XTCSER also zeroes the
;XUBRDY word of the UDB, so that the small computer must send a
;restart before XTCSER believes it is alive once more.
;.le;14 (XTDST, needs privileges, min 2 arguments) -- "get dead-start info" retrieves
;the dead-start protocol word for each unit in the argument list.
;This dead-start word was previously used when bootstrapping a
;small computer. LIP11M never sends it at all
;.le;17 (XTSTAT, min 2 arguments) -- this call provides overall
;statistics about XTCSER. The size of the argument
;block determines how many arguments are returned from the
;following list:
;.list
;.le;DBGPAR (contains address and length of XTDUMP trace buffer)
;.le;CNTINP (number of input UUOs)
;.le;CNTOUT (number of output UUOs)
;.le;CNTHIB (number of HIBERs, i.e. calls to DOZE routines)
;.le;CNTWAK (number of WAKEs, i.e. calls to XTWAK routines)
;.le;CNTQWT (number of calls to WTQEMP)
;.le;CNTWTQ (number of times HIBERing to wait for the queue to empty in WQEMP)
;.le;PSZERO (number of times we cleared pseudo-active state of a DDB in
;XTCSEC)
;.le;PSMAKE (number of times we made a DDB pseudo active)
;.le;XTCPAR (the parameters, ACTTIM in LH, and -QLPCNT in RH)
;.end list
;.le;20 (XTWAKF, needs F, min 3 arguments) -- this is the WAKE on specific events XTTSK. function.
;If FTCMP3 is on (i.e. non-zero) this function is illegal and goes to
;CPOPJ. (This is because the job is always being WAKEd with this
;feature test on.) If FTCMP3 is 0 (the default) the user may issue
;this UUO to inquire about the state of DEVIOS bits for one or
;more DDB's. The current values of the status bits are returned
;in place of the mask bits the user supplied in the argument
;block. If none of the masked bits were on, then if the user
;later issues a HIBER and one of the events corresponding to the
;bits occurs, the job will be awakened. If any of the bits specified
;in the mask are set at the time the XTTSK.#UUO is issued, the wake will NOT
;be done; it is the user's responsibility to check the current
;status returned, and not do the HIBER if a bit he is interested
;in is on.
;.end list
;-
MLP
SUBTTL XTTSK. UUO -- UUO ENTRY
;CALLING SEQUENCE:
; MOVE AS,[LENGTH,,ADDRESS OF ARGUMENT LIST]
; XTTSK. AC,
; ERROR RETURN ;AC = ERROR CODE
; SUCCESS RETURN
; . . .
; ADDR: FUNCTION
; ARGUMENTS
;
;ON ENTRY:
; (T1) = LENGTH,,ADDRESS
;
XTUUO:: NULL
PUSHJ P,SAVE3## ;SAVE PRESERVED AC'S
HRR M,T1 ;M GETS ARGUMENT LIST ADDRESS
HLRE P3,T1 ;P3 GETS LIST LENGTH
JUMPLE P3,ECOD1## ;LENGTH MUST BE POSITIVE
PUSHJ P,GETWDU## ;GET FUNCTION INTO T1
CAML T1,[CUSDEF] ;FUNCTION MUST BE WITHIN CUSTOMER DEFINED CODES
CAILE T1,DECDEF ; AND DEC DEFINED CODES
POPJ P, ; ERROR IF NOT
LDB T2,[POINT 9,FUNTAB(T1),10] ;GET MINIMUM ARG LIST LENGTH
CAMGE P3,T2 ;IS LIST LONG ENOUGH?
JRST ECOD1## ; NO, ERROR
MOVE P2,T1 ;SAVE FUNCTION
PUSHJ P,GETWD1## ;GET TASK ID
SUBI P3,2 ;UPDATE ARG COUNT
SKIPL P1,FUNTAB(P2) ;IS A DDB REQUIRED?
JRST XTUUO0 ;(NO) CHECK FOR PRIVILIGES
PUSHJ P,FNDDDB ;(YES) SEE IF DDB OKAY
PJRST ECOD2## ;SHOULD BE THERE
MOVE P1,FUNTAB(P2) ;GET TABLE ENTRY
XTUUO0: NULL
IFN FTMP,<
PUSH P,T1 ;PRESERVE TASK ID
MOVEI T1,0 ;GET A ZERO
PUSHJ P,ONCPUN## ; AND GET TO THE DA28'S CPU
POP P,T1 ;RESTORE TASK ID
>
TLZN P1,XT.PRV ;ANY PRILIGES REQUIRED
JRST @FUNTAB(P2) ;(NO) GO TO TASK PROCESSING
PUSHJ P,PRVJ## ;(YES) CHECK THEM
JRST @FUNTAB(P2) ;OKAY YOU MAY DO IT
PJRST ECOD0## ;NO PRIVILEGES
SUBTTL XTTSK. UUO -- XT.RDR, XT.RDS, XT.SCH, XT.DEL
;SEND READY TO RECEIVE
;ARGUMENT LIST:
; SIXBIT /DEVICE/ OR CHANNEL NUMBER
;SEND READY TO SEND
;ARGUMENT LIST:
; SIXBIT /DEVICE/ OR CHANNEL NUMBER
XTRDR: NULL
PUSHJ P,MAKRFI ;MAKE THE RFI CODE
SKIPA ;AND FALL IN COMMON CODE
XTRDS: NULL
PUSHJ P,MAKRFO ;MAKE RFO CODE
;START OF CODE SHARED BY SEND RFO OR RFI
PUSHJ P,SENDW ;SEND CODE AND WAIT TILL DONE
PUSHJ P,XIOWAT ;WAIT FOR COMPLETION
MOVE S,DEVIOS(F) ;GET A FRESH COPY
TDNE S,[ IOEND,,RHSTOP ] ;ALL ARE WRONG
PJRST ECOD3## ;I/O ERROR
JRST CPOPJ1## ;SUCESS RETURN
;SET DEVICE CHARACTERISTICS
;NOT YET DEFINED
XTSCH: POPJ P,0 ;UNDEFINED FUNCTION
;DELETE A TASK
;ARGUMENT LIST:
; SIXBIT /DEVICE/ OR CHANNEL NUMBER
XTDEL: NULL
MOVSI T1,XT.PRM ;DELETE EVEN PERMANENT DDBS
ANDCAM T1,DVXDSC(F) ;
MOVEI T1,ASSCON ;IF ASSIGNED BY CONSOLE,
TDNN T1,DEVMOD(F) ; DEASG WILL GIVE SKIP RETURN
AOS (P) ;GIVE SUCCESS RETURN
PJRST DEASG1## ;DEASSIGN & RELEASE
SUBTTL XTTSK. UUO -- XT.IDN
;BUILD AN EXTERNAL TASK (MAKE A DDB)
;PARAMETER LIST FORMAT:
; SIXBIT /DEVICE NAME/
; SIXBIT /EP NAME/
; XWD TASK UNIT ID, TASK ID
; XWD PERMANENT FLAG, BUFFER SIZE
; EXP DEVMOD BITS
; XWD FLAGS,ATTRIBUTE BYTE
XTIDN: NULL
MOVSI P1,PHONLY ;SEARCH ONLY PHYSICAL NAMES
PUSHJ P,DEVSRC## ;LOOK FOR A DDB WITH THIS NAME
SKIPA ;NOT FOUND IS GOOD
JRST ECOD2## ; FOUND IS ERROR
MOVE P2,T1 ;SAVE NAME FOR LATER
PUSHJ P,GETWD1## ;GET NAME OF EXTERNAL PROCESSOR
PUSHJ P,FNDEXP ;FIND EXTERNAL PROCESSOR UDB
JRST ECOD3## ; ERROR IF NOT FOUND
PUSHJ P,GETWD1## ;GET TASKID
HLRZ P1,T1 ;SEPARATE TASK UNIT ID
HRRZ T1,T1 ; AND TASK ID
CAIG T1,PR.TIM ;LARGE
CAILE P1,PR.UIM_-PR.TIS ; ID'S
JRST ECOD4## ; NOT ALLOWED
LSH P1,PR.TIS ;MOVE TASK UNIT OVER
IORB P1,T1 ; AND COMBINE WITH TASK ID
JUMPE P1,ECOD4## ;ZERO ID NOT ALLOWED
PUSHJ P,FNDTSK ;ANOTHER DDB WITH THIS ID NOT ALLOWED
SKIPA
PJRST ECOD4## ;ERROR
MOVEI T2,XTCDDW ;LOAD DDB SIZE
PUSHJ P,GETWDS## ;GET CORE FOR NEW DDB
JRST ECOD5## ; NO ROOM, TELL USER
HRRZ F,T1 ;THIS IS THE DDB
HRLI T1,XTCDDB ;BUILD BLT WORD
BLT T1,XTCDDW-1(F) ;COPY PROTOTYPE TO NEW DDB
HRLM F,XTCDDB+DEVSER ;LINK NEW DDB INTO CHAIN
MOVEM U,DVXUDB(F) ;LINK DDB TO UDB
HLR T1,XUBDDB(U) ;PICK UP START OF UDB DDB LIST
HRLM T1,DVXUDB(F) ;LINK DDB TO REST OF DDB'S
HRLM F,XUBDDB(U) ;LINK UDB TO DDB
MOVEM P2,DEVNAM(F) ;SET DEVICE NAME
MOVEM P1,DVXDSC(F) ;SET TASK ID INTO DDB
SUBI P3,2 ;PROCESSED TWO MORE WORDS
JUMPLE P3,XTIDN1 ;IF NO MORE ARGS, THEN SET DEFAULTS
PUSHJ P,GETWD1## ;GET NEXT ARG
TRNE T1,7777 ;NEW DEFAULT BUFFER SIZE?
DPB T1,PBUFSZ## ;YES, SET IT
HLRZ T2,T1 ;GET FLAG
CAIE T2,-1 ;WANT PERMANENT DDB?
JRST XTIDN1 ; NO
PUSHJ P,PRVJ## ;YES, PRIVILEGED TO MAKE ONE?
JRST XTIDN2 ;YES
XTIDN1: DPB J,PJOBN## ;NO, SET OWNER'S JOB NUMBER
MOVEI T1,ASSCON ;SET
IORM T1,DEVMOD(F) ; ASSIGNED BIT
JRST XTIDN3 ;GO CHECK FOR MORE PARMS
XTIDN2: MOVSI T1,XT.PRM ;THIS DDB WILL STAY
IORM T1,DVXDSC(F) ;
XTIDN3: SOJLE P3,CPOPJ1## ;IF NO MORE PARMS, EXIT
PUSHJ P,GETWD1## ;GET DEVMOD BITS
TRO T1,ASSCON ;SAVE ASSCON BIT
ANDM T1,DEVMOD(F) ;TURN OFF UNWANTED BITS
SOJLE P3,CPOPJ1## ;EXIT IF DONE
PUSHJ P,GETWD1## ;GET NEXT ARG
DPB T1,DVYTAT ;SET ATTRIBUTES BYTE
AND T1,DSCBTS ;MASK OUT UNWANTED BITS
IORM T1,DVXDSC(F) ;SET FLAGS
JRST CPOPJ1## ;EXIT
$LOW
DSCBTS: XWD 0,0 ;FLAGS MASK
$HIGH
SUBTTL XTTSK. UUO -- XT.MMD
;SPECIFY CORRESPONDENCE BETWEEN HARDWARE AND INIT MODE
;ARGUMENT LIST:
; SIXBIT /NAME/ OR EXP CHANNEL
; XWD INIT MODE, HARDWARE MODE
; XWD . . .
; . . .
XTMMD: NULL
SOJL P3,CPOPJ1## ;IF NO ARGS LEFT, EXIT
PUSHJ P,GETWD1## ;GET NEXT ARG
HLRZ T2,T1 ;SEPARATE OUT INIT MODE
HRRZS T1 ; AND HARDWARE MODE
CAIG T1,20 ;HARDWARE MODE .GE. 20?
CAILE T2,17 ; AND INIT MODE .GE. 17?
JRST ECOD3## ;YES, ERROR
MOVEI T3,1 ;POSITION ACCESS BIT
LSH T3,(T2) ; . . .
IORM T3,DEVMOD(F) ;THIS MODE ALLOWED NOW
CAIN T1,20 ;DID HE REALLY WANT TO DISALLOW IT?
ANDCAM T3,DEVMOD(F) ;YES, TURN IT OFF
IDIVI T2,^D9 ;DIVIDE BY MODES/WORD
MOVNS T3 ;CALCULATE
ADDI T3,10 ; BIT POSITION (SCALED BY 4)
ROT T3,-4 ;SET BIT POSITION WITHIN WORD
TLO T3,(POINT 4,0(F),35) ;BUILD BYTE POINTER
HRRI T3,DVXMOD(T2) ;SET ADDRESS INTO POINTER
DPB T1,T3 ;PUT MODE INTO CORE
JRST XTMMD ;LOOP FOR NEXT ARG
IFE FTCMP3,<
SUBTTL XTTSK. UUO -- XTWAKF
;ONLY THERE FOR SYSTEMS WITH NO EXTRANEOUS WAKES
;XTWAKF SET A WAKE EVENT FLAG IN A DDB WORD (DVXWAK)
;RETURN TO THE JOB THE SET OF ALL FLAGS SET FOR THE DDB
;IF NO FLAGS WERE SET AND EVENTS WERE SPECIFIED THEN A WAKE
;WILL BE DONE IF A FLAG IS RAISED LATER ON.
;ARGUMENTS:
; FUNCTION
; LIST OF ONE OR MORE PAIRS OF WORDS
;THE FORMAT OF AN ARGUMENT PAIR IS:
; DDB OR CHANNEL NUMBER
; EVENT MASK
;THE EVENT MASK WILL BE UPDATED TO THE SET DEFINED
;FOR THE DDB
XTWAKF: NULL
SOJL P3,CPOPJ1## ;ALL ARGUMENTS PROCESSED
PUSHJ P,GETWD1## ;GET NEXT ARGUMENT
MOVEM T1,DVXWAK(F) ;AND UPDATE THE FLAG
PUSHJ P,IFEBTS ;SEE IF ANY BITS ARE SET
SETZM DVXWAK(F) ;IN THAT CASE DISABLE THE WAKE
MOVE T1,T2 ;GET CURRENT MASK
PUSHJ P,PUTWDU## ;AND STORE IT
SOJL P3,CPOPJ1## ;MORE ARGUMENTS?
PUSHJ P,GETWD1## ;GET DDB NAME OR CHANNEL
PUSHJ P,FNDDDB ;FIND THE DDB
PJRST ECOD2## ;WRONG IT IS BNOT KNOWN
JRST XTWAKF ;NEXT ROUND
>;END OF FTCMP3=0
SUBTTL XTTSK. UUO -- XT.GCH, XTSTAT
;RETURN DEVICE CHARACTERISTICS TO USER
;ARGUMENT LIST:
; SIXBIT /DEVICE NAME/ OR CHANNEL NUMBER
; SPACE FOR RETURNED VALUES
XTGCH: NULL
CAILE P3,CHLEN ;DON'T RETURN MORE INFORMATION
MOVEI P3,CHLEN ; THAN I KNOW ABOUT
MOVEI P1,CHLST ;GET ADDR OF LIST
JRST XTGCHL ;SHARE XTSTAT LOGIC
;XTSTAT ALLOWS A USER TO OBTAIN DA28 CONFIGURATION DATA
XTSTAT: NULL
ADDI P3,1 ;GET RID OF GETWD1 CALL
SUBI M,1 ;IN XTUUO CODE
CAILE P3,CHLENS ;MORE THAN THE MAXIMUM
MOVEI P3,CHLENS ;THEN LIMIT HIM
MOVEI P1,STLIST ;GET THE LIST AND
;SHARE LOGIC WITH XTGCH
XTGCHL: NULL
MOVE T1,@0(P1) ;GET FIRST PARM
CAIE P1,IOSPOS ;GETTING DEVIOS
JRST XTGCH0 ;NO
PUSHJ P,XTCIOS ;YES DIFFERENT LOGIC
MOVE T1,S ;COPY
XTGCH0: PUSHJ P,PUTWD1## ;MOVE WORD TO USER AREA
AOS P1 ;INCREMENT LIST POINTER
SOJG P3,XTGCHL ;LOOP IF HE WANTS MORE
JRST CPOPJ1## ;SUCCESS RETURN
CHLST: DVXCTL(F)
DEVSTS(F)
IOSPOS: DEVIOS(F)
DVXDSC(F)
DEVMOD(F)
DEVCHR(F)
DVXPST(F) ;PROTOCOL STATUS
DVXXCW(F) ;LAST CONTROL WORD TRANSMITTED
CHLEN==.-CHLST ;GCH LIMIT
STLIST: DBGPAR ;DEBUG PARAMETERS
CNTINP ;NUMBER OF INPUT UUO'S
CNTOUT ;NUMBER OF OUTPUT UUO'S
CNTHIB ;NUMBER OF HIBERS IN WAIT FOR AN EVENT
CNTWAK ;NUMBER OF EVENT WAKES
CNTQWT ;COUNT OF ENTERING WTQEMP
CNTWTQ ;NUMBER OF TIMES HIBERRING TO TO Q WAIT
PSZERO ;NUMBER OF TIMES PSEUDO ACTIVE LOST
PSMAKE ;NUMBER OF TIMES PSEUDO ACTIVE INVOKED
XTCPAR
CHLENS==.-STLIST
SUBTTL XTTSK. UUO -- XT.ATB
;DIDDLE ATTRIBUTES BYTE
;ARGUMENT LIST:
; SIXBIT /DEVICE NAME/ OR CHANNEL NUMBER
; FUNCTION,,BITS
; . . .
XTATB: NULL
LDB P1,DVYTAT ;GET CURRENT ATTRIBUTES
XTATBL: SOJL P3,XTATBE ;EXIT IF NO MORE ARGS
PUSHJ P,GETWD1## ;GET NEXT ARG
HLRZ T2,T1 ;SEPARATE OUT FUNCTION CODE
JUMPE T2,ECOD3## ;CODE .GT. 0
CAILE T2,XTATBN ; AND .LT. MAX?
JRST ECOD3## ; NO, ERROR
XCT XTATBF-1(T2) ;DO FUNCTION
JRST XTATBL ;LOOP FOR MORE
XTATBE: DPB P1,DVYTAT ;STORE NEW ATTRIBUTES
JRST CPOPJ1## ;SUCCESS RETURN
XTATBF: ;table of instructions of XCT for sub-function [7136]
MOVEM T1,P1 ;(1) SET NEW BYTE
PUSHJ P,XTATBR ;(2) RETURN BYTE
ANDCAM T1,P1 ;(3) ANDCAM BITS
ANDM T1,P1 ;(4) AND BITS
IORM T1,P1 ;(5) OR BITS
PUSHJ P,ATSEND ;(6) SEND BYTE TO TASK
XTATBN==.-XTATBF
XTATBR: NULL
MOVE T1,P1 ;MOVE BYTE
ANDI T1,377 ;GET RID OF EXTRA BITS
HRL T1,T2 ;RESTORE FUNCTION
PUSHJ P,PUTWDU## ;PUT INTO ARG LIST
POPJ P, ;RETURN
ATSEND: NULL
MOVE T3,P1 ;COPY ATTRIBUTE BYTE TO SFI
SEND XAB ;DO NOT WAIT
POPJ P,
SUBTTL XTTSK. UUO -- SEND CLOSE INFO
;ARGUMENT LIST:
; SIXBIT /DEVICE-NAME/ OR CHANNEL NUMBER
; CLOSE CODE (0-3)
XTCLS: NULL
PUSHJ P,GETWD1## ;FETCH ARG
CAIGE T1,3 ;CHECK RANGE
SKIPN T1 ;AND VALIDITY
MOVEI T1,3 ;SUPPLY DEFAULT
XCT XTCLTB-1(T1) ;PERFORM FUNCTION
PUSHJ P,XIOWAT ;WAIT TILL DONE
MOVE S,DEVIOS(F) ;GET A FRESH COPY
TRNE S,RHSTOP ;CHECK FOR ERRORS
PJRST ECOD3##
JRST CPOPJ1##
XTCLTB: POPJ P, ;(1)CLOSE INPUT
PUSHJ P,XMTEOF ;(2)SEND EOF
PUSHJ P,XMTEOF ;(3)SEND EOF
SUBTTL XTTSK. UUO -- SPECIAL UNIT FUNCTIONS XTFRCL, XTLDXL, XTDSTL
;ROUTINE TO FORCE A UNIT OFF-LINE
;ARGUMENT LIST:
; SIXBIT /EP NAME/
; ......
XTFRCL: NULL
SOJL P3,CPOPJ1## ;RETURN IF NO MORE ARGS
PUSHJ P,GETWD1## ;GET ARG
XTFRC: NULL
PUSHJ P,FNDEXP ;FIND UNIT #
PJRST ECOD4## ;NO SUCH UNIT
PUSHJ P,FRCOFL ;FORCE UNIT OFFLINE
PJRST ECOD3## ;YOU LOOSE
JRST XTFRCL ;AND YOU WIN
;ROUTINE TO SET JAM BIT IN CTL (FORCE LOAD)
;ARGUMENT LIST:
; SIXBIT /EP NAME/ OR EPX,,-1 FOR ALL UNITS
; ......
XTLDXL: NULL
SOJL P3,CPOPJ1## ;RETURN IF NO MORE ARGS
PUSHJ P,GETWD1## ;GET ARG
XTLDX:: NULL
HRRZ T2,T1 ;CHECK SPECIAL
CAIN T2,-1 ;...
JRST XTLDXA ;FORCE UNITS ON-LINE
PUSHJ P,FNDEXP ;FIND UNIT #
PJRST ECOD4## ;LOSE
PUSHJ P,GRBCTL ;GET CTL
MOVE T1,XUBUNO(U) ;UNIT #
LSH T1,UNILSH
XCT XTSCNO##(W) ;SET CODE
MOVEI T1,XC.CON!XC.JAM
XCT XTCCNO##(W) ;POW
PUSHJ P,GIVCTL ;RETURN CTL
JRST XTLDXL ;HANDLE MORE
XTLDXA: NULL
PUSHJ P,FNDKON ;FIND KDB
JRST ECOD4##
MOVE W,U ;KDB ADDR TO CORRECT PLACE
PUSHJ P,GRBCTL ;GO GET CTL
PUSHJ P,XTRETX ;GIVE CONTROL BACK
JRST XTLDXL ;CONTINUE
;ROUTINE TO RETURN DEAD-START INFO FROM UDB
;ARGUMENT LIST:
; SIXBIT /EP NAME/
; ......
;RETURNS D-S INFO OVER EP-NAME
XTDSTL: NULL
SOJL P3,CPOPJ1## ;RETURN IF NO MORE ARGS
PUSHJ P,GETWD1## ;GET NEXT ARG
XTDST: NULL
PUSHJ P,FNDEXP ;LOCATE UDB
PJRST ECOD4## ;LOSAGE
MOVEI T1,0 ;CLR INFO
EXCH T1,XUBDST(U) ;FETCH DEAD-START WORD
PUSHJ P,PUTWDU## ;GIVE TO CALLER
JRST XTDSTL ;TRY NEXT
SUBTTL XTTSK. UUO -- XTGRB, XTRET MAINTENANCE FUNCTIONS
;ROUTINE TO GRAB A CONTROLLER WHOSE NAME APPEARS IN T1
;ARGUMENT LIST:
; SIXBIT /CONTROLLER NAME/
XTGRB: NULL
TRNN T1,-1 ;GRNTEE ZERO IN RH
PUSHJ P,FNDKON ;LOOK FOR CONTROLLER
JRST ECOD4## ;LOSE
MOVE W,U ;KDB ADDRESS TO W
PUSHJ P,GRBCTL ;GO GET IT
MOVEI T2,XKBUDB##(W) ;GET START OF UDB LIST
XTGRB1: HRRZ U,0(T2) ;LOCATE A UDB
JUMPE U,CPOPJ1## ;RETURN WHEN END FOUND
SETZM XUBRDY(U) ;MARK UNIT NOT READY
AOJA T2,XTGRB1 ;GO DO NEXT
;ROUTINE TO RETURN CONTROLLER TO SYSTEM USE AND RESTART SCANNER
;ARGUMENT LIST:
; SIXBIT /CONTROLLER NAME/
XTRET: NULL
TRNN T1,-1 ;GUARANTEE ZERO IN RH
PUSHJ P,FNDKON ;FIND KDB
JRST ECOD4## ;NO SUCH KDB
MOVE W,U ;ADDRESS TO W
SKIPN XKBGRB##(W) ;IS IT REALLY GRABBED?
JRST CPOPJ1## ;THE COMPETITION DID IT
AOS (P) ;SET FOR SKIP RETURN
XTRETX: MOVEI T1,XC.JAM ;FORCE EM ON-LINE
XCT XTCCNO##(W)
PJRST GIVCTL ;GIVE CONTROLLER BACK
SUBTTL XTTSK. SUBROUTINES -- DELETE AN XTC DDB
;ROUTINE TO DELETE A DDB
;CALL:
; MOVEI F,DDB
; PUSHJ P,XTKLDB
; POPJ P,
XTKLDB::NULL ;SUBROUTINE TO DELETE A DDB (ALSO
;CALLED FROM DEASSIGN CODE)
PUSHJ P,XTCDEV ;SEE IF IT IS A TASK DDB
PJRST CPOPJ## ;NO
MOVSI T1,XT.PRM ;PERMANENT FLAG VALUE
TDNE T1,DVXDSC(F) ;IS IT ON?
POPJ P, ;THEN DO NOT DELETE IT
HRRZ T1,DVXUDB(F) ;LOCATE ITS UDB
HLRZ T2,XUBDDB(T1) ;START DOWN UDB'S DDB LIST
CAIE T2,0(F) ;FOUND THE DDB YET?
JRST KDBUL ;NO, FOLLOW LIST
HLRZ T3,DVXUDB(F) ;YES, LOCATE NEXT DDB
HRLM T3,XUBDDB(T1) ;TAKE DDB OUT OF LIST
JRST KDBD ;GO TAKE DDB OUT OF SYSTEM LIST
KDBUL: MOVE T1,T2 ;FOLLOW DDB LIST
HLRZ T2,DVXUDB(T1) ;
CAIE T2,0(F) ;FOUND DDB YET?
JRST KDBUL ;NO, LOOP
HLRZ T3,DVXUDB(F) ;YES, LOCATE NEXT DDB
HRLM T3,DVXUDB(T1) ;TAKE THIS ONE OUT OF LIST
KDBD: MOVEI T2,XTCDDB ;LOCATE FIRST POSSIBLE DDB
KDBDL: MOVE T1,T2 ;FOLLOW DDB LIST
HLRZ T2,DEVSER(T1) ;
CAIE T2,0(F) ;FOUND MINE YET?
JRST KDBDL ;NO, LOOP
HLRZ T3,DEVSER(T2) ;YES, FOLLOW ONE MORE
HRLM T3,DEVSER(T1) ;TAKE MINE OUT OF LIST
MOVEI T1,XTCDDW ;GET DDB SIZE
PJRST GIVWDS## ;FREE THE CORE
SUBTTL XTTSK. SUBROUTINES -- XTCDEV, XTCIOS
;XTCDEV CALLED TO FIND WHETHER A DDB IS A TASK DDB AND
;TO RETURN S IN THAT CASE WITH THE IO.XXX BITS BIT
;NORMAL RETURN NO TASK DDB
;SKIP RETURN A TASK DDB, S REPLACED
;NO ACCUS (EXCEPT S ON A SKIP RETURN) ARE CHANGED
XTCDEV: NULL
PUSH P,T1 ;SAVE ACCU
MOVE S,DEVIOS(F) ;GET STANDARD S
LDB T1,DEYTYP## ;GET DEVICE TYPE
ANDI T1,77 ;MASK UNNEEDED BITS
CAIE T1,.TYXTC ;IS IT A TASK DDB?
PJRST TPOPJ## ;(NO) FALSE RETURN
LDB T1,[POINT 4,DVXPST(F),8] ;GET PTOTOCOL STATUS
DPB T1,[POINT 4,S,27] ;AND COPY TO MAKE IT VISIBLE
PJRST TPOPJ1## ;TRUE EXIT
XTCIOS::NULL ;CALLED FROM REST OF MONITOR TO GET DEVIOS
PUSHJ P,XTCDEV ;GET S
POPJ P, ; IGNORE FALSE RETURN.
POPJ P,
SUBTTL XTTSK. SUBROUTINES -- FNDxxx SEARCH ROUTINES
;ROUTINE TO LOCATE KDB WHOSE NAME IS IN T1
;RETURNS KDB ADDRESS IN U
FNDKON: MOVEI U,XKB0## ;BASE ADDRESS
HLLZ T2,T1 ;CONTROLLER NAME IN T2
FNDKN1: CAMN T2,XKBNAM##(U) ;THIS ONE?
JRST CPOPJ1## ;YES - GIVE GOOD RETURN
HRRZ U,XKBKDB##(U) ;LINK TO NEXT
JUMPN U,FNDKN1
POPJ P, ;ERROR RETURN
;SUBROUTINE TO FIND DDB WITH GIVEN TASK ID ON THIS EP
;CALL:
; MOVEI T1,TASKID ;12 BITS
; PUSHJ P,FNDTSK
; ERROR RETURN
; SUCCESS RETURN ;WITH (F)=ADDRESS OF DDB
FNDTSK: NULL
HLRZ F,XUBDDB(U) ;LOCATE FIRST DDB
FNTSK1: JUMPE F,CPOPJ## ;WE HAVE FAILED IF OUT OF DDBS
LDB T2,DVYTID ;GET TASK ID
HRRZ U,DVXUDB(F) ;SET UP U
HRRZ W,XUBKDB(U) ; AND W
CAMN T1,T2 ;THIS IT?
JRST CPOPJ1## ; YES
HLRZ F,DVXUDB(F) ;NO, LOCATE NEXT DDB
JRST FNTSK1 ;LOOP
;SUBROUTINE TO FIND DDB WITH GIVEN NAME
; AND PERFORM ACCESS CHECKING
;CALL:
; MOVE T1,[SIXBIT /DDB NAME/] OR MOVEI T1,CHANNEL
; PUSHJ P,FNDDDB
; FAILURE RETURN
; SUCCESS RETURN ;WITH (F) = ADDRESS OF DDB
FNDDDB: NULL
PUSHJ P,DVCNSG## ;LOCATE DDB
JRST ECOD2## ; ERROR IF NONE
LDB T2,DEYTYP## ;GET DEVICE TYPE CODE
ANDI T2,77 ;MASK DOWN TO TYPE BITS
CAIE T2,.TYXTC ;IS IT AN EXTERNAL TASK?
JRST ECOD2## ; NO, ERROR
HRRZ U,DVXUDB(F) ;SET UP U
HRRZ W,XUBKDB(U) ; AND W
LDB T2,PJOBN## ;GET CONTROLLING JOB NUMBER
CAME T2,.CPJOB## ;THIS JOB OWN IT?
PUSHJ P,PRVJ## ; OR OPR JOB?
JRST CPOPJ1## ;YES, SUCCESS RETURN
JRST ECOD2## ; NO, ERROR
;FIND UDB WITH GIVEN NAME
;CALL:
; MOVE T1,[SIXBIT /EP NAME/]
; PUSHJ P,FNDEXP
; ERROR RETURN
; NORMAL RETURN ;WITH (U) = ADDRESS OF UDB
FNDEXP: NULL
PUSHJ P,FNDKON ;LOCATE KDB FOR THIS ONE
POPJ P, ;ERROR
MOVEI T2,XKBUDB##(U) ;GET START OF UDB LIST
FNDXP1: HRRZ U,0(T2) ;LOCATE A UDB
JUMPE U,CPOPJ## ;ERROR IF NONE
CAME T1,XUBNAM(U) ;THIS THE UDB?
AOJA T2,FNDXP1 ;NO, TRY ANOTHER
HRRZ W,XUBKDB(U) ;SET UP CONTROLLER ADDRESS
JRST CPOPJ1## ;YES, SUCCESS RETURN
;FIND SPECIFIED UNIT
;CALL:
; MOVE T2,<DESIRED UNIT>
; MOVE T3,<DESIRED XKB>
; PUSHJ P,FNDUNI
; ERROR RETURN
; NORMAL RETURN - U SETUP
FNDUNI: NULL
HRRZ U,XKBUDB##(T3) ;LOOK AT FIRST UNIT
FNDUN0: CAMN T2,XUBUNO(U) ;THIS DA ONE?
JRST CPOPJ1## ;YES - GIVE GOOD RETURN
HRRZ U,XKBUDB##(T3) ;NO - GET NEXT UDB
JUMPE U,CPOPJ## ;DONE IF ZERO
AOJA T3,FNDUN0 ;TRY NEXT
SUBTTL INITIALIZATION AT SYSINI TIME
;SUBROUTINE TO INIT THE DA28-C CALLED AT ONCE TIME
;
XTCINI: NULL
PUSHJ P,SAVE1## ;NEED A P AC
SETZM DEVNAM+XT0DDB ;CLEAR OUT DEVICE NAME
MOVEI W,XKB0## ;START WITH FIRST XKB
XTINL1: SETZM XKBIUN##(W) ;CLEAR INTERRUPT
SETZM XKBDDB##(W) ; FLAGS
SETZM XKBGRB##(W) ;FLAG NOT YET GRABBED
SETOM XKBLOK##(W) ;GIVE UP THE CONTROL
MOVEI P1,XKBUDB##(W) ;ADDRESS OF FIRST UDB ADDRESS
XTINL2: SKIPN U,(P1) ;ADDRESS OF NEXT UDB
JRST XTINL7 ;JUMP IF DONE
SETZM XUBRDY(U) ;NEED A NEW RESTART
SETZM XUBQUE(U) ;TAKE OFF ANY QUEUES
SETZM XUBLOK(U) ;NO I/O GOING ON
IFN FTFRC,<CALL FRCOFL> ;FORCE UNIT OFFLINE
IFE FTFRC,<
SETZ F, ;NO DDB!
MOVE T1,XUBUNO(U) ;GET UNIT NUMBER
LSH T1,UNILSH ;SHIFT TO HARDWARE POSITION
IORI T1,XS.CLR!XS.ETI;DA28 BITS TO SELECT UNIT,
XCT XTSCNO##(W) ;CLEAR DA28, AND ENABLE TIMING ERRORS
MOVEI T1,XC.ERR!XC.CON;CONNECT TO SPECIFIC UNIT
XCT XTCCNO##(W) ;AND CLEAR ERRORS
XCT XTSCNI##(W) ;READ DA28 STATUS
TRNE T1,XS.NRD ;UNIT READY?
AOJA P1,XTINL2 ;NO, STEP TO NEXT UNIT
;UNIT IS THERE, SEND A RESTART -10
PUSHJ P,MAKREL ;GET A RESTART -10 COMMAND
MOVE T2,T4 ;AND PUT IT IN T2 FOR XTSDTO
MOVEI T1,XC.ERR!XC.FST!XC.CON!XC.OUT!XC.BSY!DM.BIN
XCT XTCCNO##(W) ;PREPARE DA28 TO SEND COMMAND WORD
XCT XTSDTO##(W) ;TELL SMALL COMPUTER TO RESTART
MOVEI T3,XC.ERR!XC.DUN;ERROR AND DONE BIT MASK
MOVEI T2,^D16000 ;A SMALL NUMBER OF CLOCK TICKS
XCT XTCCNI##(W) ;READ DA28 [COMMAND] STATUS
TDNN T1,T3 ;IF ERROR OR DONE THEN FINISHED
SOJG T2,.-2 ;ELSE LOOP A [SHORT] WHILE
TRNE T1,XC.ERR ;TERMINATE DUE TO ERROR?
JRST XTINL4 ;YES, ABORT THIS UNIT
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
;READ SMALL COMPUTER RESPONSE IF HE'S QUICK ENOUGH
MOVEI T1,XC.ERR ;TURN OFF CONNECT BIT
XCT XTCCNO##(W) ;SO SMALL COMPUTER GETS EOT
MOVN T3,XUBUNO(U) ;GET UNIT NUMBER
HRLI T3,(1B0) ;UNIT SELECT BIT
LSH T3,(T3) ;POSITION FOR THIS UNIT
ANDCMI T3,-1 ;CLEAR EXTRANEOUS JUNK
MOVEI T2,^D16000 ;A SMALL NUMBER OF CLOCK TICKS
XCT XTSCNI##(W) ;READ DA28 STATUS
TDNN T1,T3 ;OUR UNIT RESPONDED?
SOJG T2,.-2 ;NOT YET
JUMPLE T2,XTINL4 ;NO, HE'LL JUST HAVE TO WAIT A WHILE
MOVEI T1,XC.FST!XC.CON!XC.BSY!DM.BIN
XCT XTCCNO##(W) ;PREPARE TO READ RESPONSE
XCT XTSDTI##(W) ;READ SMALL COMPUTER RESPONSE
MOVEM T1,XUBRCW(U) ;SAVE IT
XCT XTCCNI##(W) ;READ DA28 [COMMAND] STATUS
TRNN T1,XC.ERR ;IF ERROR THEN ABORT
TRNN T1,XC.EOT ;IF NOT EOT THEN ABORT
JRST XTINL4 ;ERROR OR NOT-EOT (I.E., DATA)
LDB T1,XUYMFC ;GET MAJOR FUNCTION RECEIVED
CAIE T1,FN.RST ;A RESTART?
JRST XTINL4 ;NO, ABORT
LDB T1,XUYFSC ;GET SUB-FUNCTION
CAIL T1,SF.6BP ;IN RANGE OF
CAILE T1,SF.2BP ;SMALL-COMPUTER RESTART?
JRST XTINL4 ;NO, TOSS OUT COMMAND
SETOM XUBRDY(U) ;YES, FLAG UNIT READY TO GO
XTINL4: MOVEI T1,XS.CLR ;CLEAR ALL BIT
XCT XTSCNO##(W) ;RELEASE DA28 AND REMOTE SMALL COMPUTER
> ;END IFE FTFRC
AOJA P1,XTINL2 ;POINT TO NEXT UDB
;ALL UNITS INITIALIZED AS APPROPRIATE, PUT DA28 CONTROLLER ONLINE
XTINL7: PUSHJ P,CLRERR ;START WORLD
HRRZ W,XKBKDB##(W) ;GO TO NEXT KDB
JUMPN W,XTINL1 ;LOOP BACK UNLESS DONE
POPJ P,0 ;RETURN
$INIT
;ROUTINE TO CREATE ALL UDBS (CALLED BY LINKDB)
XTCLNK::PUSHJ P,SAVE2## ;SAVE P1 AND P2
MOVEI W,XKB0## ;GET LOC OF FIRST KDB
XTCLN1: MOVEI T1,1B33 ;WANT TO READ
XCT XTCCNO##(W) ; DA28 FEATURE REG
XCT XTSDTI##(W) ;READ FEATURES
JUMPE T1,XTCLN4 ;NOT THERE
ANDI T1,17 ;WANT ONLY NUMBER OF UNITS
MOVE P1,T1 ;SAVE UNITS
MOVEI P2,XKBUDB##(W) ;GET ADDRESS OF UDB TABLE
XTCLN2: MOVEI T1,XUBSIZ ;SIZE OF UDB
PUSHJ P,INICOR## ;ALLOCATE CORE
MOVEM T2,0(P2) ;SAVE UDB ADDRESS
MOVEM W,XUBKDB(T2) ;LINK UDB TO KDB
MOVE T3,P2 ;GET UDB STORAGE POINTER
SUBI T3,XKBUDB(W) ;CALCULATE UNIT NUMBER
MOVEM T3,XUBUNO(T2) ;STORE IN XUB
ADDI T3,2120 ;CONVERT TO SIXBIT
TRZN T3,10
LSH T3,6
LSH T3,6 ;POSITION IN WORD
MOVEM T3,XUBNAM(T2) ;MOVE INTO UNIT NAME
MOVE T3,XKBNAM(W) ;PICK UP KNOTROLLER NAME
HLLM T3,XUBNAM(T2) ;FILL IN REST OF UNIT NAME
XTCLN3: AOS P2 ;BUMP UDB TABLE POINTER
SOJGE P1,XTCLN2 ;LOOP IF MORE UNITS
XTCLN4: HRRZ W,XKBKDB##(W) ;NO, GET ADDR OF NEXT KDB
JUMPN W,XTCLN1 ;LOOP IF IT IS THERE
POPJ P, ;RETURN
$HIGH
PLM
;+
;.lm 0
;.hl 1 Initialization code
;^^
; There are two pieces of initialization code for the DA28 software: XTCINI
;and XTCLNK, both in XTCSER.
;The routine LINKSR in ONCE calls LINKDB in COMMON to build the
;DDBs XTCLNK is called by LINKDB to loop through all the KDBs and building
;UDBs for all the units (taken from section zero free core) that could
;conceivably exist (as determined by the scan limit setting on the DA28C).
; XTCINI is called later during SYSINI via the initialization dispatch entry
;to clean up the XTCSER data base for a given controller and also to attempt
;to send a "restart -10" control word to all small
;computer interfaces. If a small computer is up and answers quickly, XTCINI
;sets XUBRDY to -1 so that the first I/O attempt does not have to wait for the
;restart.
;-
MLP
SUBTTL INPUT UUO -- DUMP MODE
;HERE FROM UUOCON WITH ALL THE AC'S SET UP .
XTCDIN: NULL
PUSHJ P,INSET ;SETUP
POPJ P, ;ERROR - IMPROPER MODE
PUSHJ P,DMPSET ;GET DUMP MODE DATA
PJRST ADRERR## ;OOPS SOMETHING IS WRONG
PJRST INPCOM ;EXECUTE COMMON CODE
SUBTTL INPUT UUO -- BUFFERED MODE
;HERE FROM UUOCON WHEN THE USER DOES AN INPUT UUO
;ACS CONTAIN:
; S - DEVICE STATUS
; P - PUSH DOWN POINTER TO JOB DATA AREA
; J - JOB NUMBER
; R - ADDRESS OF JOBDAT
; F - XTC DDB
; P1 - CHANNEL NUMBER
; P4 - ADDRESS OF CPU DATA BLOCK
XTCIN: NULL
PUSHJ P,INSET ;SET UP ALL GOOD THINGS
POPJ P, ;ERROR - IMPROPER MODE
HRRZ T1,DEVIAD(F) ;GET INPUT BUFFER ADDRESS
PUSHJ P,BUFCLR## ;GO CLEAR IT
PJRST ADRERR## ;ADDRESS CHECK
MOVE T2,DEVIAD(F) ;POINT TO BUFFER HEADER
EXCTUX <LDB T3,[POINT 17,0(T2),17]> ;GET THE BUFFER SIZE
SUBI T3,1 ;SUBTRACT OVERHEAD
HRRM T3,DVXBSZ(F) ;REMEMBER THE SIZE
;****FALL INTO COMMON INPUT CODE
;CODE SHARED BY DUMP AND BUFFERED MODES
INPCOM: NULL
AOS CNTINP ;COUNT THE INPUTS
TRNE S,IO.BYP ;CHECK BYPASSING
JRST [HRRZM T3,DVXWFO(F) ;SAVE W.C.
JRST XTCIN1]
PUSHJ P,XISYNC ;GET IN SYNC
PJRST XFRRST ;ERROR
HRRZ T3,DVXWFO(F) ;GET HIS BUFFER SIZE
CAILE T3,@DVXBSZ(F) ;COMPARE AGAINST OURS
PJRST XTCBTL ;BLOCK IS TOO LARGE
HRRM T3,DVXBSZ(F) ;REMEMBER FOR WFI
XTCIN0: PUSHJ P,CHKMOD ;CHECK DATA MODE
PJRST XTCIPM ;IMPROPER MODE
XTCIN1: NULL
PUSHJ P,IFDMP ;SEE IF DUMP MODE
SKIPA T1,DEVIAD(F) ;BUFFERED MODE
PJRST XMTWFI ;THEN ALL SET
HRRZ T2,DVXWFO(F) ;PICK UP WORD COUNT
EXCTXU <MOVEM T2,1(T1)> ; STORE IN BUFFER
PUSHJ P,SETIOW ;SET UP IOWD LOGIC
XMTWFI: NULL
POP P,T1 ;REMOVE RETURN TO ZAPACT CODE
PUSHJ P,MAKACT ;ACTIVATE DEVICE
PUSHJ P,MAKWFI ;MAKE WFI WORD
IFE FTCMP0,<
PUSHJ P,ADDSIZ ;ADD SIZE TO IT
> ;IFE FTCMP0
PJRST SENDW ;SEND AND DO NOT WAIT
;AND RETURN VIA ZAPACT
;SUBROUTINE TO ESTABLISH INPUT SYNC WITH THE EXTERNAL TASK
;CALL WITH:
; PUSHJ P,XISYNC
; RETURN HERE IF I/O ERROR
; RETURN HERE IF OK TO SEND WFI
;THIS ROUTINE STARTS AT UUO LEVEL AND IS SHARED WITH
;INTERRUPT LEVEL
;
XISYNC: COROUT <IOEND!IORWFI!IORWFO,,RHSTOP> ;START OF COROUTINE
XISYN0: NULL
MOVE S,DEVIOS(F) ;GET DEVICE STATUS
TDNE S,[IOEND,,RHSTOP] ;GET EXIT CONDITIONS
$CPOPJ ;EXIT TO CALLER AT UUO LEVEL
MOVE T1,DVXPST(F) ;GET THE PROTOCOL STATUS
TLNE T1,IORWFO ;IS SMALL COMPUTER
$POPJ1 ;DO THE RIGHT THING!
TLNE T1,IOXRFI ;DID WE SEND AN RFI?
JRST XISYN1 ;YES--DO NOT SEND ANOTHER
PUSHJ P,MAKRFI ;MAKE RFI WORD
IFE FTCMP0,< ;ADDING THE COUNT
PUSHJ P,ADDSIZ ;ADD SIZE TO WORD
> ;IF ZERO
PUSHJ P,SENDW ;SEND (OR TRY) AND DO NOT WAIT
XISYN1: NULL
MOVE S,DEVIOS(F) ;IT MAY HAVE CHANGED
TDNE S,[IOEND,,RHSTOP] ;AT THE END
$CPOPJ ;EXIT TO CALLER AT UUO LEVEL
MOVE T1,DVXPST(F) ;GET STATUS AGAIN
TLNE T1,IORWFI ;IS SMALL COMPUTER WAITING FOR
JRST [MOVEI S,IOIMPM ;YES--LIGHT IO.IMP
IORB S,DEVIOS(F)
SEND OPE
$CPOPJ] ;AND GO BACK
;CATCH UP WITH THE LATEST EVENTS OR SYNCHRONIZE
$SYNC <IOEND!IORWFI!IORWFO,,RHSTOP> ;GET IN SYNC WITH REMOTE
JRST XISYN0 ;SEE IF IT CAME
PLM
;+
;.lm 0
;.hl 1 Input/Output Routines
;^^
;.subtitle Input and Output Routines
; The main use of XTCSER is to transfer data between processes in two computers using the normal
;IN(PUT) and OUT(PUT) monitor calls. This section of the code contains
;support for dump and buffered mode input, dump and buffered mode output, CLOSE and RELEAS UUO's.
;Because of the basic similarities both between dump and buffered
;mode I/O and between input and output, a good deal of code is common
;to all the variations of I/O calls.
; The basic flow of both IN and OUT UUO processing is as follows:
;.list
;.le;Set up for the proper type of I/O (dump or buffered) and go
;to a common routine to actually do it.
;.le;xxxCOM -- if IO.BYP set to bypass protocol exchange (for example
;in a bootstrap program) skip over the next step.
;.le;call a subroutine XdSYNC (where "d" is I for input and O for output) to get in synchronization with the
;small computer. This routine uses the co-routine mechanism (described below)
;to start the protocol word exchange at UUO level, continue it (if
;necessary) at interrupt level and finally return to UUO level (giving
;a success or failure indication) when finished. If the attempt failed,
;simply give error return to UUOCON on IN or OUT call.
;.le;Once we are in sync with the small computer (i.e. we both
;agree on the direction of data transfer) start the data transfer.
;This is slightly different depending upon whether we are doing input
;or output. For input, the synchronization phase ends when we have
;received a WFO, and therefore this step sends the WFI and
;sets things up so that the next remote interrupt (REMINT) starts the incoming data transfer.
;For output, the synchronization phase ends when we have received an
;RFI and therefore this step sends the WFO. When we receive the WFI
;we will start the outgoing data transfer.
;.end list
;.lm 0
;.hl 2 Co-routine Mechanism
;^^
; The so-called co-routine mechanism allows the UUO to begin at
;UUO level, to wait there for the occurrence of various events,
;to continue processing at interrupt level after these
;events and, when all has been completed, to return to UUO level.
;It does this by starting the "co-routine" code with a call to
;$COROU which removes the return PC of the caller of the co-routine
;from the stack and stores it in the DVXPRC word of the
;DDB. To wait for some particular events to occur the XISYNC or
;XOSYNC routine issues a $SYNC macro, which calls the SYNC$ routine with
;a mask of bits to be wakened on. If any of the
;bits are on, the SYNC$ routine merely returns (so that the XISYNC or
;XOSYNC routine can continue either by sending more protocol words or
;by exiting). If no bits are on, if it is called at UUO level
;it POPs the return address into DVXCOR (which both flags that a co-routine is running and remembers where to continue the
;co-routine) and calls DOZE0 to HIBER; if it is called
;at interrupt level it merely POPs the return PC (of the SYNC$ call) into
;DVXCOR and returns (to the return PC of the call to CHKPRC).
; To exit, the co-routine executes one of two macros, $CPOPJ and $POPJ1 (which call CPOPJ$ and CPOPJ1$
;respectively). These adjust the return PC in DVXPRC as required (either
;by doing nothing or incrementing it by one, respectively) and then test if
;they are at interrupt or UUO level. If at UUO level, they simply
;jump to the address contained in DVXPRC to return to the
;co-routine caller. If at interrupt level, they merely do a wakejob
;call, which will wake UUO level (which is in the HIBER resulting from
;the first $SYNC done at UUO level).
; An example will make this clearer; both co-routines have the format:
;.list;.le;XdSYNC: -- call $COROUT to store the XdSYNC caller's return PC in DVXPRC
;.le;various tests for completion. The error completions use $CPOPJ
;and the successful completions use $POPJ1 to exit the co-routine.
;.le;$SYNC with mask bits for events of interest (i.e. error bits and
;bits corresponding to the arrival of control words we are waiting for).
;.le;A jump back to step 2.
;.end list
;In the case of the input sync routine (XISYNC) the
;tests are:
;.list
;.le;If there are any error or EOF bits exit via $CPOPJ.
;.le;If we have received a WFO exit via $POPJ1.
;.le;If we have not sent an RFI, call MAKRFI to make it and SENDW to start sending it.
;.le;If we have received WFI (i.e. we are both trying to input) set
;IOIMPM error bit and exit via $CPOPJ.
;.end list
; We are now ready to describe a possible sequence of events during
;an input UUO.
;.list
;.le;The IN UUO processing starts at UUO level and does a PUSHJ#P,XISYNC
;at INPCOM+n.
;.le;XISYNC routine calls $COROU, which stores the XISYNC caller's
;return PC (namely INPCOM+n+1) in DVXPRC and then returns to XISYNC.
;.le;XISYNC performs its tests, finds no errors and decides it
;needs to send an RFI. The call to MAKRFI builds the
;control word, and the call to SENDW either starts it out if the DA28C
;was idle, or queues it to be started (whenever the DA28C completes
;whatever it is doing) if the DA28C was not free.
;.le;XISYNC does a $SYNC which puts the bits upon which the co-routine
;should awaken into DVXMSK. Since this call is at UUO level and none of the
;desired bits are on, SYNC$ will call DOZE0 which will HIBER the job.
;It will also POP the return address (i.e. that of the instruction
;after the $SYNC macro in XISYNC) into DVXCOR.
;.le;At some later time a done interrupt comes in which signals the
;end of transmission of the RFI. This sets the bit IOXRFI. The
;interrupt routine then calls CHKPRC which notices that DVXCOR is
;non-zero (i.e.#a co-routine is running) and sees if any bits in
;the co-routine mask (DVXMSK) are on. None are, because IOXRFI is
;not among the bits tested.
;.le;Even later the remote processor wants to do output. This
;causes first a remote interrupt at the 10, which merely sets up
;to read the control word, and then later a done interrupt when
;the read of the control word is finished. It is a WFO, and sets IORWFO.
;This time the CHKPRC call finds that a bit included in DVXMSK is set and therefore
;jumps to the address in DVXCOR, i.e. to right after the $SYNC
;macro. This is a jump back to try the synchronization tests over again.
;.le;We now execute the co-routine test loop again, but this time at
;interrupt level. Because IORWFO is set and there are no
;error bits, we do a $POPJ1 which increments DVXPRC by one, clears DVXCOR
;to indicate that the co-routine has exited, sees that we are at
;interrupt level and therefore calls XTWAKE and returns (to the caller
;of CHKPRC) to dismiss the interrupt.
;.le;When the scheduler gets around to scheduling our job again, we find
;ourselves after the HIBER call in SYNC$. The code here notices
;that DVXCOR is zero (i.e. the co-routine is finished) and
;so jumps to the address in DVXPRC (now INPCOM+n+2) which continues
;the input UUO by beginning the sending of the WFI and then returning
;to UUOCON.
;(It can do this because we have started the input. UUOCON will
;put the job in I/O wait if necessary.)
;.end list
;Note that if the WFO control word had been received from
;the small computer before the -10 issued the IN UUO, the entire
;XISYNC routine would have only been executed once and only at
;UUO level.
;.hl 2 Input UUO
;^^
;.subtitle Input UUO
; The code to service IN or INPUT UUO's has two entries:
;XTCDIN for dump mode and XTCIN for buffered mode. They
;merely set up some things a little bit differently, then merge at INPCOM (common input code).
;The reason for this is that XTCSER builds its own IOWD list for data
;transfers in the DDB; dump mode simply copies the user IOWD's
;into the DDB and buffered mode simply constructs an IOWD to describe
;the buffer. After that, all other operations that XTCSER
;needs to perform are identical.
; The major requirement for input is that the proper protocol words
;be exchanged with the small computer. INPCOM calls XISYNC to ensure
;this. XISYNC is one of two examples (the other is XOSYNC) of the
;co-routine mechanism described above. XISYNC will return to the
;success return (skip) if a WFO has been seen and no conflicts exist.
;It will give the error word if it receives a WFI (indicating that
;both sides are trying to do input) or if any error or EOF bits are
;set in DEVIOS (for example by reject or restart or EOF control words).
;.hl 3 Detailed Logic
;^^
;The following is the detailed logic of the input code:
;.list
;.le;XTCDIN: -- call INSET to do input setup. This routine:
;.list;.le;sets the IO bit in DEVIOS to 0 to indicate input
;.le;sets FRSTIN bit in DEVIOS (used as a flag if we
;have to copy data in image-binary mode)
;.le;then skips into the common part of OUTSET.
;.end list
;The routine OUTSET:
;.list
;.le;set the IO bit to one for output (this is skipped when
;INSET skips into this routine)
;.le;sets up F, U, W, S, J and R by calling SETACS
;.le;calls GETMOD to get (from DVXMOD) the hardware mode that
;corresponds to the software mode in DEVIOS and to store it
;in DVXBSZ.
;.le;checks if user has privileges if IO.BYP was set and
;if not, goes to SETIPM to give IOIMPM error.
;.le;if not bypassing, calls RDYCHK to wait until we know that
;the small computer is up (by the fact that it sent
;a restart).
;.le;PSACT: -- falls into the code that makes
;the job I/O active but not really for data transfer (yet).
;It stores ACTTIM in DVXPAC so that we can time out this
;"pseudo-active" state. If the transfer doesn't happen soon, we
;are taken out of IOACT state; just before the transfer takes
;place we are made active again.
;This routine also places a call to ZAPACT (which
;clears I/O active and all protocol status) on the stack
;so that in error cases this will do the clean up for us. When
;we get ready to do the real data transfer this is cleaned up.
;.end list
;.le;XTDIN then calls DMPSET which copies the user IOWDs into
;the .IOLEN words starting at DVXIWD in the DDB. If there are
;more IOWDs than will fit, DVXIWA will have a non-zero value and
;DVXLLM and DVXULM will have values so we can call COMCHK and NXTCMR
;at interrupt level when we have finished as much as we have got.
;DMPSET also calculates the transfer size and stores it in DVXBSZ.
;XTCDIN then branches to INPCOM.
;.le;XTCIN: -- this is the buffered mode entry. It also calls INSET
;(see above) to set things up for input, then gets the address of the
;buffer from DEVIAD and calls BUFCLR (in UUOCON) to clear it.
;From the buffer header in the user address space it extracts the
;size in words, and stores it in DVXBSZ. Then it falls into INPCOM.
;.le;INPCOM: -- common input code. This increments the number
;of inputs done (CNTINP) and if not bypassing the protocol calls
;the input co-routine XISYNC to get in synchronization with the small computer (see below).
;If the result is an error, it jumps to XFRRST which clears the protocol
;status and returns (using the ZAPACT call on the stack to clear
;everything out).
;INPCOM then compares the size the small computer wants to send with
;the size of the buffer we have, and if the former is too large gives
;a "block to large" (IOBKTL) error.
;It then calls CKHMOD to compare the mode requested and desired, and gives
;the improper mode error (IOIMPM) if they do not match.
;If it is dump mode, it goes to XMTWFI; else it gets the word count
;the small computer will send, stores that in the user's
;buffer header, then calls SETIOW to generate the IOWD cells in the
;DDB to describe the buffer and falls into XMTWFI.
;.le;XMTWFI: -- the first thing this routine does is pop the ZAPACT call off the stack. Then it calls MAKACT to ensure that the job is really
;I/O active now, calls MAKWFI to build the WFI control word, calls
;SENDW to start it out (or queue it) and returns to UUOCON, the input started.
;.end list
; The only remaining piece of code to decribe for the INPUT UUO is
;XISYNC:
;.list
;.le;XISYNC: -- call $COROUT to put co-routine return in DVXPRC and
;event bits into DVXMSK.
;Then fall into the checking loop, XISYN0.
;.le;XISYN0: -- this routine consists of a series of tests.
;They are:
;.list;.le;test for EOF or error bits in DEVIOS and if
;any are present, exit co-routine via call to $CPOPJ.
;.le;Test DVXPST for bit saying we have received a WFO (IORWFO) and if
;it is set, take success exit from co-routine via $POPJ1.
;.le;Test if we have sent RFI yet (IOXRFI) and if not, call MAKRFI
;to make it, ADDSIZ to add the data transfer size to it and SENDW
;to send it.
;.le;XISYN1: -- test again for error or EOF bits in DEVIOS and
;exit co-routine $CPOPJ if any are on.
;.le;test if we have received a WFI control word and if so, send
;a "reject operation" control word back to the small computer and
;exit co-routine $CPOPJ after setting IOIMPM to give an error to the user.
;.end list
;.le;XISYNC then calls $SYNC to wait for some significant event (errors, EOF, receipt of WFO or WFI). This will
;cause UUO level to go to sleep until the co-routine eventually exits.
;Whenever one of the specified events occurs, interrupt level
;will execute the co-routine code beginning immediately after the $SYNC
;call.
;.le;after the $SYNC call, the co-routine merely jumps back to XISYN0 to try
;all the tests again.
;.end list
;-
MLP
SUBTTL OUTPUT UUO -- DUMP MODE
XTCDOU: NULL
PUSHJ P,OUTSET ;SETUP OUTPUT
POPJ P, ;ERROR - IMPROPER MODE
PUSHJ P,DMPSET ;GET DUMP MODE DATA
PJRST ADRERR## ;ADDRESS ERROR
PJRST OUTCOM ;GO TO COMMON OUT CODE
SUBTTL OUTPUT UUO -- BUFFERED MODE
XTCOUT: NULL
PUSHJ P,OUTSET ;SET UP GOOD STUFF
POPJ P, ;ERROR - IMPROPER MODE
XTCOUA: NULL
MOVE T1,DEVOAD(F) ;POINT TO BUFFER
EXCTUX <HRRZ T1,1(T1)> ;PICK UP WORD COUNT
HRRM T1,DVXBSZ(F) ;STORE NUMBER OF WORDS
JUMPN T1,OUTCO0 ;GO TO COMMN CODE
PUSHJ P,ADVBFE## ;SEE IF THERE ARE OTHER ONES?
POPJ P, ;NONE
PJRST XTCOUA ;TRY IT AGAIN
OUTCO0: NULL
PUSHJ P,SETIOW ;SET UP THE BUFFER LOGIC
;*****FALL INTO OUTCOM CODE
;START OF COMMON OUTPUT CODE
OUTCOM: NULL
AOS CNTOUT ;COUNT THE OUTPUTS
HRRZ T1,DVXBSZ(F) ;GET THE WC
CAILE T1,7777 ;FIELD LIMITATION
PJRST XBTLRG ;BLOCK IS TOO BIG
TRNE S,IO.BYP ;BYPASS?
JRST XTCOU1 ;YES -- SKIP OVER SYNC
PUSHJ P,XOSYNC ;GET IN SYNC
PJRST XFRRST ;ERROR
XTCOU0: NULL
MOVE T1,DVXPST(F) ;CURRENT STATUS
TLNN T1,IORRFI ;SEEN A RFI
JRST XTCOU1 ;APPARENTLY NO NEED FOR IT
HRRZ T1,DVXRFI(F) ;GET THE COUNT
CAIGE T1,@DVXBSZ(F) ;IF WE DO NOT AGREE THEN
PJRST XTCBTL ;SEN A BLOK TO LARGE MESSAGE
XTCOU1: NULL
POP P,T1 ;GET RID OF ZAPACT RETURN
PUSHJ P,MAKACT ;YOU BETTER GET ACTIVE
TRNN S,IO.BYP ;BYPASSING ALL?
JRST XTCOU2 ;NO USE A WFO
PUSHJ P,D28GET ;GET THE DA28 CONTROL
PUSHJ P,D28WTF ;WAIT FOR A DDB PROCES
JRST DDBIO0 ;ADDRESSABLE AND S OKAY
XTCOU2: NULL
PUSHJ P,MAKWFO ;MAKE A WFO
PUSHJ P,ADDSIZ ;ADD THE SIZE TO IT
PJRST SENDW ;AND THROW IT OUT
;AND RETURN VIA ZAPACT
;SUBROUTINE TO GET INTO OUTPUT SYNC
;CALL WITH:
; PUSHJ P,XOSYNC
; RETURN HERE IF IO ERROR
; RETURN HERE IF OK TO START OUTPUT
;
XOSYNC: NULL
COROUT <IORWFI!IORWFO!IORRFI!IOXWFO,,RHERR> ;EVENTS
MOVE T1,DVXPST(F) ;GET THE PROTOCOL STATUS
TLNE T1,IORWFI ;IS HE WAITING FOR US?
$POPJ1 ;(YES) SEND THE DATA
TLNE T1,IOXRFO ;DID WE SEND AN RFO
JRST XOSYN1 ;(YES) ONCE IS ENOUGH
PUSHJ P,MAKRFO ;MAKE THE RFO
IFE FTCMP0,< ;ADD THE NEGATIVE COUNT
PUSHJ P,ADDSIZ ;ADD THE SIZE TO IT
> ;IF ZERO
PUSHJ P,SENDW ;AND OUT YOU GO
XOSYN1: NULL
MOVE T1,DVXPST(F) ;IT CAN HAVE CHANGED
TLNE T1,IORWFO ;DID WE GET A WFO
JRST [MOVEI S,IOIMPM ;YES--FATAL ERROR
IORB S,DEVIOS(F)
SEND OPE ;INFORM EP
$CPOPJ ]
TLNE T1,IORWFI!IORRFI ;DID HE START TO WAIT
$POPJ1 ;YES SEND WFO IF POSSIBLE
$SYNC <IORWFI!IORWFO!IORRFI,,RHERR> ;SEE YOU LATER
MOVE S,DEVIOS(F) ;GET S
TRNN S,RHERR ;ANY ERRORS?
JRST XOSYN1 ;NO--KEEP WAITING
$CPOPJ ;ERROR RETURN
PLM
;+
;.lm 0
;.hl 2 Output UUO Processing
;^^
;.subtitle Output UUO
; The output UUO code is very similar to the input UUO code. The
;following is a detailed description:
;.list
;.le;XTCDOU: -- dump mode entry, calls OUTSET (see above) to
;set up everything and then DMPSET to copy the user IOWD's
;to the DDB and save the transfer size in DVXBSZ. Then jumps to OUTCOM.
;.le;XTCOUT: -- buffered mode entry calls OUTSET as well.
;.le;XTCOUA: -- then it gets the address of the user buffer from DEVOAD
;followed by the size of the data transfer, which it stores in
;DVXBSZ. If the size is zero, it calls ADVBFE in
;UUOCON to let the latter know this buffer is finished and if UUOCON
;indicates (by the skip return) that there is another, goes back to
;XTCOUA to examine that one. If the ADVBFE call produces no
;more buffers, it just ends the OUTPUT by returning to UUOCON.
;If the buffer did have data, it falls into XTCOU0.
;.le;XTCOU0: -- calls SETIOW to set up the IOWD parts
;of the DDB to describe the buffer then falls into OUTCOM.
;.le;OUTCOM: -- start of code common to dump and buffered mode.
;Increments the number of OUTPUTs we have done (CNTOUT), gets the data
;transfer size and compares it to 7777(8). If it is greater, jumps
;to XBTLRG to set block too large error bit in DEVIOS (IOBKTL) and to
;call SETIOD to let UUOCON know we are finished.
;If the size of the transfer is within range, OUTCOM tests if IO.BYP
;is set; if not, it calls XOSYNC to synchronize protocol word exchange
;with the small computer (see below).
;If this co-routine returns an error (non-skip) OUTCOM transfers control
;to XFRRST which clears protocol status and returns via ZAPACT to
;finish the UUO.
;.le;XTCOU0: -- tests if we have seen an RFI control word and
;if not goes to XTCOU1. Otherwise, compares the size in the RFI to the
;user's size, and set IOBKTL and calls SETIOD if our output won't fit.
;.le;XTCOU1: -- this first gets rid of the ZAPACT call on the top
;of the stack, then calls MAKACT to ensure that the job is I/O active, then test IO.BYP. If it is not set, jumps to XTCOU2 to
;send a WFO. Otherwise it calls D28GET to see if DA28 is free.
;If so (skip return) it goes directly to DDBIO to start
;data transfer, otherwise it calls D28WTF to wait
;till hardware is finished and then go to DDBIO at interrupt level.
;.le;XTCOU2: -- here to do normal output I/O. The code calls
;MAKWFO to build the WFO control word, ADDSIZ to put the transfer
;size into it, and SENDW to send it or queue it, and then returns
;to UUOCON with the OUTPUT completed.
;.end list
; The co-routine for
;output is again very similar to that for input. Here it is:
;.list
;.le;XOSYNC: -- call $COROUT to set up coroutine stuff.
;Then test if we have already received WFI; if so exit coroutine with success return.
;.le;Test if we have sent RFO, and if not call
;MAKRFO, ADDSIZ and SENDW to do so.
;.le;XOSYN1: -- testing loop for output co-routine. This is the
;part of the coroutine that can be executed either at UUO level (the
;first time) or at interrupt level.
;Performs these tests:
;.list
;.le;If we have received a WFO (i.e. both are trying to output)
;set IOIMPM, send a "reject operation" control word to the small
;computer and exit co-routine with error ($CPOPJ).
;.le;If we have received either WFI or RFI, exit co-routine with
;success return ($POPJ1).
;.end list
;XOSYNC then calls $SYNC to wait for any of 1) receipt of WFI,
;2) receipt of RFI, 3) receipt of WFO or any error bits.
;When $SYNC returns it tests if the
;wake-up reason was an error bit and if so exits the co-routine
;$CPOPJ. Otherwise it goes back to XOSYN1 to repeat its
;tests.
;.end list
;-
MLP
SUBTTL I/O UUO SUBROUTINES -- INSET, OUTSET, PSACT, MAKACT
;ROUTINES TO SETUP FOR INPUT/OUTPUT AND TO
;WAIT FOR DA28 TO BE FREE
INSET: NULL
MOVSI S,IO ;SET FOR INPUT
ANDCAB S,DEVIOS(F) ;...
MOVSI S,FRSTIN ;USED BY BINARY I/O
SKIPA ;GO AND SET BIT
OUTSET: NULL
MOVSI S,IO ;SET FOR OUTPUT
IORB S,DEVIOS(F) ;...
PUSHJ P,SETACS ;SET UP THE ACCS
TDNE S,[ IOEND,,RHSTOP] ;ERROR FLAGS
POPJ P,
PUSHJ P,GETMOD ;SET UP MODE BYTES
TRNE S,IO.BYP ;IF SPECIAL - CHECK PRIVS
PUSHJ P,PRVJ## ;...
AOSA 0(P) ;ALL SO FAR OKAY
JRST SETIPM ;ERROR - GIVE IPM RETURN
TRNN S,IO.BYP ;NEED TO SKIP RDYCHK
PUSHJ P,RDYCHK ;CHECK EP UP
;PSACT MAKE DEVICE PSEUDO ACTIVE
PSACT: NULL
MOVEI T1,ZAPACT ;CLEAR ACTIVITY CODE
EXCH T1,(P) ;AND GET RETURN ADDRESS
PUSH P,T1 ;AND STORE ADDRESS OF CALLER
HRROI T1,ACTTIM ;GET PSEUDO HUNG TIME
MOVEM T1,DVXPAC(F) ;SET THE COUNT
AOS XKBPAC##(W) ;FLAG THAT CONTROL HAS PSEUDO ACTIVE ONE
AOS XUBPAC(U) ;AND COUNT IN UNIT BLOCK
AOS PSMAKE ;ACCOUNT
CONO PI,PI.OFF ;NO INTERFERENCE
JRST MAKAC0 ;AND BECOME ACTIVE
;FALL INTO MAKACT CODE
;MAKACT MAKE A JOB UNDISTURBED IO ACTIVE
MAKACT: NULL ;SUBROUTINE TO MAKE JOB I/O ACTIVE
CONO PI,PI.OFF ;SILENCE
SKIPN DVXPAC(F) ;PSEUDO ACTIVE??
JRST MAKAC0 ;NOPE NORMAL STUUF
SETZM DVXPAC(F) ;REMOVE THE FLAG
SOSGE XUBPAC(U) ;ACCOUNT IN UDB
STOPCD .,DEBUG,TC5,
SOSGE XKBPAC##(W) ;AND IN KDB
STOPCD .,DEBUG,TC6,
SALL
MAKAC0: MOVE S,DEVIOS(F) ;THIS IS UNIQUE!!
TLZ S,IOBEG ;ONLY ONCE
PUSHJ P,SETACT## ;MAKE IT ACTIVE
JRST ONPOPJ## ;AND RETURN ACTIVE
SUBTTL I/O UUO SUBROUTINES -- IFDMP, XTCBTL, ZAPACT, XTCIPM, XFRRST, SETIPM
;IFDMP CPOPJ BUFFERED MODE CPOPJ1 DUMP MODE SAVES ALL ACCS
IFDMP: PUSH P,T1 ;GET SCRATCH
LDB T1,PIOMOD ;GET I/O MODE
CAIL T1,DR ;DUMP MODE
PJRST TPOPJ1## ;YAP SKIP
PJRST TPOPJ## ;NO NORMAL
;ROUTINE TO RETURN BLOCK-TOO-LARGE ERROR TO USER
XTCBTL: NULL
PUSHJ P,MAKBTL ;BLOCK TOO LARGE TO SWALLOW
PUSHJ P,SENDW ;MAKE SURE IT GETS THERE
XBTLRG: NULL
MOVEI S,IOBKTL ;LITE A BIT
XTCRTE: NULL
IORB S,DEVIOS(F)
PJRST SETIOD## ;EXIT AFTER SETTING DONE
;ANY CALLER TO OFF PSACT WILL COME HERE BEFORE RETURNING TO
;THE CALLER, THIS ALLOWS ACCOUNTING OF PAC JOBS
ZAPACT: NULL
CONO PI,PI.OFF ;NO INTERRUPTS!
SKIPN DVXPAC(F) ;PSEUDO ACTIVE
JRST ZAPAC0 ;NOPE
SETZM DVXPAC(F) ;NO LONGER
SOSGE XUBPAC(U) ;ACCOUNT
STOPCD .,DEBUG,TC3,
SOSGE XKBPAC##(W) ;IN UDB AND XKB
STOPCD .,DEBUG,TC4,
SALL
ZAPAC0: MOVE S,DEVIOS(F) ;GET I/O STATUS
PUSHJ P,CLRACT## ;AND QUIETLY UPDATE S
SETZM DVXPST(F) ;NO HERITAGE
JRST ONPOPJ## ;ALL IS SAFE AGAIN
;ROUTINE TO SET IMPROPER MODE
XTCIPM: NULL
PUSHJ P,MAKIDM ;IMPROPER DATA MODE
PUSHJ P,SENDW ;SEND IT AND WAIT
MOVEI S,IOIMPM ;LITE A BIT
JRST XTCRTE ;AND RETURN ERROR
;ROUTINE TO RESET INFO REGARDING THIS XFER ON AN I/O ERROR
XFRRST: NULL
SETZM DVXPST(F) ;ZAP THE PROTOCOL STATUS
POPJ P, ;RETURN TO UUOCON
SETIPM: NULL
MOVEI S,IOIMPM ;SET SPECIAL BIT
IORB S,DEVIOS(F)
POPJ P, ;ERROR RETURN
SUBTTL I/O UUO SUBROUTINES -- DMPSET, SETIOW, NXTIOW
;SUBROUTINE TO COMPUTE THE NUMBER OF WORDS IN A DUMP MODE
; COMMAND LIST. AND TO BUILD IOWD LIST
;CALLED ON 2 LEVELS: UUO OR INT LEVEL
;ON INTERRUPT LEVEL DO NOT CALL COMCHK , AS T2, T3 AND M ARE SET UP
;FOR NXCMR CALL
;CALLED WITH:
; MOVEI M,ADDRESS-OF-LIST (UVA)
; PUSHJ P,LSTSIZ
; RETURN HERE IF THERE IS AN ERROR
; RETURN HERE ANSWER IN T1
DMPSET: NULL
PUSHJ P,SAVE2## ;SAVE P1
SETZM P1 ;NO WORDS YET
MOVEI P2,DVXIWD(F) ;START ADDRESS OF LIST
MOVEM P2,DVXCUR(F) ;REMEMBER THE START
SETZM DVXIWA(F) ;AND ASSUME ALL IN LIST
CONSZ PI,PI.IPA ;AT INTERRUPT LEVEL
PUSHJ P,NXCMR## ;(YES) CONTINUE
CONSO PI,PI.IPA ;AT INTERRUPT LEVEL
PUSHJ P,COMCHK## ;(NO) LOOK AT FIRST IOWD
DMPSE0: JUMPE T1,DMPSE2 ;ALL IOWDS GOTTEN
JUMPN S,CPOPJ## ;A LOSER
;***NOTE ANY CHANGE TO THE NEXT INSTRUCTION SHOULD REFLECT ITSELF
;IN THE ADDI INSTRUCTION IN SETIOW
SUBI T1,-1(R) ;UNDO COMCHK ADDITION
;AND MAKE ADDRESS THE START ADDRESS
MOVEM T1,(P2) ;STORE THE IOWD
HLRE T1,T1 ;GET POSITIVE WC
MOVN T1,T1 ; ..
JUMPLE T1,CPOPJ## ;A LOSING IOWD
ADD P1,T1 ;ADD INTO TOTAL
CAIE P2,DVXILS(F) ;IS LIST FULL NOW?
JRST DMPSE1 ;MAYBE WILL SEE LATER
MOVEM M,DVXIWA(F) ;REMEMBER M
MOVEM T2,DVXULM(F) ;SAVE UPPER LIMIT
MOVEM T3,DVXLLM(F) ;SAVE LOWER LIMIT
JRST DMPSE2 ;ALL DONE NOW
DMPSE1: PUSHJ P,NXCMR## ;GET THE NEXT COMMAND
AOJA P2,DMPSE0 ;DO NEXT WORD
DMPSE2: CONSO PI,PI.IPA ;AT INTERRUPT LEVEL DON'T UPDATE
HRRM P1,DVXBSZ(F) ;REMEMBER THE TRANSFER SIZE
CAIGE P2,DVXILS(F) ;A TERMINATOR NEEDED
SETZM (P2) ;ZAP IT NIL
MOVE S,DEVIOS(F) ;RESTORE S IT WAS CLOBBERED
PJRST CPOPJ1##
COMMENT %
I/O IS DONE BY USING THE FOLLOWING MECHANISM:
STARTING AT LABEL DVXIWD IS AN IOWD WHIBH HAS TO BE USED
FOR THE FIRST TRANSFER. FOR OTHER TRANSFERS A LIST OF OTHER POINTERS
MAY FOLLOW TERMINATED EITHER BY A ZERO OR TERMINATING
AT LABEL DVXILS, IN WHICH CASE DVXIWA CONTAINS THE VALUE TO BE USED
ON NXCMR CALLS
%
;SETIOW CALLED BY BUFFERED I/O
SETIOW: NULL
TLNN S,IO ;DOING INPUT?
SKIPA T1,DEVIAD(F) ;GET UVA OF BUFFER
MOVE T1,DEVOAD(F) ;GET UVA OF OUTPUT BUFFER
;****ANY UPDATE TO THE FOLLOWING INSTRUCTION MUST KEEP IN MIND
;THAT AT DMPSE0+2 DUMPMODE IOWDS ARE UPDATED
ADDI T1,2 ;ONE MORE FOR ADDRESS
HRRZ T2,DVXBSZ(F) ;GET XFER SIZE
MOVNS T2 ;IN A NEGATIVE WAY
HRL T1,T2 ;MAKE THE IOWD
MOVEM T1,DVXIWD(F) ;STORE THE IOWD
SETZM DVXIWD+1(F) ;TERMINATE THE LIST
SETZM DVXIWA(F) ;INDICATE NO MORE THERE
MOVEI T2,DVXIWD(F) ;GET START ADDRESS
MOVEM T2,DVXCUR(F) ;AND REMEMBER THAT
POPJ P,
;NXTIOW GENERATE THE NEXT DA28 IOWD OR WARN THAT THE BUFFER IS EMPTY
;CPOPJ ALL I/O IS READY
;CPOPJ1 NEXT IOWD IS IN T1
NXTIOW: NULL
MOVE T1,DVXCUR(F) ;GET ADDRESS OF CURRENT IOWD REMAINDER
CAIE T1,DVXILS+1(F) ;IF AT THE END OF THE LIST
JRST NXTIO0 ;NO GET IOWD
SKIPN M,DVXIWA(F) ;GET OLD M BACK
POPJ P, ;ALL SET NOW
MOVE T2,DVXULM(F) ;GET THE UPPER LIMIT
MOVE T3,DVXLLM(F) ;GET THE LOWER LIMIT
PUSHJ P,DMPSET ;DO DUMB STUFF
PJRST NXTERR ;IOLIST GOT CLOBBERED
JRST NXTIOW ;RESTART THE CALL
NXTIO0: NULL
MOVE T1,@DVXCUR(F) ;GET CURRENT IOWD
JUMPGE T1,CPOPJ## ;ALL HAS BEEN DONE
PUSHJ P,SBINIO ;LEAVE IF BINARY I/O
PUSHJ P,MPIOWD ;MAP THE IOWD
MOVEM T2,@DVXCUR(F) ;UPDATE IOWD
JUMPL T2,CPOPJ1## ;ALL IS OKAY
AOS DVXCUR(F) ;POINT TO NEXT IOWD
PJRST CPOPJ1## ;ALL IS OJAY NOW
SUBTTL I/O UUO SUBROUTINES -- SBINIO
;SBINIO IS USED TO SPLIT BINARY AND NON BINARY MODES
;IN BINARY MODE ALL DATA IS XFERRED VIA A MONITOR BUFFER IN THE
;CONTROLLER DATA BLOCK.THIS MODE IS RATHER SLOW AS IT HAS TO
;UNPACK AND PACK BYTES . MOREOVER ITRUNS ON INTERRUPT LEVEL
SBINIO: NULL
LDB T2,DVYIOM ;SEE IF A BINARY STREAM
CAIE T2,11 ;SLOW OR
POPJ P, ;FASTER!
PUSH P,P1 ;NO SENSE TO CALL SAVE1
PUSHJ P,GXFSIZ ;T2_# OF WORDS ; P1_-# OF WORDS
TLNN S,IO ;IF INPUT AND
TLZN S,FRSTIN ;FIRST SEGMENT IS NOT TRUE
JRST BINOLD ;THEN COMMON LOGIC
MOVSI S,FRSTIN ;ELSE
ANDCAB S,DEVIOS(F) ;CLEAR THE FLAG
JRST GBNIOW ;AND GET THE IOWD
BINOLD: NULL
HRLS T2 ;GET THE IOWD UPDATE
ADDM T2,@DVXCUR(F) ;UPDATE THE OLD VALUE
HRLI T1,(POINT 12,0) ;BUILD POINTER TO USER AREA
HRRZ T3,T2 ;AND GET THE BYTE COUNT
IMULI T3,3 ;3 BYTES PER WORD
MOVE T2,[POINT 18,XKBMBF##(W)] ;INTERMEDIATE AREA
TLNE S,IO ;IF OUTPUT THEN
JRST SBNOUT ;USE OTHER WAYS
SBNINP: NULL
ILDB T4,T2 ;GET A BYTE
EXCTXU <IDPB T4,T1> ;STORE IN USER AREA
SOJG T3,SBNINP ;ALL BYTES
SKIPGE T1,@DVXCUR(F) ;SEE IF DONE
JRST [ CALL GXFSIZ ;GET TRANSFER SIZE
JRST GBNIOW ] ;GET NEXT IOWD
POP P,P1 ;GET P1 BACK
AOS DVXCUR(F) ;ADVANCE IOWD POINTER
POP P,T1 ;GET RID OF CALL RETURN
PJRST NXTIOW ;TRY AGAIN
SBNOUT: NULL
EXCTUX <ILDB T4,T1 > ;GET THE USERS BYTE
IDPB T4,T2 ;AND STORE IT IN MONITOR BUF.
SOJG T4,SBNOUT ;EMPTY ALL
GBNIOW: NULL
LSH P1,CNTLSH ;SHIFT COUNT IN PLACE
HRRI P1,XKBMBF##(W) ;INTERMEDIATE STORE
MOVE T1,P1 ;EREIS RESULT EXPECTED
POP P,P1 ;GET THE COW BACK
POP P,T2 ;ZAP RETURN
POPJ P,
GXFSIZ: NULL
HLRE P1,T1 ;GET THE AREA SIZE
MOVN T2,P1 ; plus
CAILE T2,MAXBSZ ;TOO BIG
MOVEI T2,MAXBSZ ;(YES) THAN LESS
MOVN P1,T2 ;UPDATE HIM TOO
POPJ P,
SUBTTL I/O UUO SUBROUTINES -- MPIOWD
;MPIOWD MAP THE IOWD IN T1 INTO A DA28 POINTER
;ON A KI10 RETURN THE REMAINDER OF THE IOWD IN T2
;AND THE DA28 IOWD IN T1
;CALL:
; .T1=IOWD WORD TO BE MAPPED
; DEVICE IS IOACTIVE
; USER'S UPMP IS SET UP ON A KI10
MPIOWD: NULL
PUSHJ P,SAVE2## ;GET SAME ARM SPACE
PUSH P,T1 ;SAVE THE IOWD
HRRZS T1 ;GET RID OF EXTRA BITS
EXCTUX <MAP T2,(T1)> ;GET PHYSICAL ADDRESS
TLZ T2,(MP.NAD) ;CLEAR JUNK KL-PAGING BITS
MOVE T4,(P) ;GET ADDRESS BACK @GAIN
ANDI T4,PG.BDY ;GET OFFSEP IN PAGE
MOVEI T3,PAGSIZ ;GET THE PAGE SIZE
SUBI T3,(T4) ;GET THE CAPACITY IN THIS PAGE
HLRE T4,(P) ;NUMBER OF WORDS GOING OUT
MOVNS T4 ;GET THE POSITIVE NUMBER
TDZA P2,P2 ;# OF WORDS IN THIS TRANSFER
IOWSIZ: MOVEI T3,PAGSIZ ;THIS MUCH IN THE PAGE
ADD P2,T3 ;NUMBER GOING NOW
CAML P2,T4 ;ENOUGH SPACE
PJRST IOWDON ;ALL IS DONE
MOVE P1,T2 ;GET PHYSICAL ADDRESS
ADDI P1,PAGSIZ ;NEXT PHY PAGE
ADDI T1,PAGSIZ ;NEXT VIRT PAGE
EXCTUX <MAP T3,(T1)> ;GTE NEW PHYSICAL ADDRESS
TLZ T3,777760 ;CLEAR RANDOM KL-PAGING BITS
CAMN T3,P1 ;NEXT PHY PAGE MATCH NEXT VRTUAL PAGE?
JRST IOWSIZ ;(YES) KEEP ADDING
IOWDON: CAMLE P2,T4 ;MORE THAN REQUIRED?
MOVE P2,T4 ;THEN GET THE RIGHT AMOUNT
MOVN T1,P2 ;negative NUMBER GOING OUT
LSH T1,CNTLSH ;SHIFT IN RIGHT PLACE
IOR T1,T2 ;COMPLETE IOWD
SOS T1 ;MAKE AN IOWD
POP P,T2 ;GET OLD IOWD
ADD T2,P2 ;AND UPDATE
SUBM P2,T4 ;NUMBER FOR NEXT TIME
HRL T2,T4 ;FOR NEXT TIME
POPJ P,
SUBTTL I/O UUO SUBROUTINES -- RDYCHK
;SUBROUTINE TO WAIT FOR A RESTART FROM THE SMALL CPU
;CALL WITH:
; PUSHJ P,RDYCHK
; RETURN HERE WHEN READY
;
RDYCHK: NULL ;CHECK IF SMALL COMPUTER HAS SENT RESTART
SKIPGE XUBRDY(U) ;IS HE READY
POPJ P,0 ;YES--JUST RETURN
PUSHJ P,MAKREL ;GET RESTART
PUSHJ P,SENDW ;AND GET IT ACROSS
PUSHJ P,DOZE0 ;WAIT A WHILE [7136]
SKIPGE XUBRDY(U) ;is he ready now [7136]
POPJ P,0 ;yes -- just return [7136]
PUSH P,U ;SAVE U
PUSHJ P,HNGSTP## ;GENERATE OPR MESSAGE
POP P,U ;RESTORE U
MOVEI S,RHERR ;CLEAR OUT ANY ERRORS
ANDCAB S,DEVIOS(F)
JRST RDYCHK ;MAKE SURE IT IS READY NOW
SUBTTL CLOSE AND RELEAS UUOS
;CLOSE INPUT
XTCLSI: NULL
; MOVEI S,IODEND ;ASSUME DUMP MODE
; PUSHJ P,IFDMP ;IS THAT TRUE?
; MOVSI S,IOEND ;NO SO CHANGE OUR MIND
; IORB S,DEVIOS(F) ;SET GOOD BITS
POPJ P,
;CLOSE OUTPUT
XTCLSO: NULL
HRRZ U,DVXUDB(F) ;GET THE UDB ADDRESS
SKIPL XUBRDY(U) ;IS UNIT REALLY READY
JRST XTCLS0 ;NO DO NOT SEND ANYTHING
PUSHJ P,IFDMP ;ONLY IF NOT DUMP MODE
PUSHJ P,OUT## ;TERMINATE OUTPUT
PUSHJ P,WSYNC## ;WAIT FOR I/O TO COMPLETE
PUSHJ P,SETACS ;GETA LL ACCS
TRNN S,IO.BYP ;BYPASS?
PUSHJ P,XMTEOF ;SEND EOF
XTCLS0: MOVSI T1,IORRFI!IORWFI!IOXRFO
ANDCAB T1,DVXPST(F) ;CLEAR THE BITS
PJRST WTQEMP ;AND WAIT FOR SEND QUEUE TO EMPTY
;XTCREL RELEASE A DEVICE IS EQUIVALENT TO SENDING A RESTART TASK
XTCREL: NULL
PUSHJ P,SETACS ;WE NEED MORE DATA
SKIPGE XUBRDY(U) ;TO CHECK FOR READY
TRNE S,IO.BYP ;BYPASSING
JRST XTCRE0 ;DO NOT TOUCH THE INTERFACE
IFE FTCMP1,< ;SEND RESTART TASK IF 0
PUSHJ P,MAKRTK ;MAKE RESTART TASK
PUSHJ P,SENDW ;AND GET IT ACROSS
>;END IFE FTCMP1
XTCRE0: SETZM DVXPST(F) ;ALL SET
PJRST WTQEMP ;WAIT FOR AN EMPTY SEND QUEUE
SUBTTL INTERRUPT SERVICE -- XTCINT, CLRERR, SETSCN
;HERE ON AN INTERRUPT WITH THE ACS SAVED AND W POINTING
; TO THE CONTROLLER DATA BLOCK.
;P IS THE PUSH DOWN POINTER ALL ELSE IS RANDOM
XTCINT::NULL
XCT XTSCNI##(W) ;GET CONI DAS,
MOVEM T1,XKBDAS##(W) ;STORE THEM
XCT XTCCNI##(W) ;GET CONI DAC,
MOVEM T1,XKBDAC##(W) ;ALWAYS THE LATEST ONE
TRNE T1,XC.BSY ;IS THE DA28-C BUSY?
STOPCD CPOPJ##,DEBUG,BSY, ;*++DA28 BUSY
SALL
; SKIPGE XKBLOK##(W) ;DO WE BELIEVE THAT IT IS IN USE? [7136]
; TRNN T1,XC.SRQ ;NO AND A SELECT REQUEST? [7136]
TRNE T1,XC.SRQ ;NO SELECT REQUESTS
PJRST REMINT ;ELSE IT IS A REMOTE INTERRUPT
SKIPE F,XKBDDB##(W) ;IS THERE A DDB WAITING FOR DONE
JRST DDBINT ;YES--HANDLE THAT CASE
SKIPE U,XKBIUN##(W) ;RECEIVE CONTROL WORD?
JRST UNIINT ;YES--GO WORRY ABOUT THAT
TRNE T1,XC.SCN!XC.TST!XC.JAM!XC.ERI!XC.FT!XC.EOT
STOPCD .+1,DEBUG,SCB, ;*++SPURIOUS CONI BIT
SALL
CLRERR: NULL
MOVEI T1,XS.CLR+XTCCHN##
XCT XTSCNO##(W) ;WE LOST, CLEAR DEVICE
SETSCN: NULL
SETOM XKBLOK##(W) ;FREE THE CONTROL VARIABLE
MOVEI T1,XC.SCN
XCT XTCCNO##(W) ;TURN ON SCANNER
POPJ P,
SUBTTL INTERRUPT SERVICE -- REMINT, DOINP
;HERE WHEN SMALL COMPUTER ASKS FOR AN INTERRUPT
;COME HERE WITH RESULT OF CONI DAC,T1
REMINT: NULL
PUSHJ P,IDLE28 ;SEE IF REALLY IDLE!!
STOPCD .+1,DEBUG,TC2, ;SHOULD NOT HAPPEN
TRNE T1,XC.ERR ;CHECK ERRORS
STOPCD .+1,DEBUG,RIE, ;*++REMOTE INTERUPT ERROR
MOVEI T1,0
XCT XTCCNO##(W) ;CLR COMMAND REG
SKIPL XKBLOK##(W) ;IS THE CONTROL FREE?
STOPCD .+1,STOP,KNF, ;*++CONTROL NOT FREE, SOFTWARE BUG
SETZM XKBLOK##(W) ;NOW CLAIM CONTROL
LDB T2,[POINT 4,XKBDAS##(W),21] ;GET UNIT ADR FROM STATUS WORD
MOVSI T1,(1B0) ;T1 USED FOR TESTING REQ STATUS
MOVN T3,T2 ;T2 HAS NUMBER OF SHIFTS FOR T1
LSH T1,(T3) ;POSITION REQ STATUS TEST WORD
TDNN T1,XKBDAS##(W) ;REQ BIT CORRESPONDING TO CODE SHOULD BE ON
PJRST CLRERR ;WE WAS HERE, BUT YOU WASN'T
;NOW YOU IS HERE, BUT WE ISN'T
MOVE T3,W ;START WITH FIRST UNIT
PUSHJ P,FNDUNI ;FIND UNIT
STOPCD CPOPJ##,DEBUG,NUI, ;*++NON EX UNIT INTERRUPTING(NO UDB)
SALL
SKIPE F,XUBLOK(U) ;WAITING FOR THIS?
JRST DOINP ;YES: GO START INPUT
HRRZM U,XKBIUN##(W) ;UNIT DOING XFR
MOVEI T1,RECUCW ;WHERE TO GO ON DONE
HRRZM T1,XUBIPC(U) ; INTERRUPT
MOVEI T1,XUBRCW-1(U) ;ADDRESS OF PLACE TO GET WORD
HRLI T1,WC(1) ;1 WORD XFER
PUSHJ P,SETKCW ;LOAD UP THE CONTROL WORD
MOVEI T1,XUBRCW(U) ;ADDR OF CONTROL WORD
PUSHJ P,OUCHE## ;GET IT OUT OF CACHE
MOVEI T1,XC.CON!XC.BSY!XC.FST!DM.BIN!XC.MEM
XCT XTCCNO##(W)
POPJ P,
;ROUTINE TO START INPUT XFER FOR DDB FOUND IN F
DOINP: NULL
SETZM XUBLOK(U) ;NOW FREE
PUSHJ P,SETACI ;GET INTERRUPT ACCS
MOVE T1,DVXPST(F) ;GET PROTOCOL STATUS
TLNN T1,IOXWFI ;AND GUARANTEE A WFI LEFT
STOPCD .,STOP,TC1,
SALL
IFN FTKL10,< ;FLUSH CACHE
PUSHJ P,CSDMP## ;TO CORE
>
PJRST DDBIO ;START @/O FOR THE DDB
PLM
;+
;.LM 0
;.hl 1 Interrupt Service
;^^
;.subtitle Interrupt Service
; The DA28C generates an interrupt under three circumstances:
;.list
;.le;if the small computer raises "select request" (i.e. wants to
;output something to the -10), known as a "remote" interrupt.
;.le;when a DMA data transfer (either to or from the -10)
;completes, known as a "done" interrupt.
;.le;if any of the hardware error bits set (e.g. timing error), known
;as an "error" interrupt.
;.end list
;The very beginning of the interrupt code is in COMDEV; there are
;the instructions which form part of the skip chain for
;the PI channel that the DA28C is on. If the skip chain test
;succeeds (i.e.#the DA28C really has interrupt-causing
;bits on) this code loads W with the address of the KDB and jumps
;to XTCINT.
;.lm 0
;.hl 2 XTCINT
;^^
;.subtitle XTCINT
; XTCINT is the common interrupt routine for all DA28C's
;on the system (it keeps them straight by the value of W).
;If the interrupt is a select request from the
;small computer, control passes to the routine REMINT. If the
;XKBDDB word is non-zero it means that we expect a done interrupt
;for the transfer of actual data (as opposed to protocol words) and
;control passes to the routine DDBINT (which tries to continue the
;data transfer by calling DDBIO to process the next IOWD). Otherwise the interrupt
;should be a done interrupt for a control word transfer, either
;to or from the small computer. In both cases
;XTCSER had placed the UDB address (and DDB address if applicable)
;into XKBIUN, as well as the PC of the routine to process the done interrupt
;into XUBIPC. (XTCSER did this when it started the DMA transfer request
;on the DA28C hardware.)
;If XKBIUN is non-zero, control passes to
;UNIINT, which in turn jumps to the address in XUBIPC.
;This will be one of four routines:
;.list
;.le;RECUCW if we were reading a control word from the
;small computer. REMINT sets it up.
;RECUCW then dispatches (based on the function code of the control word)
;to the appropriate routine (usually called RECxxx where "xxx" is a mnemonic
;for the type of control word received) to extract the information from
;the control word and process it.
;.le;XDNDDB if we were sending a control word and we had a DDB.
;The routine PHS2F0 sets it up.
;.le;XDNXUB if we were sending a control word, the DA28C was available and we had no DDB.
;The routine PHS2NF sets it up.
;.le;XDNXU0 if we were sending a control word that came from the UDB
;queue. This is set up when SCNQUE on a previous interrupt finds
;that something has been queued and calls PHS2N0 to send it out.
;.end list
;All the interrupt routines exit by calling SCNQUE which looks for
;control word transfers which were queued because the DA28C was busy at
;the time SENDW was called. These can be related to a DDB (in which case
;DVXQUE is non-zero) or only to a unit (in which case XUBQUE points to a
;chain of 4-word free core blocks containing all the information about the
;request). If there are no queued control words to send, SCNQUE calls CLRERR
;to reset the DA28C hardware which falls into SETSCN which
;starts the DA28C scanning all the small computers for select requests.
;.lm 0
;.hl 2 DDBIO
;^^
; Most of the work of actual data transfer (as opposed to control
;word transfer) is done by the routine DDBIO.
; The first call to DDBIO comes about in one of two ways:
;.list
;.le;If we are doing input, we store the DDB address in XUBLOK when
;we send the WFI. A subsequent select request should be for
;the output of the data. REMINT checks XUBLOK, and if it is non-zero
;it goes to DOINP which jumps to DDBIO to do the first IOWD.
;.le;If we are doing output, the routine RECWFI transfers control to
;DDBIO to start outputting the first IOWD.
;.end list
;The input and output UUO processing code stores user virtual
;address IOWDs in the DDB at DVXIWD to describe the data transfer to
;be accomplished. DDBIO processes these IOWD's successively
;(it keeps a pointer to which it is working on in DVXCUR) by
;calling NXTIOW. If NXTIOW indicates
;that there are no IOWD's left, DDBIO goes to IOREDY which clears
;XKBDDB and finishes up the I/O processing. If NXTIOW finds another
;IOWD it returns it (converted to physical addresses by MPIOWD) and
;DDBIO stores F in XKBDDB (so no-one can interrupt the transfer)
;and starts this IOWD going.
;-
MLP
SUBTTL INTERRUPT SERVICE -- UNIINT
;HERE WHEN WE GET AN INTERRUPT FOR A UNIT
;AC U POINTS TO UNIT DATA BLOCK, W POINTS TO THE CONTROLLER DB
; NO OTHER ACS CONTAIN USEFUL INFORMATION (EXCEPT P).
UNIINT: NULL
SETZB T1,XKBIUN##(W) ;WE NO LONGER USE IT
XCT XTCCNO##(W) ;DISCONNECT (RELEASES SMALL COMPUTER)
MOVE T1,XKBDAC##(W) ;GET CONI DAC BITS
TRNE T1,XC.DUN ;IS DONE SET?
TRNE T1,XC.ERR ;ANY ERROR BITS?
PJRST UNIERR ;(YES) A UNIT ERROR
HLRZ F,U ;GET THE DDB ADDRESS IF ANY
SKIPE F ;IF A DDB THEN
MOVE S,DEVIOS(F) ;THEN GET THE STATUS
HRRZS U ;AND CLEAN UP U
;TRANSFER TO EITHER:
; RECUCW
; XDNXUB
; XDNDDB
PJRST @XUBIPC(U) ;GO TO EITHER RECUCW OR XDNXUB OR XDNDDB
SUBTTL INTERRUPT SERVICE -- RECUCW
;HERE TO RECEIVE A CONTROL WORD FROM A UNIT
RECUCW:NULL
IFE LIVE,<
SETZ T1,
IFE FTKL10 <
DATAI APR,T1 ;READ CONSOLE
HRR T1,.TRCF ;AND TRACE FLAGS
>;end IFE FTKL10
IFN FTKL10<HRRZ T1,.TRCF> ;TRACE FLAGS
TDNN T1,[40,,1] ;TRY EITHER
PUSHJ P,TRCRCW ;PRINT CW
>;end IFE LIVE
IFN FTKL10,<
MOVEI T1,XUBRCW(U) ;ADDRESS OF RECEIVED CONTROL WORD
PUSHJ P,OUCHE## ;MAKE SURE WE GET THE NEW VALUE
>;end IFN FTKL10
LDB T1,XUYMFC ;GET MAJOR FUNCTION CODE
SETOM F ;GET ALL ONES
CAIE T1,FN.DST ;IS IT DEAD-START
CAIN T1,FN.RST ;IS IT A RESTART
SETCMM F ;ZAP NO DDB
LDB T1,XUYTIF ;GET TASK ID
SKIPE F ;DO NOT LOOK FOR DDB
PUSHJ P,FNDTSK ;FIND THE DDB
SETZM F ;NO DDB FOR TASK
IFN .DBLEN,<
PUSHJ P,RCPUT ;LEAVE TRACES
>
JUMPE F,RCUCW2 ;JUMP IF NO DDB
PUSHJ P,SETACI ;SET INTERRUPT ACCUS
MOVE T1,XUBRCW(U) ;GET DATA FROM UNIT STORAGE
MOVEM T1,DVXCTL(F) ;AND SET IT IN DDB
RCUCW2: LDB T1,XUYMFC ;GET MAJOR FUNCTION CODE
HRRZ T2,UNIFTB(T1) ;GET DISPATCH TABLE ENTRY
SKIPE F ;OKAY IF NO DDB
HLRZ T2,UNIFTB(T1) ;GET DDB ADDRESS
PUSHJ P,(T2) ;CALL THE SERVICE BUREAU
PUSHJ P,CHKPRC ;CHECK FOR COROUTINES AND SKIP!
PJRST SCNQUE ;SCAN THE WORK LOAD
;TABLE OF WHAT TO DO FOR VARIOUS FUNCTIONS
UNIFTB: XMTFNE,,XMTFNE ;(00)ILLEGAL FUNCTION
XMTFNE,,TTYFUN ;(01)TTY FUNCTION
RECREJ,,RECREJ ;(02)REJECT
RECACK,,XMTNOT ;(03)UNDEFINED
RECCLS,,XMTNOT ;(04)CLOSE
RECATB,,XMTNOT ;(05)MANIPULATE ATTRIBUTE BYTE
XMTFNE,,RECRST ;(06)RESTART
XMTFNE,,RECDST ;(07)DEAD-START
XMTFNE,,XMTFNE ;(10)FUNCTION NOT IMPLEMENTED
XMTFNE,,XMTFNE ;(11)UNDEFINED
XMTFNE,,XMTFNE ;(12)UNDEFINED
XMTFNE,,XMTFNE ;(13)UNDEFINED
RECRFI,,XMTNOT ;(14)READY FOR INPUT
RECRFO,,XMTNOT ;(15)READY FOR OUTPUT
RECWFI,,XMTNOT ;(16)WAITING FOR INPUT
RECWFO,,XMTNOT ;(17)WAITING FOR OUTPUT
PLM
;+
;.lm 0
;.hl 2 RECUCW
;^^
;.subtitle RECUCW
; This routine processes the received protocol words. If the type
;code from the control word is "dead start"
;or "restart", it assumes it doesn't need a DDB; otherwise
;it calls FNDTSK to find a DDB corresponding to the task ID in
;the control word. It then looks up the word corresponding to
;that function in a table (UNIFTB) which has the routine
;which processes the control if you have a DDB in the LH, and
;the routine which processes the function when you do
;not have a DDB (which includes all restarts) in
;the RH.
; The following list contains which routines are executed for
;the receipt of which control words:
;.list
;.le;TTY function -- with a DDB only sends back a "reject function error"; without a DDB goes to TTYFUN to process it.
;TTYFUN then dispatches on the subtype code:
;.list
;.le;character -- TTYCHR checks if the line number specified is
;an XTCSER line and if it is, calls RECINT in SCNSER
;with the character.
;.le;character acknowledge -- TTYACK checks the line
;and then calls XMTINT in SCNSER. This will ship out the next
;character (if any) via the ISR dispatch to XTCTYP.
;.le;get a TTY line -- TTYGET send a TTY NAK if the line
;is already in use or not an XTCSER line; otherwise it marks the
;line as in use and sends a TTY ack (TTY more).
;.le;TTY nak -- ignores by going to CPOPJ.
;.le;Free a TTY line -- sends a TTY Nak if line isn't ours, frees
;line if it is.
;.end list
;.le;reject -- both with and without DDB go to RECREJ; however if the
;DDB is not there, this exits to CPOPJ. If the DDB is there it uses
;the sub-function reason code to index into a table of error
;bits (RJBTTB), ORs the bit into DEVIOS and clears IOACT.
;.le;ack -- if there is no DDB it goes to XMTNOT to send a "reject no task" to the
;small computer. Otherwise goes to RECACK which simply sets IO.ACK in DEVIOS.
;.le;close -- if there is no DDB goes to XMTNOT to send a "reject no task"; if there is a DDB goes to RECCLS which checks the sub-function
;code to make sure its "close eof" (if not it sends a "reject function error").
;Then it clears IORRFO, IORWFO and IOXRFI (have received RFO,
;have received WFO and have sent RFI) bits in the protocol status
;word (DVXPST) and set IODEND (dump mode) or IOEND (buffered mode) for UUOCON.
;.le;attribute byte -- goes to XMTNOT if no DDB; goes to
;RECATB if there is a DDB which dispatches on the sub-function
;into table ATBDTB to perform the following functions:
;.list
;.le;transmit ATB -- goes to XMTXAB to send the "here is attribute byte"
;control word.
;.le;here is ATB -- goes to ATBSTO which extracts the 8-bit
;attribute from the control word and stores it in DVXDSC.
;.le;set ATB bits -- goes to ATBSET which gets the 8-bit
;mask of bits to set from the control word and ORs them into DVXDSC.
;.le;clear ATB bits -- goes to ATBCLR which gets the 8-bit
;mask of bits to clear from the control word and ANDCs it into DVXDSC.
;.end list
;.le;restart -- always goes to RECRST (DDB or no DDB) which dispatches
;on the sub-function code via table RSTTAB as follows:
;.list
;.le;restart -8, -11, -5 -- go to RSTUNI which sets the
;XUBRDY word to -1 (to signal that small computer is
;alive) and then calls DDBRST to terminate I/O for each DDB on
;the unit. After this, it also clears all XTCSER TTY lines on the unit.
;.le;restart REP -- goes to RSTREP which exits if there is no
;DDB, and then calls DDBRST to terminate I/O on all DDB's that
;have the same REP field.
;.le;restart -10 -- goes to XMTOPE to send a "reject operation error" control word back to small computer.
;.le;restart task -- goes to RSTTSK which tries to find the DDB
;corresponding to the task ID. If there is none it responds with
;a reject no task. If there is one, it calls DDBRST to terminate I/O
;on this DDB.
;.le;restart status -- goes to RSTSTS; if the code from the small
;computer indicates that it has gone down it calls RSTUNI
;to terminate I/O on all DDB's and free all XTCSER TTY lines.
;In either case, it gets its opinion of the small computer's state from
;XUBRDY and sends it back in a restart status control word.
;.end list
;.le;dead start -- always goes to RECDST; this looks for a DDB with
;a task ID of -1 and exits if not found. Then it points
;to the appropriate UDB (based on the DDB) and examines the XUBDST
;word. If it is non-zero (i.e. a previous dead start is
;pending) it exits. Otherwise it stores the
;received control word in XUBDST so that a program may read it (with
;the appropriate XTTSK. function).
;.le;RFI -- goes to XMTNOT if no DDB and RECRFI if there is a DDB.
;This routine extracts the word count, makes it positive and stores
;it in DVXRFI; then it sets the IORRFI bit in DVXPST.
;.le;RFO -- goes to XMTNOT or RECRFO depending upon DDB; RECRFO
;merely sets IORRFO (have received RFO) in DVXPST.
;.le;WFO -- goes to XMTNOT if no DDB and RECWFO if there is a DDB.
;This routine checks if IOXWFO (have transmitted WFO) set, and if so sets IOIMPM error in DEVIOS and also sends a "reject operation error" to the small computer.
;Otherwise it sets IORWFO (have received WFO) in DVXPST, gets the word
;count, makes it positive in the RH of DVXWFO, gets the mode and stores
;it in the LH of DVXWFO.
;.le;WFI -- goes to XMTNOT if no DDB, RECWFI if DDB; this
;routine checks for IOXWFI and if it is one sets IOIMPM error
;in DDB and sends a "reject operation error" to the small computer.
;Otherwise it sets IORWFI (have received WFI) in DVXPST and tests
;if we have sent WFO yet (IOXWFO); if not, it merely exits. If so,
;it flushes the cache (KL10 only) and goes to DDBIO to
;start transferring data.
;.end list
;-
MLP
SUBTTL INTERRUPT SERVICE -- CHKPRC, CHKWAK
;CHKPRC CALLED TO VERIFY WHETHER A COROUTINE SHOULD RUN
;OR THE JOB HAS TO BE WAKED. THIS ROUTINE ALWAYS SKIPS
;SO SKIP RETURNS CAN BE PROPAGATED
CHKPRC: NULL
JUMPE F,CPOPJ## ;NO BUSINESS HERE
MOVEM S,DEVIOS(F) ;STORE S NOW
IFN FTCMP3,< ;MANY EXTRA WAKES
PJRST XTWAKA ;ALWAYS WAKE
>;END IFN FTCMP3
IFE FTCMP3,< ;WAKE SELECTIVELY NOT UNNEEDED
PUSHJ P,CHKWAK ;SEE IF A WAKE IS REQUIRED
SKIPN DVXCOR(F) ;ANYONE WAITING?
POPJ P, ;NOPE JUST GO BACK
MOVE T1,DVXMSK(F) ;GET THE SYNC MASK
PUSHJ P,IFEBTS ;SEE WHAT IS SET
SKIPA ;IN THAT CASE CONTINUE PROCES
POPJ P, ;NOTHING TO DO
MOVE S,DEVIOS(F) ;USE THE LATEST COPY
PJRST @DVXCOR(F) ;YES MAKE PROGREESS
> ;END OF FTCMP3=0
;ROUTINES TO CHECK EVENTS FOR A DDB
;IFEBTS VERIFY IF ANY OF THE EVENT FLAGS IN T1 IS SET
;T2 IS DESTROYED AND CONTAINS THE CURRENT SET OF EVENT FLAGS
IFEBTS: NULL
MOVE T2,DEVIOS(F) ;GET DEVIOS
TLZ T2,^-IOEND ;BUT ONLY THIS IN LEFT HALF
IOR T2,DVXPST(F) ;AND ADD PROTOCOL STATUS
TDNN T2,T1 ;IF NO BIT IS SET THEN
AOS (P) ;GIVE A SKIP RETURN
POPJ P,
IFE FTCMP3,< ;IF STANDARD VERSION
;CHKWAK CHECK IF A WAKE SHOULD BE DONE FOR A DEVICE
CHKWAK: NULL
JUMPE F,CPOPJ## ;ONLY FOR DDB'S
SKIPN T1,DVXWAK(F) ;ANY WAKE REQUESTS
POPJ P, ;NO JUST POPJ P,
PUSHJ P,IFEBTS ;ALLREADY ANY EVENT THERE
SKIPA ;(YES) TAKE A CLOSER LOOK
POPJ P, ;(NO) LATER MAYBE
SETZM DVXWAK(F) ;ONCE IS ENOUGH
PJRST XTWAKA ;ALWAYS WAKE
> ;END OF IFE FTCMP3
SUBTTL INTERRUPT SERVICE -- DDBINT, IOREDY, BUFDON, DDBRST
;HERE ON AN INTERRUPT FOR A DDB
DDBINT: NULL
SETZM XKBDDB##(W) ;FORGET THE PAST ASAP
PUSHJ P,SETACI ;SET UP INTERRUPT ACCUS
SKIPE XKBIUN##(W) ;MAKE SURE THIS IS A UNIQUE INT
STOPCD .+1,DEBUG,UIP, ;*++NOT A UNIQUE INT
SALL
MOVE T1,XKBDAS##(W) ;GET STATUS BITS
MOVEM T1,DEVSTS(F) ;STORE FOR DEVSTS UUO
MOVE T1,XKBDAC##(W) ;GET THE CONI BITS
TRNE T1,XC.EOT!XC.DUN ;CHECK FOR DONE OR EOT
TRNE T1,XC.ERR!XC.SRQ ;UNEXPECTED CONDITION
JRST DDBERR ;YES--PONDER THE ERROR
XCT XTCDTI##(W) ;GET THE W.C.
IFN FTCMP2,< ;IF CLEMENT THEN
PUSHJ P,IFDMP ;SKIP SHORT TRANSFER IN DUMP MODE
> ;SKIPS WHEEN DUMP
JUMPL T1,CKDINP ;JUMP IF TOO SHORT
DDBIO: NULL
PUSHJ P,SVEUF## ;MAKE USER ADDRESSABLE
MOVEM S,DEVIOS(F) ;SAVE S FOR PROBLEMS
DDBIO0: MOVEM F,XKBDDB##(W) ;TO DDBINT
PUSHJ P,NXTIOW ;GET NEXT I/O WORD
PJRST IOREDY ;ALL IS DONE
MOVE S,DEVIOS(F) ;RELOAD S
TLNN S,IO ;DOING INPUT?
PJRST STINPT ;YES GO ON WITH THE BUSINESS
PJRST STOUTP ;NO CONTINUE THE OUTPUT
;IOREDY CALLED WHEN ANY I/O TRANSACTION IS READY
IOREDY: NULL
IFN .DBLEN,<
TLNN S,IO ;OUTPUT?
JRST IOR000 ;NO INPUT
PUSHJ P,IFDMP ;DUMP MODE
PUSHJ P,XDPUT ;NORMAL SKIPS!!
PUSHJ P,XDDPUT ;DUMP DOESNOT SKIP
JRST IOR001 ;SKIP OTHER TRACE
IOR000: PUSHJ P,IFDMP ;IF NOT DUMP MODE
PUSHJ P,RDPUT ;THEN HERE AND SKIP RETURN
PUSHJ P,RDDPUT ;DUMP MODE INPUT
IOR001:
>
SETZB T1,XKBDDB##(W) ;DISCONNECT REMOTE
XCT XTCCNO##(W) ;BY THIS
PUSHJ P,FINDDB ;FINISH ALL FOR THE DDB
PJRST SCNQUE ;ALL SET
;BUFDON SPECIALS FOR BUFFRED MODES
BUFDON: NULL
TLNE S,IO ;DOING INPUT?
PJRST ADVBFE## ;NO JUST ADVANCE
IFN FTKL10,< ;FOR THE CACHE
PUSHJ P,CSDMP## ;FLUSH CORE
>
PJRST ADVBFF## ;(YES) GO BACK VIA ADVANCE BUFFERS
;DDBRST CLEAN UP A DDB
DDBRST: NULL
MOVEI T1,ASSCON!ASSPRG ;SEE IF BUSY
TDNN T1,DEVMOD(F) ;CHECK THE BITS
POPJ P, ;NO
PUSHJ P,SETACS ;GET THE ACCS SET UP
TRO S,IOIMPM!IODTER ;SET ERROR FLAGS
;FALL INTO FINDDB
;CONTINUED ON NEXT PAGE
SUBTTL INTERRUPT SERVICE -- FINDDB, FINUNI
;CONTINUED FROM PREVIOUS PAGE
;FINDDB FINISHES ALL FOR A DDB AND ENSURES THAT THE JOB
;WILL RUN AGAIN REGARDLESS OF ITS STATE. THIS CODE IS CALLED
;ON INTERRUPT LEVEL WITH A POSSIBLE ERROR FLAG SET IN S
FINDB0: NULL
MOVEM S,DEVIOS(F) ;UPDATE S FOR CALLER
FINDDB: NULL
PUSHJ P,SVEUF## ;MAKE USER ADDRESSABLE
IFE FTCMP3,<
PUSHJ P,CHKWAK ;SEE IF HE IS INTERESTED IN ERRORS
> ;END OF IFE FTCMP3
PUSHJ P,XTWAKE ;WAKE ONLY IF SLEEPING
MOVE S,DEVIOS(F) ;GET STATUS
SKIPN DVXCOR(F) ;IS THERE A COROUTINE ACTIVE
JRST FINDD0 ;(NO) PLAIN VANILLA
PUSHJ P,@DVXCOR(F) ;CALL THE GHOST
SETZM DVXCOR(F) ;DAWN KILLS HIM
FINDD0: SKIPN DVXPAC(F) ;PSEODO ACTIVE?
JRST FINDD1 ;NO FORGET IT
SETZM DVXPAC(F) ;YOU WERE IT
SOS XKBPAC##(W) ;ONE LESS TO BOTHER ABOUT
SOS XUBPAC(U) ;SO SPEED UP
FINDD1: MOVE T1,DVXPST(F) ;GET THE STATUS
TRNE S,IO.BYP ;IF IO ACTIVE AND
TRNN S,IOACT ;BYPASSING
TLNE T1,ANYACT ;OR ACTIVE IN NORMAL MODE
SKIPA ;THEN DO BUFFER DONE LOGIC
JRST FINDD2 ;ELSE SO NO BUFFER STUFF
PUSHJ P,IFDMP ;IF DUMP MODE
PUSHJ P,BUFDON ;THEN FINISH BOFFERS
JFCL ;2 RETURNS MORE OR ALL DONE
PUSHJ P,SETIOD## ;IN CASE IN IOW STATE
FINDD2: SETZM DVXPST(F) ;ZAP THE PROTOCOL
SETZM DVXQUE(F) ;FORGET THE HISTORY
PJRST CLRACT## ;FINISH THE LAST TRACES
;FINUNI FINISH ALL FOR A UNIT
FINUNI: NULL
SETZM XUBRDY(U) ;UNIT IS NOT READY
;ADD UNIT CLEAN UP HERE
PUSH P,F ;SAVE CURRENT F
CLNDDB: NULL
HLRZ F,XUBDDB(U) ;GET FIRST DDB
JUMPE F,DDBDUN ;DONE WITH DDB'S
CLNDD0: NULL
PUSHJ P,SETACS ;SET THE ACCS RIGHT
PUSHJ P,FINDDB ;FINISH THE DDB
HLRZ F,DVXUDB(F) ;GET NEXT DDB
JUMPN F,CLNDD0 ;AND RELEASE THE TASK
DDBDUN: NULL
POP P,F ;GET F BACK
MOVE S,DEVIOS(F) ;RESTORE S
POPJ P,
;!!ADD ERROR BIT TO S
SUBTTL ERROR ROUTINES -- UNIERR, DWNUNI
;UNIERR CALLED WHEN A UNIT ERROR HAS BEEN DETECTED
UNIERR: NULL
MOVE T1,XKBDAS##(W) ;GET LAST CONI DAS,
MOVE T2,XKBDAC##(W) ;AND LAST CONI DAC,
TRNN T2,XC.EOT ;CHECK EOT'S
TRNE T1,XS.NRD!XS.TER!XS.REM!XS.PAR!XS.NXM ;CHECK ERRS
JRST [PUSHJ P,DWNUNI ;REPORT LOSAGE
PJRST SCNQUE] ;D28CLR WAS CALLED BY DWNUNI
TRNE T1,XS.CON ;IF NOT CONNECT - IGNORE
PUSHJ P,CHKCER ;REPORT CONNECT ERROR
PUSHJ P,D28CLR ;ZAP DA28 ERRORS
PUSHJ P,FINUNI ;FINISH THE UNIT
PJRST SCNQUE ;AND RESTART IT
;HERE ON A HARDWARE ERROR
DWNUNI: NULL ;HERE TO PRINT ERROR MESSAGE
PUSHJ P,CHKTYP ;CAN WE SAFELY TYPE OUT?
JRST DWNUN1 ;NO--GO CLEAR ERRORS
PUSH P,U ;SAVE XUB ADDRESS
PUSHJ P,ERRSTS ;PRINT ERROR STATUS
POP P,U ;RESTORE POINTER TO XUB
DWNUN1: MOVEI T1,XS.CLR+XTCCHN##
XCT XTSCNO##(W) ;CLEAR ERRORS
SETZM XUBRDY(U) ;UNIT IS OFFLINE
PJRST FINUNI
;PRINT ERROR STATUS
ERRSTS: MOVEI T1,OPM.SO!OPM.CT ;SEND TO ORION OR CTY IF NO ORION
PUSHJ P,OPRMSG## ;WE WANT AN OPERATOR MESSAGE
POPJ P, ;NO CORE OR NO ORION--PUNT
PUSHJ P,INLMES## ;ADD TEXT
ASCIZ /DA28 Hardware Error/
PUSHJ P,OPRHDR## ;BIND OFF THE HEADER
PUSHJ P,INLMES## ;PRINT TEXT
ASCIZ / Status: /
MOVE T1,XKBDAS##(W) ;GET THE STATUS
PUSHJ P,HWDPNT## ;PRINT AS HALF-WORDS
PUSHJ P,PCRLF## ;END LINE
PUSHJ P,INLMES## ;PRINT TEXT
ASCIZ / Command: /
MOVE T1,XKBDAC##(W) ;GET COMMAND STATUS
PUSHJ P,HWDPNT## ;PRINT AS HALF-WORDS
PUSHJ P,PCRLF## ;END LINE
PUSHJ P,INLMES## ;PRINT TEXT
ASCIZ / IOWD: /
XCT XTCDTI##(W)
PUSHJ P,HWDPNT## ;PRINT AS HALF-WORDS
PUSHJ P,PCRLF## ;END LINE
PUSHJ P,INLMES##
ASCIZ / Data: /
XCT XTSDTI##(W)
PUSHJ P,HWDPNT## ;PRINT AS HALF-WORDS
PJRST PCRLF## ;END LINE AND PRINT STATUS
SUBTTL ERROR ROUTINES -- CHKCER, DDBERR, NXTERR
;SUBROUTINE TO MAKE SURE WE HAVE A CONNECT ERROR
;CALL WITH:
; PUSHJ P,CHKCER
; NEVER RETURNS
;
CHKCER: NULL
PUSHJ P,CHKTYP ;CAN WE SAFELY TYPE?
JRST CHKCE1 ;NO
PUSH P,U ;SAVE POINTER TO XUB
PUSHJ P,CERSTS ;PRINT CONNECT ERROR STATUS
POP P,U ;RESTORE XUB
CHKCE1: PUSHJ P,FRCOFL ;FORCE UNIT OFFLINE
PJRST SCNQUE ;AND LOOK FOR WORK
CERSTS: MOVEI T1,OPM.SO!OPM.CT ;SEND TO ORION OR CTY IF NO ORION
PUSHJ P,OPRMSG## ;WE WANT AN OPERATOR MESSAGE
POPJ P, ;NO CORE OR NO ORION--PUNT
PUSHJ P,INLMES## ;ADD TEXT
ASCIZ /DA28 Connect Error/
PUSHJ P,OPRHDR## ;BIND OFF THE HEADER
PUSHJ P,INLMES## ;PRINT TEXT
ASCIZ / Status: /
MOVE T1,XKBDAS##(W) ;GET UNIT NUMBER
PUSHJ P,HWDPNT## ;PRINT AS HALF-WORDS
PUSHJ P,PCRLF## ;END LINE
PUSHJ P,INLMES## ;PRINT TEXT
ASCIZ / Forced unit offline /
PJRST PCRLF## ;END LINE AND PRINT MESSAGE
;HERE ON AN ERROR
DDBERR: NULL
;T1 CONTAINS CONI DAC,
TRNE T1,XC.SCN!XC.TST!XC.JAM!XC.SRQ!XC.ERI
STOPCD .+1,DEBUG,DA28B, ;*++DA28 IS BROKEN
SALL
TRO S,IODERR ;LIGHT A BIT FOR USER
MOVE T1,DEVSTS(F) ;REFETCH ERROR BITS
TRNE T1,XS.NRD!XS.TER!XS.REM!XS.PAR!XS.NXM
JRST [PUSHJ P,DWNUNI ;REPORT THE LOSSAGE
PJRST SCNQUE ] ;TRY YOUR LUCK
PUSHJ P,CHKCER ;MAKE SURE WE HAVE A CONNECT ERR
TRO S,IOIMPM ;MARK THE ERROR
PUSHJ P,FINDB0 ;STOP ALL DDB STUFF
PJRST SCNQUE ;LOOK FOR NEXT REQUEST
;HERE ON A TRANSFER WITH THE WRONG NUMBER OF WORDS TRANSFERED
NXTERR: NULL
POP P,T1 ;GET RID OF CALL RETURN
TRO S,IOBKTL ;FLAG THAT ERROR IN DEVIOS
SETERR: NULL
PUSHJ P,D28CLR ;RECOVER
PUSHJ P,FINDB0 ;FINISH DDB
PJRST SCNQUE ;AND SCAN AGAIN
CKDINP: NULL
TRO S,IOBKTL ;BLOCK TOO LARGE
JRST SETERR ;SET THE FLAG
;SUBROUTINE TO CHECK ON THE SAFETY OF TYPING OUT XTCSER MESSAGES.
;CALL IS:
;
; PUSHJ P,CHKTYP
; NOT-SAFE
; SAFE
;
;SINCE SOME ROUTINES WANT TO TYPE OUT AT INTERUPT LEVEL WHICH
;CAN RESULT IN A SCNSER/NETSER DEADLOCK (IF SCNSER OR NETSER IS
;RUNNING WITH SCNSER INTERLOCK SET (FONDLING CHUNKS FOR EXAMPLE)
;AND XTCSER INTERRUPTS AND TRIES TO TYPE THEN THE SYSTEM HANGS)
;THEY SHOULD CALL CHKTYP FIRST. THE "NOT-SAFE" RETURN SAYS TO
;***NOT*** TYPE OUT (SYSTEM WILL HANG), THE "SAFE" RETURN SAYS
;IT IS PROBABLY OK.
CHKTYP:
IFN FTMP,<
CONSZ PI,PI.IPA ;AT INTERRUPT LEVEL?
SKIPGE SCNLOK## ;AND WITH SCNSER INTERLOCK?
> ;END IFN FTMP
AOS (P) ;NO, SAFE TO TYPE
POPJ P, ;RETURN AS APPROPRIATE
SUBTTL DEBUGGING CODE -- CONSOLE CONTROL WORD TRACE
;ROUTINE TO PRINT CONTENTS OF XUBRCW(U)
IFE LIVE,<
TRCRCW: PUSH P,T1
MOVEI T1,"R"
MOVE T2,XUBRCW(U) ;GET INFO TO PRINT IN T2
JRST TRACWD
TRCXCW: PUSH P,T1
MOVEI T1,"X"
MOVE T2,XUBXCW(U) ;INFO TO PRINT
SKIPE F ;MAY BE IN DDB
MOVE T2,DVXXCW(F)
TRACWD: PUSHJ P,CHKTYP ;DARE WE TYPE?
JRST TPOPJ# ;NO - DISCARD TYPEOUT
PUSH P,U ;SAVE UDB POINTER
PUSH P,T2 ;SAVE INFO
PUSH P,T1 ;SAVE DIRECTION
MOVE U,OPRLDB## ;FETCH LDB POINTER
PUSHJ P,INLMES##
ASCIZ /UNIT: /
LDB T3,[POINT 6,XKBNAM##(W),17]
ADDI T3,40 ;CONTROLLER ID IN ASCII
PUSHJ P,COMTYO## ;PRINT IT
MOVE T1,-2(P) ;GET UDB POINTER
MOVE T1,XUBUNO(T1) ;UNIT # IN T1
PUSHJ P,PRTDI8## ;PRINT IT IN OCTAL
PUSHJ P,PRSPC## ;PRINT A SPACE
POP P,T3 ;PUT CHAR IN T3
PUSHJ P,COMTYO## ;PRINT IT
PUSHJ P,INLMES##
ASCIZ /CW: /
POP P,T1 ;RESTORE INFO
PUSHJ P,HWDPNT## ;PRINT AS HALF-WORDS
PUSHJ P,CRLF## ;EOL
POP P,U ;RESTORE U
JRST TPOPJ## ;restore T1 and return
$LOW
.TRCF: BLOCK 1 ;tracing flags
;RH 1 (bit 35) disables receive CW console trace
;RH 4 (bit 33) disables xmit CW console trace
$HIGH
; ...still in IFE LIVE
SUBTTL DEBUGGING CODE -- EXECUTION TRACE
IFN FTETR < ;if execution trace enabled
;Subroutines to implement execution trace. Always give skip
; returns, even if not tracing. ETRCON turns on software trace
; bit, ETRCOF turns off software trace bit, and ETRACE does
; trace.
ETRCON: ;subroutine to turn on trace bit
AOS 0(P) ;set skip return
PUSH P,T1 ;get register to use
MOVSI T1,ETR.ON ;get trace bit
IORM T1,ETRFLG ;and turn it on
JRST TPOPJ## ;and exit
ETRCOF: ;turn off trace bit
AOS 0(P) ;set skip return
PUSH P,T1 ;get register to use
MOVSI T1,ETR.ON ;get trace bit
ANDCAM T1,ETRFLG ;turn it off
JRST TPOPJ## ;and exit
ETRACE: ;subroutine to trace PC's
AOS 0(P) ;set skip return
SKIPL ETRFLG ;only trace if sign bit on
POPJ P, ;return if not
;here to store caller's PC and PI state
PUSH P,T1 ;save T1
PUSH P,T2 ;save T2 also
MOVE T1,-2(P) ;get PC of caller
SUBI T1,2 ;back it up to address of PUSHJ
CONI PI,T2 ;get PI status
PUSHJ P,TRCINS ;insert both into trace table
POP P,T2 ;restore T2
JRST TPOPJ ;and exit
TRCINS: ;subroutine to insert entry into trace table
SETZM EPIFLG ;assume interrupts not off
CONSO PI,PI.ON ;check if PI system on
SETOM EPIFLG ;already off, don't turn on later
CONO PI,PI.OFF ;this may be redundant
MOVEM T1,@EPNT ;put PC into trace buffer
HRLM T2,@EPNT ;put PI status into trace buffer
AOS EPNT ;adjust pointer
MOVEI T2,EBUFE ;get address of end of buffer
CAMLE T2,EPNT ;check if there
JRST TRCINE ;no, exit
MOVE T1,ETRFLG ;get flag bits
TLNE T1,ETR.ST ;check if stop (no wraparound) bit on
TLZ T1,ETR.ON ;if yes, turn off trace
MOVEM T1,ETRFLG ;update flags
MOVEI T2,EBUF ;get address of beginning of trace buffer
MOVEM T2,EPNT ;and store as new pointer
TRCINE: ;here when done inserting trace entry
SKIPL EPIFLG ;skip if interrupts were off at entry
JRST ONPOPJ ;turn on interrupts and return
POPJ P, ;else just return
$LOW
ETRFLG: Z ;software flag bits for ex. trace
; LH bits
ETR.ON==(1B0) ;enable tracing (must be sign)
ETR.ST==(1B1) ;disallow wraparound
EPIFLG: Z ;switch to indicate whether or not
;to turn on PI system at exit
; 0=turn on, -1=do nothing
EPNT: EBUF ;pointer to next entry in trace table
EBUF: BLOCK ENMENT ;trace buffer
EBUFE=. ;one word past end
$HIGH
>;end IFN FTETR
>;end IFE LIVE
SUBTTL RECEIVE CONTROL WORDS -- ATTRIBUTE BYTE
;HERE WHEN WE RECEIVE MAJOR FUNCTION FN.ATB
RECATB: NULL
LDB T1,DVYFSC ;GET THE SUBFUNCTION CODE
CAILE T1,SF.AAB ;IN RANGE?
PJRST XMTFNE ;NO--SEND A REJECT
PJRST @ATBDTB(T1) ;DISPATCH ON SUBFUNCTION
ATBDTB: XMTFNE ;(0)ILLEGAL
XMTXAB ;(1)SEND OUT THE ATB
ATBSTO ;(2)HERE IS THE BYTE
ATBSET ;(3)SET SETECTED BITS
ATBCLR ;(4)CLEAR SELECTED BITS
;HERE TO SET A NEW ATB
ATBSTO: NULL
LDB T1,DVYSFI ;GET THE NEW BYTE
DPB T1,DVYTAT ;STORE THE NEW BYTE
POPJ P,
;HERE TO SET SELECTED BITS
ATBSET: NULL
SKIPA T3,[IOR T1,T2] ;INSTRUCTION FOR SETTING BITS
;HERE TO CLEAR SELECTED BITS
ATBCLR: NULL
MOVE T3,[ANDCA T1,T2] ;INSTRUCTION FOR CLEARING BITS
LDB T1,DVYTAT ;GET THE OLD BYTE
LDB T2,DVYSFI ;GET THE MASK
XCT T3 ;MODIFY T1
DPB T1,DVYTAT ;STORE UPDATED BYTE
POPJ P,
SUBTTL RECEIVE CONTROL WORDS -- CLOSE
;HERE ON A CLOSE
RECCLS: NULL
LDB T1,DVYFSC ;GET SUB-FUNCTION
CAIE T1,SF.EOF ;GRNTEE CORRECT CODE
PJRST XMTFNE ;SEND REJECT
MOVSI T1,IORRFO!IORWFO!IOXRFI
ANDCAM T1,DVXPST(F) ;AND ZAP THE CRAP
LDB T1,PIOMOD ;GET THE IOMOD
CAIL T1,DR ;IF NOT DUMP MODE
TROA S,IODEND ;THE SET THE LAST WORD FLAG
TLO S,IOEND ;SET END OF FILE BIT
POPJ P,
SUBTTL RECEIVE CONTROL WORDS -- REJECT
;SUBROUTINE TO RECEIVE A REJECT COMMAND
;CALL WITH:
; PUSHJ P,RECREJ
; RETURN HERE
;
;NOTE: REJECTS CAN NEVER SEND THE SMALL COMPUTER ANYTHING (ESPECIALY
; A REJECT) SINCE THAT COULD CAUSE AN ENDLESS LOOP. SO WHATEVER,
; WE DO WE MUST DO IT QUIETLY
;
RECREJ: NULL
JUMPE F,CPOPJ## ;RETURN IF NO DDB
LDB T1,DVYFSC ;GET THE FUNCTION SUB CODE
CAIG T1,RJVMAX ;TOO BIG?
IOR S,RJBTTB(T1) ;NO GET ERROR BIT
TRZ S,IOACT ;NO HUNG DEVICES
POPJ P,
RJBTTB: 0 ;(0)ERROR
IOIMPM ;(1)EXTERNAL TASK DOES NOT EXIST
IODERR ;(2)HUNG
IOIMPM ;(3)FUNCTION ERROR
IOIMPM ;(4)IMPROPER MODE
IODTER ;(5)IMPROPER DATA MODE
IOBKTL ;(6)BLOCK TOO LARGE
IODTER ;(7)DATA ERROR
IOIMPM ;(10)OPERATION ERROR
RJVMAX==.-RJBTTB-1
SUBTTL RECEIVE CONTROL WORDS -- READY FOR INPUT
;SUBROUTINE TO PROCESS A READY FOR INPUT
RECRFI: NULL
LDB T1,DVYWDC ;GET THE WORD COUNT
HRROI T1,770000(T1) ;NEGATIVE
MOVMM T1,DVXRFI(F) ;STORE POSITIVE FOR XOSYNC
MOVSI T1,IORRFI ;GOT A RFI
JRST SETBIT ;AND SETTHE BIT
;FALL IN RECRFO EXIT
;SUBROUTINE TO PROCESS A READY FOR OUTPUT
RECRFO: NULL
MOVSI T1,IORRFO ;I GOT A RFO
SETBIT: NULL
IORM T1,DVXPST(F) ;SET IT
POPJ P,
;SUBROUTINE TO PROCESS A ACK FROM AN EXTERNAL TASK
;JUST FIND TASK AND WAKE HIM UP
RECACK: NULL
TRO S,IO.ACK ;SET BIT FOR HIM
POPJ P,
SUBTTL RECEIVE CONTROL WORDS -- WAITING FOR INPUT
;SUBROUTINE TO PROCESS A WAITING FOR INPUT
;CALL WITH:
; PUSHJ P,RECWFI
; RETURN HERE
;
RECWFI: NULL
MOVE T1,DVXPST(F) ;GET THE STATUS
TLNE T1,IOXWFI ;DEADLY EMBRACE?
JRST [TRO S,IOIMPM ;YES--LIGHT AN ERROR BIT
PJRST XMTOPE] ;SEND A REJECT
TLO T1,IORWFI
MOVEM T1,DVXPST(F) ;STORE THE UPDATED VALUE
TLNN T1,IOXWFO ;SEND WFO YET?
POPJ P, ;NO- GO BACK
IFN FTKL10,< ;FLUSH THE CACHE
PUSHJ P,CSDMP## ;NOW
>
PJRST DDBIO ;START UP I/O
SUBTTL RECEIVE CONTROL WORDS -- WAITING FOR OUTPUT
;SUBROUTINE TO PROCESS A WFO FROM AN EXTERNAL TASK
;CALL WITH:
; PUSHJ P,RECWFO
; RETURN HERE
;
RECWFO: NULL
MOVE T1,DVXPST(F) ;GET THE PROTOCOL STATUS
TLNE T1,IOXWFO ;ARE WE ALSO WAITING?
JRST [TRO S,IOIMPM ;YES-- SET IMPROPER MODE
PJRST XMTOPE] ;SEND A REJECT
TLO T1,IORWFO
MOVEM T1,DVXPST(F) ;STORE IT
LDB T1,DVYWDC ;GET THE WORD COUNT
HRROI T1,770000(T1) ;SIGN EXTEND
MOVM T1,T1 ;MAKE POSITIVE
HRRM T1,DVXWFO(F) ;STORE IN DDB
LDB T1,DVYMOD ;GET MODE
HRLM T1,DVXWFO(F) ;SAVE FOR LATER
POPJ P,
SUBTTL RECEIVE CONTROL WORDS -- RESTART
;SUBROUTINE TO PROCESS A RESTART MESSAGE
;CALL WITH:
; PUSHJ P,RECRST
; RETURN HERE
;
RECRST: NULL
LDB T1,XUYFSC ;GET SUB-FUNCTION
CAILE T1,SF.LNG ;IN RANGE
PJRST XMTFNE ;NO - ERROR
PJRST @RSTTAB(T1) ;DO FUNCTION
RSTTAB: XMTFNE ;(00) ILLEGAL
RSTUNI ;(01) UNIT RESTART PDP-11
RSTUNI ;(02) UNIT RESTART PDP-15
RSTUNI ;(03) UNIT RESTART PDP-8
RSTREP ;(04) RESTART REP
XMTOPE ;(05) RESTART PDP-10 IMPOSSIBLE
RSTTSK ;(06) RESTART A TASK
RSTSTS ;(07) RECEIVE UP STATUS
SF.LNG==.-RSTTAB ;LENGTH OF TABLE
RSTUNI: SETOM XUBRDY(U) ;FLAG AS READY
HLRZ F,XUBDDB(U) ;GET POINTER TO FIRST DDB
RSTUN1: NULL
JUMPE F,RSTUN2 ;DONE IF NO DDB
PUSHJ P,DDBRST ;RESTART EACH DDB
HLRZ F,DVXUDB(F) ;STEP TO NEXT DDB
JRST RSTUN1 ;LOOP BACK
RSTUN2: MOVE T1,[MTTD28##,,TTLTAB##]
HRL U,W ;FOLD POINTERS
CAMN U,0(T1) ;ON THIS UNIT?
SETZM 0(T1) ;YES - FLUSH
AOBJN T1,.-2 ;LOOP UNTIL DONE
POPJ P,
RSTTSK: NULL
LDB T1,XUYTIF ;GET TASK ID
PUSHJ P,FNDTSK ;SEE IF IT EXISTS
PJRST XMTNOT ;NOPE!
PUSHJ P,DDBRST ;YES - RESTART
POPJ P,
RSTSTS: NULL
LDB T1,[POINT 16,XUBRCW(U),31] ;GET STATUS
PUSH P,XUBRDY(U) ;SAVE THE CURRENT STATUS
SKIPE XUBRDY(U) ;IF DOWN OR
JUMPN T1,RSTST0 ;UP ACCORDING TO 10 AND DOWN ACCORDING TO EP
PUSHJ P,RSTUNI ;THEN JUST DO RESTART
RSTST0: POP P,T1 ;GET OLD STATUS
MOVSI T4,316000 ;RESTART STATUS
DPB T1,[POINT 16,T4,31] ;TRANSMIT OUR OLD OPINION
PJRST SENDW ;GET IT ACROSS
RSTREP: NULL
PUSHJ P,SAVE1## ;SAVE P1
LDB P1,XUYUNI ;GET UNIT ID
HLRZ F,XUBDDB(U) ;GET DDB LIST
RSTRP1: JUMPE F,CPOPJ## ;DONE WHEN NO MORE
LDB T1,DVYUNI
CAMN T1,P1 ;CHECK SAME UNITS
PUSHJ P,DDBRST ;YES - RESTART
HLRZ F,DVXUDB(F) ;GET NEXT
JRST RSTRP1
SUBTTL RECEIVE CONTROL WORDS -- DEAD-START
;SUBROUTINE TO PROCESS A DEAD-START MESSAGE
;FIND TASK OWNING TASK WITH 7777 ID
;THE WAKE IT UP AND STORE INFO FROM INTERUPTING UNIT
RECDST: NULL
MOVEI T1,7777 ;GET DEFAULT TASK ID
PUSHJ P,FNDTSK ;LOCATE OWNING JOB
POPJ P, ;IGNORE NO TASK
PUSHJ P,SETACS ;SET UP S , J AND R
SKIPN T1,XUBDST(U) ;IGNORE IF ONE PENDING
MOVE T1,XUBRCW(U) ;FETCH NEW CTL WORD
MOVEM T1,XUBDST(U) ;AND SAVE AS DEAD-START INFO
PJRST XTWAKA ;WAKE JOB
SUBTTL RECEIVE CONTROL WORDS -- TTY FUNCTION
;SUBROUTINE TO PROCESS A TTY FUNCTION
;CALL WITH:
; PUSHJ P,TTYFUN
; RETURN HERE
;
TTYFUN: NULL
LDB T1,XUYFSC ;GET FUNCTION SUB CODE
CAILE T1,SF.TTR ;FUNCTION IN RANGE?
PJRST TTYNAK ;NO--SEND A REJECT
PUSH P,U ;PRESERVE U
PUSH P,W ;AND W
PUSHJ P,@TTFTAB(T1)
POP P,W
JRST UPOPJ##
TTFTAB: TTYNAK ;(0) ERROR
TTYCHR ;(1) CHAR IN SFI
TTYMOR ;(2) XMIT DONE
TTYGET ;(3) GET A TTY
CPOPJ## ;(4) JUST SWALLOW
TTYRET ;(5) RETURN A TTY
;SUBROUTINE TO GET A PROCESS A TTY CHAR FROM SMALL COMPUTER
;CALL WITH:
; PUSHJ P,TTYCHR
; RETURN HERE
;
TTYCHR: NULL
PUSHJ P,CHKLIN ;CHECK LINE GOODNESS
PJRST TTYNAK ;SEND REJECT
LDB T3,XUYSFI ;GET THE CHAR
MOVE U,T1 ;COPY LINE # IN U
PUSHJ P,RECINT## ;CALL SCNSER
SETZ F, ;NO TRACE VALUES
POPJ P,
;SUBROUTINE TO PROCESS A TTY MORE
;CALL WITH:
; PUSHJ P,TTYMOR
; RETURN HERE
;
TTYMOR: NULL
PUSHJ P,CHKLIN ;CHECK LINE GOODNESS
PJRST TTYNAK ;SEND REJECT
MOVE U,T1 ;COPY LINE # INTO U
PUSHJ P,XMTINT##
SETZ F, ;ZAP SCNSER DDB
POPJ P,
;SUBROUTINE TO CHECK IF LINE # BELONGS TO THIS UNIT
;CALL:
; PUSHJ P,CHKLIN
; RETURN HERE IF NOT CORRECT #
; RETURN HERE WITH LINE # IN T1
CHKLIN: NULL
LDB T1,XUYTIF ;GET TASK ID FIELD
PUSHJ P,XTCTTY ;CHECK IF ON DA-28
POPJ P, ;INACTIVE
SKIPA ;TRY THIS
POPJ P, ;NOT DA-28 LINE
HRL U,W ;FOLD POINTERS
CAMN U,T2 ;T2 CONTAINS TTLTAB ENTRY
AOS (P) ;SKIP RETURN
POPJ P, ;RETURN
;ROUTINE TO CHECK IF LINE # IN T1 IS ON DA28
;RETURN IN T1 - ORIGINAL LINE #
; T2 - TTLTAB ENTRY IF VALID LINE #
; T3 - ADJUSTED TTLTAB INDEX
;CALL:
; PUSHJ P,XTCTTY
; RETURN HERE IF INACTIVE XTC LINE
; RETURN HERE IF ACTIVE XTC LINE
;RETURN HERE IF NOT XTC LINE
XTCTTY::NULL
MOVE T3,T1 ;COPY LINE #
SUBI T3,D28OFS## ;REMOVE OFFSET
JUMPL T3,CPOPJ2## ;NOT XTC LINE IF NEG
CAIL T3,TTD28N## ;CHECK UPPER BOUND
JRST CPOPJ2##
SKIPE T2,TTLTAB##(T3) ;CHECK IF ACTIVE LINE #
AOS 0(P) ;SKIP IF ACTIVE
POPJ P, ;RETURN
;SET UP T4 WITH TTY # AND SEND NAK
TTYNAK: NULL
LDB T4,XUYTIF ;SET UP REC'D LINE #
PUSHJ P,MAKTTN ;GET XCW
HRRZS U ;GET RID OF LEFT HALF
PJRST SENDW ;THERE IT GOES
;SUBROUTINE TO PROCESS A TTY RETURN
;CALL WITH:
; PUSHJ P,TTYRET
; RETURN HERE
TTYRET: NULL
PUSHJ P,CHKLIN ;IS IT OURS?
PJRST TTYNAK ;NO--SEND A REJECT
SETZM TTLTAB##(T3) ;RETURN THE LINE NUMBER
POPJ P,
SUBTTL RECEIVE CONTROL WORDS -- TTY SUBROUTINES
;XTCOFL IS XTCSER OFF LINE
XTCOFL: NULL
PUSHJ P,XTCTTY ;CHECK THE LINE
POPJ P, ;AN INACTIVE XTC LINE
JRST CPOPJ1## ;THIS IS A GOOG XTC LINE
POPJ P, ;NOT MY BUSINESS
;SUBROUTINE TO PROCESS A REQUEST FOR TTY LINE NUMBER
;CALL WITH:
; PUSHJ P,TTYGET
; RETURN HERE
;
TTYGET: NULL
LDB T1,XUYTIF ;GET LINE # FIELD
JUMPN T1,TTYGLN ;HANDLE SPECIAL IF NON-ZERO
MOVE T1,[MTTD28##,,TTLTAB##]
SKIPE (T1) ;SKIP IF FREE
AOBJN T1,.-1 ;LOOP OVER ALL LINES
JUMPG T1,TTYNAK ;JUMP IF NO FREE LINES
HRLM W,(T1) ;STORE POINTERS INTO
HRRM U,(T1) ; TABLE ENTRY
MOVNI T4,TTLTAB## ;SET UP LINE
ADDI T4,D28OFS##(T1) ; NUMBER
TTYG1: PUSH P,T4 ;SAVE LINE NUMBER
PUSH P,U ;AND UNIT NUMBER
PUSH P,W ;AND KDB ADDRESS
LDB T1,XUYSFI ;GET LDB INFO
HRRZ T2,LINTAB##(T4) ;GET LDB POINTER
DPB T1,[POINT 6,LDBDCH##(T2),17]
LSH T1,-6 ;SHIFT OVER
DPB T1,[POINT 2,LDBBYT##(T2),2]
MOVEI T3,LNTDHC## ;TURN OFF IRMA CATCHER
MOVE U,T4 ;LNCREC LIKES LINE #'S
PUSHJ P,LNCREC## ;...
;U NOW POINTS TO LDB
LDB T1,XUYMOD ;GET ADDITIONAL INFO BITS
TRNE T1,10 ;SHOULD WE RESET?
JRST TTYG2 ;NO
PUSHJ P,TSETBI## ;RESET LINE BUFFERS
PUSHJ P,TSETBO## ;...
SETZM LDBXNP##(U) ;CLEAR XON POINTER
SETZM LDBFLP##(U) ;CLEAR FILL POINTER
MOVSI T1,(1B0) ;LDLOIP
ANDCAM T1,LDBDCH##(U)
TTYG2: SETZ F, ;GET RID OF F IF SET
POP P,W ;GET KDB ADDRESS BACK
POP P,U ;AND UDB ADDRESS
POP P,T3 ;GET LINE NUMBER
PUSHJ P,MAKTTM ;TELL THE NAME
PJRST SENDW ;AND LET IT BE KNOWN
TTYGLN: PUSHJ P,XTCTTY ;CHECK IF OK TO HAVE THIS ONE
JRST TTYGL1 ;YES - PROCEED
JRST TTYNAK ;ALREADY ACTIVE
JRST TTYNAK ;NOT AN XTC LINE
TTYGL1: HRLM W,TTLTAB##(T3) ;STORE KDB
HRRM U,TTLTAB##(T3) ; AND UDB INFO
MOVE T4,T1 ;COPY LINE # INTO T4
JRST TTYG1 ;AND EXIT
;LDB INFORMATION IN SFI FIELD DEFINED AS FOLLOWS:
;
;BIT 8 & 9 - FILLER CLASS CODE
; 10 - THIS TTY IS A SLAVE
; 11 - THIS TTY HAS LOWER CASE
; 12 - THIS TTY HAS HARDWARE TABS
; 13 - THIS TTY HAS LOCAL COPY
; 14 - THIS TTY HAS HARDWARE FF & VT
; 15 - NO AUTOMATIC CRLF
; 16 - DON'T RESET I/O BUFFERS
; 17 - NO ECHO ANYTHING!
SUBTTL RECEIVE CONTROL WORDS -- DA28 SCHEDULING SUBROUTINES
;SUBROUTINE TO FIND THE NEXT THING TO DO
;CALL WITH:
; PUSHJ P,SCNQUE
; RETURN HERE
SCNQUE: NULL
PUSHJ P,IDLE28 ;IS 28 IDLING?
POPJ P, ;(NO) WAIT FOR IT TO BECOME FREE
SKIPE T1,XKBREQ##(W) ;A GRAB CONTROL REQUEST ACTIVE?
PJRST ZAPCTL ;(YES) HIDE CONTROL AND WAKE USER
MOVE T3,W ;START WITH FIRST UNIT
JRST SCNQL3 ;GET FIRST UNIT
SCNQL1: SKIPE T1,XUBQUE(U) ;UNIT IN QUEUE?
PJRST PHS2N0 ;TRANSMIT FOR NON F PROCES
HLRZ F,XUBDDB(U) ;POINT TO FIRST UNIT
JUMPE F,SCNQL3 ;JUMP IF NO TASKS ON THIS UNIT
SCNQL2: SKIPE T1,DVXQUE(F) ;IS THIS DDB WAITING?
JRST [PUSHJ P,SETACS ;CONTEXT SWITCH
JRST (T1)] ;GIVE IT CTL
HLRZ F,DVXUDB(F) ;STEP TO NEXT DDB
JUMPN F,SCNQL2 ;LOOP FOR NEXT DDB
SCNQL3: HRRZ U,XKBUDB##(T3) ;POINT TO NEXT UNIT
JUMPE U,CLRERR ;RETURN IF NO MORE UDB'S
SKIPE XUBLOK(U) ;OK IF UNIT FREE
AOJA T3,SCNQL3 ; IF LOCKED SKIP IT
AOJA T3,SCNQL1 ;ELSE TRY NEXT
;IDLE28 CALLED TO FIND OUT WHETHER THE DA28C IS FREE TO USE OR NOT
;NO ACCS ARE CHANGED , W SHOULD POINT TO
;CONTROLLER BLOCK
IDLE28: NULL
SKIPN XKBDDB##(W) ;I/O BUSY
SKIPE XKBIUN##(W) ;OR PROTOCOL BUSY
POPJ P, ;THEN DA28C IS NOT IDLE
SKIPE XKBGRB##(W) ;DID SOME ONE GRAB THE CONTROL
POPJ P, ;THEN IT CANNOT BE USED
PJRST CPOPJ1## ;IT IS FREE
SUBTTL TTY FUNCTION SCNSER INTERFACE
;ISR DISPATCH TABLE FOR XTCSER TTY'S
XTTDSP::JRST XTCTYP ;(0) SEND CHAR IN T3
POPJ P, ;(1) NO MODEM CONTROL
POPJ P, ;(2) NO ONCE A SEC CHECK
POPJ P, ;(3) NO ISR INIT (YET)
POPJ P, ;(4) CHANGE HDW PARAMS
POPJ P, ;(5) SEND LINE CONTROL MSG
POPJ P, ;(6) SET ELEMENT #
POPJ P, ;(7) REMOTE STUFF
JRST XTCOFL ;(10) OFFLINE
;SUBROUTINE TO SEND A TTY CHARACTER
XTCTYP: NULL
LDB T1,LDPLNO## ;GET LINE # IN T1
PUSH P,T3 ;SAVE THE CHAR
PUSHJ P,XTCTTY ;SEE IF A GOOD LINE
JRST T3POPJ## ;INACTIVE LINE
SKIPA T3,T1 ;COPY LINE NUMBER INTO T3
JRST T3POPJ## ;NOT AN XTC TTY
POP P,T4 ;RESTORE CHAR
PUSH P,U ;SAVE SCANNER WORLD
PUSH P,W
PUSH P,F
HRRZ U,T2 ;SET UP XTCSER WORLD
HLRZ W,T2 ;XTCTTY SET UP T2
MOVE T2,T4 ;GET CHAR IN THECRIGHT ACC
MOVEI F,0 ;NO DDB
PUSHJ P,XMTTTC ;PUT OUT CHAR
JFCL ;WE TRIED
POP P,F ;RESTORE ETC...
POP P,W
JRST UPOPJ## ;AND RETURN
SUBTTL TRANSMITTERS OF CONTROL WORDS
DEFINE XMT(FUN),<
XLIST
XMT'FUN: PUSHJ P,MAK'FUN ;;GET PROTOCOL WORD IN T4
PJRST SENDW ;;WAIT ONLY ON UUO LEVEL!!
LIST
> ;END OF XMT
XMT(EOF) ;TRANSMIT EOF
XMT(NOT) ;TRANSMIT NOT A JOB
XMT(XAB) ;ATTRIBUTE BYTE
XMT(TTC) ;GET CHARACTER OUT
XMT(OPE) ;BAD OPERATION
;SPECIAL TRANSMITTERS
XMTFNE: NULL
SETZM F ;NO DDB NO MATTER WHO CALLS
PUSHJ P,MAKFNE ;MAKE THE CODE
PJRST SENDW ;SEND IT
SUBTTL MAKE CONTROL WORDS -- MAKxxx
IF2,< .XCREF ..AA,..BB,..CC>
DEFINE MAK(MFC,FSC,SFI),<
MAK'FSC:NULL
MOVSI T4,<<<FN.'MFC>_4+<SF.'FSC>>_^D10> ;GET OPCODES
..AA==0
..BB==0
..CC==0
IFDIF <SFI><I>,<..AA==1>
IFDIF <MFC><TTY>,<..BB==1>
IFIDN <MFC>,<REJ>,<..CC==1>
IFE <..AA+..BB+..CC>,<
PJRST FINMSG ;SEND THE CONTROL WORD
>
IFN <..AA&..BB>,<
IFN ..CC,<
PJRST FINMS0 ;;ZERO T2,T3 AND LOAD DATA
> ;END OF IFN ..CC
IFE ..CC,<
PJRST FINMS2 ;;ZERO T2,T3 ONLY
> > ;END OF IFE..CC AND ..AA AND ..BB
IFE <..AA&..BB>,<
IFN <..AA+..BB>,<
IFN ..AA,< SETZ T2, > ;;NO SUB FUNCTION
IFN ..BB,< SETZ T3, > ;;TASK ID IS IN DDB
IFN ..CC,< PJRST FINMS1 >;;GET T3 FROM DDB
IFE ..CC,< PJRST FINMSG >;;TERMINATE THE THING
> ;END OF IFN <..AA+..BB>
> ;END OF IFE <..AA&..BB>
LIST
>
XALL ;LIST EXPANSION
MAK TTY,TTC,I, ;TTY CHARACTER
MAK TTY,TTN, ;TTY REJECT
MAK TTY,TTM, ;TTY MORE
MAK RFI,RFI, ;SEND AN RFI
MAK RFO,RFO, ;SEND AN RFO
MAK WFO,WFO, ;SEND A WFO
MAK WFI,WFI, ;SEND A WFI
MAK REJ,NOT, ;NO DDB FOR TASK
MAK REJ,FNE, ;FUNCTION ERROR
MAK REJ,IMP, ;IMPROPER MODE
MAK REJ,IDM, ;IMPROPER DATA MODE
MAK REJ,BTL, ;BLOCK TOO LARGE
MAK REJ,DTE, ;DATA ERROR
MAK REJ,OPE, ;OPERATION ERROR
MAK CLS,EOF, ;END-OF-FILE
MAK RST,REL, ;RELEASE
MAK RST,RTK, ;RESTART TASK
MAK ATB,XAB,I, ;XMT ATTRIBUTE BYTE
SALL ;NO MORE LISTING OF EXPANSION
SUBTTL MAKE CONTROL WORDS -- FINISH UP COMMON CODE
IF2,< PURGE MAK,..AA,..BB,..CC>
;SUBROUTINE TO FINISH A PROTOCOL WORD IN T4
;CALL WITH:
; MOVEI T4,MAJOR-FUNCTION-CODE+SUBFUNCTION CODE
; MOVEI T2,SUPP.-FUNCTION-INFORMATION
; MOVEI T3,TASKID [OR 0 TO GET FROM DDB]
; PUSHJ P,FINMSG
; RETURN HERE
FINMS0: NULL
SETZB T2,T3 ;ZAP BOTH
FINMS1: NULL
PJUMPN F,FINMSG ;GET IT FROM DDB
LDB T3,XUYTIF ;GET RECEIVED WORD'S DATA
SKIPA ;JUMP PAST ZAPPING T3
FINMS2: NULL
SETZB T2,T3 ;ZONK
FINMSG: NULL
DPB T2,[POINT 8,T4,15];STORE SUPP. FUNCTION INFORMATION
SKIPE T1,F ;SKIP IF NO DDB
LDB T1,DVYIOM ;GET THE I/O MODE
DPB T1,[POINT 4,T4,19] ;STORE THE MODE
JUMPE F,[JUMPN T3,.+1 ;PROCEDE IF WE CAN GET TASK ID
POPJ P, ];DONE
SKIPN T3 ;SKIP IF ALREADY KNOW TASK ID
LDB T3,DVYTID ;GET THE TASK ID
DPB T3,[POINT 12,T4,31] ;STORE IN CONTROL WORD
POPJ P,
SUBTTL MAKE CONTROL WORDS -- SUBROUTINES ADDSIZ, GETMOD, CHKMOD
;ADDSIZ ADD THE SIZE OF THE TRANSFER TO THE PROTOCOL WORD
ADDSIZ: NULL
HRRZ T1,DVXBSZ(F) ;GET THE CURRENT SIZE
MOVNS T1 ;GET THE MINUS AMOUNT
DPB T1,[POINT 12,T4,15] ;STORE THE SIZE
POPJ P, ;THAT'S ALL
;SUBROUTINE TO GET THE HARDWARE MODE FROM THE DDB
;CALL WITH:
; MOVE F,ADDRESS-OR-DDB
; PUSHJ P,GETMOD
; RETURN HERE MODE IN T1
GETMOD: NULL
LDB T1,PIOMOD ;GET DATA MODE
IDIVI T1,^D9 ;DIVIDE BY BYTES/WORD
MOVN T2,T2 ;CALCULATE THE BIT POSITION
ADDI T2,10 ; ..
ROT T2,-4 ; ..
IOR T2,[POINT 4,DVXMOD(F),35] ;MAKE INTO A BYTE POINTER
ADDI T2,(T1) ;THROW IN REMAINDER
LDB T1,T2 ;GET THE MODE
DPB T1,DVYIOM ;SAVE THE I O MODE
IDIVI T1,^D9 ;GET WA AND BYTE AD
MOVE T1,HDWDPM(T1) ;GET THE MODE WORD
IMULI T2,4 ;NUMBER OF BITS
LSH T1,777740(T2) ;AND SHIFT THE BYTE IN PLACE
ANDI T1,17 ;MASK OUT THE HDW MODE
DPB T1,DVYHWM ;STORE IT
POPJ P,
;BYTES CORRESPOND TO THE SEQUENCE MODE 0,1,2,.....
HDWDPM: BYTE (4) MD.ASC,MD.ASC,MD.ASC,MD.ASC,MD.ASC,MD.ASC,MD.ASC,MD.ASC,MD.IMI
BYTE (4) MD.PKI,MD.PKI,MD.PKI,MD.BIN,MD.IMI,MD.ASC,MD.BIN
;ROUTINE TO CHECK IF DATA MODE RECEIVED FROM EP IS REASONABLE
CHKMOD: NULL
LDB T1,DVYHWM ;GET THE HARDWARE MODE
HLRZ T2,DVXWFO(F) ;GET MODE REC'D
CAMN T2,MODTAB(T1) ;SEE IF WE LIKE IT
AOS (P) ;MODE ARE THE SAVE GIVE SKIP
POPJ P, ;RETURN
MODTAB: EXP 2 ;(0) IMAGE
EXP 0 ;(1) ASCII
EXP 3 ;(2) PACKED IMAGE
EXP 1 ;(3) BINARY
SUBTTL MAKE CONTROL WORDS -- SETACS
;EP SENDS
; 0 FOR ASCII
; 1 FOR BINARY
; 2 IMAGE
; 3 PACKED IMAGE
;SUBROUTINE TO SET UP ALL THE AC'S IN SIGHT
;CALL WITH:
; MOVE F,ADDRESS-OF-DDB
; PUSHJ P,SETACS
; RETURN HERE WITH S,J,R,U AND W SETUP
SETACI:
SETACS: NULL
HRRZS F ;CLEAR LH OF F
HRRZ U,DVXUDB(F) ;U = ADDRESS OF UDB
HRRZ W,XUBKDB(U) ;W = ADDRESS OF KDB
MOVE S,DEVIOS(F) ;SET UP S
LDB J,PJOBN## ;J = JOB NUMBER
POPJ P,0 ;RETURN
SUBTTL MAKE CONTROL WORDS -- RING BUFFER CONTROL WORD TRACE
;ROUTINES TO SUPPORT GIANT RING BUFFER TRACE
IFN .DBLEN,<
RCPUT: MOVSI T1,(1B0)
MOVE T2,XUBRCW(U) ;CW IN T2
JRST CPUT
XCPUT: MOVEI T1,0 ;FLAGS
MOVE T2,XUBXCW(U)
SKIPE F
MOVE T2,DVXXCW(F) ;MAYBE IN DDB
JRST CPUT
RDPUT: AOS (P) ;SKIP DUMP TRACE
TDZA T2,T2
RDDPUT: MOVSI T2,-1 ;MARK DUMP MODE
MOVSI T1,(3B1) ;FLAGS
JRST CPUT
XDPUT: AOS (P) ;SKIP DUMP TRACE
TDZA T2,T2
XDDPUT: MOVSI T2,-1
MOVSI T1,(1B1)
CPUT: SKIPE F
HLR T1,DEVIOS(F) ;INCLUDE DEVIOS IF THERE
IOR T2,XUBUNO(U) ;ADD UNIT #
LDB T3,[POINT 3,XKBNAM##(W),17]
DPB T3,[POINT 3,T1,17] ;INCLUDE CONTROLLER ID
MOVE T3,.DBUFP ;GET POINTER
MOVEM T1,(T3)
MOVEM T2,1(T3) ;STASH INFO
ADDI T3,1
AOBJN T3,.+2
MOVE T3,[-.DBLEN,,.DBUF]
MOVEM T3,.DBUFP
POPJ P, ;RETURN
$LOW ;LOW DATA
.DBUFP::-.DBLEN,,.DBUF
.DBUF:: BLOCK 2*.DBLEN
$HIGH
>
SUBTTL MAKE CONTROL WORDS -- SENDW
COMMENT \
SEND ROUTINE FOR PROTOCOL WORDS.
PROTOCOL WORDS CAN BE GENERATED BY 2 TYPES OF PROCESSES:
1 PROCESSES ASSOCIATED WITH A DDB
2 PROCESSES WITHOUT A DDB
THE GENERATION CAN MOREOVER TAKE PLACE AT 2 LEVELS:
A INTERRUPT LEVEL
B UUO LEVEL
THE SENDING PROCESS CONSISTS OF 2 PHASES:
P1 GETTING THE CLEARANCE TO SEND
P2 INITIATION OF THE HARDWARE PROCESS
P3 COMPLETION OF THE HARDWARE PROCESS
THE GOAL IS THAT EVERYBODY CALLS THE SAME ROUTINE AND THAT
AUTOMATICALLY ALL THE RIGHT THINGS WILL HAPPEN
IN ORDER TO DO THIS PHASE 2 WILL BE DESCRIBED FIRST:
PHASE 2:
IF .F 'NEQ' 0
THEN (DVXXCW[.F]_.T4;DVXIPC[.F]_XDNDDB;XMTADR_DVXXCW[.F])
ELSE (XUBXCW[.U]_.T4;XUBIPC[.U]_XDNXUB;XMTADR_XUBIPC[.U];XKBIUN[.W]_.U);
XKBDDB[.W]_.F; FOR INTERRUPT CODE
D28OUT(XMTADR,"1 WORD");
;END OF PHASE 2
PHASE 2 HAS THE FOLLOWING PROPERTIES:
1 NO ASSUMPTION FOR THE PROCESS LEVEL IS MADE
2 FOR EACH PROCESS TYPE THE ACCESS RIGHT HAS TO BEACQUIRED TO
THE DATA BASE OF THE TYPE
3 THE RIGHT TO USE THE HARDWARE HAS TO BEACQUIRED
4 THE UNIT MUST BE UNLOCKED, THIS MEANS WE EXPECT TO DO DATA INPUT
ONLY FROM THIS UNIT.IT IS POSSIBLE FOR SCNQUE TO FIND WORK FOR A UNIT
WHICH IS IN THE LOCKED STATE.UNIT ERRORS AND REJECTS SHOULD UNLOCK
THE UNIT!!
GIVEN THIS THE LOGIC FOR PHASE 1 IS:
IF "AT UUO LEVEL"
THEN ( IF 'NEQ' .F THEN XIOWA0; !!!WAIT FOR UUO USER TO STOP USING THE DDB
!!!!!*****START OF CRITICAL SECTION VULNERABLE TO:
!!!!!*****1. INTERRUPTS
!!!!!*****2. GRANTED INTERRUPTS
IF 'NOT' "GET DA28 CONTROL" 'AND' "UNIT UNLOCKED" THEN
IF .F 'EQL' 0 THEN (Q FUNCTION;EXIT(DOZE0)!REVIVES WORLD)
ELSE (SAVE FUNCTION;SET DVXQUE[.F];RETURN))
;END OF PHASE 1
EXCEPT FOR MINOR DETAILS THIS IS THE COMPLETE CONTENT OF PHASE 1
NOTE THAT PHASE 1 STARTS A CRITICAL SECTION, TERMINATED BY EITHER:
THE DOZE0 CALL OR THE RETURN. IN PHASE 2 THE HARDWARE INITIATION
REVIVES THE WORLD
\
SENDW: NULL
CONSO PI,PI.IPA ;IS A INTERRUPT PROCES HERE
JRST PHASE1 ;NO START PHASE 1
JUMPE F,PHS2NF ;PHASE 2 AND NO DDB
JRST PHS2F ;PHASE 2 AND A DDB
PHASE1: NULL
JUMPE F,NODDB ;NO DDB IN THIS CASE
PUSH P,T4 ;SAVE PROTOCOL WORD
PUSHJ P,XIOWA0 ;WAIT TILL DDB SPACE IS AVAILABLE
MOVE T4,(P) ;RESTORE T4
POP P,DVXST4(F) ;USE DDB NOW AS STORAGE
NODDB: PUSHJ P,D28GET ;TRY TO GET CONTROL AND UNIT
JRST SWAIT ;WE HAVE TO WAIT
JUMPE F,PHS2NF ;PHASE 2 STARTED
JRST PHS2F ;HERE TOO IF THERE IS A DDB
;COME HERE IF DA28 IN USE , UNIT IS LOCKED OR UDB IN USE
SWAIT: NULL
JUMPE F,D28WNF ;WAIT THERE IS NO DDB
XYXY: NULL
PUSHJ P,D28WTF ;WAIT WITH A DDB
SETZM DVXQUE(F) ;NO MORE WAITING
;HERE START THE PHASE 2 ROUTINES AND THE PHASE 3 ROUTINES
;IT IS MANDATORY THAT PHS2F STARTS IMMEDIATELY AFTER THE CALL
;TO D28WTNF
;COME HERE AT INTERRUPT LEVEL FROM SCNQUE FOR A DELAYED SEND
;THIS CODE IS UNLABELED , BUT PRINTX WILL CATCH PROBLEM MAKERS
MOVE T4,DVXST4(F) ;GET THE CW BACK
;COME HERE WHEN THE TRANSFER WAS INITIATED AT INTERRUPT LEVEL
;DUE TO AN EVENT CREATED BY A RECEIVED CTLWD
PHS2F: NULL
MOVEM T4,DVXXCW(F) ;STORE THE PROTOCOL WORD
MOVE T1,[ IOEND,,IODEND] ;END OF FILE STATUS
TDNN T1,DEVIOS(F) ;FOR DDB
JRST PHS2F0 ;NOPE
LDB T1,DVYXMF ;GET MAJOR FUNCTION
CAIE T1,FN.RFI ;AND IF IT IS AN RFI
JRST PHS2F0 ;NO LET IT GO
PUSH P,U ;SAVE UNIT
PUSH P,F ;AND DDB
PUSHJ P,SCNQUE ;SO ALL WILL BE BACK
POP P,F ;GET IT BACK IN LINE
JRST UPOPJ## ;SO WORD DOES NOT CHANGE FOR UUO LEVEL
PHS2F0: NULL
MOVEI T2,XDNDDB ;DONE CODE ADDRESS
MOVEI T1,DVXXCW-1(F) ;MAKE IT EASY FOR D28OUT
PJRST D28XCW ;XMIT A CONTROL WORD
XDNDDB: NULL
IFN .DBLEN,<
PUSHJ P,XCPUT ;TRACE IT
>
LDB T1,DVYXMF ;WHAT WAS SENT OUT
CAIN T1,FN.WFI ;A WFI
MOVEM F,XUBLOK(U) ;LOCK THE UNIT
MOVE T1,MSBTTB(T1) ;GET THE BIT
IORM T1,DVXPST(F) ;AND FLAG IT
SKIPE DVXQUE(F) ;IF THERE IS A QUEUE THEN
PJRST SCNQUE ;LOOK FOR WORK
MOVSI T1,WAKTSK ;ELSE A WAKE ON AN EMPTY Q ACTIVE
TDNN T1,DEVIOS(F) ;CHECK IT
PJRST SCNQUE ;NO GET THE INTERFACE GOING
ANDCAM T1,DEVIOS(F) ;WE DID THE WAKE AND ONCE WILL DO
PUSHJ P,XTWAKE ;WORKTIME
PJRST SCNQUE ;LOOK AROUND
MSBTTB: 0 ;(0) UNDEFINED
0 ;(1) TTY FUNCTION
0 ;(2) REJECT
0 ;(3) ACK
0 ;(4) CLOSE
0 ;(5) MODIFY ATTRIBUTE BYTE
0 ;(6) RESTART
0 ;(7) UNDEFINED
0 ;(10) UNDEFINED
0 ;(11) UNDEFINED
0 ;(12) UNDEFINED
0 ;(13) UNDEFINDE
IOXRFI,,0 ;(14) READY FOR INPUT
IOXRFO,,0 ;(15) READY FOR OUTPUT
IOXWFI,,0 ;(16) WAITING FOR INPUT
IOXWFO,,0 ;(17) WAITING FOR OUTPUT
;PHS2NF DO CONTROL WORD TRANSMISSION FOR NON F PROCESSES
PHS2NF: NULL
MOVEI T2,XDNXUB ;NO Q TO BOTHER ABOUT
PHS2N1: NULL
MOVEM T4,XUBXCW(U) ;STORE THE PROTOCOL
MOVEI T1,XUBXCW-1(U) ;MAKE IT EASY
PJRST D28XCW ;SEND THE WORD
;COME HERE WHEN A QUEUE ENTRY WAS SERVICED
XDNXU0: NULL
MOVE T1,XUBQUE(U) ;GET THE 4 WORD BLOCK ADDRESS
PUSH P,3(T1) ;SAVE THE LINK ADDRESS
PUSH P,1(T1) ;SAVE THE JOB NUMBER
MOVEI T2,4 ;WORDS USED
EXCH T1,T2 ;SWAP
PUSHJ P,GIVWDS## ;GIVE THE FREE CORE BACK
POP P,T1 ;GET THE JOB NUMBER
JUMPE T1,XDNXU1 ;NUL JOB SO DON'T WAKE
PUSH P,W ;ELSE IT EVAPORATES
PUSHJ P,WAKJOB## ;BACK TO WORK
POP P,W ;GET XKB ADDRESS BACK
XDNXU1: POP P,T1 ;GET NEXT XUB REQUEST
MOVEM T1,XUBQUE(U) ;STORE NEXT WORK REQUEST
JUMPN T1,PHS2N0 ;MISUSE OUR PRILIGES
SETZM XUBEND(U) ;ZAP THE END POINTER
;COME HERE TO TRACE AND NOT DEQUE AS SCNQUE WILL DO THIS
XDNXUB: NULL
IFN .DBLEN,<
PUSHJ P,XCPUT
>
PJRST SCNQUE ;SCHEDULE WORK
PHS2N0: NULL
MOVE T4,(T1) ;GET CONTROL WORD
MOVEI T2,XDNXU0 ;A Q ENTRY WAS PROCESSED
PJRST PHS2N1 ;MISUSE OUR POSITION
PLM
;+
;.lm 0
;.hl 1 Send Control Words
;^^
;.subtitle SENDW
; XTCSER must be able to send protocol words to
;different processes running on different small computers all at
;the same time, and also be able to do so both at UUO level and at
;interrupt level. It simplifies the code a great deal if there
;exists a single routine to call which correctly
;determines the state of the DA28C hardware and which either
;immediately initiates the transfer if the DA28C is free or queues
;the request to be initiated later.
; This routine is called SENDW and is divided into two parts.
;The first is called PHASE1 and its purpose is to get permission to
;use the DA28 hardware (and wait if we cannot). This part is
;only used at UUO level since we only run at interrupt level when
;the DA28 has just completed some transfer and is therefore known
;to be idle. The second part is called PHASE2 and has as
;its purpose the starting of the hardware to do the transfer. Then
;there is also a PHASE3, which consists of executing the proper
;termination code when the hardware transfer has finished.
; As this is a reasonably crucial routine in XTCSER, I will
;give the logic in quite some detail:
;.list
;.le;SENDW: -- this is the only entry; the protocol word to be
;sent is in T4. If it is for a DDB F must have the DDB address
;and if it is not for a DDB F must be 0.
;If the caller is executing at interrupt level, skip phase1
;entirely and go to PHS2F if there is a DDB and PHS2NF if there is
;no DDB.
;.le;PHASE1: -- here only at UUO level. (Note that there are two possibilities
;concerning the DA28C hardware: it may be busy or it may not be busy.
;There are also two situations in which we may find ourselves -- with
;a DDB or without. If the DA28C is busy we must queue up the request
;somehow and ensure that the UUO waits long enough for completion.)
;If there is a DDB call XIOWA0. This routine returns immediately if DVXQUE
;is zero, i.e. this DDB does not already
;have a control word queued to go out. Otherwise it calls DOZE0 and
;tries again later. Thus control only passes through this point in
;the DDB case when DVXQUE is free. (Note that the check is made
;with interrupts turned off, but that after we see that it is free
;we turn interrupts back on again. This does not hurt because only
;UUO level can put anything into DVXQUE and we are the only
;ones running at UUO level.)
;When we have ensured our ability to queue the DDB we store the
;protocol word in it (at DVXST4). If we do have to wait, we will
;continue at interrupt level with none of our old context, so this
;is essential.
;.le;NODDB: -- here either with F=0 or with (F .NE. 0) .AND. (DVXQUE = 0).
;Here we call D28GET to attempt to get the DA28C hardware. This routine
;turns off interrupts and returns non-skip if the DA28C is not
;available (with interrupts still off).
;If we get the hardware (skip return) we are finished PHASE1 and
;do precisely what SENDW: did if it was at interrupt level -- namely
;go to PHS2F if we have a DDB and PHS2NF if we do not.
;If we cannot get the hardware, that means we must queue the request.
;In this case we go to D28WNF if we have no DDB, and to XYXY: if we
;have a DDB.
;.le;XYXY: -- here we call D28WTF which pops the return PC off
;the stack into DVXQUE, turns on interrupts and returns to
;the caller of SENDW. The non-zero nature of DVXQUE will cause
;the SCNQUE call at some later interrupt to continue the code at the
;PC in DVXQUE. At this point we clear DVXQUE (we will be the next
;control word out because the hardware is idle because we are at
;interrupt level), copy the saved protocol word (DVXST4) back into
;T4 and fall into PHS2F.
;.le;PHS2F: -- we get here either at UUO level if we got the hardware
;or at interrupt level to actually ship out the control word.
;The code first copies it from T4 into DVXXCW, then tests for the
;special combination of sending RFI when EOF bits are set.
;If this is not the case, the code goes to PHS2F0 to set the
;address to continue with this when the control word is done to
;XDNDDB and calls D28XCW to actually start the hardware transfer and
;return to the caller (of SENDW if at UUO level or of SCNQUE if at interrupt level).
;If we are sending an RFI when we already have EOF bits set we simply
;call SCNQUE to try to select something else to do and avoid sending the control word.
;There are only two times we will be in this situation -- if we are
;doing an INPUT UUO and the EOF came in between the time we tested
;for it at XISYNC and the time we decided to send the RFI. The
;EOF condition will eventually give an error return to the IN
;UUO and in this case we do not want to send the RFI because
;it would be misleading to the small computer.
;Similarly, the XTTSK function to send an RFI checks
;for error bits and gives an error return, and similarly there
;is a race if the EOF comes in at the inappropriate moment.
;By throwing away the RFI in this case, however, we must
;ensure that we do not leave the DA28 neither doing a transfer
;nor scanning, hence the call to SCNQUE.
;.le;PHS2F0: -- here we actually send the control word on the
;behalf of a DDB. Put address of control word (DVXXCW) minus 1
;into T1, address of where to pass control when the done
;interrupt (XDNDDB) into T2, call D28XCW to start the
;output, and return to caller (either of SENDW at UUO level
;or SCNQUE at interrupt level).
;.le;PHS2NF: -- here to send out control word not for a DDB. Same
;as PHS2F except that the address for resuming after an interrupt
;is XDNXUB and the source of the control word (saved from T4 value)
;is XUBXCW.
;.le;PHS2N0: -- this routine is only entered by SCNQUE when it
;finds there is something to send in the XUBQUE.
;This routine gets the control word from the 4-word block, sets up
;the interrupt done address as XDNXU0, calls D28XCW and returns.
;.le;XDNDDB: -- this is where we come at interrupt level when the transfer
;of a control word for the DDB is finished. This code inserts the
;transmitted control word in the control-word trace buffer, then
;checks if we have just transmitted a WFI and if so, stores
;the DDB address in XUBLOK (indicating that the next transfer
;on this unit must be data and not some control word for another
;task-to-task transfer).
;In any case, the bit corresponding to the control word
;function code is gotten from MSBTTB and ORed into DVXPST.
;Then if DVXQUE is zero (i.e. we have shipped all that is queued
;for this DDB) and WAKTSK bit is set in DEVIOS (only set up by XIOWA0 before
;its call to DOZE0) it calls XTWAKE to wake up UUO level.
;Finally, this routine (in all cases) calls SCNQUE to either find another
;transfer to do or to set the scanner going, then exits the interrupt.
;.le;XDNXU0: -- this is the done interrupt routine when we got
;the control word from the XUBQUE queue of 4-word blocks. This routine
;gets the address of the 4-word block we just finished,
;copies the link to the next four word block and the job number,
;frees the 4-word block, calls WAKJOB in UUOCON to wake up the job (if
;the job number is non-zero) and copies the link to the next
;four-word block into XUBQUE. If this is zero (i.e. there are
;no more requests) it clears the XUBEND pointer to
;the last queue entry as well and falls into XDNXUB to trace the
;control word and exit via SCNQUE. If there is another
;entry into the queue it saves some time by not calling SCNQUE but
;instead jumping directly to PHS2N0 (where SCNQUE would go if
;it selected the same unit to work on).
;.le;XDNXUB: -- this is the interrupt routine executed on the done
;interrupt of a control word that was not associated
;with a DDB and had not been queued, as well as the exit
;of the queued case. This routine simply calls XCPUT to
;trace the control word we finished sending, and exits via SCNQUE.
;.end list
;-
MLP
SUBTTL MAKE CONTROL WORDS -- WAIT ROUTINES
;D28WTF WAIT PRIMITIVE FOR A UUO PROCESS WITH A DDB
;NO WAIT WILL BE DONE IF NOT DESIRED
D28WTF: NULL
POP P,DVXQUE(F) ;CODE TO RUN
CONO PI,PI.ON+PI.TNP+XTCBIT## ;HEAR AGAIN
POPJ P,
;D28WNF WAIT ON UUO LEVEL FOR A UUO PROCESS WHEN THE CONTROLLER IS NOT
;FREE THIS USES A LIST OF 4 WORD DATA BLOCKS:
;WORD 0 PROTOCOL WORD
;WORD 1 JOB NUMBER WAITING
;WORD 2 SPARE (ZERO)
;WORD 3 LINK TO NEXT TASK BLOCK OR NIL
;THE LIST HEAD IS IN XUBTSK AND THE END OF THE LAST TASK BLOCK IN
;XUBEND
D28WNF: NULL
PUSH P,T4 ;SAVE THE PROTOCOL WORD
MOVEI T2,4 ;WE WISH A FOUR WORD BLOCK
PUSHJ P,GETWDS## ;GET CORE
SKIPA ;NO ONE FREE YET
JRST GOTCOR ;WE GOT IT
CONO PI,PI.ON+PI.TNP+XTCBIT## ;REVIVE
PUSHJ P,DOZE1 ;SLEEP A BIT
POP P,T4 ;GET CTLW BACK
PUSHJ P,D28GET ;SEE IF CONTROL IS FREE NOW?
JRST D28WNF ;(NO) WAIT SOME MORE
PJRST PHS2NF ;(YES) START PHASE 2 OF SEND NOW
GOTCOR: NULL
POP P,(T1) ;LOAD PROTOCOL WORD
MOVEM J,1(T1) ;STORE JOB NUMBER
SETZM 2(T1) ;SPARE
SETZM 3(T1) ;AND LINK ARE ZERO
MOVE T2,T1 ;COPY OUR ADDRESS
CONO PI,PI.OFF ;NO PROBLEMS
EXCH T2,XUBEND(U) ;GET END POINTER OR ZERO
SKIPE T2 ;BE CAREFUL
MOVEM T1,3(T2) ;LINK IN THE CHAIN
SKIPN XUBQUE(U) ;IF THERE IS NO Q THEN
MOVEM T1,XUBQUE(U) ;MAKE ONE
PJRST DOZE0 ;RETURN AFTER SLEEPING
;XIOWAT USED TO WAIT UNTIL ALL PREVIOUS ACTIVITIES FOR THE
;DDB ARE FINISHED
XIOWAT: NULL
PUSHJ P,WAIT1## ;WAIT FOR I/O TOCOMPLETE
;ENTRY FOR ACTIVE (I/O) JOBS
XIOWA0: NULL
CONO PI,PI.OFF ;SEE IT THE SAFE WAY
SKIPN DVXQUE(F) ;IS DDB READY FOR USE
PJRST ONPOPJ## ;(YES) USE IT
;GET PI'S ON IN DOZE0
MOVSI T1,WAKTSK ;SET THE WAKE REQUEST
IORM T1,DEVIOS(F) ;SO WE WILL WAKE AGAIN
PUSHJ P,DOZE0 ;SLEEP TILL ALL IS READY
JRST XIOWA0 ;MAKE SURE ALL IS OKAY
;XIOWT1 WAIT AND SAVE T1
XIOWT1: NULL
PUSH P,T1 ;SAVE T1
PUSHJ P,XIOWAT ;WAIT TILL ALL FREE
PJRST TPOPJ## ;GO BACK WITH GOOD T1
;CODE TO WAIT UNTIL ALL SENDING OF CONTROL WORDS IS COMPLETED
;THERE ARE 2 STEPS
;1 GUARANTEE THAT THE QUE IS EMPTY (CALL TO XIOWAT)
;2 GUARANTEE THAT NO WORD IS IN THE DA28C PIPELINE
WTQEMP: NULL
PUSHJ P,XIOWAT ;GET THE AUTHORITY OVER DVXQUE
AOS CNTQWT ;NUMBER OF WAITS DONE
HRRZS F ;GURANTEE A UNIQUE VALUE
WTLOP0: HRLZ T1,XTCPAR ;GET THE WAIT PARAMETER
WTLOP1: HLRZ T2,XKBIUN##(W) ;GET THE DDB IF ANY
CAME T2,F ;IS IT US
CAMN F,XKBDDB##(W) ;USING THE DA28C
SKIPA ;IN USE BY US
POPJ P, ;WE ARE NOT USING IT
AOBJN T1,WTLOP1 ;TRY ONCE MORE
JUMPL T1,CPOPJ## ;ALL DONE
AOS CNTWTQ ;SLEEPING FOR THE Q
PUSHJ P,DOZE1 ;SLEEP SORTLY
JRST WTLOP0 ;TRY AGAIN
SUBTTL MAKE CONTROL WORDS -- ROUTINES TO GET ACCESS TO DA28 HARDWARE
;GRBCTL GRAB THE CTL FOR A JOB UNTIL HE GIVES IT BACK
GRBCTL: NULL
PUSHJ P,D28GET ;GET THE CONTROL
SKIPA T1,XKBREQ##(W) ;SEE IF OTHER REQUESTORS
JRST PACIFY ;REALLY REMOVE IT
JUMPE T1,GRBCT0 ;NONE GET IT
PUSHJ P,DOZE1 ;JUST KEEP TRYING
JRST GRBCTL ;UNTIL YOU GET IT
GRBCT0: MOVEM J,XKBREQ##(W) ;SET THE JOB NUMBER
PUSHJ P,DOZE0 ;WAIT A WHILE
SKIPL XKBLOK##(W) ;SEE IF WE REALLY GOT IT
STOPCD .,STOP,TC7, ;WE LOST
SALL
POPJ P, ;USE IT
;GIVCTL GIVE THE CONTROLLER BACK
GIVCTL: NULL
SETZM XKBGRB##(W) ;NO LONGER GRABBED
MOVEI T1,XKBSKP## ;SKIP CONDITION
HRRM T1,XKBINT##(W) ;RESTORE THE SKIP CHAIN
SETOM XKBLOK##(W) ;MAKE THE CONTROL FREE
PJRST SCNQUE ;AND GET LIVE GOING AGAIN
;ZAPCTL IS CALLED TO ALLOCATE THE CONTROL TO THE JOB IN T1
ZAPCTL: NULL
SETZM XKBREQ##(W) ;REQUEST IS OVER
PUSH P,W ;SAVE ADDRESS
PUSHJ P,WAKJOB## ;WAKE THE JOB
POP P,W ;GET ADDRESS BACK
PUSHJ P,D28GEI ;GET AT INTERRUPT LEVEL
PACIFY: NULL
HLLZS XKBINT##(W) ;TAKE IT OUT OF THE SKIP CHAIN
SETOM XKBGRB##(W) ;MARK IT AS GRABBED
POPJ P,
;D28GET THIS BOOLEAN FUNCTION CAN BE CALLED AT UUO AND INTERRUPT
;LEVEL AND WILL TRY TO CLAIM THE INTERFACE.
;NOTE THAT WHEN TRUE IS RETURNED THEN THE DA28 IS DEACTIVATED
; ON UUO LEVEL AND ON A FALSE RETURN THE DA28 IS SILENCED
;THE LOGIC IS :
;D28GET_IF ON INTERRUPT LEVEL THEN TRUE
; ELSE
; (SILENCE THE WHOLE WORLD;
; IF CONTROL BUSY THEN FALSE ELSE ("DEACTIVATE" CONTROL;TRUE)
D28GET: NULL
CONSZ PI,PI.IPA ;AT INTERRUPT LEVEL
JRST D28GE0 ;YES
CONO PI,PI.OFF+PI.TFP+XTCBIT##
SKIPGE XKBLOK(W) ;IS CONTROL FREE
SKIPE XUBLOK(U) ;AND UNIT UNLOCKED
POPJ P, ;NO FALSE!!
JUMPN F,D28GEI ;ALL OKAY FOR DDB STUFF
SKIPE XUBQUE(U) ;ARE ANY REQUESTS FORGOTTEN
STOPCD .,DEBUG,TC0, ;SEE IF IT OCCURRED
SALL
D28GEI: MOVEI T1,XS.CLR ;CLEAR DAC BIT
XCT XTSCNO##(W) ;ZAP DAC
SETZ T1, ;ZAP T1 NOW
XCT XTCCNO##(W) ;TO CLEAR REMOTE INTERRUPT
CONO PI,PI.ON+PI.TNP+XTCBIT##
D28GE0: SETZM XKBLOK##(W) ;NO COMPETETION
PJRST CPOPJ1## ;YOU GOT IT
SUBTTL DATA TRANSFER BEGIN -- STOUTP, STINPT
;SUBROUTINE TO START UP AN OUTPUT TRANSFER
;CALL WITH:
; MOVE T1,<IOWD>
; PUSHJ P,STOUTP
; RETURN HERE
;
STOUTP: NULL
IFE FTKL10,<
HLRZ T2,T1 ;FIXUP FOR HARDWARE FORMAT
LSH T2,4
HRL T1,T2
>;END IFE FTKL10
PUSHJ P,SETKON ;SET UP HARDWARE
LDB T1,DVYHWM ;GET HARDWARE MODE
LSH T1,MODLSH ;GET IT IN PLACE
IORI T1,XC.CON!XC.OUT!XC.BSY!XC.MEM!XC.FST ;START THE TRANSFER
XCT XTCCNO##(W)
POPJ P,0 ;RETURN
;SUBROUTINE TO START AN INPUT TRANSFER
;CALL WITH:
; MOVE T1,<IOWD>
; PUSHJ P,STINPT
; RETURN HERE
;
STINPT: NULL
IFE FTKL10,<
HLRZ T2,T1 ;ADJUST WC FOR HARDWARE
LSH T2,4
HRL T1,T2
>;END IFE FTKL10
MOVEI T2,0 ;SET TO CLEAR OUT DR
XCT XTSDTO##(W) ;...
PUSHJ P,SETKON ;SET UP HARDWARE
LDB T1,DVYHWM ;GET THE HARDWARE MODE
LSH T1,MODLSH ;SHIFT MODE IN THE RIGHT PLACE
IORI T1,XC.CON!XC.BSY!XC.MEM!XC.FST ;START THE TRANSFER
XCT XTCCNO##(W)
POPJ P,0 ;RETURN
SUBTTL DATA TRANSFER BEGIN -- D28XCW TO START CONTROL WORD
;D28XCW XMIT A CONTROL WORD
;.T1 IS THE CW ADDRESS
;.T2 IS THE XMIT DONE CODE ADDRESS
D28XCW: NULL
HRLI T1,WC(1) ;ONE WORD GOES
HRL U,F ;COPY DDB OR NO DDB
MOVEM U,XKBIUN##(W) ;REMEMBER THE UNIT
HRRZM T2,XUBIPC(U) ;SET COMPLETION ADDRESS
SETZ T2,
IFE LIVE,<
IFE FTKL10 <
DATAI APR,T2 ;READ CONSOLE
HRR T2,.TRCF ;AND TRACE FLAGS
>;end IFE FTKL10
IFN FTLK10 <HRRZ T2,.TRCF> ;AND TRACE FLAGS
TDNN T2,[10,,4] ;TRY EITHER SWITCH
PUSHJ P,TRCXCW ;call trace routine
>;end IFE LIVE
;FALL INTO D28OUT
;D28OUT GET OUT DATA
D28OUT: NULL
PUSH P,T1 ;SAVE ADDRESS OF CONTROL WORD
ANDI T1,-1 ;JUST ADDRESS
PUSHJ P,OUCHE## ;GET OUT INTO PHYSICAL MEMORY
POP P,T1 ;RESTORE IOWD
PUSHJ P,SETKCW ;SET CONTROL
MOVEI T1,XC.CON!XC.OUT!XC.BSY!DM.BIN!XC.MEM!XC.FST
XCT XTCCNO##(W) ;GO
POPJ P,
SUBTTL DATA TRANSFER BEGIN -- SETUP SUBROUTINES SETKON, D28CLR, FRCOFL
;SUBROUTINE TO LOAD DA28 REGS FOR DATA XFER
;CALL WITH:
; MOVE T1,<IOWD FOR DAC>
; PUSHJ P,SETKCW/SETKON
; RETURN HERE
;CALL SETKCW FOR CONTROL-WORD DATA TRANSFER (NO NEED TO SET T1 WITH
;AN IOWD) OR SETKON FOR A TRUE DATA TRANSFER (NEEDS IOWD AND WILL
;FLUSH THE CACHE ON A KL-10.
SETKON: NULL
IFN FTKL10 <
PUSHJ P,CSDMP## ;FLUSH OUT CACHE FOR DMA DA28-C
>;END IFN FTKL10
SETKCW: NULL ;NON-FLUSH ENTRY
XCT XTCDTO##(W) ;LOAD DAC
MOVE T1,XUBUNO(U) ;PICK UP NEW UNIT NUMBER
LSH T1,UNILSH ;SHIFT THE UNIT NUMBER
IORI T1,XS.ETI+XTCCHN## ;SET TIMING ERRORS AND PIA
;THE FOLLOWING CODE IS TO HANDLE THE DA28-C HARDWARE BUG FIXED BY
;ECO 7. DA28-C'S PRIOR TO THIS ECO WOULD CAUSE THE SMALL COMPUTER
;TO SEE AN ERROR ON THE RE-SELECTING OF THE SAME UNIT IN THE CODE
;FIELD (THE DA28-C INTERNALLY WENT THROUGH A 0-CODE STATE SETTING
;THE NEW CODE, WHICH 0-CODE STATE WAS PERCEIVED BY THE SMALL COM-
;PUTER INTERFACE, WHICH THOUGHT IT HAD BEEN DISCONNECTED). THIS
;PROBLEM WAS ONLY VISIBLE ON UNITS OTHER THAN UNIT 0, AND TYPICALLY
;ONLY UNDER HEAVY SYSTEM LOAD. IF THE DA28-C IS PRE-ECO 7 THEN
;SET ECO7=0.
IFE ECO7,<
PUSH P,T1 ;SAVE DESIRED UNIT/PIA
XCT XTSCNI##(W) ;READ CURRENT DA28-C STATUS
IORI T1,XS.ETI ;TURN ON THIS FLAG
ANDI T1,<17_UNILSH>!XS.ETI!7 ;REDUCE TO IMPORTANT BITS
CAMN T1,(P) ;RE-SELECTING SAME UNIT?
JRST TPOPJ## ;YES, THEN DO NOTHING
POP P,T1 ;NO, RESTORE NEW UNIT DESIRED
> ;END OF DA28-C PRE-ECO 7 HANDLER
XCT XTSCNO##(W) ;LOAD UNIT CODE & PIA
POPJ P, ;RETURN
;D28CLR CLEAR ALL DA28 ERRORS
D28CLR: NULL
MOVEI T1,XS.CLR+XTCCHN##
XCT XTSCNO##(W) ;CLR ERRORS
POPJ P,
;FRCOFL IS CALLED WITH W AND U SET UP IN THE PROPER WAY
;THERE ARE 2 RETURNS YOU LOSE OR YOU WIN
FRCOFL: NULL
PUSHJ P,GRBCTL ;FIRST GET THE CONTROL
MOVE T1,XUBUNO(U) ;GET THE UNIT NUMBER
LSH T1,UNILSH ;IN THE RIGHT PLACE
XCT XTSCNO##(W) ;AND SET THE UNIT FIELD
MOVEI T1,XC.CON ;NEXT
XCT XTCCNO##(W) ;CONNECT SO FORCE SET BY AN EP
SETZ T1, ;WILL DISAPPEAR NEXT
XCT XTCCNO##(W) ;WHEN WE DISCONNECT
DELAYY T1 ;DELAY FOR DA28Y'S
MOVE T1,XUBUNO(U) ;GET THE UNIT NUMBER
LSH T1,UNILSH ;IN THE RIGHT PLACE
IORI T1,XS.FRC ;GET FORCE BIT
XCT XTSCNO##(W) ;AND DRIVE IT HOME
DELAYY T1 ;WAIT FOR THE Y
MOVEI T1,XC.CON ;CONNECT NEXT
XCT XTCCNO##(W) ;BACK TO UNIT
XCT XTCCNI##(W) ;GET THE STATUS
TLNE T1,XC.DRD ;IS IT NOT READY
AOS -1(P) ;(YES) SO SET WIN RETURN
SETZ T1, ;ZAP T1 AS SCNQUE WILL CLEAR
XCT XTCCNO##(W) ;DISCONNECT
PJRST GIVCTL ;GIVE IT BACK
SUBTTL COROUTINE SUPPORT ROUTINES $COROUT, SYNC$, CPOPJx
;$COROUT ENABLES A SIMPLE COROUTINE MECHANISM BETWEEN
;UUO AND INTERRUPT LEVEL.THE ESSENTIAL THING IS THAT NOTHING IS LEFT
;ON THE STACK ON A COROUTINE EXIT.THE BENEFIT IS THE LACK OF THE
;NEED TO HAVE STACK SPACE IN THE DDB
$COROUT:NULL
CONSZ PI,PI.IPA ;IF AT INTERRUPT LEVEL THEN
POPJ P, ;IGNORE AS ALL IS SETUP
MOVEM T1,DVXMSK(F) ;RESET MASK
EXCH T1,(P) ;GET RETURN ADDRESS AND SAVE T1
EXCH T1,-1(P) ;REMOVE RETURN TO COROUT CALLER
MOVEM T1,DVXPRC(F) ;REMEMBER THE CALLER
PJRST TPOPJ## ;RESTORE T1 AND FALL IN COROUTINE
;SYNC$ WAIT FOR ACTION AT INTERRUPT LEVEL
;THIS ROUTINE DEPENDS ON THE RACE FREE OPERATION OF THE WAKE
;HIBER MECHANISM
;IT WILL SUSPEND OPERATIONS AND RETURN TO THE CALL POINT
;NEEDED AGAIN
;CAN BE CALLED AT UUO AND INTERRUPT LEVEL
SYNC$: NULL
MOVEM T1,DVXMSK(F) ;REDEFINE THE MASK
CONSZ PI,PI.IPA ;AT INTERRUPT LEVEL
JRST SYNC30 ;A DIFFERENT STORY
SYNC10: HRLZ T3,XTCPAR ;RETRY COUNT
SYNC20: PUSHJ P,IFEBTS ;SEE IF ANYTHING CAME
POPJ P, ;WAITING IS OVER
AOBJN T3,SYNC20 ;TRY IT THIS MANY TIMES
CONO PI,PI.OFF ;DON'T BOTHER ABOUT DA28
PUSHJ P,IFEBTS ;ANY BITS SET
PJRST ONPOPJ## ;YES TURN ON PI AND RETURN
POP P,DVXCOR(F) ;HERE INTERRUPT LEVEL SHOULD GO ON
PUSHJ P,DOZE0 ;SLEEP A WHILE
SKIPN DVXCOR(F) ;ANY COROUTINE STILL ACTIVE?
PJRST @DVXPRC(F) ;(NO) JUMP BACK
PUSH P,DVXCOR(F) ;put co-routine address back on stack [7136]
JRST SYNC10 ;JUST TRY IT AGAIN
SYNC30: NULL
PUSHJ P,IFEBTS ;IF ANY BITS THEN
POPJ P, ;ALL SET SO GO BACK
POP P,DVXCOR(F) ;NO CONTINUE HERE
POPJ P, ;THE COROUTINE
;ESCAPE CODE FROM INTERRUPT LEVEL
;CPOPJ$ IF ON UUO LEVEL THEN GO TO CPOPJ ELSE WAKE JOB
;CPOJ1$ IF ON UUO LEVEL THEN GO TO CPOPJ1 ELSE GO TO <.DVXIPC+1>
;CPOJ2$ IF ON UUO LEVEL THEN GO TO CPOPJ2 ELSE GO TO <.DVXIPC+2>
;
CPOJ2$: NULL
AOS DVXPRC(F) ;SKIP ONE MORE
CPOJ1$: NULL
AOS DVXPRC(F) ;AND ONE MORE
CPOPJ$: NULL
SETZM DVXCOR(F) ;NO MORE WATING
CONSO PI,PI.IPA ;AT UUO LEVEL
PJRST @DVXPRC(F) ;ALL SET
PUSHJ P,XTWAKE ;WAKE THE JOB
POPJ P,
SUBTTL SLEEP AND WAKE ROUTINES
;SLEEPY CODE
DOZE0: NULL
JUMPE F,DOZE00 ;NO F SO FORGET
MOVSI S,HIBTSK ;HIBERNATE FLAG
IORB S,DEVIOS(F) ;SET THE FLAG
AOS CNTHIB ;COUNT HIBERS
DOZE00: TDZA T1,T1 ;SLEEP VERY LONG
DOZE1: MOVEI T1,2 ;SLEEP SHORTLY
CONO PI,PI.ON+PI.TNP+XTCBIT## ;START LIFE AGAIN
PUSH P,W ;SAVE THE KDB
PUSHJ P,HIBER## ;THERE YOU GO [7136]
POP P,W ;GET CONTROLLER ADDRESS BACK
MOVE S,DEVIOS(F) ;GET THE CHANGED VALUE
POPJ P,
;SUBROUTINE TO WAKE UP A SLEEPING JOB
;CALL WITH:
; MOVEI F,ADDRESS-OF-DDB [OR 0]
; PUSHJ P,XTWAKE
; RETURN HERE
;
XTWAKE: NULL
JUMPE F,CPOPJ## ;NO-OPERATION IF NO DDB
MOVSI S,HIBTSK!WAKTSK ;IT WILL BE RESET!!
TDNN S,DEVIOS(F) ;CHECK IT
JRST XTWAK0 ;NO LEAVE JOB ALONE
ANDCAB S,DEVIOS(F) ;ZAP THE HIBER FLAG
;XTWAKA WAKE ALWAYS ENTRY FOR REC DST
XTWAKA: NULL
PUSH P,T1 ;SAVE T1
LDB T1,PJOBN## ;GET JOB NUMBER
JUMPE T1,TPOPJ## ;NOP IF JOB 0
PUSH P,W ;SAVE W
AOS CNTWAK ;COUNT THE WAKES
PUSHJ P,WAKJOB## ;WAKE THE JOB
POP P,W ;RESTORE W
POP P,T1 ;GET T1 BACK
XTWAK0: MOVE S,DEVIOS(F) ;FOR CALLER
POPJ P,
SUBTTL EVENT COUNTERS
$LOW ;STORE IN LOW
;DATA STORAGE FOR STATISTICS
CNTHIB:BLOCK 1 ;NUMBER OF HIBERS
CNTWAK:BLOCK 1 ;NUMBER OF WAKES
CNTINP:BLOCK 1 ;NUMBER OF INPUTS
CNTOUT:BLOCK 1 ;NUMBER OF OUTPUTS
PSZERO:BLOCK 1 ;# OF LOOSING PSEUDO ACTS
PSMAKE:BLOCK 1 ;# OF PSEUDO ACTIVE MAKES
CNTWTQ:BLOCK 1 ;#OF HIBERS IN WTQEMP
CNTQWT:BLOCK 1 ;# OF HIBERS FOR WTQEMP
DBGPAR: IFE .DBLEN,< Z> ;NO TRACE BUFFER
IFN .DBLEN,< .DBUFP,,.DBLEN> ;ADDRESS AND LENGTH OF TRACE BUFFER
XTCPAR::ACTTIM,,-QLPCNT ;PARAMETERS
;ACTTIM IS # OF PSEUDO ACTIVE SECONDS
;QLPCNT IS # OF TRIES BEFORE A HIBER STARTS
XALL
$LIT ;LITERALS
SALL
PLM
;+
;.lm 0
;.chapter Debugging Aids
;^^\\
; ^THERE ARE THREE DEBUGGING FEATURES AVAILABLE WITH
;^^XTCSER\\:
;.SKIP
;.LIST
;.LE;AN IN-CORE TRACE OF PROTOCOL WORDS TRANSFERRED IN BOTH DIRECTIONS
;(NORMALLY ENABLED) TOGETHER WITH A CATEGORY ^C PROGRAM (CALLED ^^XTDUMP\\)
;TO PRINT THE CONTENTS OF THIS TABLE;
;.LE;A DYNAMIC TRACE OF PROTOCOL MESSAGES ON THE CONSOLE ^^TTY\\ AS THEY ARE SENT
;OR RECEIVED AND
;.LE;AN IN-CORE TRACE OF EXECUTION FLOW WITHIN ^^XTCSER\\
;.END LIST
;.HL 1 ^^XTDUMP\\
;.SUBTITLE ^^XTDUMP\\
; ^THE ^^XTDUMP\\ PROGRAM READS THE PROTOCOL WORD TRACE
;TABLE OF EITHER A RUNNING MONITOR, OR FROM AN ^^EXE\\ FILE
;DUMP OF A CRASH.
;^IT PRINTS THE CONTENTS ON DEVICE ^^LPT:\\ IN A SEMI-FORMATTED
;FASHION.
;^^XTDUMP\\ MAY BE ASSEMBLED BY ASSEMBLING ^^MACROS.MAC\\ TO
;PRODUCE A UNIVERSAL FILE ^^MACROS.UNV\\, THEN ASSEMBLING
;^^XTDUMP\\ AND ^^EXESUB\\, AND FINALLY LINKING THESE TWO
;MODULES TOGETHER WITH ^^HELPER\\ AND ^^SCAN\\.
; ^TO DUMP THE TRACE TABLE OF A RUNNING
;MONITOR, THE USER NEED ONLY START THE PROGRAM; IT DETERMINES
;THE LOCATION AND SIZE OF THE TRACE TABLE BY ISSUING AN
;^^XTTSK\\ ^^UUO\\.
; ^TO DUMP THE TRACE TABLE FROM A CRASH FILE, THE USER MUST
;START THE PROGRAM BY TYPING A LINE OF THE FORM
;.SKIP
;.INDENT 10
;^^RU XTDUMP\\-FILESPEC
;.SKIP
;WHERE "FILESPEC" CONTAINS THE NAME OF THE FILE CONTAINING
;THE CRASH.
;^IN THIS CASE, ^^XTDUMP\\ WILL ASK THE USER TO ENTER
;THE ADDRESS OF THE TRACE TABLE (VALUE OF ^^.DBUFP\\ IN
;^^XTCSER\\) AND ITS LENGTH (USUALLY 400, WHICH IS
;VALUE OF ^^DBLEN\\ IN ^^XTCSER\\).
; ^THE FOLLOWING IS AN EXAMPLE OF THE OUTPUT OF ^^XTDUMP\\:
;.SKIP.NOFILL.NOJUSTIFY
;^^
;030734/ 400001,,000200 777570,,200020 _<-- A0 WFO (1)
;030736/ 000001,,000201 737573,,600020 --_> A0 WFI (1)
;030740/ 600001,,000201 777777,,000000 _< D
;030742/ 400001,,000200 202000,,200020 _<-- A0 CLSEOF (1)
;030744/ 000001,,000200 314003,,600020 --_> A0 RSTRTK (1)
;030746/ 400001,,000202 202000,,200020 _<-- A0 CLSEOF (1)
;030750/ 000001,,000202 314003,,600020 --_> A0 RSTRTK (1)
;030752/ 400001,,000000 314000,,200020 _<-- A0 RSTRTK (1)
;030754/ 000001,,000000 102000,,000020 --_> A0 REJNOT (1)
;030756/ 400001,,000002 777764,,200020 _<-- A0 WFO (1)
;030760/ 000001,,000201 737767,,600020 --_> A0 WFI (1)
;030762/ 600001,,000201 777777,,000000 _< D
;030764/ 400001,,000200 637570,,200020 _<-- A0 RFI (1)
;030766/ 000001,,000221 677573,,600020 --_> A0 RFO (1)
;030770/ 000001,,000221 777573,,600020 --_> A0 WFO (1)
;030772/ 400001,,000221 737570,,200020 _<-- A0 WFI (1)
;030774/ 200001,,000221 777777,,000000 _> D
;.SKIP.FILL.JUSTIFY
;\\
;^THE COLUMN ON THE LEFT IS THE ADDRESS (IN THE MONITOR) OF THE
;TRACE BUFFER ENTRY. ^IT IS FOLLOWED BY THE TWO WORDS AT THAT ADDRESS
;IN OCTAL. ^THE FIRST WORD INDICATES WHAT TYPE OF TRACE ENTRY IT
;IS (DATA OR CONTROL WORD), THE DIRECTION, THE CONTROLLER AND THE UNIT.
;(^FOR MORE DETAIL, SEE THE ROUTINES ^^XCPUT\\ AND ^^RCPUT\\ IN THE
;LISTING OF ^^XTCSER\\.)
;^THE NEXT WORD IS THE ACTUAL CONTROL WORD TRANSFERRED.
;^THE FINAL PORTION OF THE LINE IS AN "INTERPRETATION" OF THIS
;DATA, GIVING THE DIRECTION (VIA THE ARROW, TO THE LEFT MEANS
;TO THE -10), THE CONTROLLER AND UNIT (^A0), THE
;TYPE OF CONTROL WORD (^^RFI, RFO\\, ETC.) AND THE TASK ^^ID\\
;(IN PARENTHESES).
; ^^NOTE\\: ^^XTDUMP\\ IS NOT A SUPPORTED PROGRAM; IT IS
;SUPPLIED WITH ^^XTCSER\\ BECAUSE OF ITS USEFULNESS IN TRACKING
;DOWN PROTOCOL PROBLEMS FOR CUSTOMERS IMPLEMENTING ^^LIPS\\
;ON A SMALL COMPUTER.
;.HL 1 ^CONSOLE AND ^EXECUTION ^TRACE
;.SUBTITLE ^CONSOLE ^TRACE
; ^THE OTHER TWO DEBUGGING FEATURES OF ^^XTCSER\\ REQUIRE
;RE-ASSEMBLING ^^XTCSER\\ WITH SOME DEBUGGING SWITCHES
;ON.
;^BOTH ARE UNDER THE CONTROL OF THE FEATURE TEST
;SWITCH "^^LIVE\\", WHICH IS NORMALLY ENABLED
;(-1) AND WHICH IS DISABLED BY SETTING ITS VALUE TO 0.
;(^THE RATIONALE BEHIND THIS NAME IS:
;IF THE SYSTEM IS "LIVE" IT IS NOT DEBUGGING, AND IF IT IS
;DEBUGGING IT IS NOT "LIVE".)
;.HL 2 ^CONSOLE ^TRACE OF ^PROTOCOL ^WORDS
;.SUBTITLE ^CONSOLE ^TRACE
; ^THIS FEATURE ALLOWS THE DYNAMIC TRACING OF PROTOCOL
;MESSAGES ON THE SYSTEM CONSOLE.
;^EACH DIRECTION OF MESSAGE CAN BE INHIBITED FROM THE TRACE BY
;EITHER SETTING A SWITCH IN THE SWITCH REGISTER (^^KA\\ AND
;^^KI\\) OR BY SETTING A SOFTWARE BIT IN THE WORD
;"^^.TRCF\\".
;^THIS FEATURE IS MOSTLY USEFUL WHEN DEBUGGING A ^^DA28\\
;DRIVER ON A SMALL COMPUTER WITH SOMETHING LIKE ^^DDT\\, WHICH
;IMPLIES THAT THE CONTROL WORDS TO BE TRACED ON THE CONSOLE APPEAR
;RELATIVELY INFREQUENTLY. ^IF THE PROTOCOL IS RUNNING AT FULL SPEED
;THE CONSOLE WON'T BE ABLE TO KEEP UP, AND DATA (IN THE
;TRACE) WILL BE LOST.
;BECAUSE OF THIS, IN CURRENTLY DISTRIBUTED ^^XTCSER\\S THIS TRACE IS
;DISABLED BY ASSEMBLING THE APPROPRIATE TWO BITS IN THE
;WORD ^^.TRCF\\ (TO INHIBIT CONSOLE TRACE OF RECEIVE AND TRANSMIT
;CONTROL WORDS) AS ONES.
;.HL 2 ^EXECUTION ^TRACE
;.SUBTITLE ^EXECUTION ^TRACE
; ^THE THIRD DEBUGGING FEATURE IS GOVERNED BY THE
;FEATURE TEST SWITCH ^^FTETR\\.
;^THIS IS NORMALLY SET ON (-1) BY DEFAULT IF
;^^LIVE\\ IS ON (0) AND MAY BE TURNED OFF BY
;SETTING ^^FTETR\\ TO 0.
;^THIS CAUSES EVERY ^^NULL\\ MACRO CALL (USUALLY AT EVERY LABEL) IN ^^XTCSER\\ TO GENERATE A
;TWO-WORD CALL TO AN EXECUTION TRACE ROUTINE.
;^THIS ROUTINE DOES NOTHING IF THE SIGN BIT OF
;THE WORD "^^ETRFLG\\" IS NOT ON; HOWEVER, IF IT IS
;ON, IT STORES THE ^^RH\\ OF THE CURRENT ^^CONI PI\\
;STATE IN THE ^^LH\\ OF THE TRACE TABLE ENTRY, AND
;THE CURRENT ^^PC\\ IN THE ^^RH\\ OF THE TRACE TABLE
;ENTRY.
;^THE TRACE BUFFER BEGINS AT ^^EBUF\\, AND IS "^^ENMENT\\"
;ENTRIES LONG (CURRENT DEFAULT IS 4000 OCTAL).
;^ANOTHER BIT IN ^^ETRFLG\\ (NAMELY ^^ETR.ST\\) INHIBITS
;THE TRACE CODE FROM WRAPPING AROUND THE BUFFER (THEREFORE
;DESTROYING PREVIOUS ENTRIES).
;^THIS IS USEFUL WHEN YOU WANT TO START COLLECTING TRACE
;INFORMATION FROM A GIVEN POINT FOR AS LONG AS POSSIBLE.
;^IF THIS BIT IS CLEAR, THE TRACE WILL WRAP AROUND, AND THE
;WORD ^^EPNT\\ WILL INDICATE THE NEXT WORD TO USE
;IN THE TRACE BUFFER.
;^THIS MODE OF OPERATION IS USEFUL IF YOU WANT TO
;TRACE AS MUCH INFORMATION AS POSSIBLE ENDING AT A CERTAIN
;POINT.
; ^A CALL TO THE TRACE ROUTINE MAY BE MODIFIED
;BY THE USER (VIA ^^EDDT\\) FOR SEVERAL REASONS:
;.LIST
;.LE;TO ELIMINATE A TAG FROM ANY TRACING, REPLACE THE
;^^PUSHJ P,ETRACE\\ WITH A ^^SKIPA\\
;(IF YOU WISH TO ELIMINATE A TAG FROM TRACING PERMANENTLY,
;YOU MAY EDIT THE ^^NULL\\ MACRO TO HAVE THE WORD "^^NOTRACE\\"
;AS AN ARGUMENT)
;.LE;TO START TRACING AT A SPECIFIED TAG,
;REPLACE THE ^^PUSHJ P,ETRACE\\ WITH A ^^PUSHJ P,ETRCON\\
;(WHICH SETS THE SIGN BIT OF THE ^^ETRFLG\\ WORD TO ENABLE
;TRACING)
;.LE;TO STOP TRACING AT A SPECIFIED TAG,
;REPLACE THE ^^PUSHJ P,ETRACE\\ WITH A ^^PUSHJ P,ETRCOF\\
;(WHICH CLEARS THE SIGN BIT OF THE ^^ETRFLG\\ WORD TO
;PREVENT FURTHER TRACING)
;.END LIST
;^^NOTE:\\ THAT THE TRACE ROUTINE IS CODED TO PROPERLY
;HANDLE ONLY SINGLE SKIPS BEFORE A ^^NULL\\ MACRO
;CALL; DOUBLE SKIPS (SUCH AS SUBROUTINE RETURNS) WILL
;NOT WORK.
; ^THE EXECUTION TRACE BUFFER IS SUITABLE FOR EXAMINING
;WITH AND MONITOR ^^DDT\\, I.E.#^^EDDT\\ IF STAND-ALONE
;OR ^^FILDDT\\ IF IN A CRASH OR DURING TIMESHARING.
; ^THE FOLLOWING IS AN EXCERPT FROM THE ^^FILDDT\\ OUTPUT OF
;THE TRACE BUFFER FROM A RUNNING MONITOR (HOWEVER THE TRACE
;BIT HAD AT THIS POINT BEEN TURNED OFF). IT WAS DONE WITH THE
;_<^^ALT\\_>^Y COMMAND (SO THE OUTPUT WOULD GO TO
;^^LPT:\\) WITH ^^LPT:\\ ASSIGNED TO ^^DSK:\\. ^THE CONTENTS OF THE
;^^.DDT\\ FILE WAS MERELY A NOT-WORD SEARCH OF THE TRACE BUFFER FOR
;0.
;^THE COMMENTS AT THE END OF EACH LINE ARE A RUNNING COMMENTARY ^I ADDED
;TO SHOW WHAT IS GOING ON. ^THE TRACE SHOWS WHAT HAPPENS DURING
;A SINGLE DATA TRANSFER FROM THE -10 TO THE 11.
;.NOFILL.NOJUSTIFY.SKIP
;^^
;30236/ JBTJLT+53,,XTCINT_# interrupt occured
;30237/ JBTJLT+53,,REMINT_# it was select request
;30240/ JBTJLT+53,,IDLE28_# DA28 hdw idle?
;30241/ JBTJLT+53,,FNDUNI_# yes, so look for UDB
;30242/ JBTJLT+53,,SETKON_# unit not locked, set up read CW
;30243/ JBTJLT+53,,XTCINT_# another interrupt
;30244/ JBTJLT+53,,UNIINT_# done and XKBDDB=0, so CW done
;30245/ JBTJLT+53,,RECUCW_# done for read of CW
;30246/ JBTJLT+53,,FNDTSK_# find DDB for task ID
;30247/ JBTJLT+53,,SETACS_# trace word and set ACs from DDB
;30250/ JBTJLT+53,,RECRFI_# dispatch on CW type=RFI
;30251/ JBTJLT+53,,SETBIT_# ##set IORRFI in DVXPST and return
;30252/ JBTJLT+53,,CHKPRC_# can we further co-routine
;30253/ JBTJLT+53,,CHKWAK_# no, see if we need to wake job
;30254/ JBTJLT+53,,SCNQUE_# no, look for work
;30255/ JBTJLT+53,,IDLE28_# ##check if DA28 idle
;30256/ JBTJLT+53,,CLRERR_# yes, but no work so clear it
;30257/ JBTJLT+53,,SETSCN_# set it scanning and exit
;30260/ DBS_#+43,,XTCIOS_# someone did GETSTS or something
;30261/ DBS_#+43,,XTCDEV_# ##which looks at DEVIOS
;30262/ DBS_#+43,,XTCDOU_# dump mode OUT UUO
;30263/ DBS_#+43,,OUTSET_# set IO bit in DEVIOS
;30264/ ##DBS_#+43,,SETACS_# ##and ACs from DDB info
;30265/ ##DBS_#+43,,GETMOD_# ##set up hdw mode based on softw mode
;30266/ ##DBS_#+43,,RDYCHK_# ##check if unit believed up
;30267/ ##DBS_#+43,,PSACT_# ##yes, make us pseudo-active
;30270/ DBS_#+43,,DMPSET_# copy user IOWDs into DVXIWD
;30271/ DBS_#+43,,OUTCOM_# common code dump/buffered OUT
;30272/ DBS_#+43,,XOSYNC_# start synchronization co-routine
;30273/ DBS_#+43,,$COROU_# ##save co-rout return in DVXPRC
;30274/ DBS_#+43,,MAKRFO_# ##no errors, must send RFO
;30275/ DBS_#+43,,FINMS2_# ##make it in T4
;30276/ DBS_#+43,,FINMSG_# ##and finish it
;30277/ DBS_#+43,,ADDSIZ_# ##add transfer size
;30300/ DBS_#+43,,SENDW_# ##try to output it
;30301/ DBS_#+43,,PHASE1_# ##at UUO level
;30302/ DBS_#+43,,XIOWA0_# ##wait for DVXQUE to be zero
;30303/ DBS_#+43,,D28GET_# ##it was, try to get DA28
;30304/ DBS_#+43,,PHS2F_# ##it was idle, start output
;30305/ DBS_#+43,,PHS2F0_# ##not RFI when EOF, so put it out
;30306/ DBS_#+43,,D28XCW_# ##send it; done will be XDNDDB
;30307/ DBS_#+43,,D28OUT_# ##set up hardware for output
;30310/ DBS_#+43,,SETKON_# ##and controller, flush cache
;30311/ DBS_#+43,,XOSYN1_# ##back in synch co-routine
;30312/ DBS_#+43,,CPOJ1$_# ##all done, RFI already seen
;30313/ DBS_#+43,,CPOPJ$_# ##increment DVXPRC, exit co-routine
;30314/ DBS_#+43,,XTCOU0_# check if counts agree
;30315/ DBS_#+43,,XTCOU1_# yes, check if bypassing
;30316/ DBS_#+43,,MAKACT_# make job IO active
;30317/ DBS_#+43,,XTCOU2_# not bypassing, use WFO
;30320/ DBS_#+43,,MAKWFO_# build it
;30321/ DBS_#+43,,FINMS2_# finish it off
;30322/ DBS_#+43,,FINMSG_# ...
;30323/ JBTUPM+103,,XTCINT ####interrupt!!
;30324/ JBTUPM+103,,UNIINT_# ####done for CW output
;30325/ JBTUPM+103,,XDNDDB_# ####where we told it to go
;30326/ JBTUPM+103,,SCNQUE_# ####set bit, and check for work
;30327/ JBTUPM+103,,IDLE28_# ####hardware idle
;30330/ JBTUPM+103,,CLRERR_# ####nothing to do, so clear hdw
;30331/ JBTUPM+103,,SETSCN_# ####set scanner going
;30332/ DBS_#+43,,ADDSIZ_# add size to CW
;30333/ DBS_#+43,,SENDW_# try to send it
;30334/ DBS_#+43,,PHASE1_# at UUO level
;30335/ DBS_#+43,,XIOWA0_# DVXQUE 0
;30336/ DBS_#+43,,D28GET_# yes, hdw free
;30337/ DBS_#+43,,PHS2F_# yes, start it
;30340/ DBS_#+43,,PHS2F0_# CW send
;30341/ DBS_#+43,,D28XCW_# send it
;30342/ DBS_#+43,,D28OUT_# set up hardware
;30343/ DBS_#+43,,SETKON_# and flush cache and go
;30344/ JBTUPM+103,,XTCINT my, another interrupt
;30345/ JBTUPM+103,,UNIINT_# done for CW
;30346/ JBTUPM+103,,XDNDDB_# where we told it to go
;30347/ JBTUPM+103,,SCNQUE_# set bit, exit looking for work
;30350/ JBTUPM+103,,IDLE28_# hdw free
;30351/ JBTUPM+103,,CLRERR_# yes, no work, clear hdw
;30352/ JBTUPM+103,,SETSCN_# set up scanner
;30353/ JBTUPM+103,,XTCINT_# another interrupt
;30354/ JBTUPM+103,,REMINT_# select request
;30355/ JBTUPM+103,,IDLE28_# check if we really were idle
;30356/ JBTUPM+103,,FNDUNI_# find UDB
;30357/ JBTUPM+103,,SETKON_# XUBLOK 0 (so not data) so read CW
;30360/ JBTUPM+103,,XTCINT_# interrupt
;30361/ JBTUPM+103,,UNIINT_# done for CW
;30362/ JBTUPM+103,,RECUCW_# which we read
;30363/ JBTUPM+103,,FNDTSK_# get DDB from task ID
;30364/ JBTUPM+103,,SETACS_# got one, set up other ACs
;30365/ JBTUPM+103,,RECWFI_# dispatch for CW type
;30366/ JBTUPM+103,,DDBIO_# start data transfer
;30367/ JBTUPM+103,,NXTIOW_# get next (really 1st) IOWD
;30370/ JBTUPM+103,,NXTIO0_# ...
;30371/ JBTUPM+103,,SBINIO_# got one, do we need to copy
;30372/ JBTUPM+103,,STOUTP_# no, map it and start output
;30373/ JBTUPM+103,,SETKON_# flush cache and do it
;30374/ JBTUPM+103,,CHKPRC_# look for progress on co-routines
;30375/ JBTUPM+103,,CHKWAK_# none, look for wake requests
;30376/ JBTUPM+103,,SCNQUE_# none, look for work
;30377/ JBTUPM+103,,IDLE28_# ##check if idle
;30400/ JBTUPM+103,,XTCINT_# no, leave things alone till interrupt
;30401/ JBTUPM+103,,DDBINT_# DDBIO set XKBDDB so we get here
;30402/ JBTUPM+103,,SETACS_# set up all ACs
;30403/ JBTUPM+103,,DDBIO_# continue data transfer
;30404/ JBTUPM+103,,NXTIOW_# look for IOWD
;30405/ JBTUPM+103,,NXTIO0_# ...
;30406/ JBTUPM+103,,IOREDY_# no more, we are finished
;30407/ JBTUPM+103,,FINDDB_# finish I/O for DDB
;30410/ JBTUPM+103,,CHKWAK_# see if UUO level needs to wake
;30411/ JBTUPM+103,,XTWAKE_# yes, do it
;30412/ JBTUPM+103,,SCNQUE_# look for work
;30413/ JBTUPM+103,,IDLE28_# ##are we idle
;30414/ JBTUPM+103,,CLRERR_# ##yes but no work, clear hdw
;30415/ JBTUPM+103,,SETSCN_# set up scanner and exit
;30416/ DBS_#+43,,XTCIOS_# someone else
;30417/ DBS_#+43,,XTCDEV_# ##trying to look at DEVIOS
;.FILL.JUSTIFY.SKIP
;\\
; ^WHEN USING THE EXECUTION TRACE, REMEMBER THAT ^^XTCSEC\\ IS
;CALLED ONCE A SECOND; IF YOU DO NOT PROMPTLY TURN OFF TRACING
;(BY CLEARING THE SIGN BIT OF ^^ETRFLG\\ WITH
;^^FILDDT\\ OR WITH AN ^^ETRCOF\\ CALL) THIS WILL GRADUALLY WIPE
;OUT ALL INFORMATION IN THE CIRCULAR BUFFER (UNLESS
;THE NO-WRAP BIT IN ^^ETRFLG\\ WAS SET).
;-
MLP
XTCEND::END