Google
 

Trailing-Edge - PDP-10 Archives - bb-kl11m-bm - t20src/subdcn.mac
There are 7 other files named subdcn.mac in the archive. Click here to see a list.
;	COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1989.
;	ALL RIGHTS RESERVED.
;
;	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.
;
;	THE INFORMATION IN THIS  SOFTWARE IS SUBJECT  TO CHANGE WITHOUT  NOTICE
;	AND SHOULD  NOT  BE CONSTRUED  AS  A COMMITMENT  BY  DIGITAL  EQUIPMENT
;	CORPORATION.
;
;	DIGITAL ASSUMES NO  RESPONSIBILITY FOR  THE USE OR  RELIABILITY OF  ITS
;	SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
	TITLE SUBDCN - MX's DECnet Subfork
	TWOSEG
	RELOC 400000

	SEARCH MONSYM,MACSYM,PROLOG

	SD.INI==0		;Function code for INIT
	SD.OPN==1		;Function code for OPEN
	SD.RD==2		;Function code for READ
	SD.WRM==3		;Function code for WRITE MESSAGE
	SD.WRS==4		;Function code for WRITE STRING
	SD.MAX==SD.WRS		;Max function code
	SD.MIN==SD.INI		;Min function code

;Other constants and variables
	BIT0==1B0		;
	DORBEL==1B0		;Our doorbell is channel 0
	OPNBEL==1B1		;DECnet Link "Open"

;OPNCHN contains the value for T3 in an MTOPR% .MOACN function to turn on
;"Data Available" and "Connection" interrupts on channel 1.

	OPNCHN==FLD(1,MO%DAV)+FLD(1,MO%CDN)+FLD(.MONCI,MO%INA)

;OFFCHN contains the value for T3 in an MTOPR% .MOACN function to turn off
;the "Data Available" and "Connection" interrupts.

	OFFCHN==FLD(.MOCIA,MO%DAV)+FLD(.MOCIA,MO%CDN)+FLD(.MOCIA,MO%INA)

	STKSIZ==200		;Arbitrary stack size
				; We don't need nearly so much...

;Offsets into private page
	SFFLG==0		;Flag bits
	SFFUN==1		;Function code
	SFAC2==2		;Other args
	SFAC3==3		;
	SFAC4==4		;
	CHTAB==5		;36 word channel table for interrupts
	LVTB1==51		;3 word interrupt level table
	LVTB2==52		;
	LVTB3==53		;
	INPC1==54		;Storing PC during level 1 interrupt
	INPC2==55		;Storing PC during level 2 interrupt
	SVJFN==56		;The JFN of the open link
	SVPTR==57		;The byte pointer for the link
	SVINT==60		;The interrupt channel number
	INTCH==61		;The interrupt channel mask
	QUAYLE==62		;3 dummies, used during $DMPACS
	BENTSN==63
	DUKAKS==64
	LAST==777		;The last location on the page

;Macro definitions

DEFINE $TRACE (TXT,%DONE) <
	TXNN F,SD%DBG
	JRST %DONE
	PUSH P,T1
	HRROI T1,[ASCIZ /TXT
/]
	PSOUT
	POP P,T1
%DONE:
>

DEFINE $TRFUN (%DONE) <
	TXNN F,SD%DBG
	JRST %DONE
	PUSH P,T1
	HRRO T1,FNDBG(Q2)
	PSOUT%
	POP P,T1
%DONE:
>
DEFINE $DMPACS (%DONE) <
	TXNN F,SD%DBG
	JRST %DONE
	MOVEM T1,QUAYLE(P6)
	MOVEM T2,BENTSN(P6)
	MOVEM T3,DUKAKS(P6)
	HRROI T1,[ASCIZ /Subfork ACs:
/]
	PSOUT
	MOVEI T1,.PRIOU
	MOVE T3,[NO%MAG!NO%LFL!FLD(15,NO%COL)+10]
	MOVE T2,F
	NOUT
	 JFCL
	MOVE T2,QUAYLE(P6)
	NOUT
	 JFCL
	MOVE T2,BENTSN(P6)
	NOUT
	 JFCL
	MOVE T2,DUKAKS(P6)
	NOUT
	 JFCL
	MOVE T2,T4
	NOUT
	 JFCL
	MOVE T2,P6
	NOUT
	 JFCL
	HRROI T1,[ASCIZ /
/]
	PSOUT
	MOVE T1,QUAYLE(P6)
	MOVE T2,BENTSN(P6)
	MOVE T3,DUKAKS(P6)
%DONE:
>
;
; When we enter the main loop, the ACs are expected to be set up in the
; following manner:
;
; F/  Status bits for ACSTAT
	SD%RUN==1B0		;Should be set.
	SD%ERR==1B1		;We set this if an error occurs.
	SD%DNE==1B2		;We set this if the error is a DECnet
                                ;disconnect
	SD%DBG==1B3		;If set by MX, we PSOUT trace info
	SD%REA==777777		;We store the error/disconnect code here
