Trailing-Edge
-
PDP-10 Archives
-
BB-BT99T-BB_1990
-
10,7/mon/nulfek.mac
There are 8 other files named nulfek.mac in the archive. Click here to see a list.
TITLE NULFEK - LOCAL NETWORK "FRONT END" SERVICE ROUTINE - V014
SUBTTL WEM/ 17 APR 90
SEARCH F,S,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
; 1978,1979,1980,1982,1984,1986,1988,1990.
;ALL RIGHTS RESERVED.
.CPYRT<1978,1990>
XP VNLFEK,014 ;PUT VERSION NUMBER IN GLOB AND LOADER MAP
NULFEK::ENTRY NULFEK
COMMENT @
The "null" FEK is intended to behave the same as any normal FEK except
for the fact that any "output" messages it is given are returned as "input"
messages. This allows the -10 to talk to itself on lonely nights when the
operators have gone home. Currently it's only use is in the implementation
of local task's. Whether of not this method is smaller than the local tasks
of yesteryear may be debated. It's certianly slower. It has however, the
following redeeming features.
a) Task to task may be completly debugged on a singly -10 cpu. (Even
the fancy connect processing)
b) Common code is used as much as possible. This means that local
tasks won't get broken every week.
c) I don't have to worry about the case of two 100k user jobs trying
to talk to each other via local tasks on a 256k machine. (As far
as I can tell trying to lock both jobs in core would simply hang
the system...)
A few things should be mentioned about the code. First, the code attempts
to perform the proper byte conversion and data compression operations normally
delegated to the front-end -11. These functions will also be required by the
KS-10 project. Steal this code. Second, one can run the "null" FEK as fast
as one wants simply by putting the call go "NLFCPY" in the approiate place. I
expect that the optimal place is in the "NLFRDD" and "NLFWRT" routines for
maximum through put, though for controlled debugging, I suggest some less
synchronous place such as a clock interrupt.
@
SUBTTL 1.0 NULL FEK ENTRY POINTS. (VECTORED HERE BY THE FEK BLOCK)
NLFDSP::CAIL T1,FF.ONC ;RANGE CHECK THE FUNCTION CODE
CAILE T1,FF.CPW ; CODE AND STOP IF BAD
STOPCD .,STOP,NULFNC, ;++ FUNCTION CODE OUT OF RANGE
JRST @.+1(T1) ;DISPATCH ON FUNCTION CODE
IFIW NLFONC ;ONCE ONLY CODE
IFIW NTFSEC## ;ONCE/SECOND CODE (USE NETSER'S DEFAULT)
IFIW NLFRDD ;READ REQUEST
IFIW NLFWRT ;WRITE REQUEST
IFIW NTDSTP## ;CRASH. SHOULD NEVER HAPPEN
IFIW NTDSTP## ;DOWN. SHOULD NEVER HAPPEN
IFIW NTDSTP## ;UP. SHOULD NEVER HAPPEN
IFIW CPOPJ## ;STATION CONTROL (WE'RE NOT INTERESTED)
IFIW CPOPJ## ;OUR CPU IS GOING TO SLEEP
IFIW CPOPJ## ;OUR CPU IS WAKING UP
NLFONC: MOVSI T1,FK.ONL!FK.NID!FK.NUL ;GET THE BITS THAT SYSINI CLEARS
IORB T1,FEKBLK(J) ;AND SET THEM SO THIS FEK IS "ALIVE"
POPJ P, ;THAT'S ALL
NLFRDD: AOS FEKBSI(J) ;MARK "INPUT ACTIVE"
MOVSI T1,FK.STO ;GET THE "KICK OUTPUT BIT"
IORM T1,FEKBLK(J) ; AND TELL CLOCK LEVEL TO TRY OUTPUT
POPJ P, ;WE DON'T CALL NLFCPY HERE BECAUSE
; WE WOULD BUILD THE STACK UP TOO HIGH
NLFWRT:;PJRST NLFCPY ;CALL THE COPY ROUTINE
;NLFCPY ROUTINE CALLED TO PROCESS ONE OUTPUT PCB AND COPY IT IN TO ONE
; INPUT PCB, FINALLY CALLING FEKINT TWICE SO THAT NETSER NOTICES.
;CALL MOVEI J,FEK
; PUSHJ P,NLFCPY
;RETURN CPOPJ ;AFTER CALLING "FEKINT"
;
;REGISTER USAGE FOR THIS IS
; S := USUALLY USED TO PASS THE NEXT CHAR TO BE COPIED
; T1 := THE COUNT OF CHARS TO TAKE FROM THE "OUTPUT" PCB
; T2 := THE BYTE POINTER USED IN REMOVING CHARS FROM THE "OUTPUT" PCB
; T3 := THE COUNT OF CHARS PUT IN THE "INPUT" PCB
; T4 := THE BYTE POINTER USED TO PUT CHARS IN THE "INPUT" PCB
; P1-P3 :=LOCAL STORAGE FOR THE ROUTINES THAT MUST TO BYTE PACKING.
; U := POINTER TO THE "OUTPUT" PCB (THE ONE WE READ DATA FROM)
; W := POINTER TO THE "INPUT" PCB (THE ONE WE WRITE DATA TO)
; J := POINTER TO THE FEK (AT ENTRY), OR RETURN ADDR FOR "QUICKIES"
;
NLFCPY::JSP T1,SETUP ;PUSH W, U, S AND SET UP S
NLFCP1: AOSE FEKBSO(J) ;TRY TO GET THE OUTPUT INTERLOCK
JRST [MOVSI T1,FK.STO;IF THE OTHER CPU IS COPYING,
IORM T1,FEKBLK(J); THEN MAKE SURE HE LOOKS AT US LATER
JRST EXIT] ; AND LEAVE. (1 CPU'S ENOUGH)
SKIPLE FEKOCT(J) ;MAKE SURE THERE IS OUTPUT TO GO
SKIPGE FEKBSI(J) ; AND MAKE SURE WE'VE GOT AN INPUT BUFFER
JRST [SETOM FEKBSO(J);IF WE CAN'T COPY NOW, CLEAR OUTPUT ACTIVE
JRST EXIT] ; AND EXIT
HRRZ U,FEKOAD(J) ;GET THE OUTPUT (WE READ FROM IT) PCB
HRRZ W,FEKIAD(J) ;GET THE INPUT (WE WRITE TO IT) PCB
SETZ T3, ;WE HAVE COPIED NO BYTES TO THE INPUT PCB
MOVE T4,PCBPTR(W) ;BUT THIS IS WHERE WE'LL PUT 'EM WHEN WE DO.
MOVE T1,PCBCTR(U) ;THE COUNT OF THE NUMBER OF CHARS IN THE HEADER
MOVE T2,PCBPTR(U) ;BYTE POINTER TO THE HEADER SECTION
CPY1: SOJL T1,CPY2 ;COUNT DOWN THE HEADER CHARS
ILDB S,T2 ;GET THE NEXT BYTE
IDPB S,T4 ;STORE IT IN THE "INPUT" PCB
AOJA T3,CPY1 ;LOOP OVER ALL HEADER CHARS
CPY2: LDB T1,PCBPCV## ;GET THE CONVERSION CODE
CAIL T1,PCV.NC ;RANGE CHECK
CAILE T1,PCV.BN ; IT BEFORE DISPATCHING OFF OF IT
STOPCD .,STOP,NULCCR, ;++ CONVERSION CODE OUT OF RANGE
PUSHJ P,@[ ;DISPATCH TO PROPER COPY ROUTINE
IFIW C.NC ;NO CONVERSION/COMPRESSION
IFIW C.LP ;LINE PRINTER COMPRESSION
IFIW C.BN](T1) ;BINARY CONVERSION
MOVEM T3,PCBCTR(W) ;STORE THE COUNT OF CHARS COPIED
NETOFF ;NO INTERRUPTS WHILE HACKING QUEUES
HRRZM U,FEKODN(J) ;STORE THE EMPTIED PCB
HRRZ U,PCBBLK(U) ;GET POINTER TO "NEXT" PCB TO BE OUTPUT
HRRZM U,FEKOAD(J) ; AND MAKE IT "FIRST"
SOS FEKOCT(J) ;DECREMENT THE NUMBER OF PCB'S TO BE OUTPUT
NETON ;INTERRUPTS OK NOW
SETOM FEKBSI(J) ;CLEAR INPUT ACTIVE
MOVEI T1,FI.RDD ;GET THE "INPUT DONE" BIT
PUSHJ P,FEKINT## ;LET NETSER GROVEL ON RECYCLED DATA
MOVEI T1,FI.ODN ;GET THE "OUTPUT DONE" BIT
PUSHJ P,FEKINT## ;LET NETSER CALL US BACK WITH A NEW OUTPUT PCB
SETOM FEKBSO(J) ;CLEAR OUTPUT ACTIVE
JRST NLFCP1 ;GO SEE IF THERE ARE ANY MORE TO DO
;C.NC ROUTINE TO DO A QUICK "NO COMPRESSION" COPY
C.NC: MOVE T1,PCBCT2(U) ;GET THE SECONDARY BYTE COUNT
MOVE T2,PCBPT2(U) ;GET THE SECONDARY BYTE POINTER
C.NC1: SOJL T1,CPOPJ## ;LOOP OVER ALL CHARACTERS
ILDB S,T2 ;GET THE NEXT 8 BIT CHAR
IDPB S,T4 ;AND STORE IT IN THE "INPUT" MESSAGE
AOJA T3,C.NC1 ;KEEP IT UP UNTIL ALL CHARS COPIED
;C.LP ROUTINE TO SEND THE SECONDARY DATA OF A PCB WITH LINE PRINTER
; COMPRESSION
;
;DATA FOR LINE PRINTER IS COMPRESSED AS FOLLOWS:
; 1CCCCCCC CCCCCCC IS CHARACTER
; 01XXXXXX XXXXXX IS NUMBER OF BLANKS
; 001XXXXX XXXXX IS REPETITION FOR FOLLOWING CHAR
;
;REGISTER USAGE IS
; P1 := REPEAT COUNT
; P2 := CHAR BEING REPEATED
; P3 := NEXT CHAR (READ HERE AND COMPARED WITH P2)
;
C.LP: JSP T1,SAVE4 ;PUSH J, P1, P2, P3
MOVE T1,PCBCT2(U) ;GET THE SECONDARY BYTE COUNT
MOVE T2,PCBPT2(U) ;GET THE BYTE POINTER
SETZ P1, ;INITIALIZE THE REPEAT COUNT
SOJL T1,RTN4X ;COUNT OFF THE FIRST BYTE
ILDB P2,T2 ;READ THE FIRST BYTE FOR COMPARISON
LPLOOP: SOJL T1,NMATCH ;COUNTING DOWN IS THE SAME AS NO-MATCH
ILDB P3,T2 ;GET THE NEXT BYTE
CAIN P2,(P3) ;IS IT THE SAME AS THE LAST?
AOJA P1,LPLOOP ;IF SO, COUNT IT AND CONTINUE
NMATCH: JUMPE P1,SINGLE ;IF P1 = 0, THEN ONLY ONE CHAR TO SEND
AOS P1 ;ACCOUNT FOR THE FIRST CHAR
CAIN P2," " ;ARE WE COMPRESSING SPACES?
JRST SPACES ;IF SO. TREAT THEM ESPECIAL
CHAR: CAIG P1,37 ;WAS THIS REPEATED TOO MANY TIMES FOR ONE BYTE
JRST CHARX ;NO. WE CAN SEND IT AT ONCE
MOVEI S,77 ;MAXIMUM REPEAT COUNT
JSP J,WRITE8 ;SEND THE COUNT
MOVEI S,(P2) ;GET THE CHARACTER WE REPEATED
JSP J,WRITE8 ;AND SEND THAT
SUBI P1,37 ;INDICATE THAT WE HAVE SEND SOME
JRST CHAR ;GO BACK AND SEE IF IT WAS ENOUGH
CHARX: MOVEI S,40(P1) ;GET THE REPEAT COUNT
JSP J,WRITE8 ;SEND THAT
MOVEI S,(P2) ;GET THE CHARACTER
JSP J,WRITE8 ;AND SEND THAT
JRST ADVNCE ;COPY P2 := P3, CLEAR P1 AND LOOK FOR MORE.
SPACES: CAIG P1,77 ;MORE SPACES THAN WE CAN COMPRESS IN 1 BYTE
JRST SPACEX ;IF NOT. SEND THE COUNT AND GO BACK TO LOOP
MOVEI S,177 ;WE CAN SEND 77 IN ONE BYTE.
JSP J,WRITE8 ;SEND THEM
SUBI P1,77 ;ACCOUNT FOR THE SPACES SENT
JRST SPACES ;AND TRY TO SEND MORE
SPACEX: MOVEI S,100(P1) ;GET THE "SPACE" BIT AND THE COUNT
JSP J,WRITE8 ;SEND THE SPACES
JRST ADVNCE ;ADVANCE THE CHARACTERS AND READ SOME MORE
SINGLE: MOVEI S,200(P2) ;GET THE "SINGLE CHAR" BIT
JSP J,WRITE8 ;SEND THE CHARACTER
ADVNCE: SETZ P1, ;CLEAR THE REPEAT COUNT
MOVEI P2,(P3) ;ADVANCE THE CHARACTER TO MATCH
JUMPG T1,LPLOOP ;GO BACK TO LOOP IF THERE ARE MORE CHARS TO DO
JRST RTN4X ;OTHERWISE RESTORE THE STACK AND POPJ
;*** FOOTNOTE ***
COMMENT \
Currently the line-printer compression code does not work. The code
must be made smart enough to fixup the "CNT" field for the message whose
data it is compressing. This involves re-parsing the NCL header and poking
in the new "CNT" (Which is NEVER longer. Either shorter or the same length)
\
;C.BN ROUTINE TO DO A "BINARY" (IE 12 BIT) COPY.
; THE BASIC IDEA IS TO USE FANCY BYTE MOTION TO PLACE THE 4 BIT SUB-BYTES
C.BN: JSP T1,SAVE4 ;PUSH J, P1, P2, AND P3
MOVE T1,PCBCT2(U) ;GET THE SECONDARY BYTE COUNT (12 BIT BYTES)
MOVE T2,PCBPT2(U) ;GET THE SECONDARY BYTE POINTER.
C.BN1: SOJL T1,RTN4X ;IF ALL DONE. RETURN 4 AND POPJ
ILDB P1,T2 ;GET THE FIRST 12 BITS
LDB S,[POINT 8,P1,31] ;SEND THE FIRST 8 BITS (LEAVE 4)
JSP J,WRITE8
SOJL T1,C.BNX ;IF WE COUNT OUT NOW WE HAVE 4 LEFT.
ILDB P2,T2 ;GET SECOND 12 BITS
LDB S,[POINT 4,P2,27] ;GET 4 LOW BITS FROM NEW 12 BIT BYTE
DPB P1,[POINT 4,S,31] ;PUT 4 HIGH BITS IN FROM OLD 12 BIT BYTE
JSP J,WRITE8 ;SEND THE 8 BITS
LDB S,[POINT 8,P2,35] ;GET THE LAST 8 BITS FROM NEW 12
JSP J,WRITE8 ;SEND THOSE
JRST C.BN1 ;LOOP UNTIL "OUTPUT" IS EXHAUSTED
C.BNX: LDB S,[POINT 4,P1,35] ;HERE WE HAVE 4 BITS LEFT OVER. GET THEM IN S
LSH S,4 ;MAKE THEM HIGH ORDER BITS. FILL WITH ZEROS
JSP J,WRITE8 ;SEND THE BYTE
JRST RTN4X ;POP STACK AND POPJ
;UTILITY ROUTINES USED BY THE NULL FEK
;WRITE8 ROUTINE TO OUTPUT 8 BITS TO THE "INPUT" PCB
;CALL MOVE S,CHAR
; JSP J,WRITE8
;RETURN JRST (J)
;
WRITE8: IDPB S,T4 ;STORE THE CHARACTER
AOJA T3,(J) ;COUNT IT AND RETURN
;SETUP SAVE 3 REGISTERS. SETUP S AND RETURN
;CALL JSP T1,SETUP
;RETURN JRST (T1)
;
SETUP: PUSH P,W ;SAVE THE NDB POINTER (OR WHATEVER)
PUSH P,U ;SAVE THE PCB POINTER
PUSH P,S ;SAVE THE STATUS REGISTER
HLLZ S,FEKBLK(J) ;GET THE FLAGS
JRST (T1)
;EXIT RESTORE THE STACK AND POPJ
;
EXIT: POP P,S ;RESTORE THE STATUS
POP P,U
POP P,W
POPJ P,
;SAVE4 ROUTINE TO SAVE 4 COMMONLY USED REGISTERS
;CALL JSP T1,SAVE4
;
SAVE4: PUSH P,J
PUSH P,P1
PUSH P,P2
PUSH P,P3
JRST (T1)
;RTN4X RESTORE THE 4 REGIXTERS AND EXIT (POPJ)
;
RTN4X: POP P,P3
POP P,P2
POP P,P1
POP P,J
POPJ P,
XLIST ;DON'T LIST LITERALS
$LIT
LIST
END