mirror of
https://github.com/PDP-10/stacken.git
synced 2026-02-15 12:16:07 +00:00
1488 lines
49 KiB
Plaintext
1488 lines
49 KiB
Plaintext
TITLE MPXSER - SERVICE FOR DEVICE MPX: AND RELATED FUNCTIONS V157
|
||
SUBTTL DONALD A. LEWINE 21-JUNE-88
|
||
|
||
SEARCH F,S,DEVPRM
|
||
IFN FTNET,<SEARCH NETPRM>
|
||
|
||
$RELOC
|
||
$HIGH
|
||
|
||
;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
|
||
; 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988.
|
||
;ALL RIGHTS RESERVED.
|
||
|
||
.CPYRT<1973,1988>
|
||
|
||
XP VMSGSR,157
|
||
|
||
MPXSER::ENTRY MPXSER
|
||
|
||
;AC USAGE WITHIN MPXSER:
|
||
;
|
||
;S) DEVICE STATUS. ALWAYS DEVIOS(F)
|
||
|
||
;P) PUSH DOWN POINTER
|
||
|
||
;J) USERS JOB NUMBER.
|
||
|
||
;R) ADDRESS OF USERS JOB IF KA10, 341000 IF KI10
|
||
|
||
;F) ADDRESS OF A DDB. THIS IS EITHER THE MPX DDB OR
|
||
; THE DEVICE CONTROLED BY THE MPX DDB. USE CAUTION.
|
||
|
||
;U) NOT USED TODAY
|
||
|
||
;T1-T4) TEMPS. ARGS TO SUBROUTINES PASSED IN
|
||
; THESE AC'S.
|
||
|
||
;M) ADDRESS FOR GETWRD/PUTWRD. USERS UUO.
|
||
|
||
;W) NOT USED TODAY
|
||
|
||
;P1) CHANNEL NUMBER
|
||
|
||
;P2) ADDRESS OF THE MPX DDB.
|
||
|
||
;P3) ADDRESS OF THE TARGET DDB.
|
||
|
||
;P4) ADDRESS OF THE CONNECTED DEVICE TABLE
|
||
;FORMAT OF THE CONNECTED DEVICE TABLE:
|
||
;
|
||
; !------------------!------------------!
|
||
; ! SIZE OF CDT ! # OF FREE SLOTS !
|
||
; !------------------!------------------!
|
||
; ! UDX FOR DEV #1 ! ADDRESS OF DDB #1!
|
||
; !------------------!------------------!
|
||
; ! UDX FOR DEV #2 ! ADDRESS OF DDB #2!
|
||
; !------------------!------------------!
|
||
; ! UDX FOR DEV #3 ! ADDRESS OF DDB #3!
|
||
; !------------------!------------------!
|
||
; ! UDX FOR DEV #4 ! ADDRESS OF DDB #4!
|
||
; !------------------!------------------!
|
||
; / /
|
||
; / /
|
||
; !------------------!------------------!
|
||
; ! UDX FOR DEV #N ! ADDRESS OF DDB #N!
|
||
; !------------------!------------------!
|
||
;
|
||
;NOTE THE CDT IS KEPT SORTED BY UDX SO IT IS EASY (AT LEAST FAST)
|
||
; TO CONVERT A UDX FOR A CONNECTED DEVICE TO A DDB ADDRESS.
|
||
|
||
CDTFRE==0 ;OFFSET FOR THE COUNT OF THE NUMBER OF FREE
|
||
; SLOTS IN CDT
|
||
|
||
CDTSIZ==0 ;OFFSET FOR THE CDT WORD COUNT. THIS INCLUDES
|
||
; THIS WORD
|
||
|
||
CDTQNT==40 ;NUMBER OF WORD TO GET EACH TIME THE CDT FILLS UP
|
||
|
||
CDT4WD==<<CDTQNT+3>/4> ;NUMBER OF 4 WORD BLOCKS IN A CDT QUANTUM
|
||
CDTQNT==CDT4WD*4 ;REDEFINE SO LOW 2 BITS ARE ALWAYS ZERO
|
||
|
||
;DEVICE DEPENDENT BITS IN DEVIOS
|
||
MPXVMF==1B0 ;ON IF A DEVICE IS IN TROUBLE AND THE OUTPUT
|
||
; BUFFER IS PAGED OUT
|
||
SUBTTL AUTOCONFIGURE
|
||
|
||
|
||
;DRIVER CHARARCTERISTICS
|
||
; MPX = MPXCNF
|
||
; MPX = MULTIPLEXED CHANNEL
|
||
; 0 = MAXIMUM DEVICES IN SYSTEM
|
||
; 0 = KONTROLLER TYPE
|
||
; 0 = MAXIMUM DRIVES PER KONTROLLER
|
||
; 0 = HIGHEST DRIVE NUMBER ON KONTROLLER
|
||
; MDSEC0 = SECTION FOR KDB/UDB
|
||
; MDSEC0 = SECTION FOR DDB
|
||
DRVCHR (MPX,MPX,0,0,0,0,MDSEC0,MDSEC0,<DR.SFT>)
|
||
|
||
.ORG DEVLEN
|
||
MPXLEN:! ;LENGTH OF MPX DDB
|
||
.ORG
|
||
|
||
|
||
$LOW
|
||
MPXDDB: DDBBEG (MPX,MPXLEN)
|
||
SETWRD (DEVCHR,<103>) ;DEVCHR
|
||
SETWRD (DEVSER,<MCSEC0+MPXDSP>) ;DEVSER
|
||
SETWRD (DEVMOD,<DVIN!DVOUT!DVLNG,,14407>) ;DEVMOD
|
||
SETWRD (DEVTYP,<<.TYMPX*.TYEST>,,DEPEVM>) ;DEVTYP
|
||
SETWRD (DEVCPU,<707B8>) ;DEVCPU
|
||
DDBEND
|
||
$HIGH
|
||
|
||
|
||
EQUATE (LOCAL,0,<MPXCKT,MPXKDB,MPXKLN,MPXUDB,MPXULN>)
|
||
EQUATE (LOCAL,0,<MPXICD,MPXICL,MPXINT,MPXULB,MPXULP>)
|
||
|
||
MPDDSP: DRVDSP (MPX,,MPXDDB,MPXLEN,0)
|
||
|
||
$HIGH
|
||
MPXCFG: SKIPGE MPXNUM ;INITIALIZED YET?
|
||
SETZM MPXNUM ;INIT DDB SERIAL NUMBER
|
||
POPJ P, ;FOR NOW
|
||
;DISPATCH TABLE FOR MPX
|
||
|
||
JRST CPOPJ1## ;MPX IS ALWAYS ON-LINE
|
||
POPJ P,0 ;SPECIAL ERROR STATUS
|
||
JRST REGSIZ## ;SIZE CAN BE GOTTEN FROM DDB
|
||
POPJ P,0 ;SYSINI CALL
|
||
POPJ P,0 ;HUNG DEVICE
|
||
MPXDSP: JRST MSGREL ;RELEASE
|
||
POPJ P,0 ;CLOSE
|
||
JRST MSGDOU ;OUTPUT
|
||
JSP T1,MSGIN ;INPUT
|
||
JRST ILLOPR ;ENTER
|
||
JRST ILLOPR ;LOOKUP
|
||
JRST ILLOPR ;DUMP MODE OUTPUT
|
||
JRST ILLOPR ;DUMP MODE INPUT
|
||
JRST ILLOPR ;USETO
|
||
JRST ILLOPR ;USETI
|
||
JRST ILLOPR ;UGETF
|
||
JRST ILLOPR ;RENAME
|
||
POPJ P,0 ;INPUT CLOSE
|
||
JRST ILLOPR ;UTPCLR
|
||
JRST ILLOPR ;MTAPE
|
||
|
||
;HERE ON AN OPERATION WHICH IS ILLEGAL FOR MPX:
|
||
ILLOPR: JSP T1,ERRPTU## ;PRINT THE MESSAGE
|
||
ASCIZ /Illegal operation for multiplex device/
|
||
JRST UUOPCP## ;PRINT PC AND STOP THE JOB
|
||
SUBTTL NON-IO INTERFACE WITH UUOCON
|
||
|
||
;SUBROUTINE TO BUILD THE MPX DDB
|
||
;CALL WITH:
|
||
; MOVE T1,NAME-OF-DEVICE
|
||
; PUSHJ P,TSTMPX
|
||
; RETURN HERE IF NOT AN OPEN UUO FOR 'MPX'
|
||
; RETURN HERE WITH DDB BUILT AND F SETUP
|
||
TSTMPX::CAME T1,[SIXBIT 'MPX'] ;IS THIS MPX:?
|
||
POPJ P,0 ;NORMAL CASE.
|
||
HRLZ T1,.USMUO ;UUO OP CODE
|
||
IOR T1,.USMUE ;EA-CALC
|
||
|
||
TDZ T1,[777,,UPHNLY] ;ONLY CALLI
|
||
CAMN T1,[FILOP.] ;FILOP?
|
||
JRST TSTMP1 ;YES, ALLOW THAT
|
||
HLRZS T1 ;OR OPEN
|
||
CAIE T1,(OPEN)
|
||
POPJ P,0 ;NOPE. ERROR RETURN
|
||
TSTMP1: SE1ENT ;ENTER SECTION ONE
|
||
PUSHJ P,AUTLOK## ;INTERLOCK AUTCON
|
||
POPJ P, ;BUSY & INTERRUPT LEVEL??
|
||
PUSHJ P,SAVT## ;SAVE T2 THRU T4
|
||
SETZB T1,T3 ;NO DEVICE CODE, NO CHANNEL DATA BLOCK
|
||
XMOVEI T2,MPDDSP ;DRIVER DISPATCH
|
||
PUSHJ P,AUTSET## ;RESET THINGS
|
||
AOS T1,MPXNUM ;NUMBER OF CALLS TO TSTMPX
|
||
HRLI T1,'MPX' ;INCLUDE GENERIC DEVICE NAME
|
||
SETZ T2, ;LOCAL DEVICE
|
||
PUSHJ P,AUTDDB## ;CREATE A DDB
|
||
POPJ P, ;NO MORE CORE
|
||
PUSHJ P,AUTULK## ;RELEASE INTERLOCK
|
||
JRST CPOPJ1## ;GOOD RETURN
|
||
|
||
|
||
$LOW
|
||
MPXNUM: EXP -1 ;DDB SERIAL NUMBER
|
||
$HIGH
|
||
;HERE TO RELEASE ALL DEVICES CONNECTED TO THE MPX
|
||
; CALLED BY ZAPMPX AND THROUGH RELEASE DISPATCH
|
||
|
||
MSGREL: PUSHJ P,SAVE4## ;SAVE THE P'S
|
||
MSGRE1: HRRZ P4,DEVXTR(F) ;ANY DEVICES CONNECTED?
|
||
JUMPE P4,CPOPJ## ;NO--KILL OFF MPX DDB
|
||
HLRZ P4,DEVXTR(F) ;GET ADDRESS OF CDT
|
||
MOVE P2,F ;SAVE F IN P2
|
||
HRRZ F,1(P4) ;ADDRESS OF FIRST DDB
|
||
HRRZS DEVBUF(F) ; SO DISCONNECT DOESN'T TRY TO RETURN BUFFERS
|
||
HRRZS DEVBUF(P2) ;DITTO FOR MPX ITSELF
|
||
MOVEI P1,RELEA1## ;UNCONDITIONAL DISCONNECT
|
||
PUSHJ P,DISCON ;REMOVE THE CONNECTION
|
||
JFCL ;DEVICE NOT CONNECTED
|
||
MOVE F,P2 ;RESTORE F
|
||
JRST MSGRE1 ;SEE IF ANY DEVICES CONNECTED
|
||
|
||
;SUBROUTINE TO WIPE OUT THE MPX DDB ON RELEASE
|
||
;CALL WITH:
|
||
; MOVEI F,ADDRESS-OF-DDB-TO-ZAP
|
||
; PUSHJ P,ZAPMPX
|
||
; RETURN HERE
|
||
|
||
ZAPMPX::PUSHJ P,MSGREL ;DISCONNECT ALL DEVICES FIRST
|
||
MOVEI T1,MPXLEN ;DDB LENGTH
|
||
MOVEI T2,(F) ;DDB ADDRESS
|
||
PJRST AUTKIL## ;DELETE THE DDB
|
||
SUBTTL CONNECT UUO
|
||
|
||
;UUO TO CONNECT A DEVICE TO AN MPX CHANNEL
|
||
;CALL WITH:
|
||
; MOVEI AC,E
|
||
; CNECT. AC, -OR- CALLI AC,130
|
||
; RETURN HERE ERROR CODE IN AC
|
||
; RETURN HERE UDX IN AC
|
||
;
|
||
; E: XWD FUNCTION,CHAN
|
||
; SIXBIT /DEVICE/
|
||
;
|
||
CONECT::PUSHJ P,SAVE4## ;SAVE VOLITILE AC'S
|
||
HRR M,T1 ;PICK UP THE
|
||
PUSHJ P,GETWDU## ; FIRST ARGUMENT
|
||
HRRZ P1,T1 ;COPY CHANEL NUMBER
|
||
HLRZ P3,T1 ;GET FUNCTION CODE
|
||
PUSHJ P,SETUF##
|
||
PJRST ECOD6## ;ELSE GENERATE ERROR
|
||
HRLM P1,.USCTA ;STORE MPX CHANNEL #
|
||
MOVE P2,F ;SET F=ADDRESS OF MPX DDB
|
||
LDB T2,PDVTYP## ;GET THE DEVICE TYPE
|
||
CAIE T2,.TYMPX ;IS THIS AN MPX DDB?
|
||
PJRST ECOD1## ;NO--PUNT
|
||
CAILE P3,CNFNMX ;SKIP IF NOT TOO BIG
|
||
PJRST ECOD10## ;ERROR 10 -- INVALID FUNCTION
|
||
JRST @CNFNTB(P3) ;DISPATCH
|
||
|
||
;TABLE OF FUNCTIONS
|
||
CNFNTB: JRST ECOD10## ;(0)NO FUNCTION 0
|
||
JRST CONDEV ;(1)CONNECT
|
||
JRST CDCDEV ;(2)CONDITIONAL DISCONNECT
|
||
JRST UDCDEV ;(3)UNCONDITIONAL DISCONNECT
|
||
JRST OFEDEV ;(4)OUTPUT FEASIBILITY CHECK
|
||
CNFNMX==.-CNFNTB-1
|
||
;SUBROUTINE TO CONNECT A DEVICE
|
||
;CALLED ONLY FROM CONECT
|
||
;
|
||
CONDEV: PUSHJ P,GETWD1## ;PICK UP DEVICE NAME
|
||
MOVEI T3,ASSPRG ;REJECT INITED DEVICES
|
||
PUSHJ P,DVASRC## ;LOOK FOR GENERIC DEVICE
|
||
SKIPA ;NOT A GENERIC DEVICE
|
||
JRST CNDEV4 ;FREE GENERIC DEVICE
|
||
PUSHJ P,DVCNSG## ;LOOK UP IN DEVICE CHAIN
|
||
JRST ECOD2## ;NO SUCH DEVICE
|
||
CNDEV4: PUSHJ P,LGLMPX ;OK TO USE?
|
||
PJRST ECOD3## ;CAN NOT USE THAT TYPE OF DEVICE
|
||
MOVE P3,F ;SAVE DDB ADDRESS
|
||
PUSH P,J ;SAVE J
|
||
MOVE J,.CPJCH## ;PICK UP JOB/CONTEXT HANDLE
|
||
MOVE T1,DEVNAM(F) ;PICK UP DEVICE NAME
|
||
MOVEI T2,ASSPRG ;INIT BIT
|
||
TDNN T2,DEVMOD(F) ;ALREADY INITED?
|
||
PUSHJ P,ASSASG## ;NO--TRY TO INIT
|
||
JRST [POP P,J ;PHASE STACK
|
||
JRST ECOD11##] ;DEVICE NOT INITIED OR CONNECTED
|
||
SKIPGE DEVSPL(F) ;SPOOLED DEVICE?
|
||
JRST [PUSHJ P,RELEA4## ;YES--KILL THE DDB
|
||
POP P,J ;RESTORE J
|
||
JRST ECOD12##] ;GIVE ERROR RETURN
|
||
POP P,J ;RESTORE J
|
||
PUSHJ P,GETCDT ;SET P4 = CDT ADDRESS
|
||
JRST CNOCOR ;NO MORE FREE CORE
|
||
HRRE T1,CDTFRE(P4) ;GET FREE SLOT COUNT
|
||
JUMPG T1,CNDEV1 ;JUMP IF ROOM
|
||
PUSHJ P,XPNCDT ;EXPAND THE CDT
|
||
PJRST CNOCOR ;NO MORE CORE
|
||
CNDEV1: SOS CDTFRE(P4) ;COUNT THE SLOT
|
||
MOVE T1,DEVNAM(F) ;PICK UP THE DEVICE NAME
|
||
PUSHJ P,UIONDX## ;COMPUTE UDX
|
||
PJRST [PUSHJ P,RELEA4## ;YES--KILL THE DDB
|
||
PJRST ECOD3##] ; AND GIVE ERROR RETURN
|
||
MOVEI T3,1(P4) ;ADDRESS OF FIRST SLOT
|
||
CNDEV2: HLRZ T4,(T3) ;COPY UDX FROM CDT
|
||
JUMPE T4,CNDEV3 ;JUMP IF TABLE EMPTY
|
||
CAIL T1,(T4) ;DOES IT GO HERE
|
||
AOJA T3,CNDEV2 ;NO--KEEP LOOKING
|
||
HLRZ T2,CDTSIZ(P4) ;SIZE OF CDT
|
||
ADDI T2,-1(P4) ;ADDRESS OF LAST WORD
|
||
MOVE T4,-1(T2) ;PICK UPNEXT TO LAST WORD
|
||
MOVEM T4,(T2) ;STORE AS THE LAST WORD
|
||
CAIE T2,(T3) ;SKIP IF WE MOVED ENOUGH
|
||
SOJA T2,.-3 ;LOOP OVER ENTIRE CDT
|
||
CNDEV3: HRLM T1,(T3) ;STORE UDX
|
||
HRRM P3,(T3) ;STORE DDB ADDRESS
|
||
AOS DEVXTR(P2) ;INCREMENT NUMBER OF CONNECTED DEVICES
|
||
PUSHJ P,CNDDBI ;DO SOME INITIALIZATION
|
||
HRRZ T4,DEVSER(F)
|
||
PUSHJ P,DSZ(T4)
|
||
JRST CPOPJ1## ;GOOD RETURN
|
||
|
||
CNOCOR: PUSHJ P,RELEA4## ;CLEAR ASSPRG & PJOBN
|
||
PJRST ECOD4## ;AND SAY NO FREE CORE
|
||
;SUBROUTINE TO CLEAN UP A DDB BEING CONNECTED TO DEVICE MPX
|
||
;CALL WITH:
|
||
; P2 = ADDRESS OF MPX DDB
|
||
; P3 = ADDRESS OF TARGET DDB
|
||
; PUSHJ P,CNDDBI
|
||
; RETURN HERE
|
||
CNDDBI: MOVEI T2,DEPMSG ;FLAG AS CONTROLED VIA MPXSER
|
||
IORM T2,DEVMSG(P3) ; ..
|
||
HRRM P2,DEVXTR(P3) ;LINK TARGET BACK TO MPX DDB
|
||
MOVSI T1,0 ;CLEAR OUT BOTH
|
||
MOVE F,P3 ; DEVIAD AND DEVOAD
|
||
DPB T1,PDVOAD## ; SO WE DO NOT LOOK
|
||
DPB T1,PDVIAD## ; ACTIVE BUFFERS
|
||
SETZM DEVBUF(F) ;ALSO ZAP DEVBUF
|
||
HRR M,DEVIOS(P2) ;GET STATUS FROM MPX DDB
|
||
PUSHJ P,SETIOS## ;SET AS STATUS OF TARGET DDB
|
||
MOVSI T1,IOFST!IOBEG
|
||
IORM T1,DEVIOS(P3)
|
||
MOVEI T1,DEPAIO ;NON BLOCK
|
||
TDNE T1,DEVAIO(P2) ;CHECK MPX
|
||
IORM T1,DEVAIO(P3) ;SET IN TARGET
|
||
MOVEI T1,DEPDEL ;DISABLE ERROR LOGGING (ALSO FULL SCNSER PTY)
|
||
ANDCAM T1,DEVSTA(P3) ;CLEAR IT FIRST
|
||
TDNE T1,DEVSTA(P2) ;CHECK MPX
|
||
IORM T1,DEVSTA(P3) ;PROPAGATE STATE TO TARGET
|
||
MOVEI T1,DVDIBP ;BATCH PTY (ALSO DISABLE MESSAGE REASSEMBLY)
|
||
ANDCAM T1,DEVCHR(P3) ;CLEAR IT FIRST
|
||
TDNE T1,DEVCHR(P2) ;CHECK MPX
|
||
IORM T1,DEVCHR(P3) ;PROPAGATE STATE TO TARGET
|
||
MOVE F,P3 ;MAKE SURE OF DDB POINTER
|
||
MOVSI T2,DVTTY ;IF THIS IS A TTY
|
||
TDNE T2,DEVMOD(P3) ; (TEST)
|
||
PUSHJ P,TTYMPX## ;LET SCNSER DO SOME INITIALIZATION
|
||
POPJ P,0 ;RETURN
|
||
;TABLE OF DEVICE TYPES WHICH MAY BE CONNECTED
|
||
;DEVICE IS OK IF 1B<DEVTYP> IS = 1
|
||
|
||
DEFINE TYPBTS(A),<
|
||
IRP A,<
|
||
ZZ..=ZZ..!1B<.TY'A>
|
||
>>
|
||
|
||
ZZ..==0
|
||
TYPBTS <LPT,PTP,TTY,PTY,RDA>
|
||
TYPMSK: EXP ZZ..
|
||
|
||
;SUBROUTINE TO SEE IF DEVICE CAN BE USED ON MPX:
|
||
;CALL WITH:
|
||
; MOVE F,DDB-ADDRESS
|
||
; PUSHJ P,MGLMPX
|
||
; RETURN HERE IF NO GOOD
|
||
; RETURN HERE IF OK
|
||
;RESPECTS T1
|
||
LGLMPX::LDB T2,PDVTYP## ;GET DEVICE TYPE
|
||
CAIN T2,.TYTTY ;TTY?
|
||
JRST CPOPJ1## ;YES--ALWAYS GOOD
|
||
IFN FTNET,<
|
||
CAIE T2,.TYCDR ;A CDR?
|
||
JRST LGLMP1 ;NO
|
||
LDB T3,PDVSTA## ;YES, LOCAL?
|
||
CAME T3,JBTLOC##
|
||
JRST CPOPJ1## ;REMOTE CDR IS OK
|
||
LGLMP1:>
|
||
MOVSI T3,(1B0) ;SETUP BIT
|
||
MOVN T2,T2 ;MAKE COUNT NEGATIVE
|
||
LSH T3,(T2) ;SHIFT BIT
|
||
TDNN T3,TYPMSK ;VALID TYPE?
|
||
POPJ P,0 ;NO--RETURN
|
||
JRST CPOPJ1## ;WIN
|
||
;SUBROUTINE TO DO A DISCONNECT (CALLED FROM REASSIGN)
|
||
;CALLED WITH:
|
||
; F=ADDRESS OF DEVICE DDB
|
||
; PUSHJ P,MPXDIS
|
||
; RETURN HERE IF NOT MPX'ED
|
||
; RETURN HERE IF DISCONNECTED
|
||
MPXDIS::MOVEI T1,DEPMSG
|
||
TDNN T1,DEVMSG(F) ;MPX'ED?
|
||
POPJ P, ;NO
|
||
PUSHJ P,SAVE4##
|
||
MOVEI P1,RELEA1## ;DO RELEASE
|
||
HRRZ P2,DEVXTR(F) ;LOCATE MPX DDB
|
||
PJRST DISCON ;DO DISCONNECT
|
||
|
||
;SUBROUTINE TO DO A DISCONNECT (CALLED ONLY FROM CNECT. UUO)
|
||
;CALLED WITH:
|
||
; P2 = ADDRESS OF MPX DDB
|
||
; PUSHJ P,CDCDEV OR UDCDEV
|
||
; RETURN HERE IF ERROR
|
||
; RETURN HERE IF OK
|
||
CDCDEV: SKIPA P1,[EXP URELEA##] ;RELEASE AND CLOSE
|
||
UDCDEV: MOVEI P1,RELEA1## ;RESET
|
||
PUSHJ P,GETWD1## ;PICK UP DEVICE NAME
|
||
PUSHJ P,FNDDDB ;FIND DEVICE DATA BLOCK
|
||
JRST ECOD2## ;MUST BE VALID DEVICE
|
||
IFN FTMP,<
|
||
PUSHJ P,SETCPP## ;GET ON CORRECT CPU FOR DEVICE
|
||
JRST ECOD11## ;CPU DEAD, SAY DEVICE UNAVAILABLE
|
||
>
|
||
;FALL INTO DISCON
|
||
;SUBROUTINE TO DISCONNECT A DEVICE
|
||
;CALLED WITH:
|
||
; F = ADDRESS OF DDB
|
||
; P1 = ADDRESS OF ROUTINE TO CALL (RELEA1)
|
||
; P2 = ADDRESS OF MPX DDB
|
||
; PUSHJ P,DISCON
|
||
; RETURN HERE ON ERROR (USER AC UPDATED)
|
||
; RETURN HERE IF OK
|
||
DISCON: HLR M,DEVBUF(P2) ;ADDRESS OF THE RING HEADER
|
||
HRRZS P3,F ;ADDRESS OF THE TARGET DDB FOR VMCHEK
|
||
; ALSO ZERO LH(F) FOR CAIN BELOW
|
||
TRNE M,-1 ;OK IF NO BUFFERS (RELEASE)
|
||
PUSHJ P,VMCHKH ;MAKE SURE ALL BUFFERS ARE IN CORE IN
|
||
; CASE THEY SHOULD BE RECLAIMED
|
||
MOVE S,DEVIOS(F) ;SETUP S
|
||
LDB T1,PJOBN## ;GET THE JOB # OF OWNER
|
||
MOVEI T2,ASSPRG ; INIT BIT
|
||
TDNE T2,DEVMOD(F) ;SKIP IF NOT INITED
|
||
CAME T1,J ;SKIP IF INITED BY THIS JOB
|
||
JRST ECOD5## ;NO--BOUNCE HIM
|
||
HLRZ P4,DEVXTR(P2) ;GET CDT ADDRESS
|
||
JUMPE P4,ECOD5## ;IF NONE, THERE ARE NO DEVICES IN CDT
|
||
HLRZ T1,CDTSIZ(P4) ;NUMBER OF WORDS IN CDT
|
||
SUB T1,CDTFRE(P4) ;LESS NUMBER OF FREE WORDS GIVES # ENTRIES
|
||
MOVEI T1,-1(T1) ;CLEAR LH AND SUBTRACT 1
|
||
MOVEI T2,1(P4) ;ADDRESS OF FIRST SLOT
|
||
MOVE T3,T2 ;2 COPIES
|
||
DCNDVL: MOVE T4,(T2) ;GET AN ENTRY
|
||
CAIN F,(T4) ;IS THIS THE ONE TO ZAP?
|
||
AOJA T2,DCNDV1 ;YES--GET THE NEXT ENTRY
|
||
MOVEM T4,(T3) ;STORE BACK ENTRY
|
||
ADDI T2,1 ;UPDATE SOURCE
|
||
ADDI T3,1 ;UPDATE DESTINATION
|
||
DCNDV1: SOJG T1,DCNDVL ;MOVE THE WHOLE CDT DOWN
|
||
CAIN T2,(T3) ;DID WE FIND AN ENTRY?
|
||
JRST ECOD5## ;NO--DEVICE NOT CONNECTED
|
||
SETZM -1(T2) ;ZERO OLD LAST ENTRY IN CDT
|
||
CAIN P1,RELEA1## ;UNCONDITIONAL DISCONNECT?
|
||
PUSHJ P,RTNOB ;YES, RETURN BUFFERS TO FREE LIST
|
||
MOVEI T2,DEPMSG ;NO LONGER CONTROLED
|
||
ANDCAM T2,DEVMSG(F) ; BY MPXSER
|
||
SOS T2,DEVXTR(P2) ;1 LESS DEVICE CONNECTED
|
||
AOS CDTFRE(P4) ; AND 1 MOVE FREE SLOT
|
||
TRNE T2,-1 ;SKIP IF CDT NOW EMPTY
|
||
JRST DISXIT ;ELSE JUST EXIT
|
||
HLRZ T1,CDTSIZ(P4) ;NUMBER OF WORDS IN CDT
|
||
MOVEI T2,(P4) ;ADDRESS OF CDT
|
||
PUSHJ P,GIVWDS## ;RETURN CDT
|
||
SETZB P4,DEVXTR(P2) ;FLAG AS HAVING NO CDT
|
||
DISXIT: MOVE T1,P1 ;COPY ROUTINE ADDRESS
|
||
AOS (P) ;SKIP RETURN
|
||
PJRST CALSER ;CALL SERVICE ROUTINE
|
||
;SUBROUTINE TO SETUP CDT
|
||
;CALL WITH:
|
||
; P2 = ADDRESS OF DDB
|
||
; PUSHJ P,GETCDT
|
||
; RETURN HERE IF NO CORE
|
||
; RETURN HERE P4=ADDRESS OF CDT
|
||
GETCDT: HLRZ P4,DEVXTR(P2)
|
||
JUMPN P4,CPOPJ1## ;ALL DONE IF NON-ZERO
|
||
MOVEI T2,CDTQNT ;NUMBER OF WORDS TO GET
|
||
PUSHJ P,GETWDS## ; ..
|
||
POPJ P,0
|
||
MOVE T2,[CDTQNT,,CDTQNT-1] ;SIZE AND FREE COUNT
|
||
MOVEM T2,CDTSIZ(T1) ;STORE INFO
|
||
MOVEM T1,P4 ;STORE ADDRESS
|
||
HRLZM T1,DEVXTR(P2) ;STORE ADDRESS
|
||
HRRZM T1,DEVCID(P2) ;STORE NEXT INPUT DEV
|
||
SETZM 1(P4) ;ZERO UNUSED WORDS
|
||
HRLI T1,1(P4) ;FROM
|
||
HRRI T1,2(P4) ;TO
|
||
BLT T1,CDTQNT-1(P4) ;ZAP
|
||
JRST CPOPJ1## ;GOOD RETURN
|
||
|
||
;SUBROUTINE TO RETURN FULL BUFFERS WHICH HAVE
|
||
; NOT BEEN OUTPUT YET TO THE FREE LIST
|
||
;CALL WITH:
|
||
; F = ADDRESS OF THE CONNECTED DDB
|
||
; PUSHJ P,RTNOB
|
||
; ALWAYS RETURN HERE
|
||
|
||
RTNOB: MOVSI T1,DVTTY ;DEVICE IS A TTY BUT
|
||
TDNN T1,DEVMOD(F) ;IF A TTY, DON'T CALL WAIT1 (IOACT GETS LEFT ON)
|
||
PUSHJ P,WAIT1## ;MAKE SURE I/O ISN'T GOING ON NOW
|
||
HLRZ T1,DEVBUF(F) ;ADDRESS OF THE ACTIVE LIST
|
||
JUMPE T1,CPOPJ## ;RETURN IF NO BUFFERS ON LIST
|
||
RTNOB1: PUSHJ P,ADVBFE## ;RETURN BUFFER TO THE FREE LIST
|
||
POPJ P, ;ALL DONE
|
||
JRST RTNOB1 ;RETURN NEXT BUFFER
|
||
;SUBROUTINE TO EXPAND A FULL CDT
|
||
;CALL WITH:
|
||
; MOVE P2,ADDRESS-OF-MPX-DDB
|
||
; MOVE P4,ADDRESS-OF-CDT
|
||
; PUSHJ P,XPNCDT
|
||
; RETURN HERE IF NO MORE CORE
|
||
; RETURN HERE DDB AND P4 UPDATED
|
||
|
||
XPNCDT: HLRZ T2,CDTSIZ(P4) ;CURRENT SIZE
|
||
ADDI T2,CDTQNT ;PLUS AMOUNT TO EXPAND
|
||
PUSHJ P,GETWDS## ;GET THAT MUCH CORE
|
||
POPJ P,0 ;NO MORE CORE
|
||
AOS (P) ;WE HAVE WON
|
||
HRL T1,P4 ;COPY THE OLD ADDRESS
|
||
PUSH P,CDTSIZ(P4) ;REMEMBER THE OLD SIZE
|
||
HRRM P4,(P) ;AND ADDRESS
|
||
MOVE T2,[CDTQNT,,CDTQNT] ;AMOUNT WE ADDED
|
||
ADDB T2,CDTSIZ(P4) ;UPDATE THE CDT
|
||
HLRZ T2,T2 ;PUT NEW SIZE IN THE RH
|
||
ADDI T2,(T1) ;WHERE TO STOP BLT
|
||
MOVEI P4,(T1) ;ALSO FIX P4 BEFORE BLT ZAPS AC
|
||
SETZM (P4) ;ZERO OUT THE NEW CDT
|
||
HRLZ T3,P4 ;BUILT A BLT
|
||
HRRI T3,1(P4) ;POINTER
|
||
BLT T3,-1(T2) ;ZAP!!
|
||
SUBI T2,CDTQNT+1 ;NEW STOP ADDRESS
|
||
BLT T1,(T2) ;COPY THE CDT TO IT'S NEW HOME
|
||
HRLM P4,DEVXTR(P2) ;REMEMBER ADDRESS OF THE CDT
|
||
HRRZM P4,DEVCID(P2) ;UPDATE CURRENT BECAUSE OLD MOVED
|
||
POP P,T2 ;RESETORE OLD SIZE AND ADDRESS
|
||
HLRZ T1,T2 ;COPY NUMBER OF WORDS
|
||
TLZ T2,-1 ;CLEAR LH
|
||
PJRST GIVWDS## ;RETURN OLD CORE
|
||
;SUBROUTINE TO DETERMINE OUTPUT FEASIBILITY FOR A MPX-CONTROLLED DEVICE
|
||
;CALLED ONLY BY CNECT. MONITOR CALL
|
||
|
||
OFEDEV: PUSHJ P,MPXTBL ;FIRST AND FOREMOST GET I/O GOING
|
||
PUSHJ P,GETWD1 ;GET DEVICE UDX FROM CNECT. CALL
|
||
PUSHJ P,FNDDDB ;FIND THE DEVICE QUICKLY
|
||
; NO GENERAL DEVICE SEARCHES HERE FOR
|
||
; SPEED AND EFFICIENCY CONSIDERATIONS
|
||
PJRST ECOD2## ;NO SUCH DEVICE, USER LOSES
|
||
LDB T1,PDVTYP## ;SEE WHAT SORT OF DEVICE WE CAME UP WITH
|
||
CAIE T1,.TYTTY ;A TTY?
|
||
JRST OFEDE2 ;NO
|
||
PUSHJ P,TTYOFE## ;YES, ASK SCNSER'S OPINION
|
||
JRST OFEDE5 ;AND FORGET THE DATA REQUEST COUNT
|
||
|
||
OFEDE2:
|
||
IFE FTNET,<TRO T1,-1> ;FLAG LOCAL DEVICE IF NO NETWORKS
|
||
IFN FTNET,<
|
||
MOVE T1,DEVCHR(F) ;NOT A TTY, GET CHARACTERISTICS
|
||
TLNN T1,DVCNET ;A NETWORK (DATA REQUEST) DEVICE?
|
||
TROA T1,-1 ;NO, LOCAL, FLAG AS SUCH
|
||
HRRZ T1,DEVDRQ(F) ;YES, RETURN OUTPUT DATA REQUEST COUNT
|
||
> ;END IFN FTNET
|
||
|
||
OFEDE5: HLL T1,DEVEVM(F) ;GET ADDRESS OF USER OUTPUT BUFFER
|
||
TLNN T1,-1 ;UNLESS NOT EVM MAPPED
|
||
HRL T1,DEVOAD(F) ;IN WHICH CASE GET TRUE USER ADDRESS
|
||
JRST STOTC1## ;RETURN VALUE TO USER
|
||
SUBTTL SENSE. UUO -- RETURN DEVICE INFORMATION
|
||
|
||
;UUO TO RETURN INFORMATION ABOUT A SPECIFIC DEVICE
|
||
;CALL WITH:
|
||
; MOVE AC,[LENGTH,,ADDR]
|
||
; SENSE. AC,
|
||
; RETURN HERE (ERROR CODE IN AC)
|
||
;
|
||
;ADDR CONTAINS:
|
||
;
|
||
; !------------------!------------------!
|
||
; ! UDX, CHANNEL NUMBER OR SIXBIT DEV !
|
||
; !------------------!------------------!
|
||
; ! LENGTH OF BLOCK ! ADDR OF BLOCK !
|
||
; !------------------!------------------!
|
||
; / /
|
||
; / /
|
||
; !------------------!------------------!
|
||
; ! UDX, CHANNEL NUMBER OR SIXBIT DEV !
|
||
; !------------------!------------------!
|
||
; ! LENGTH OF BLOCK ! ADDR OF BLOCK !
|
||
; !------------------!------------------!
|
||
;
|
||
;
|
||
;
|
||
;EACH BLOCK GETS:
|
||
;
|
||
; !------------------!------------------!
|
||
; ! SIXBIT DEVICE NAME FOR DEVICE !
|
||
; !------------------!------------------!
|
||
; ! 0 ! GETSTS INFO !
|
||
; !------------------!------------------!
|
||
; ! DEVSTS WORD !
|
||
; !------------------!------------------!
|
||
;
|
||
;
|
||
;NOTE: THIS UUO IS RESTARTABLE FOR VM
|
||
;
|
||
SENSE:: PUSHJ P,SAVE2## ;SAVE P1 AND P2
|
||
HRRZ P1,T1 ;ADDRESS OF POINTER TABLE
|
||
HLRZ P2,T1 ;NUMBER OF ENTRIES
|
||
SENSE1: SUBI P2,2 ;TWO MORE WORDS?
|
||
JUMPL P2,CPOPJ1## ;NO--ALL DONE
|
||
HRR M,P1 ;GET THE FIRST WORD
|
||
PUSHJ P,GETWDU## ;GET THE WORD
|
||
PUSHJ P,DVCNSG## ;FIND THE DDB
|
||
JRST ECOD1## ;(1)ILLEGAL DEVICE
|
||
AOS M,P1 ;POINT TO NEXT WORD
|
||
PUSHJ P,GETWDU## ;GET THE WORD
|
||
PUSHJ P,SNSDEV ;STORE THE SENSE INFO
|
||
AOJA P1,SENSE1 ;LOOP OVER ALL THE DEVICES
|
||
;SUBROUTINE TO STORE THE SENSE INFO FOR ONE DEVICE
|
||
;CALL WITH:
|
||
; T1 = COUNT,,ADDR
|
||
; F = ADDRESS OF DDB
|
||
; PUSHJ P,SNSDEV
|
||
; RETURN HERE
|
||
;
|
||
SNSDEV: HRR M,T1 ;COPY ADDRESS
|
||
HLRE T2,T1 ;COPY COUNT
|
||
SOJL T2,CPOPJ## ;EXIT IF COUNT .LE. 0
|
||
MOVE T1,DEVNAM(F) ;PICK UP DEVICE NAME
|
||
PUSHJ P,PUTWDU## ;STORE FOR USER
|
||
SOJL T2,CPOPJ## ;EXIT IF COUNT = 1
|
||
HRRZ T1,DEVIOS(F) ;PICK UP I/O STATUS WORD
|
||
PUSHJ P,PUTWD1## ;STORE FOR USER
|
||
SOJL T2,CPOPJ## ;EXIT IF COUNT = 2
|
||
MOVE T1,DEVSTS(F) ;GET DEVICE STATUS
|
||
PJRST PUTWD1## ;STORE AND RETURN
|
||
SUBTTL ERLST. UUO -- RETURN THE STATUS FOR ALL DEVICE WITH ERRORS
|
||
|
||
;ERLST. UUO
|
||
;CALL WITH:
|
||
; MOVEI AC,BLOCK
|
||
; ERLST. AC,
|
||
; RETURN HERE ERROR CODE IN AC
|
||
; RETURN HERE BLOCK UPDATED
|
||
;
|
||
;FORMAT OF BLOCK:
|
||
;
|
||
; !------------------!------------------!
|
||
; ! # OF WORD IN BLK ! CHANNEL NUMBER !
|
||
; !------------------!------------------!
|
||
; ! NUMBER OF DEVICES WHICH HAVE ERRORS !
|
||
; !------------------!------------------!
|
||
; ! UDX FOR FIRST DEV! GETSTS FOR DEV !
|
||
; !------------------!------------------!
|
||
; / /
|
||
; / /
|
||
; / /
|
||
; !------------------!------------------!
|
||
; ! UDX FOR LAST DEV ! GETSTS FOR DEV !
|
||
; !------------------!------------------!
|
||
;
|
||
;NOTE: THE NUMBER OF DEVICE WHICH HAVE ERROR WILL BE GREATER THAT THE
|
||
; NUMBER OF UDX'S RETURNED IF THERE WAS NOT ENOUGH ROOM IN THE
|
||
; BLOCK.
|
||
;
|
||
ERLST:: PUSHJ P,SAVE4## ;SAVE SOME AC'S
|
||
HRR M,T1 ;ADDRESS OF BLOCK
|
||
PUSHJ P,GETWDU## ;GET THE WORD
|
||
MOVEI P2,0 ;ERROR COUNT
|
||
HLRZ P3,T1 ;NUMBER OF WORDS IN BLOCK
|
||
HRRZ P1,T1
|
||
PUSHJ P,SETUF##
|
||
JRST ECOD1## ;(1)NOT AN OPEN CHAN #
|
||
LDB T1,PDVTYP## ;GET DEVICE TYPE
|
||
CAIE T1,.TYMPX ;SKIP IF MPX:
|
||
JRST ECOD2## ;NOT MPX: DEVICE
|
||
AOS P1,M ;WHERE TO PUT ERROR COUNT
|
||
HLRZ P4,DEVXTR(F) ;SET P4 = ADDRESS OF CDT
|
||
JUMPE P4,ERLSTX ;JUMP IF NO DEVICES CONNECTED
|
||
HLRZ T1,CDTSIZ(P4) ;NUMBER OF WORDS IN CDT
|
||
SUB T1,CDTFRE(P4) ;MINUS FREE = # IN USE
|
||
MOVNI T4,-1(T1) ;MAKE NEGATIVE
|
||
HRLZ T4,T4 ;PUT IN LH
|
||
HRRI T4,1(P4) ;POINTER IN RH
|
||
ERLSTL: HRRZ F,(T4) ;GET POINTER TO DDB
|
||
JUMPE F,ERLSTA ;SHOULD NEVER HAPPEN
|
||
MOVE T1,DEVIOS(F) ;GET STATUS
|
||
TRNN T1,760000 ;ANY ERRORS?
|
||
JRST ERLSTA ;NO--LOOK AT NEXT DEVICE
|
||
HLL T1,(T4) ;TOSS IN UDX
|
||
ADDI P2,1 ;COUNT ERROR
|
||
SOSL P3 ;SKIP IF NO ROOM
|
||
PUSHJ P,PUTWD1## ;ELSE STORE
|
||
ERLSTA: AOBJN T4,ERLSTL ;LOOP BACK OVER ALL DEVICES
|
||
ERLSTX: MOVE T1,P2 ;COUNT OF ERRORS
|
||
HRR M,P1 ;WHERE TO PUT IT
|
||
PUSHJ P,PUTWDU## ;STORE IT
|
||
JRST CPOPJ1## ;GOOD RETURN
|
||
SUBTTL CLRST. UUO -- CLEAR DEVICE STATUS
|
||
|
||
;UUO TO CLEAR DEVICE STATUS
|
||
;CALL WITH:
|
||
; MOVE AC,[LENGTH,,BLOCK]
|
||
; CLRST. AC,
|
||
; RETURN HERE ERROR CODE IN AC
|
||
; RETURN HERE IF OK
|
||
;
|
||
;BLOCK CONTAINS:
|
||
;
|
||
; !------------------!------------------!
|
||
; ! UDX, CHAN # OR SIXBIT DEVICE NAME !
|
||
; !------------------!------------------!
|
||
; ! 0 ! SETSTS VALUE !
|
||
; !------------------!------------------!
|
||
; ! UDX, CHAN # OR SIXBIT DEVICE NAME !
|
||
; !------------------!------------------!
|
||
; ! 0 ! SETSTS VALUE !
|
||
; !------------------!------------------!
|
||
; / /
|
||
; / /
|
||
; / /
|
||
; !------------------!------------------!
|
||
; ! UDX, CHAN # OR SIXBIT DEVICE NAME !
|
||
; !------------------!------------------!
|
||
; ! 0 ! SETSTS VALUE !
|
||
; !------------------!------------------!
|
||
;
|
||
CLRST:: PUSHJ P,SAVE2## ;SAVE P1 AND P2
|
||
HRRZ P1,T1 ;SAVE ADDRESS IN P1
|
||
HLRZ P2,T1 ;SAVE COUNT IN P2
|
||
CLRSTL: SUBI P2,2 ;COUNT ANOTHER TWO WORDS
|
||
JUMPL P2,CPOPJ1## ;ALL DONE IF NEGATIVE
|
||
HRR M,P1 ;GET ADDRESS OF DEVICE
|
||
PUSHJ P,GETWDU## ;GET DEVICE NAME
|
||
PUSHJ P,DVCNSG## ;FIND THE DDB
|
||
JRST ECOD1## ;(1) ILLEGAL DEVICE NAME
|
||
LDB T1,PJOBN## ;GET THE OWNER
|
||
CAME T1,.CPJOB## ;IS IT THIS JOB?
|
||
JRST ECOD2## ;(2) DEVICE NOT OWNED BY THIS JOB
|
||
PUSHJ P,GETWD1## ;GET THE NEW STATUS
|
||
TLNE T1,-1 ;ANYTHING IN LH?
|
||
PJRST ILLMOD## ;YES--ILLEGAL DATA MODE
|
||
HRR M,T1 ;COPY RH BITS
|
||
PUSHJ P,SETIOS## ;SET THE STATUS
|
||
ADDI P1,2 ;ADVANCE TO NEXT ENTRY
|
||
JRST CLRSTL ;LOOP OVER ALL REQUESTS
|
||
SUBTTL WAIT UUO
|
||
|
||
;HERE FROM WAIT1 WHEN CALLED TO WAIT FOR AN MPX CHANNEL
|
||
|
||
MPXWAI::POP P,T1 ;RESTORE T1
|
||
PUSHJ P,SAVT## ;SAVE THE T ACS
|
||
PUSHJ P,SAVE3## ;AND THE P ACS TOO
|
||
SETZ P2, ;INITIALIZE FOR NXTDV LOOP
|
||
MOVE P3,F ;MPX DDB ADDRESS IN P3
|
||
|
||
MPXWI1: PUSHJ P,NXTDV ;GET NEXT DEVICE ON THIS MPX CHANNEL
|
||
JRST MPXWI2 ;DONE THEM ALL, RETURN
|
||
MOVEI T1,WAIT1M## ;CALL THE WAIT1 ROUTINE
|
||
PUSHJ P,CALSER ;CALL THE CALL CALLER
|
||
JFCL ;HO HUM
|
||
JRST MPXWI1 ;LOOP FOR REST OF DEVICES
|
||
|
||
MPXWI2: MOVE F,P3 ;RESTORE F
|
||
MOVE S,DEVIOS(F) ;ON G.P.'S
|
||
POPJ P, ;RETURN TO WAIT1'S CALLER
|
||
|
||
|
||
|
||
;HERE FROM UUOCON ON WAIT UUO FOR DEVICE MPX
|
||
|
||
MPXWAT::PUSHJ P,SAVE3## ;SAVE P1-P3
|
||
MPXWA0: SETZ P2, ;INDICATE FIRST CALL TO NXTDV
|
||
MOVE P3,F ;SAVE MPX DDB
|
||
MPXWA1: PUSHJ P,NXTDV ;FIND THE NEXT DEVICE CONNECTED TO THE MPX
|
||
JRST MPXWA2 ;NO MORE
|
||
MOVEI T1,WAIT1M## ;WAIT FOR I/O TO STOP ON THAT DEVICE
|
||
PUSHJ P,CALSER ;CALL WAIT1
|
||
JFCL ;HO HUM
|
||
JRST MPXWA1 ;CHECK NEXT DEVICE
|
||
MPXWA2: MOVE F,P3 ;RESTORE ADDRESS OF MPX DDB
|
||
MOVE S,DEVIOS(F) ;MPX:'S I/O STATUS
|
||
TLNN S,IOSTBL ;TROUBLE SET (DEVICE HAS OUTPUT)?
|
||
POPJ P, ;NO, ALL OUTPUT OUT, ALL DEVICES IDLE
|
||
MPXWA3: PUSHJ P,MPXTBL ;TRY TO CLEAR UP TROUBLE
|
||
MOVE S,DEVIOS(F) ;IO STATUS FOR THE MPX DDB
|
||
TLNN S,IOSTBL ;TROUBLE STILL PRESENT?
|
||
JRST MPXWA0 ;NO, WAIT FOR I/O COMPLETION
|
||
MOVEI T1,^D1 ;YES, SLEEP A WHILE
|
||
MOVE J,.CPJOB## ;CURRENT JOB'S JOB NUMBER
|
||
PUSHJ P,SLEEPF## ;WAIT FOR TROUBLE TO BE FIXED
|
||
JRST MPXWA3 ;AND TRY AGAIN
|
||
;SUBROUTINE TO SEE IF ANY DEVICE ON AN MPX CHANNEL IS IN TROUBLE
|
||
; AND IF SO, GET THE DEVICE ROUTINE STARTED AGAIN
|
||
;CALLING SEQUENCE:
|
||
; MOVE F,ADDRESS OF THE MPXDDB
|
||
; PUSHJ P,MPXTBL
|
||
;ALWAYS RETURN CPOPJ
|
||
|
||
MPXTBL: MOVSI S,IOSTBL(MPXVMF) ;DEVICE IN TROUBLE BIT
|
||
TDNN S,DEVIOS(F) ;SOME DEVICE CONNECTED TO THIS MPX IN TROUBLE?
|
||
POPJ P, ;NO, NOTHING TO DO
|
||
ANDCAB S,DEVIOS(F) ;CLEAR TROUBLE IN HOPES THAT IT WILL CLEAR UP
|
||
PUSHJ P,SAVE3## ;SAVE P1-P3
|
||
SETZ P2, ;INDICATE FIRST CALL TO NXTDV
|
||
MOVE P3,F ;SAVE ADDRESS OF THE MPX DDB
|
||
MPXTB1: PUSHJ P,NXTDV ;FIND THE NEXT DEVICE CONNECTED TO THE MPX DDB
|
||
JRST MPXTB2 ;NO MORE
|
||
TLNN S,IOSTBL ;IS THIS DDB IN TROUBLE?
|
||
JRST MPXTB1 ;NO, LOOK AT THE NEXT DDB
|
||
MOVSI T1,(MPXVMF) ;NOTE THE POSSIBILITY OF A PAGE FAULT
|
||
IORM T1,DEVIOS(P3) ; IN THE MPX DDB
|
||
HRRZ T1,DEVOAD(F) ;ADDRESS OF CURRENT OUTPUT BUFFER
|
||
PUSHJ P,UADRCK## ;CHECK THAT THE BUFFER IS OK
|
||
PUSHJ P,BRNGE## ;MAKE SURE THAT THE ENTIRE BUFFER IS IN CORE
|
||
MOVSI T1,(MPXVMF) ;A PAGE FAULT DIDN'T OCCUR
|
||
ANDCAM T1,DEVIOS(P3) ; SO CLEAR THE BIT
|
||
MOVSI S,IOSTBL ;CLEAR THE TROUBLE BIT
|
||
ANDCAB S,DEVIOS(F) ; AND SETUP S
|
||
PUSHJ P,MSGCOU ;DO A CALOUT (START UP OUTPUT)
|
||
JRST MPXTB1 ;AND LOOP OVER ALL CONNECTED DEVICES
|
||
|
||
MPXTB2: MOVE F,P3 ;RESTORE F
|
||
POPJ P, ;AND RETURN
|
||
;SUBROUTINE TO FIND THE NEXT DEVICE CONNECTED TO AN MPX CHANNEL
|
||
;CALLING SEQUENCE
|
||
; MOVE F,ADDRESS OF THE MPXDDB FOR THE FIRST CALL
|
||
; MOVEI P1,0 (FIRST CALL) OR WHAT WAS RETURNED ON PREVIOUS CALL
|
||
; ; ON SUBSEQUENT CALLS
|
||
; PUSHJ P,NXTDV
|
||
; RETURNS HERE IF NO MORE CONNECTED DEVICES
|
||
; RETURNS HERE WITH F POINTING AT THE NEXT CONECTED DEVICE,
|
||
; S SETUP FROM DEVIOS FOR THAT DEVICE
|
||
|
||
NXTDV: JUMPN P2,NXTDV1 ;JUMP IF NOT THE FIRST CALL
|
||
HRRZ P1,DEVXTR(F) ;FIRST CALL, P1 = THE NUMBER OF CONNECTED DEVICES
|
||
HLRZ P2,DEVXTR(F) ;P2 = ADDRESS OF THE CDT
|
||
NXTDV1: SOJL P1,CPOPJ## ;RETURN IF NO MORE CONNECTED DEVICES
|
||
HRRZ F,1(P2) ;ADDRESS OF THE DDB FOR THE NEXT CONNECTED DEVICE
|
||
MOVE S,DEVIOS(F) ;IO STATUS FOR THAT DDB
|
||
IFN FTMP,<
|
||
PUSHJ P,SETCPF## ;GET ON CORRECT CPU
|
||
>
|
||
AOJA P2,CPOPJ1## ;STEP P2 TO NEXT SLOT IN CDT AND SKIP RETURN
|
||
|
||
;SUBROUTINE TO DETERMINE IF THE CURRENT DEVICE IS AN MPX DDB OR IS
|
||
; CONNECTED TO AN MPX DDB
|
||
;CALLING SEQUENCE:
|
||
; MOVE F,DDB ADDRESS
|
||
; PUSHJ P,CHKMPX
|
||
;RETURNS CPOPJ IF AN MPX DDB OR A DDB FOR A DEVICE CONTROLLED BY
|
||
; MPXSER, CPOPJ1 OTHERWISE
|
||
|
||
CHKMPX::LDB T1,PDVTYP## ;DEVICE TYPE
|
||
MOVE T3,DEVMSG(F) ;WORD WHICH CONTAINS BIT WHICH SAY CONNECTED TO AN MPX
|
||
CAIE T1,.TYMPX ;AN MPX DDB?
|
||
TRNE T3,DEPMSG ;OR CONNECTED TO AN MPX CHANNEL?
|
||
POPJ P, ;YES, MULTIPLEXED RETURN
|
||
JRST CPOPJ1## ;NO, NORMAL DEVICE RETURN
|
||
SUBTTL OUT UUO
|
||
|
||
;HERE FROM UUOCON ON AN OUT UUO FOR MPX:. UUOCON HAS NOT DONE
|
||
; ANYTHING YET
|
||
|
||
MSGOUT::PUSHJ P,SAVE4## ;EAT SOME PDL
|
||
PUSHJ P,MPXTBL ;GET DEVICES GOING AGAIN IF IN TROUBLE
|
||
HLRZ P4,DEVXTR(F) ;P4 GETS ADDRESS OF CDT
|
||
JUMPLE P4,NDCERR ;BETTER BE ONE
|
||
HRRZ P2,F ;P2 IS ADDRESS OF MPX DDB
|
||
PUSHJ P,JDAADP##
|
||
HLL P2,0(T1) ; IN LEFT HALF OF P2
|
||
HLR M,DEVBUF(P2) ;ADDRESS OF OUTPUT BUFFER HDR
|
||
ADDI M,3 ;ADDRESS OF 4TH WORD
|
||
PUSHJ P,GETWDU## ;GET THE WORD
|
||
PUSHJ P,FNDUDX ;FIND THE UDX
|
||
PJRST NCDERR ;NO CONNECTED DEVICE
|
||
MOVE P3,F ;P3 HOLDS THE ADDRESS OF THE TARGET DDB
|
||
IFN FTMP,<
|
||
PUSHJ P,SETCPF## ;GET ON CORRECT CPU
|
||
>
|
||
SUBI M,3 ;FIRST WORD OF HEADER
|
||
PUSHJ P,GETWDU## ;PICK UP WORD
|
||
TLNN P2,OUTBFB ;OUTBUF DONE?
|
||
JRST FIROUT ;NO--SETUP RING
|
||
JUMPE T1,STOUT1 ;GO WAIT FOR AN EMPTY BUFFER IF NEEDED
|
||
JUMPL T1,FIROUT ;JUMP IF DUMMY OUTPUT
|
||
MOVEI T2,DEPOND ;NOTHING PENDING. DO WE KNOW IT?
|
||
TDNE T2,DEVAIO(P2) ;IF WE DON'T, WE HAVEN'T CLEANED UP THE BUFFER RING HEADER
|
||
JRST STOUT1 ; SO LET'S GO TO NXTOUT IF WE CAN
|
||
PUSH P,T1 ;SAVE ADDRESS OF FIRST BUFFER
|
||
PUSH P,M ;SAVE ADDRESS OF RING HEADER
|
||
HRR M,T1 ;SETUP M FOR VMCHEK
|
||
PUSHJ P,VMCHEK ;CHECK ALL BUFFERS ARE IN CORE
|
||
MOVEI T1,(T1) ;CLEAR LH OF 1ST BUFFER ADDR
|
||
PUSHJ P,UADRCK## ;MAKE SURE IT'S LEGAL
|
||
POP P,M ;RESTORE HEADER ADDR
|
||
MOVEI T1,(M) ;RH ONLY INTO T1
|
||
HRRZ T2,(P) ;GET 1ST BUFFER ADDRESS
|
||
PIOFF ;PREVENT RACES
|
||
EXCTUX <HRRZ T3,(T2)> ;GET POINTER TO NEXT BUFFER
|
||
EXCTXU <MOVEM T3,(T1)> ;AND STORE IT IN HEADER
|
||
PION ;ALLOW IME STOPCDS
|
||
|
||
;CONTINUED ON NEXT PAGE
|
||
;CONTINUED FROM PREVIOUS PAGE
|
||
|
||
MOVSI T1,IOUSE ;GET THE USE BIT
|
||
EXCTUU <IORM T1,(T2)> ;AND SET IT FOR THOSE DEVICES THAT CHECK
|
||
|
||
;***********************************************************************
|
||
;
|
||
;ALL DEVICES CONTROLLED BY AN MPX CHANNEL MUST EXPLICITLY CHECK THAT
|
||
;THE IOUSE BIT IS SET. IF IT IS NOT SET THEN THE DEVICE SERVICE ROUTINE
|
||
;MUST SKIP THE OUTPUT AND DIRECTLY CALL ADVBFE IMMEDIATELY. THIS IS BE-
|
||
;CAUSE THE LAST CALL TO ADVBFE MARKED THE BUFFER AS OUTPUT BUT WAS UN-
|
||
;ABLE TO FREE THE BUFFER (RETURN IT TO THE FREE LIST AND ADVANCE THE
|
||
;ACTIVE LIST TO THE NEXT BUFFER TO BE OUTPUT) DUE TO (E.G.,) A PAGE
|
||
;FAULT CHAINING DOWN THE MPX FREE LIST. ALTHOUGH THIS SHOULD NOT HAPPEN,
|
||
;IF THE DEVICE IS A NETWORK DEVICE (FOR EXAMPLE) AND IT RUNS OUT OF
|
||
;DATA REQUESTS THE DEVICE IS SHUT DOWN. AT THIS POINT THE FREE LIST CAN
|
||
;BE PAGED OUT WHILE THE DEVICE STILL HAS ACTIVE BUFFERS (DEVOAD POINTS
|
||
;TO NEXT BUFFER TO OUTPUT). IF OUTPUT IS STARTED AT THIS POINT THEN
|
||
;AT OUTPUT COMPLETION (INTERRUPT LEVEL) THE BUFFER WILL NOT BE FREED UP
|
||
;SINCE MSGBFE (ADVBFE) CAN'T CHAIN DOWN THE FREE LIST, BUT IT HAS MARKED
|
||
;THE BUFFER AS NO LONGER CONTAINING ACTIVE DATA.
|
||
;
|
||
;FOR THIS REASON ALL ROUTINES WHICH WANT TO START UP OUTPUT FOR A MPX:
|
||
;CONTROLLED DEVICE SHOULD GO THROUGH MSGCOU RATHER THAN CALLING CALOUT
|
||
;DIRECTLY.
|
||
;
|
||
;***********************************************************************
|
||
|
||
POP P,U ;ADDRESS OF BUFFER TO USE
|
||
PUSHJ P,STOCNT ;COMPUTE BYTE OR WORD COUNT AND STORE
|
||
; IN BUFFER, RETURN WITH WC IN T1
|
||
PUSH P,T1 ;SAVE COMPUTED WORD COUNT
|
||
HRRZI T3,(U) ;FIRST WORD OF BUFFER
|
||
PUSHJ P,BADRCK## ;ADDRESS CHECK
|
||
JRST ADRERR## ;DID NOT PASS
|
||
HRRI M,(U) ;ADDRESS OF THE CURRENT BUFFER
|
||
PUSHJ P,GETWDU## ;GET THE LINK WORD
|
||
HLRZ T2,T1 ;GET USER'S BUFFER SIZE
|
||
POP P,T3 ;RECALL WC FROM USER'S BYTE PTR
|
||
SKIPL T3 ;NEGATIVE WORD COUNTS ARE ILLEGAL
|
||
CAIG T2,(T3) ;DOES WORD COUNT OVERFLOW BUFFER?
|
||
JRST ADRERR## ;YES! GO PREVENT HORRIBLE THINGS.
|
||
TRZ T1,-1 ;NOT LINKED TO ANYTHING AT ALL
|
||
PUSHJ P,PUTWDU## ;STORE UPDATED LINK
|
||
HLRZ T1,DEVBUF(P3) ;PICK UP ADDRESS OF LAST FULL OUTPUT BUFFER
|
||
SKIPE T1 ;SKIP OVER CHECK IF ZERO (= JUMPE T1,NEWOBF)
|
||
PUSHJ P,UADRCK## ;ADDRESS CHECK LAST BUFFER
|
||
PIOFF ;AVOID RACES
|
||
HLRZ T2,DEVBUF(P3) ;ADDRESS OF LAST BUFFER IN LIST
|
||
JUMPE T2,NEWOBF ;JUMP IF BUFFER FREED AT INTERRUPT LEVEL
|
||
EXCTUU <HRRM U,@T1> ;STORE NEW LINK
|
||
CAIA ;START UP OUTPUT
|
||
NEWOBF: HRRM U,DEVOAD(P3) ;REMEMBER ADDRESS OF LIST
|
||
HRLM U,DEVBUF(P3) ;SAVE ADDRESS AS LAST BUFFER ON ACTIVE LIST
|
||
PION
|
||
;CONTINUED FROM PREVIOUS PAGE
|
||
|
||
STOUTP: MOVE F,P3 ;ADDRESS OF TARGET DDB
|
||
MOVSI S,IOSTBL ;MAGIC SYNC BIT
|
||
ANDCAB S,DEVIOS(F) ;CLEAR (ALSO LOAD UP S)
|
||
PUSHJ P,MSGCOU ;CALL CALOUT (TO START UP OUTPUT)
|
||
STOUT1: HLR M,DEVBUF(P2) ;ADDRESS OF NEXT BUFFER
|
||
PUSHJ P,GETWDU## ;GET IT
|
||
TRNE T1,-1 ;IS IT AVAILABLE
|
||
JRST NXTOUT ;YES--START THE NEXT OUTPUT IF WE CAN
|
||
MOVEI T1,DEPAIO ;ASYNCHRONOUS OUTPUT
|
||
TDNE T1,DEVAIO(P2) ; ..
|
||
JRST STOUT2 ;YES--DO NOT WAIT
|
||
PUSHJ P,WSYNC## ;NO--WAIT FOR I/O ACTIVE TO CLEAR
|
||
HLR M,DEVBUF(P2) ;SEE IF USER WIPED-OUT
|
||
PUSHJ P,GETWDU## ;BUFFER HEADER
|
||
TRNN T1,-1 ;IS IT 0?
|
||
JRST [MOVE F,P2 ;NEED MPXDDB
|
||
JRST ADRERR##] ;FOR ADRERR
|
||
TLZE S,IOSTBL ;ERROR NEEDING A RETRY
|
||
JRST STOUTP ;YES--RETRY
|
||
JRST STOUT1 ;NO--LOOK FOR NEXT BUFFER (BETTER BE ONE)
|
||
STOUT2: MOVEI T1,DEPOND
|
||
HRRZ F,P2
|
||
IORM T1,DEVAIO(F) ;TTY BUT NONE PENDING
|
||
POPJ P,0
|
||
;HERE ON THE FIRST OUTPUT UUO
|
||
FIROUT: TRNE T1,-1 ;OUTBUF DONE?
|
||
JRST FIROU1 ;YES--DO NOT DO ONE NOW
|
||
HRRI M,2 ;TWO BUFFERS
|
||
MOVE F,P2 ;POINT TO MPX DDB
|
||
PUSHJ P,UOUTBF## ;BUILD THE RING
|
||
FIROU1: HLR M,DEVBUF(P2) ;ADDRESS OF RING HEADER
|
||
PUSHJ P,VMCHKH ;MAKE SURE ALL BUFFERS ARE IN CORE
|
||
HLR M,DEVBUF(P2) ;ADDRESS OF RING HEADER
|
||
PUSHJ P,GETWDU## ;GET ADDRESS OF FIRST BUFFER
|
||
HRRM T1,DEVOAD(P2) ;STORE IN DDB
|
||
HRRZ T1,T1 ;CLEAR VIRGIN RING BIT
|
||
PUSHJ P,PUTWDU## ;STORE BACK IN USER SPACE
|
||
PUSHJ P,JDAADP##
|
||
MOVSI T2,OUTBFB ; UUO PROGRESS BIT IS
|
||
IORM T2,0(T1) ; SET FOR THIS CHANNEL
|
||
HRRZ T1,DEVOAD(P2) ;RESTORE T1
|
||
|
||
;HERE WHEN SETUP FOR THE NEXT OUTPUT
|
||
NXTOUT: HRRZS T1 ;CLEAR ANY LH JUNK
|
||
PUSH P,T1 ;SAVE ADDRESS OF BUFFER
|
||
PUSHJ P,BUFCLR## ;CLEAR THE BUFFER
|
||
PJRST ADRERR## ;ADDRESS CHECK
|
||
MOVEI T2,DEPOND ;CLEAR OUTPUT NOT DONE YET
|
||
ANDCAM T2,DEVAIO(P2) ; SINCE THERE IS A BUFFER AVAILABLE NOW
|
||
POP P,U ;RESTORE THE ADDRESS
|
||
HRR M,U ;PICK UP THE LINK WORD
|
||
HLRZ U,DEVBUF(P2) ;ADDRESS OF THE RING HEADER
|
||
PUSHJ P,GETWDU## ; ..
|
||
MOVEI T2,(M) ;ADDRESS OF THE DATA
|
||
LDB J,[POINT 17,T1,17] ;PICK UP BUFFER SIZE
|
||
SOJA J,IOSETC## ;STORE BYTE COUNT AND RETURN
|
||
|
||
;SUBROUTINE TO MAKE SURE ALL BUFFERS ARE IN CORE
|
||
;CALL WITH:
|
||
; M = ADDRESS-OF-FIRST-BUFFER
|
||
; P3 = ADDRESS OF THE TARGET DDB
|
||
; PUSHJ P,VMCHEK
|
||
; RETURN HERE IF ALL OK
|
||
;
|
||
VMCHKH: PUSHJ P,GETWDU## ;GET FIRST (MPX: FREE) BUFFER ADDRESS
|
||
HRR M,T1 ;TO M FOR VMCHEK
|
||
VMCHEK: PUSH P,T1 ;SAVE T1
|
||
MOVE T1,DEVIOS(P3) ;DEVICE I/O STATUS
|
||
TRNE T1,IOACT ;IF DEVICE IS I/O ACTIVE
|
||
JRST TPOPJ## ;THEN BUFFERS WILL BE ASSUMED OK
|
||
; (EVEN IF THEY AREN'T (WHICH IS QUITE
|
||
; POSSIBLE) THERE IS NOTHING THAT CAN
|
||
; BE DONE ABOUT IT IF ANY IOACT IS ON)
|
||
TRNE M,-1 ;ANY (MPX FREE LIST) BUFFERS TO CHECK?
|
||
PUSHJ P,BCHCK ;MAKE SURE BUFFERS ARE IN CORE
|
||
|
||
;WE HAVE JUST TOUCHED EVERY BUFFER IN THE FREE LIST.
|
||
;NOW CHECK OUT THE DEVICE ACTIVE BUFFER LIST.
|
||
|
||
HLR M,DEVEVM(P3) ;ASSUME EVM, GET USER VIRTUAL ADDRESS
|
||
TRNN M,-1 ;UNLESS OF COURSE NOT EVM MAPPED
|
||
HRR M,DEVOAD(P3) ;IN WHICH CASE GET TRUE USER ADDRESS
|
||
; NOTE THAT THE ABOVE THREE INSTRUCTIONS
|
||
; NEED NOT BE RUN PIOFF'ED SINCE THE WORST
|
||
; THAT CAN HAPPEN IS THAT THE DEVICE FREED
|
||
; THE BUFFER (FREE LIST KNOWN OK) BUT
|
||
; COULD NOT START UP THE NEXT BUFFER DUE
|
||
; TO A PAGE FAULT ETC. THE DEVICE WILL BE
|
||
; RESTARTED ON NEXT CALL TO MPXTBL.
|
||
TRNE M,-1 ;ANY DEVICE ACTIVE LIST BUFFERS TO CHECK?
|
||
PUSHJ P,BCHCK ;MAKE SURE BUFFERS ARE IN CORE
|
||
JRST TPOPJ## ;ALL OK
|
||
|
||
|
||
|
||
;VERIFY A BUFFER CHAIN IS IN MEMORY AND ADDRESSABLE
|
||
|
||
BCHCK: PUSHJ P,SAVE1## ;SAVE P1
|
||
MOVEI P1,^D10000 ;DEFEND AGAINST LOOPS
|
||
BCHCK1: PUSHJ P,GETWRD## ;GET LINK WORD
|
||
JRST ADRERR## ;ADDRESS CHECK
|
||
MOVEI T2,(M) ;ADDRESS OF CURRENT BUFFER
|
||
HRR M,T1 ;ADDRESS OF NEXT BUFFER
|
||
MOVE T1,T2 ;ADDRESS OF CURRENT BUFFER
|
||
PUSHJ P,BRNGE## ;CHECK IT
|
||
TRNE M,-1 ;LAST BUFFER?
|
||
SOJGE P1,BCHCK1 ;NO
|
||
JUMPL P1,ADRERR## ;JUMP IF ADDRESS CHECK
|
||
PJRST SCDCHK## ;RETURN WITHOUT HOGGING CPU
|
||
;SUBROUTINE TO DO ALL GOOD THINGS FOR BYTE COUNTS AND WORD COUNTS
|
||
;CALLED WITH:
|
||
; U = ADDRESS OF BUFFER (ACTUALY BUFFER + 1)
|
||
; M = ADDRESS OF RING HEADER
|
||
; P2 = ADDRESS OF MPX DDB
|
||
; P3 = ADDRESS OF TARGET DDB
|
||
; PUSHJ P,STOCNT
|
||
; RETURN HERE LENGTH OF BUFFER IN T1 (ALWAYS WORDS)
|
||
;
|
||
;THE COUNT IN THE BUFFER IS COMPUTED FROM THE BYTE POINTER IF IOWC=0
|
||
; AND THEN STORED IN THE BUFFER
|
||
|
||
STOCNT: PUSHJ P,SAVE1## ;SAVE P1
|
||
PUSH P,M ;PRESERVE M
|
||
PUSHJ P,GETWD1## ;PICK UP THE BYTE POINTER
|
||
MOVE P1,T1 ;SAVE POINTER IN P1
|
||
HRRI M,1(U) ;POINT TO I/O BUFFER
|
||
MOVE S,DEVIOS(P2) ;PICK UP IOS WORD
|
||
LDB T2,PIOMOD## ; AND THE ASSOCIATED I/O MODE
|
||
TRNE S,IOWC ;DID USER COMPUTE WORD COUNT
|
||
JRST STOCN7 ;YES--GO CONVERT TO WORDS
|
||
SUBI T1,1(U) ;GET THE WORD COUNT
|
||
HRRE T1,T1 ;FILL LH WITH SIGN BITS (0 I HOPE)
|
||
CAIE T2,BYTMOD ;IF "BYTE" MODE
|
||
CAIN T2,PIMMOD ;OR PACKED IMAGE MODE
|
||
JRST STOCN2 ;THEN WE MUST DEAL WITH BYTES NOT WORDS
|
||
PUSHJ P,PUTWDU## ;STORE UPDATED WORD COUNT IN BUFFER HEADER
|
||
PJRST MPOPJ## ;RESTORE M AND RETURN WITH WORD COUNT IN T1
|
||
|
||
;HERE TO DEAL WITH BYTE-MODE BUFFERS
|
||
|
||
STOCN2: LDB T3,[POINT 6,P1,11] ;BITS PER BYTE
|
||
MOVEI T2,^D36 ;BITS PER WORD
|
||
IDIVI T2,(T3) ;BYTES PER WORD
|
||
IMULI T1,(T2) ;BYTES PER CURRENT BUFFER (GENEROUS ESTIMATE)
|
||
LDB T2,[POINT 6,P1,5] ;BITS FREE IN LAST WORD OF BUFFER
|
||
CAILE T2,^D36 ;LIMIT TO ONE WORD'S WORTH
|
||
MOVEI T2,^D36 ;WHAT ABOUT OWGP'S?
|
||
LDB T3,[POINT 6,P1,11];BITS PER BYTE
|
||
IDIVI T2,(T3) ;BYTES FREE IN LAST WORD OF BUFFER
|
||
SUBI T1,(T2) ;TRUE BYTE COUNT FOR BUFFER
|
||
PUSHJ P,PUTWDU## ;STORE UPDATED BYTE COUNT IN BUFFER HEADER
|
||
SUBI P1,1(U) ;RECALCULATE THE WORD COUNT
|
||
HRRE T1,P1 ;AND POSITION IT IN T1
|
||
PJRST MPOPJ## ;RETORE M AND RETURN WITH WORD COUNT IN T1
|
||
;HERE WHEN USER-SUPPLIED WORD COUNT
|
||
|
||
STOCN7: PUSHJ P,GETWDU## ;GET THE WORD COUNT FROM USER'S BUFFER HEADER
|
||
CAIE T2,BYTMOD ;"BYTE" MODE I/O?
|
||
PJRST MPOPJ## ;NO, RETURN WITH WORD COUNT IN T1
|
||
LDB T3,[POINT 6,P1,11] ;BITS PER BYTE
|
||
MOVEI T2,^D36 ;BITS PER WORD
|
||
IDIVI T2,(T3) ;BYTES PER WORD
|
||
IDIVI T1,(T2) ;WORDS PER CURRENT BUFFER
|
||
CAILE T2,0 ;IF ANY BYTES LEFT OVER,
|
||
ADDI T1,1 ;ALLOW FOR TRAILING PARTIAL WORD
|
||
PJRST MPOPJ## ;RETURN WORD COUNT IN T1
|
||
;SUBROUTINE TO CALL CALOUT FOR AN MPX-CONTROLLED DEVICE
|
||
;CALLED WITH F/ADDRESS OF TARGET DDB
|
||
;
|
||
;HANDLES THE SPECIAL CASE OF SKIPPING THE OUTPUT BUFFER IF THE
|
||
;USE BIT IS CLEARED (SEE OUT UUO CODE).
|
||
|
||
MSGCOU: MOVE S,DEVIOS(F) ;DEVICE I/O STATUS
|
||
TRNE S,IOACT ;IS DEVICE ALREADY I/O ACTIVE?
|
||
POPJ P, ;YES, DON'T TOUCH IT!
|
||
HLRZ T1,DEVEVM(F) ;ADDRESS OF USER BUFFER
|
||
TRNN T1,-1 ;UNLESS NOT MAPPED IN EVM
|
||
HRRZ T1,DEVOAD(F) ;IN WHICH CASE DEVOAD IS USER ADDRESS
|
||
EXCTUU <SKIPG (T1)> ;IS USE BIT SET (DATA TO BE OUTPUT)?
|
||
JRST MSGCO5 ;YES, ALL IS WELL
|
||
PUSHJ P,MSGBFE ;NO, AH HA! ADVANCE PAST THIS BUFFER
|
||
POPJ P, ;CAN'T STARTUP OUTPUT (E.G., PAGE FAULT)
|
||
PUSHJ P,SCDCHK## ;BE SURE WE DON'T LOOP TOO LONG
|
||
JRST MSGCOU ;JUST TO MAKE SURE . . .
|
||
|
||
MSGCO5: MOVEI T1,CALOUT## ;BUFFER CONTAINS VALID OUTPUT DATA,
|
||
PUSHJ P,CALSER ;CALL CALOUT TO START UP OUTPUT
|
||
JFCL ;YAWN
|
||
POPJ P, ;RETURN
|
||
|
||
|
||
|
||
;SUBROUTINE TO EMULATE CALOUT FOR MPX CHANNELS
|
||
;CALLED WITH F/ ADDRESS OF MPX DDB
|
||
|
||
MSGDOU: PUSHJ P,SAVE3## ;WE USE ACS LEFT AND RIGHT
|
||
SETZ P2, ;INITIALIZE FOR NXTDV CALL LOOP
|
||
MOVE P3,F ;SAVE MPX DDB (AND SET FOR NXTDV)
|
||
|
||
MSGDO1: PUSHJ P,NXTDV ;GET NEXT DEVICE OWNED BY MPX CHANNEL
|
||
JRST MSGDO2 ;ALL DONE
|
||
PUSHJ P,MSGCOU ;CALL CALOUT TO START UP OUTPUT
|
||
JRST MSGDO1 ;LOOP FOR REST OF DEVICES
|
||
|
||
MSGDO2: MOVE F,P3 ;RESTORE F TO MPX DDB
|
||
POPJ P, ;RETURN TO CALOUT FOR MPX: DEVICE
|
||
SUBTTL MSGBFE MPXSER'S ADVBFE
|
||
|
||
;SUBROUTINE CALL WHEN AN OUTPUT BUFFER IS EMPTY
|
||
;CALLED WITH:
|
||
; MOVX F,DDB-ADDRESS (OF TARGET DEVICE)
|
||
; PUSHJ P,MSGBFE
|
||
; RETURN HERE IN NO MORE FULL BUFFERS
|
||
; RETURN HERE IF MORE OUTPUT SHOULD BE DONE
|
||
;
|
||
MSGBFE::PUSHJ P,SAVE4## ;SAVE ALL THE AC'S IN SIGHT
|
||
PUSH P,T3 ; ..
|
||
MOVE P3,F ;P3 POINTS TO TARGET DDB
|
||
HRRZ P2,DEVXTR(P3) ;P2 POINTS TO MPX DDB
|
||
HRRZ T4,DEVEVM(P3) ;DOES THIS DEVICE HAVE EVM?
|
||
JUMPE T4,NOOEVM ;NO OUTPUT EVM
|
||
MOVE T4,DEVOAD(P3) ;EXEC VIRT ADDR OF CURRENT BUFFER
|
||
MOVEM S,-1(T4) ;TODD WILL HAVE FUN FINDING THIS
|
||
MOVSI T3,IOUSE ;THE BUFFER-IN-USE BIT
|
||
ANDCAB T3,(T4) ;THIS BUFFER IS NOW EMPTY
|
||
; (SEE BIG COMMENT IN OUT UUO CODE)
|
||
HLRZ T1,DEVBUF(P2) ;POINTER TO THE HEAD OF FREE LIST
|
||
MOVEI P4,^D10000 ;MAX BUFFERS LIMIT
|
||
MOVEI P1,-1 ;IF THERE IS NO FREE BUFFER LIST
|
||
MSBFE1: PUSHJ P,IADRCK## ;MAKE SURE POINTER IS LEGAL
|
||
PJRST ADVSTP ;ILLEGAL ADDRESS
|
||
PJRST ADVSTP ;CAUGHT IN THE ACT! STOP I/O.
|
||
EXCTUU <TDNN P1,(T1)>
|
||
JRST [HLL T2,DEVEVM(P3) ;GET THE USER VIRT ADDR OF THIS BUFFER
|
||
EXCTUU <HLRM T2,(T1)>;STORE THE POINTER IN PREVIOUS BUFFER
|
||
HLLZS (T4) ;MARK END OF LIST
|
||
JRST MSBFE2] ;LOOK FOR MORE BUFFERS
|
||
EXCTUX <HRRZ T1,(T1)> ;ELSE LINK TO NEXT BUFFER
|
||
SOJG P4,MSBFE1 ;SEE IF END OF LIST YET
|
||
JRST ADVSTP ;FREE LIST MESSED UP
|
||
MSBFE2: TRNN T3,-1 ;SKIP IF THERE IS MORE TO DO
|
||
JRST ADVST2 ;NO MORE BUFFERS TO EMPTY, STOP I/O
|
||
|
||
;HERE IF THERE ARE MORE BUFFERS IN THE OUTPUT LIST
|
||
|
||
PUSHJ P,BADRCK## ;ADDRESS CHECK
|
||
JRST ADVSTP ;OOO EVIL PERSON -- STOP I/O
|
||
PUSHJ P,ADVEVM## ;MAP THE NEXT BUFFER
|
||
JRST ADVSTP ;NO MORE EVM -- RETRY ON THE NEXT UUO
|
||
DPB T1,PDVOAD## ;STORE NEW ADDRESS
|
||
PJRST ADVBU1## ;TRY TO CONTINUE
|
||
;HERE TO ADVANCE BUFFERS WHEN NOT MAPPED VIA EVM
|
||
|
||
NOOEVM: HRRZ T4,DEVOAD(P3) ;USER VIRT ADDRESS IF NOT EVM-MAPPED
|
||
EXCTUU <MOVEM S,-1(T4)>;STORE UPDATED STATUS BITS
|
||
MOVSI T3,IOUSE ;THE BUFFER-IS-FULL BIT
|
||
EXCTUX <ANDCAB T3,(T4)>;MARK BUFFER IS NOW EMPTY
|
||
; (SEE BIG COMMENT IN OUT UUO CODE)
|
||
HLRZ T1,DEVBUF(P2) ;ADDRESS OF FREE LIST
|
||
MOVEI P4,^D10000 ;SETUP A LOOP COUNTER
|
||
MOVEI P1,-1 ;SETUP AC FOR TDNN BELOW
|
||
MSBFE4: PUSHJ P,IADRCK## ;BUFFER POINTERS MESSED UP?
|
||
PJRST ADVSTP ;YES..STOP JOB.
|
||
PJRST ADVSTP ;ILLEGAL ADDRESS
|
||
EXCTUU <TDNN P1,(T1)> ;END OF THE BUFFER LIST?
|
||
JRST [EXCTUU <HRRM T4,(T1)> ;ADD TO END OF FREE LIST
|
||
EXCTUU <HLLZS (T4)> ;MAKE THIS BUFFER NEW END
|
||
JRST MSBFE5] ;SEE IF MORE BUFFERS
|
||
EXCTUX <HRRZ T1,(T1)> ;FOLLOW LINK
|
||
SOJG P4,MSBFE4 ;LOOK AT NEXT BUFFER
|
||
JRST ADVSTP ;TOO MANY BUFFERS...STOP I/O.
|
||
MSBFE5: TRNN T3,-1 ;MORE BUFFERS
|
||
JRST ADVST5 ;NO MORE BUFFERS, STOP I/O
|
||
|
||
;HERE IF THERE ARE MORE BUFFERS IN THE OUTPUT LIST
|
||
|
||
PUSHJ P,BADRCK## ;CHECK THE ADDRESS OF NEXT BUFFER
|
||
JRST ADVSTP ;BAD DO NOT USE FOR I/O
|
||
HRRM T3,DEVOAD(P3) ;VALID--STORE IN DDB
|
||
PJRST ADVBU1## ;TRY TO WRITE NEXT BUFFER
|
||
|
||
|
||
|
||
;HERE TO FORCE A DEVICE TO STOP (BUT WITH MORE DATA TO BE OUTPUT)
|
||
|
||
ADVSTP: PUSHJ P,RTNEVM## ;GIVE BACK EVM
|
||
JRST T3POPJ## ;RESTORE T3 AND RETURN
|
||
|
||
;HERE TO FORCE A DEVICE TO STOP DUE TO LACK OF DATA
|
||
|
||
ADVST2: PUSHJ P,RTNEVM## ;RETURN ANY EVM WE HAVE
|
||
ADVST5: SETZM DEVOAD(P3) ;NO FIRST BUFFER IN OUTPUT LIST
|
||
HRRZS DEVBUF(P3) ;NOR LAST BUFFER IN OUTPUT LIST
|
||
JRST T3POPJ## ;RESTORE T3, TAKE STOP I/O RETURN
|
||
SUBTTL IN UUO
|
||
|
||
;HERE FROM UUOCON ON INPUT UUO
|
||
|
||
MSGIN: PUSHJ P,SAVE4## ;SAVE P1-P4 SINCE WE USE THEM
|
||
PUSHJ P,MPXTBL ;GET DEVICES GOING AGAIN IF IN TROUBLE
|
||
MSGIN0: MOVE P2,F ;ADDRESS OF MPX DDB
|
||
HLRZ P4,DEVXTR(P2) ;ADDRESS OF CDT
|
||
JUMPE P4,NDCERR ;JUMP IF NO DEVICES CONNECTED
|
||
HRRZ P1,DEVXTR(P2) ;NUMBER OF DEVICES
|
||
ADD P4,P1 ;END OF THE CDT
|
||
AOS P3,DEVCID(P2) ;POINTER TO THE NEXT INPUT DEVICE IN THE CDT
|
||
MSGIN1: CAML P3,P4 ;BEYOND THE END OF THE CDT?
|
||
HLRZ P3,DEVXTR(P2) ;YES, GET THE ADDRESS OF THE START OF THE CDT
|
||
MOVEM P3,DEVCID(P2) ;STORE NEW CURRENT INPUT DEVICE POINTER
|
||
SOJL P1,MSGIN3 ;JUMP IF ALL INPUT DEVICES HAVE BEEN POLLED
|
||
HRRZ F,1(P3) ;ADDRESS OF THE TARGET DDB
|
||
MOVE S,DEVIOS(F) ;PICK UP STATUS FLAG
|
||
LDB T1,PDVTYP## ;GET DEVICE TYPE
|
||
CAIG T1,TYPMAX ;SKIP IF TOO BIG
|
||
PUSHJ P,ITSTAB(T1) ;SEE IF INPUT IS AVAILABLE
|
||
MSGIN2: AOJA P3,MSGIN1 ;LOOP IF NO INPUT TO BE HAD
|
||
MOVE T1,DEVCHR(F) ;DEVICE CURRENTLY OFF LINE?
|
||
TLNN T1,DVOFLN ;IF SO, DON'T CONSIDER IT IN POLLING SEQUENCE
|
||
TRNE S,IOACT ;SKIP IF NOT ACTIVE
|
||
JRST MSGIN2 ;ACTIVE--IGNORE FOR NOW AND KEEP LOOKING
|
||
MOVE T4,DEVIAD(P2) ;COPY ADDRESS OF THIS BUFFER
|
||
DPB T4,PDVIAD## ; INTO TARGET DDB
|
||
EXCTUU <SETZM 1(T4)> ;CLEAR WORD COUNT IN THE BUFFER HEADER
|
||
IFN FTMP,<
|
||
PUSHJ P,SETCPF## ;GET ON CORRECT CPU
|
||
>
|
||
MOVEI T1,CALIN## ;ROUTINE TO CALL
|
||
PUSHJ P,CALSER ;CALL SERVICE ROUTINE TO FILL 1 BUFFER
|
||
JFCL ;IGNORE SKIP/NONSKIP
|
||
HLRZ T1,1(P3) ;PICK UP THE UDX
|
||
HRRZ T2,DEVIAD(P2) ;GET UVA OF INPUT BUFFER
|
||
EXCTUU <SKIPN 1(T2)> ;IF THE SERVICE ROUTINE DON'T PUT ANYTHING
|
||
JRST MSGIN1 ; IN THE BUFFER, DONT' RETURN IT EMPTY
|
||
EXCTUU <HRLM T1,1(T2)> ;STORE IN BUFFER
|
||
MOVE F,P2 ;SETUP F TO POINT TO MPX DDB
|
||
PUSHJ P,ADVBFF## ;ADVANCE BUFFERS
|
||
JFCL
|
||
POPJ P,0 ;RETURN TO UUOCON
|
||
|
||
MSGIN3: MOVE F,P2 ;SETUP F
|
||
MOVEI T1,DEPAIO ;ASYNCHRONOUS I/O
|
||
TDNE T1,DEVAIO(F) ; ..
|
||
POPJ P,0 ;YES--RETURN
|
||
MOVEI T1,^D1 ;NO--WAIT FOR A BUFFER TO BE READY
|
||
PUSHJ P,SLEEPF## ; ..
|
||
JRST MSGIN0 ; ..
|
||
DEFINE ITEST(A),<
|
||
REPEAT TYPMAX+1,<
|
||
POPJ P,0
|
||
>
|
||
IRP A,<
|
||
RELOC .TY'A+ITSTAB
|
||
PJRST IT$'A
|
||
RELOC
|
||
>>
|
||
|
||
ITSTAB: ITEST <TTY,PTY,RDA,CDR>
|
||
;SUBROUTINE TO DETERMINE IF A TTY OR PTY DDB WILL GO INTO INPUT WAIT
|
||
;CALL WITH:
|
||
; MOVEI F,ADDRESS-OF-TTY-DDB
|
||
; PUSHJ P,IT$TTY
|
||
; RETURN HERE IF NOTHING TO READ
|
||
; RETURN HERE IF 1 FULL LINE (AT LEAST)
|
||
;
|
||
IT$PTY: LDB U,PUNIT## ;GET PTY NUMBER
|
||
ADDI U,PTYOFS## ;ADD IN MAGIC OFFSET
|
||
MOVE U,LINTAB##(U) ;GET LDB ADDRESS
|
||
PJRST TOPSOP## ;CHECK IF OUTPUT IS PRESENT
|
||
IT$TTY: SE1ENT ;ENTER SECTION 1
|
||
MOVE U,DDBLDB##(F) ;GET ADDRESS OF LDB
|
||
JUMPE U,CPOPJ## ;PUNT IF NO LDB
|
||
SKIPLE LDBBKC##(U) ;IS THERE A LINE?
|
||
JRST CPOPJ1## ;YES--RETURN TO INPUT
|
||
PJRST TTLCHK## ;NO--DO BETTER TEST
|
||
|
||
IT$RDA==:NTDIDA## ;CHECK FOR INPUT.
|
||
IT$CDR==:NTDIDA##
|
||
;SUBROUTINE TO SEE IF IOACT IS ON FOR ANY MPX DEVICE
|
||
;CALL WITH:
|
||
; F = MPX DDB
|
||
; PUSHJ P,MPXACT
|
||
; RETURN HERE IF IO ACTIVE
|
||
; RETURN HERE IF NOT ACTIVE
|
||
|
||
MPXACT::PUSHJ P,SAVE4## ;WE MUST RESPECT ALL AC'S
|
||
HLRZ P4,DEVXTR(F) ;PICK UP CDT POINTER
|
||
JUMPE P4,CPOPJ1## ;JUMP IF NO DEVICES CONNECTED
|
||
HLRZ P1,CDTSIZ(P4) ;GET TOTAL SIZE
|
||
SUB P1,CDTFRE(P4) ;LESS FREE SLOTS
|
||
MOVNI P1,-1(P1) ;MAKE NEGATIVE
|
||
JUMPE P1,CPOPJ1## ;DONE NOW IF CDT EMPTY
|
||
HRL P1,P1 ;PUT IN LH
|
||
HRRI P1,1(P4) ;POINTER TO CDT
|
||
MPXAC1: MOVEI P2,IOACT ;SET UP ACTIVE BIT
|
||
MOVE P3,(P1) ;GET POINTER TO DDB
|
||
TDNN P2,DEVIOS(P3) ;SKIP IF IOACT ON
|
||
AOBJN P1,.-2 ;LOOK AT NEXT DEVICE
|
||
JUMPGE P1,CPOPJ1## ;NO ACTIVE DEVICES
|
||
MOVSI P2,DVTTY ;ACTIVE IS IT A TTY?
|
||
TDNN P2,DEVMOD(P3) ; ..
|
||
POPJ P,0 ;FAIL--AT LEAST 1 ACTIVE DEVICE
|
||
AOBJN P1,MPXAC1 ;NO--KEEP LOOKING
|
||
PJRST CPOPJ1## ;NO ACTIVE DEVICES
|
||
|
||
|
||
|
||
;SUBROUTINE TO SEE IF IOW IS ON FOR THE MPX DDB
|
||
;CALL WITH F = DDB
|
||
; PUSHJ P,MPXIOD
|
||
; RETURN HERE IF MPX DOESN'T HAVE IOW ON
|
||
; RETURN HERE IF IOW WAS ON (CLEAR IT)
|
||
|
||
MPXIOD::PUSHJ P,SAVE2##
|
||
MOVEI P1,DEPMSG ;MPX-CONTROLLED DDB?
|
||
TDNN P1,DEVMSG(F)
|
||
POPJ P, ;NO, NON-SKIP
|
||
HRRZ P1,DEVXTR(F) ;YES, GET MPX ADR
|
||
JUMPE P1,CPOPJ##
|
||
MOVE P2,DEVIOS(P1) ;IOS
|
||
TLZN P2,IOW ;WAITING?
|
||
POPJ P, ;NO-RETURN
|
||
MOVEM P2,DEVIOS(P1) ;YES, SAVE NEW STATE
|
||
PJRST CPOPJ1## ;AND SKIP-RETURN
|
||
SUBTTL SUBROUTINES
|
||
|
||
;SUBROUTINE TO FIND A DDB EITHER IN THE CDT OR BASED ON DEVICE NAME
|
||
;CALL WITH:
|
||
; T1=UDX OR DEVICE NAME
|
||
; P2=ADDRESS OF THE MPX DDB
|
||
; PUSHJ P,FNDDDB
|
||
; NO SUCH DEVICE
|
||
; RETURN HERE DDB ADDRESS IN F
|
||
|
||
FNDDDB: TLNE T1,-1 ;A UDX?
|
||
PJRST DVCNSG## ;NO, SEARCH FOR A DEVICE
|
||
PUSHJ P,SAVE4## ;SAVE ACS
|
||
HLRZ P4,DEVXTR(P2) ;CDT
|
||
JUMPE P4,CPOPJ## ;ERROR IF THERE ISN'T ONE
|
||
;FALL INTO FNDUDX
|
||
|
||
;CONTINUED ON NEXT PAGE
|
||
;CONTINUED FROM PREVIOUS PAGE
|
||
|
||
;SUBROUTINE TO FIND A UDX IN A CDT
|
||
;CALL WITH:
|
||
; P4 = ADDRESS OF CDT
|
||
; T1 = UDX TO LOOK FOR
|
||
; PUSHJ P,FNDUDX
|
||
; UDX NOT IN CDT
|
||
; RETURN HERE DDB ADDRESS IN F
|
||
;
|
||
;AC USAGE IN FNDUDX:
|
||
;P1 = LOWER LIMIT P2 = UPPER LIMIT P3 = INCREMENT
|
||
;T2 = TEMP FOR ADDRESS CALCULATION T3 = UDX FROM TABLE FOR COMPARISON
|
||
|
||
CAIA ;ENTER HERE FROM FNDDDB WITH P?S SAVED
|
||
FNDUDX: PUSHJ P,SAVE3## ;SAVE P1 THRU P3
|
||
MOVEI P1,1 ;INDEX OF FIRST ENTRY IN CDT
|
||
HLRZ P2,CDTSIZ(P4) ;SIZE
|
||
SUB P2,CDTFRE(P4) ;MINUS FREE IS INDEX OF LAST ENTRY
|
||
FNUDX1: CAILE P1,(P2) ;IS LOWER LIMIT LESS THAN OR
|
||
; EQUAL TO UPPER LIMIT?
|
||
POPJ P,0 ;NO--UDX IS NOT IN CDT
|
||
|
||
;COMPUTE MID POINT IN RELEVANT RANGE
|
||
|
||
MOVEI P3,1(P1) ;LOWER LIMIT (+1 FOR ROUNDING)
|
||
ADDI P3,(P2) ;PLUS UPPER LIMIT
|
||
LSH P3,-1 ;DIVIDED BY TWO
|
||
MOVEI T2,(P4) ;BASE OF TABLE
|
||
ADDI T2,(P3) ;PLUS INDEX GIVE ADDRESS OF ENTRY
|
||
HLRZ T3,(T2) ;PICK UP THE UDX
|
||
JUMPE T3,FNUDX3 ;THE BEST ALGORITHMS NEED A FUDGE
|
||
CAMGE T3,T1 ;THE COMPARE
|
||
JRST FNUDX2 ;TRY LOWER HALF OF TABLE
|
||
CAMN T3,T1 ;IS THIS THE ENTRY?
|
||
JRST [HRRZ F,(T2) ;YES--PICK UP DATA
|
||
JRST CPOPJ1##] ;GIVE GOOD RETURN
|
||
FNUDX3: MOVEI P2,-1(P3) ;SET NEW UPPER LIMIT
|
||
JRST FNUDX1 ;TRY AGAIN
|
||
|
||
;HERE IF ENTRY IS TOO SMALL
|
||
FNUDX2: MOVEI P1,1(P3) ;BOOST UP THE LOWER LIMIT
|
||
JRST FNUDX1 ;TRY AGAIN
|
||
;SUBROUTINE TO CALL A SERVICE ROUTINE VIA UUOCON
|
||
;CALL WITH:
|
||
; T1 = ADDRESS OF ROUTINE TO CALL
|
||
; F = A DDB ADDRESS
|
||
; PUSHJ P,CALSER
|
||
; RETURN HERE
|
||
; OR HERE
|
||
|
||
CALSER: PUSHJ P,SAVE4## ;SAVE P1 THRU P4
|
||
MOVE P1,T1
|
||
PUSHJ P,JDAADR##
|
||
PUSH P,USRHCU## ;SAVE THIS
|
||
PUSH P,0(T1) ;AND THIS
|
||
HLL F,DEVXTR(F) ;PICK UP FLAGS
|
||
MOVE S,DEVIOS(F) ;ALWAYS NICE TO HAVE S SET UP
|
||
PUSHJ P,(P1) ;CALL ROUTINE
|
||
SOS -2(P) ;NON-SKIP
|
||
PUSHJ P,JDAADR##
|
||
HLL F,0(T1) ;GET UPDATED FLAGS
|
||
HLLM F,DEVXTR(F) ;STORE BACK IN DDB
|
||
POP P,0(T1) ;RESTORE JUNK
|
||
POP P,USRHCU## ; ..
|
||
HRRZ P1,DEVXTR(F) ;P1 POINTS TO THE MPX DDB
|
||
MOVSI P2,IOSTBL ;DEVICE OFF-LINE BIT
|
||
TDNE P2,DEVIOS(F) ;TROUBLE ON THE TARGET DEVICE?
|
||
IORM P2,DEVIOS(P1) ;YES, SET TROUBLE IN THE MPX DBB
|
||
JRST CPOPJ1## ;RETURN (SKIP MAY HAVE BEEN UNDONE)
|
||
SUBTTL ERROR ROUTINES
|
||
|
||
NDCERR: JSP T1,ERRPTU## ;PRINT MESSAGE
|
||
ASCIZ \I/O with no devices connected for \
|
||
PJRST DEVEXC## ;SAY DEVICE XXX
|
||
|
||
NCDERR: PUSH P,T1 ;SAVE UDX
|
||
PUSHJ P,DVCNSG## ;FIND REAL DDB
|
||
SKIPA T2,[SIXBIT .(NONE).] ;NO SUCH DEVICE NAME
|
||
MOVE T2,DEVNAM(F) ;REAL DEVICE NAME
|
||
PUSH P,T2 ;SAVE NAME
|
||
JSP T1,ERRPTU## ;PRINT MESSAGE
|
||
ASCIZ /Output to unconnected device [/
|
||
MOVE T2,-2(P) ;PICKUP NAME
|
||
PUSHJ P,PRNAME## ;PRINT IT
|
||
PUSHJ P,INLMES## ;ADD SOME WORDS
|
||
ASCIZ \] UDX=\
|
||
MOVE T1,-3(P) ;PICKUP UDX
|
||
PUSHJ P,PRTDI8## ;PRINT UDX
|
||
SUB P,[2,,2] ;REMOVE TWO ITEMS FROM THE STACK
|
||
PJRST UUOPCP## ;PRINT PC AND STOP JOB
|
||
MPXEND: END
|