; T1/ Function Code for ACFUNC
; T2-T4/ Function specific arguments
;
; The following functions expect arguments:
;
;	Function	ACFUNC	ACCHAN/ACBREA	ACBYTP	   ACBLEN
;
;	Initialize	sd.ini  Int. Chan. No.	Page Addr. N/A
;	Open		sd.opn	N/A		Filespec   N/A
;	Read		sd.rd	N/A		Buffer	   Buffer Len
;	Write Message	sd.wrm	N/A		Buffer	   Buffer Len
;	Write String	sd.wrs	N/A		Buffer	   Buffer Len
;Main loop begins here
SUBDCN::CAIL T1,SD.MIN		;Skip if less than min
	CAILE T1,SD.MAX		;Skip if in range
	SKIPA T1,[ARGX02]	;Out of range.  Error code in T1, Skip.
	JRST @FNCTAB(T1)	;Go do the appropriate function
				;Note that all functions except SDINIT
                                ;expect P6 to be set up.  P6 is set up by
                                ;SDINIT...

;Here if some kind of error occured with error in T1
SDERR:	TXO F,SD%ERR		;Some kind of error occured
	TXNN T1,.ERBAS		;Is this a TOPS-20 error
	TXO F,SD%DNE		;It's a DECnet error
	HRR F,T1		;Stash the error code

;Here when it's time to notify the parent either as a result of SDERR, or a
;function's normal completion.
SDDONE:	MOVEM F,SFFLG(P6)	;Squirrel away the status
	MOVE T2,INTCH(P6)	;Get the interrupt channel.
	MOVEI T1,.FHSUP		;Want to interrupt my superior.
	IIC%			;Interrupt him
	 ERJMP SDNINT		;Couldn't do it.  Give up.
	
SDWAIT:	WAIT%			;Ok, wait for the doorbell
	HALTF%			;Should never happen

;Next comes the interrupt service routine for our doorbell
SDISR:	MOVEI T1,SDNXTC		;Ready for the next command
	MOVEM T1,INPC1(P6)	;Change the PC
	DEBRK%			;Resume

;We get resumed here after the parent rings our doorbell.
SDNXTC:	DMOVE F,SFFLG(P6)	;Set up the ACs from the data page
	DMOVE T2,SFAC2(P6)	;...
	MOVE T4,SFAC4(P6)	;...
	JRST SUBDCN		;Go back to the beginning and start over

SDNINT:	$TRACE <*** IIC failed! ***>
SDHALT:	HALTF%			;Here if we can't interrupt our parent.
	JRST .-1

FNCTAB:	SDINIT			;Initialize function
	SDOPEN 			;Open function
	SDREAD 			;Read function
	SDWRTM 			;Write Message function
	SDWRTS 			;Write String function
;Routine SDINIT - Initialize Subfork
;	T2/ Interrupt Channel of Superior fork
;	T3/ Page number of our data page
;	JRST SDINIT
; 	returns to location SDDONE always
;
SDINIT:	$TRACE <SDINIT>
	RESET%			;Start fresh
	MOVX T1,.FHSLF		;Shut off all interrupts.  We don't want to
	DIR%			; be interrupted while we're in SDINIT!
	MOVX T1,<CZ%ABT+.FHSLF>	;Abort all files
	CLZFF%			; just in case some are still open.
	SKIPL T4,T2		;Skip if interrupt channel less than 0
	CAIL T2,^D36		;Skip if in range
	IFSKP.
	  $TRACE <Valid Interrupt Channel>
	  MOVE P6,T3		;Get our data page number...
	  IMULI P6,1000		;...and make it an address.

	  SETZM 1(P6)		;Clear the first location
	  HRLI T1,1(P6)		;Source,,0
	  HRRI T1,2(P6)		;Source,,Destination
	  BLT T1,LAST(P6)	;Clear the page

	  MOVX T1,BIT0		;Initialize T1
	  MOVEM T4,SVINT(P6)	;Save the channel number
	  MOVN T2,T4		;Negate T2
	  LSH T1,(T2)		;Set the appropriate bit
	  MOVEM T1,INTCH(P6)	;Store the mask here

	  MOVEI T1,INPC1(P6)	;Where we store pc for level 1 interrupts
	  MOVEM T1,LVTB1(P6)	;Set up level table
	  MOVEI	T1,INPC2(P6)	;Where we store pc for level 2 interrupts
	  MOVEM T1,LVTB2(P6)	;Set up level table

	  MOVEI T4,CHTAB(P6)	;Get the address of the channel table
	  MOVE T1,[1,,SDISR]	;Channel zero is our doorbell
	  MOVEM T1,0(T4)	;Set it in the channel table
	  MOVE T1,[2,,SDOPII]	;Channel 1 is for DECnet "Open" interrupts
	  MOVEM T1,1(T4)	;Channel table is set up
	  MOVEI T1,.FHSLF	;Process handle
	  HRLI T2,LVTB1(P6)	;Level table
	  HRRI T2,CHTAB(P6)	;Channel table
	  CIS%			;Clear any pending interrupts
	  SIR%			;Reset the PSI tables
	  EIR%			;Enable interrupt system
	  MOVX T2,DORBEL	;Turn on our doorbell
	  AIC%			;Now...
	ELSE.
	  $TRACE <Invalid Interrupt Channel>
