TITLE XTCSER - DA28 SERVICE ROUTINE AND XTTSK. UUO PROCESSOR - V161 SUBTTL DONALD LEWINE/DAL/RCR/TAH/KR/RDH/KR 26 APR 88 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. ;ALL RIGHTS RESERVED. .CPYRT<1974,1988> XP VXTCSR,161 ;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, PROXWD.................... 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 > DEFINE MLP > PLM ;+ ;.autoparagraph.flag index.flag capital.lower case.page size ,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,*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 < PUSHJ P,ETRACE ;trace execution SKIPA ;to handle skips before instruction >;end IFB >;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-4 ;AMOUNT TO SHIFT UNIT FOR CONO DAS MODLSH==^D36-^L-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),<-<_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, IFNDEF XT'X'C, 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, 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 /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 ! ; _\ ... _\ ; ! _/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), ;NO DDB NO PRIV DEFINE XF(A,B), ;A DDB IS NEEDED DEFINE XPR(A,B), ;PRIVILIGE NEEDE DEFINE XFP(A,B),> ;PRIV & DDB DEFINE XX(A,B,C),,,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, ; MOVE T3, ; 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, ;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,T2 SUBI T3,XKBUDB(F) ;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 ;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 ; 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 ;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 ;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 ;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 ;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 ;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 ;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 ;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: PUSHJ P,SAVE2## ;GET SAME ARM SPACE PUSH P,T1 ;SAVE THE IOWD HRRZS T1 ;GET RID OF EXTRA BITS EXCTUX ;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 ;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 ;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? POPJ P, ;NO, FORGET THIS THEN PUSH P,U ;SAVE POINTER TO XUB MOVE U,OPRLDB## ;SET UP FOR INLMES PUSHJ P,INLMES## ;PRINT THE MESSAGE ASCIZ / ?DA28 HARDWARE ERROR STATUS: / MOVE T1,XKBDAS##(W) ;GET THE STATUS PUSHJ P,PROXWD ;PRINT PUSHJ P,INLMES## ASCIZ / COMMAND: / MOVE T1,XKBDAC##(W) ;GET COMMAND STATUS PUSHJ P,PROXWD PUSHJ P,INLMES## ASCIZ / IOWD: / XCT XTCDTI##(W) PUSHJ P,PROXWD PUSHJ P,INLMES## ASCIZ / DATA: / XCT XTSDTI##(W) PUSHJ P,PROXWD PUSHJ P,CRLF## MOVEI T1,XS.CLR+XTCCHN## XCT XTSCNO##(W) ;CLEAR ERRORS POP P,U ;RESTORE POINTER TO XUB SETZM XUBRDY(U) ;UNIT IS OFFLINE PJRST FINUNI SUBTTL ERROR ROUTINES -- CHKCER, DDBERR, NXTERR, PROXWD ;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? POPJ P, ;NO PUSH P,U ;SAVE POINTER TO XUB MOVE U,OPRLDB## PUSHJ P,INLMES## ;PRINT THIS MSG ASCIZ/ ?CONNECT ERROR--FORCED UNIT OFF LINE / MOVE T1,XKBDAS##(W) ;GET UNIT NUMBER PUSHJ P,PROXWD ;PRINT IT POP P,U ;RESTORE XUB PTR PUSHJ P,FRCOFL ;FORCE UNIT OFFLINE PJRST SCNQUE ;AND LOOK FOR WORK ;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 PRINT T1 AS N,,N ;CALL WITH: ; MOVE T1,OCTAL-WORD ; PUSHJ P,PROXWD ; RETURN HERE PROXWD: PUSH P,T1 ;SAVE ARGUMENT HLRZ T1,T1 ;MOVE LH PUSHJ P,OCTPNT## ;PRINT IT PUSHJ P,INLMES## ;PRINT THE TEXT ASCIZ /,,/ HRRZ T1,(P) ;GET RH PUSHJ P,OCTPNT## ;PRINT IT PJRST TPOPJ## ;RETURN ;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: CONSZ PI,PI.IPA ;AT INTERRUPT LEVEL? SKIPGE SCNLOK## ;AND WITH SCNSER INTERLOCK? 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,PROXWD ;PRINT IT 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,<<_4+>_^D10> ;GET OPCODES ..AA==0 ..BB==0 ..CC==0 IFDIF ,<..AA==1> IFDIF ,<..BB==1> IFIDN ,,<..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, ; 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, ; 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 ;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, ; 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