INVIC:	  HALTF%
	ENDIF.
	JRST SDDONE		;Rejoin Main flow
;Routine SDOPEN - Open a connection
;	P6/ The address of the common data page
;	JRST SDOPEN
;	Returns to location SDERR or SDDONE as appropriate

SDOPEN:	$TRACE <Opening>
	MOVE T2,SFAC2(P6)	;Get the byte pointer
	MOVEM T2,SVPTR(P6)	;Save the byte pointer
	MOVX T1,GJ%SHT		;Use short form GTJFN
	GTJFN%			;Get the JFN
	 ERJMPR SDERR		;Something went wrong
	MOVEM T1,SVJFN(P6)	;Save the JFN here
	MOVEM T1,SFAC3(P6)	;and where the parent can see it.
	MOVX T2,<OF%RD!OF%WR>+FLD(10,OF%BSZ) ;8 bit bytes, read/write
	OPENF%			;Open the link
	 ERJMPR SDERR		;Oh well
	MOVEI T1,.FHSLF		;Set up for AIC: For me
	MOVX T2,OPNBEL		;The channel mask
	CIS%			;Clear any pending interrupts
	AIC%			;Activate the sucker
	 ERJMPR SDERR		;Not my day
	MOVE T1,SVJFN(P6)	;Get the JFN back
	MOVX T2,.MOACN		;Enable network interrupts
	MOVX T3,OPNCHN 		;Get the interrupt channel for data available
	MTOPR%			;Set it
	 ERJMPR SDERR		;Hmm...

	MOVX T2,.MORLS		;Before we wait, check to make sure that we...
	MTOPR%			;...weren't rejected while still in the MTOPR
	 ERJMPR SDERR		;Hmm...
	TXNN T3,MO%ABT!MO%SYN	;One of these bits set?
CNWAIT:	WAIT%			;No, wait for the interrupt.

;Here if (and only if) we were rejected quickly.  Otherwise, we will be
;resumed at location GOTIT by SDOPII.
	HRRZ P1,T3		;Save the reject code
	MOVE T1,SVJFN(P6)	;Get the jfn
	MOVX T2,.MOACN		;Appropriate Function code
	MOVX T3,OFFCHN		;Turn off DECnet interrupts
	MTOPR%			; with MTOPR
	 ERJMPR SDERR		;Oh well...

	MOVEI T1,.FHSLF		;My process doesn't...
	MOVX T2,OPNBEL		;...want any more interrupts on this...
	DIC%			;...channel
	 ERJMPR SDERR		;Hmm...

	MOVE T1,P1		;Get the reject code back
	JRST SDERR		;And go tell our parent.
	
SDOPII:	MOVEI T1,GOTIT		;Here if we received an interrupt
	MOVEM T1,INPC2(P6)	;Change the PC
	DEBRK%			;Dismiss the interrupt

;We get resumed here after the connect interrupt.  Turn off DECnet interrupts.
GOTIT:	MOVE T1,SVJFN(P6)	;Get the jfn
	MOVX T2,.MOACN		;Appropriate Function code
	MOVX T3,OFFCHN		;Turn off DECnet interrupts
	MTOPR%			; with MTOPR
	 ERJMPR SDERR		;Oh well...

	MOVEI T1,.FHSLF		;My process doesn't...
	MOVX T2,OPNBEL		;...want any more interrupts on this...
	DIC%			;...channel at all.
	 ERJMPR SDERR		;Hmm...
	JRST SDDONE		;All done
;Routine SDREAD/SDWRTS/SDWRTM
;	P6/ The address of the common data page
;	JRST SDREAD/SDWRTS/SDWRTM
;	Returns to location SDERR or SDDONE as appropriate

SDREAD:	TDZA Q2,Q2		;0 into the flag, skip
SDWRTS:	MOVEI Q2,1		;1 into the flag
	SKIPA			;Skip
SDWRTM: MOVEI Q2,2		;2 into the flag
	$TRFUN			;Trace the appropriate function
	MOVE T1,SVJFN(P6)	;Get the JFN
	MOVE T2,SFAC3(P6)	;Get the buffer pointer
	MOVN T3,SFAC4(P6)	;Get the size of the user's buffer
	SETZM T4		;Clear T4
	XCT SDIOT(Q2)		;Do the appropriate JSYS
	 ERJMPR SDERR		;Couldn't get it
	ADDM T3,SFAC4(P6)	;Calculate # of bytes read
	MOVEM T2,SFAC3(P6)	;Return the updated byte pointer
	JRST SDDONE		;All done

SDIOT:	SINR%			;SDREAD
	SOUT%			;SDWRTS
	SOUTR%			;SDWRTM

FNDBG:  [ASCIZ /Read Link called
/]
	[ASCIZ /Write String called
/]
	[ASCIZ /Write Message called
/]
	END