mirror of
https://github.com/PDP-10/stacken.git
synced 2026-02-03 07:10:22 +00:00
4317 lines
135 KiB
Plaintext
4317 lines
135 KiB
Plaintext
;TITLE D36COM - Common Routines for DECnet-36
|
||
|
||
|
||
;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 1976,1985,1986,1988.
|
||
;ALL RIGHTS RESERVED.
|
||
|
||
|
||
SUBTTL V. Brownell, W. Nichols & Tarl Neustaedter
|
||
;This is the common routine package for DECnet-36.
|
||
|
||
SEARCH D36PAR,MACSYM
|
||
IFN FTOPS20,<
|
||
SEARCH SCAPAR
|
||
> ;END IFN FTOPS20
|
||
SALL
|
||
|
||
IFN FTOPS10,<
|
||
.CPYRT<1976,1988>
|
||
> ;END IFN FTOPS10
|
||
|
||
IFN FTOPS20,<
|
||
SEARCH PROLOG
|
||
TTITLE D36COM,,< - Common Routines for DECnet-36>
|
||
>
|
||
|
||
IFN FTOPS10,<
|
||
SEARCH F,S
|
||
TITLE D36COM - Common Routines for DECnet-36
|
||
>
|
||
|
||
ENTRY D36INI ;DEFINE AN ENTRY POINT WHICH MUST BE CALLED,
|
||
; SO THAT WE ARE GUARANTEED THIS WILL LOAD
|
||
|
||
D36SYM ;SET UP D36 SPECIFIC PARAMETERS
|
||
|
||
|
||
IFNDEF FTD36MM,FTD36MM==1 ;Use DECnet-36 memory manager
|
||
FTBYTBLT==FTOPS20 ;NON-ZERO TO USE MONITOR-MONITOR BYTE BLT
|
||
DBGS2==FTOPS20 ;NON-ZERO TO DO SAVEAC's OF Q1/Q2 FOR ROUTINES
|
||
; USED BY LLMOP
|
||
FTFIXCOR==0 ;NON-ZERO TO FORCE PHYSICALLY CONTIGUOUS
|
||
; BUFFERS. REQUIRED BY NISRV ONCE UPON A TIME.
|
||
|
||
IFN FTOPS10,<$RELOC>
|
||
XRESCD ;RELOC TO HIGHSEG (RSCOD PSECT ON TOPS-20)
|
||
SUBTTL Table of Contents
|
||
|
||
|
||
; Table of Contents for D36COM
|
||
;
|
||
;
|
||
; Section Page
|
||
; 1. Table of Contents. . . . . . . . . . . . . . . . . . . 2
|
||
; 2. Definitions
|
||
; 2.1. External References . . . . . . . . . . . . . 3
|
||
; 2.2. Core manager data structures. . . . . . . . . 4
|
||
; 2.3. Mongenable parameters . . . . . . . . . . . . 5
|
||
; 3. Data Storage . . . . . . . . . . . . . . . . . . . . . 6
|
||
; 4. Definitions
|
||
; 4.1. Memory Manager Tables . . . . . . . . . . . . 7
|
||
; 5. MSDs
|
||
; 5.1. Initialize MS pointer for MB input. . . . . . 9
|
||
; 5.2. Initialize MS for input . . . . . . . . . . . 10
|
||
; 5.3. Set up MSD for input on received buffer . . . 11
|
||
; 5.4. Initialize MSD for output . . . . . . . . . . 12
|
||
; 6. DNSBP
|
||
; 6.1. Byte routines
|
||
; 6.1.1. Store a byte pointer . . . . . . . . 13
|
||
; 7. DNF2WG
|
||
; 7.1. Byte routines
|
||
; 7.1.1. Fetch a two word global from an MSD. 14
|
||
; 8. MSDs
|
||
; 8.1. Byte routines
|
||
; 8.1.1. Get a byte . . . . . . . . . . . . . 15
|
||
; 8.1.2. Get two bytes. . . . . . . . . . . . 16
|
||
; 8.1.3. Get HI-ORDER 4 bytes of Ethernet Addr 17
|
||
; 8.1.4. Get six byte Ethernet Address. . . . 18
|
||
; 8.1.5. Get two bytes from specified position 19
|
||
; 8.1.6. Get an extensible field. . . . . . . 20
|
||
; 8.1.7. Get a byte, skip if non-extensible . 21
|
||
; 8.1.8. Put a byte into message. . . . . . . 22
|
||
; 8.1.9. Put two bytes in message . . . . . . 23
|
||
; 8.1.10. Put two bytes to specified position. 24
|
||
; 8.1.11. Put four bytes in message. . . . . . 25
|
||
; 8.1.12. Put HI-ORDER 4 bytes of Ethernet Addr 26
|
||
; 8.1.13. Put six byte Ethernet Address. . . . 27
|
||
; 8.1.14. Put an extensible field into message 28
|
||
; 8.1.15. Put some zero bytes. . . . . . . . . 29
|
||
; 8.1.16. Skip some bytes. . . . . . . . . . . 30
|
||
; 8.1.17. Go Backwards some number of bytes. . 31
|
||
; 8.2. Read and Goto Position. . . . . . . . . . . . 32
|
||
; 8.3. Link a Message Segment into a Message Block . 34
|
||
; 8.4. Copy message block. . . . . . . . . . . . . . 35
|
||
; 8.5. Calculate length of a whole message . . . . . 36
|
||
; 8.6. Calculate Length of Message Segment . . . . . 37
|
||
; 8.7. DNMINI - Initialize an allocated message block 38
|
||
; 8.8. DNCMSD - Copy MSD chain to contiguous block . 39
|
||
; 9. Buffers
|
||
; 9.1. Copy buffer to a message segment. . . . . . . 40
|
||
; 9.2. Copy message data to a buffer . . . . . . . . 41
|
||
; 10. BYTBLT - Non fancy versions. . . . . . . . . . . . . . 42
|
||
; 11. BYTBLT - Fancy version . . . . . . . . . . . . . . . . 43
|
||
; 12. Buffers
|
||
; 12.1. Copy user buffer to a message segment . . . . 54
|
||
; 12.2. Copy message data to a user buffer. . . . . . 55
|
||
; 13. Core manager
|
||
; 13.1. Smear a block of memory with value. . . . . . 56
|
||
; 13.2. Copy some words . . . . . . . . . . . . . . . 57
|
||
; 13.3. Get Some Words. . . . . . . . . . . . . . . . 58
|
||
; 13.4. Get Some Zeroed Words . . . . . . . . . . . . 59
|
||
; 13.5. Free Some Words . . . . . . . . . . . . . . . 60
|
||
; 13.6. Get a DECnet-36 message block . . . . . . . . 61
|
||
; 13.7. Free a DECnet-36 message block. . . . . . . . 63
|
||
; 13.8. Fixed size block allocation entry points. . . 64
|
||
; 13.9. Memory manager initialization code. . . . . . 66
|
||
; 13.10. Increment count of emergency buffers. . . . . 68
|
||
; 13.11. Return number of blocks available (for router) 69
|
||
; 13.12. Get a Block from a Free Pool. . . . . . . . . 70
|
||
; 14. DNMCUB - Check for trashed UBL . . . . . . . . . . . . 72
|
||
; 15. Core manager
|
||
; 15.1. Checking routines for debugging only. . . . . 73
|
||
; 15.2. Check pointer for validity. . . . . . . . . . 74
|
||
; 16. Time
|
||
; 16.1. Get current time in ms. . . . . . . . . . . . 76
|
||
; 17. Network management
|
||
; 17.1. NTPARM - parameters . . . . . . . . . . . . . 77
|
||
; 17.2. NTCTRS - counters . . . . . . . . . . . . . . 78
|
||
; 18. Trace
|
||
; 18.1. Interface for exec-mode trace.. . . . . . . . 79
|
||
; 18.2. SCAN's output routines. . . . . . . . . . . . 80
|
||
; 18.3. Routine store character in shared buffer. . . 81
|
||
; 19. TOPS10
|
||
; 19.1. AC save routines. . . . . . . . . . . . . . . 82
|
||
; 20. Kontroller data. . . . . . . . . . . . . . . . . . . . 83
|
||
; 21. Initialization routines. . . . . . . . . . . . . . . . 84
|
||
; 22. DCNJB0 - DECnet periodic checks. . . . . . . . . . . . 85
|
||
; 23. NMX
|
||
; 23.1. Privilege checking routine. . . . . . . . . . 86
|
||
; 23.2. Time stamp a queued even block. . . . . . . . 87
|
||
; 24. TESTSB
|
||
; 24.1. Assert that Code is Running in section 1. . . 90
|
||
; 25. TOPS20
|
||
; 25.1. User mode checking routines.. . . . . . . . . 91
|
||
; 26. End of D36COM. . . . . . . . . . . . . . . . . . . . . 92
|
||
SUBTTL Definitions -- External References
|
||
|
||
;External monitor symbols
|
||
|
||
EXT %RTBSZ ;Default executor block size (STG)
|
||
EXT %DLBSZ ;Default maximum buffer size
|
||
|
||
;External monitor routines
|
||
|
||
EXT RTN
|
||
EXT RSKP
|
||
EXT XBLTA
|
||
EXT XBLTAT
|
||
|
||
;References into layers.
|
||
|
||
EXT SCJINI ;Initialize SCJSYS
|
||
EXT SCTINI ;Initialize session control, NSP and ROUTER
|
||
EXT SCTSEC ;SCLINK once-a-second routine
|
||
EXT NSPJIF ;LLINKS once-a-jiffy routine
|
||
EXT RTRON ;To turn ROUTER on
|
||
EXT RTRJIF ;ROUTER once-a-jiffy routine
|
||
EXT RTRSEC ;ROUTER once-a-second routine
|
||
EXT DNDJIF ;DNADLL once-a-jiffy routine
|
||
EXT NSPCG ;TO TELL NSP ABOUT CONGESTION
|
||
EXT NSPCR ;..
|
||
EXT NSPJB0 ;NSP periodic checks
|
||
EXT NRTINI ;Initialize NRT
|
||
|
||
;AC definition.
|
||
|
||
XP FL,FREE1 ;NEEDED BY MEMORY MANAGER. SAVES POINTER HERE
|
||
XP LH.ALF,<777777,,0> ;LEFT HALF QUANTITY
|
||
|
||
|
||
;Explanation of Byte Pointer Usage:
|
||
;
|
||
;In order to make the byte pointers in MDPTR and MDAUX work on
|
||
;both extended and non-extended machines, we build indexed byte
|
||
;pointers, with a Y field of zero initially. The byte pointers
|
||
;are always indexed by T6, which is loaded from MDALA at the
|
||
;beginning of every DNxxx routine. VGNPTR is used to point
|
||
;readers to this comment.
|
||
|
||
VGNPTR==:<POINT 8,0(T6)>
|
||
SUBTTL Definitions -- Core manager data structures
|
||
|
||
BEGSTR FB
|
||
WORD NXT ;Forward pointer in a free block
|
||
ENDSTR
|
||
|
||
BEGSTR CH ;Core handler structure
|
||
WORD BOT ;Pointer to free pool start
|
||
WORD PTR ;pointer to first free block
|
||
WORD AVL ;Number of available blocks
|
||
HWORD LWM ;;; Low water mark
|
||
HWORD REQ ;;; Size requested
|
||
;The following 3 fields are expected to be in the last word, see CHBLKS
|
||
FIELD CON,1 ;Set if this block type subject to congestion
|
||
FIELD NUM,17 ;Total blocks, alloc & unalloc.
|
||
HWORD SIZ ;Size of blocks.
|
||
ENDSTR
|
||
|
||
;On TOPS10, structure MI is referenced by COMMON.MAC with HRRZ and other
|
||
;non-BEGSTR instructions so don't change MI rashly!
|
||
|
||
BEGSTR MI
|
||
HWORD SIZ ;SIZE (IN WORDS) OF THE BLOCK
|
||
HWORD CNT ;NUMBER OF BLOCKS
|
||
ENDSTR
|
||
|
||
SUBTTL Definitions -- Mongenable parameters
|
||
|
||
|
||
;These are some default router parameters:
|
||
|
||
RADIX 10 ;NETWORK MANGLEMENT IS DECIMAL
|
||
|
||
DEFINE MP(SYMBOL,VALUE),< ;SYMBOLS DEFINED WITH MP ARE MONGENABLE
|
||
IFN FTOPS10,<EXTERN SYMBOL> ;;DEFINED IN COMNET ON TOPS-10
|
||
IFN FTOPS20,<XP SYMBOL,VALUE> ;;AND THUS NOT DEFINED HERE ON TOPS10
|
||
>
|
||
|
||
IFN FTP4R,MP %RTMXN,1023 ;MAXIMUM NODE NUMBER
|
||
MP %RTMX3,255 ;DEFAULT MAXIMUM NODE ADDRESS FOR ROUTER
|
||
MP %RTTM3,<15*1000> ;DEFAULT HELLO FREQUENCY TIMER
|
||
MP %RTTM4,<30*1000> ;DEFAULT NODE LISTENER TIMER
|
||
MP %RTITM,<1*60*1000> ;INITIALIZATION TIMER
|
||
MP %RTT3M,2 ;HELLO TIMER MULTIPLIER FOR NON-BROADCAST
|
||
MP %RTB3M,3 ;HELLO TIMER MULTIPLIER - BROADCAST ADJACENCIES
|
||
MP %RTADR,1 ;DEFAULT LOCAL ADDRESS
|
||
MP %RTHOM,1 ;DEFAULT HOME AREA
|
||
MP %RTRTY,RNT.L1 ;DEFAULT ROUTER TYPE (ROUTING)
|
||
MP %RTCST,1 ;DEFAULT COST FOR CIRCUIT
|
||
MP %RTMXR,16 ;Default maximum number of routers on an NI
|
||
MP %RTBRA,32 ;MAXIMUM NUMBER OF BROADCAST ROUTER ADJACENCIES
|
||
MP %RTBEA,64 ;MAXIMUM NUMBER OF END NODE ADJACENCIES
|
||
MP %RTCTO,<60*1000> ;Endnode cache timeout
|
||
MP %RTPRI,5 ;OUR PRIORITY TO BE THE DESIGNATED ROUTER
|
||
MP %RTMXC,100 ;MAXIMUM LINE COST
|
||
MP %RTMXH,16 ;MAXIMUM HOPS
|
||
MP %RTMXV,20 ;DEFAULT MAXIMUM VISITS
|
||
MP %RTTM1,<10*60*1000> ;DEFAULT MAXIMUM ROUTING MESSAGE INTERVAL (P-P)
|
||
MP %RTBT1,<40*1000> ;DEFAULT MAXIMUM ROUTING MESSAGE INTERVAL (NI)
|
||
XP %RTEHS,<2+7-6+21+4> ;Ethernet header size, composed of:
|
||
;+2 Ethernet padding bytes
|
||
;+7 Router Phase-IV pad bytes
|
||
;-6 corrects for assumed Phase III header
|
||
;+21 allows for full P-IV NI header
|
||
;+4 allows for 4 KLNIA CRC bytes (input)
|
||
; & for byte misalignment after BLT (output)
|
||
XP %RTVER,2 ;VERSION OF ROUTER
|
||
XP %RTECO,0 ;EDIT LEVEL OF ROUTER
|
||
XP %RTCUS,0 ;CUSTOMER VERSION NUMBER
|
||
|
||
;These are LLINKS default parameter values:
|
||
|
||
MP %NSDLY,<3*16> ;Delay factor
|
||
MP %NSWGT,10 ;Delay weight
|
||
MP %NSINA,120 ;Inactivity timer
|
||
MP %NSRTH,10 ;Retransmission threshold
|
||
MP %NSFLR,1000 ;Delay floor
|
||
MP %NSRUF,10000 ;Delay roof
|
||
MP %NSADL,2 ;ACK delay in seconds
|
||
|
||
;These are Session Control default parameter values:
|
||
|
||
XP %SCHDR,<11+6> ;LENGTH OF HEADERS BELOW SESSION CONTROL
|
||
;11 IS MAX NSP HEADER LENGTH (PHASE IV)
|
||
;6 IS ARCHITECTURALLY DEFINED RTR HDR OVERHEAD
|
||
XP %SCP2Q,1 ;PHASE II QUOTA
|
||
MP %SCINT,<30*1000> ;INCOMING TIMER VALUE
|
||
MP %SCOTT,<1*60*1000> ;OUTGOING TIMER VALUE
|
||
|
||
RADIX 8 ;LCG IS OCTAL
|
||
|
||
;Keep these definitions here! They need to be defined in OCTAL radix.
|
||
|
||
XP %RTHIO,<<BYTE (8)252,0,4,0(4)0>> ;HIORD AA-00-04-00(16)
|
||
XP %RTRMA,<<BYTE (8)253,0,0,3(4)0>> ;Multicast ID "ALL ROUTERS"
|
||
; AB-00-00-03
|
||
XP %RTEMA,<<BYTE (8)253,0,0,4(4)0>> ;Multicast ID "ALL ENDNODES"
|
||
; AB-00-00-04
|
||
SUBTTL Data Storage
|
||
|
||
RESDT
|
||
|
||
;Define static incarnation of DECnet-36 initialization block
|
||
|
||
ASSUME IB.PH2,EQ,0
|
||
ASSUME IB.RTR,EQ,0
|
||
ASSUME IB.FCM,EQ,0
|
||
ASSUME IB.NAM,EQ,1
|
||
ASSUME IB.ADR,EQ,2
|
||
ASSUME IB.MXA,EQ,3
|
||
ASSUME IB.MXB,EQ,4
|
||
ASSUME IB.DGL,EQ,5
|
||
ASSUME IB.DBL,EQ,6
|
||
ASSUME IB.BIP,EQ,7
|
||
ASSUME IB.BSZ,EQ,10
|
||
|
||
IBBLK:: 0B<POS(IBPH2)>!<%RTRTY>B<POS(IBRTR)>!<FCM.SG>B<POS(IBFCM)> ;IBFLG
|
||
IFN FTOPS20,<
|
||
SIXBIT /TOPS20/ ;IBNAM
|
||
<%RTHOM>B<POS(RN%ARE)>!<%RTADR>B<POS(RN%NOD)> ;IBADR
|
||
>; END IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
0 ;IBNAM
|
||
0 ;IBADR
|
||
>; END IFN FTOPS10
|
||
EXP %RTMXN ;IBMXA
|
||
EXP ^D80 ;IBMXB
|
||
EXP ^D0 ;IBDGL
|
||
EXP ^D8 ;IBDBL
|
||
EXP ^D50 ;IBBIP
|
||
EXP %DLBSZ ;IBBSZ
|
||
|
||
;
|
||
D36IFG::EXP 0 ;0 before DECnet initializes,
|
||
;+1 while -"- -"-
|
||
;-1 after -"- -"-
|
||
|
||
DCNSTA::EXP DS.OFF ;INITIALLY OFF, STATES ARE IN D36PAR
|
||
|
||
DNDEFS::EXP <FLD(0,PDGOL)>!<FLD(^D16,PDDQT)>!<FLD(^D50,PDIPR)>
|
||
;Flow control - Goal, Quota, Input percentage
|
||
|
||
RTRADR::EXP 0+<IFN FTOPS20,<%RTADR>> ;Our local address, setable with SETSPD
|
||
RTRHOM::EXP 0+<IFN FTOPS20,<%RTHOM>> ;Default area to which this ROUTER belongs
|
||
RTRHIO::%RTHIO ;Hi-order DECnet Ethernet address
|
||
RTRLOO::EXP 0 ;Low order part of Ethernet address (computed
|
||
; at startup by Router)
|
||
RTRBSZ::%RTBSZ ;Default block size
|
||
RTRMXN::%RTMXN ;MAXIMUM NODE NUMBER
|
||
RTRMX3::%RTMX3 ;MAXIMUM PHASE III NODE ADDRESS
|
||
EVSDRP::EXP 0 ;NON-ZERO TO HAVE ROUTER SNOOP ROUTING INFO
|
||
RTRVER::%RTVER ;VERSION OF OUR ROUTER
|
||
RTRECO::%RTECO ;EDIT LEVEL OF ROUTER
|
||
RTRCUS::%RTCUS ;CUSTOMER ARGUMENT
|
||
|
||
;Freecore pointers
|
||
|
||
IFN FTOPS10,<
|
||
.LINK .LKAHB,DCNAHB ;ADD TO SYSTEM-WIDE LINKED LIST
|
||
DCNAHB::BLOCK AHBLEN ;MEMORY ALLOCATION HEADER BLOCK
|
||
DCNAEB::BLOCK AEBLEN ;MEMORY ALLOCATION EXTENT BLOCK
|
||
DCNTCR: BLOCK 1 ;TOTAL DECNET CORE REQUIREMENTS
|
||
DCNCOR::BLOCK 1 ;POINTER TO DECNET CORE
|
||
DCNVFF::BLOCK 1 ;DECNET FIRST FREE LOCATION
|
||
>; END IFN FTOPS10
|
||
|
||
DCNEMR: BLOCK 1 ;EMERGENCY MESSAGE BLOCK THRESHOLD
|
||
DCNTSB::BLOCK 1 ;TOTAL SYSTEM BUFFERS (SET UP IN D36INI)
|
||
DCNCON::BLOCK 1 ;NON-ZERO IF SYSTEM IS CONGESTED
|
||
DCNRSB::BLOCK 1 ;RESERVED BUFFERS, MODIFIED UNDER SYSPIF
|
||
; TO PROTECT AGAINST SCTRIB CALL FROM LLINKS
|
||
DCNRHT::BLOCK 1 ;HIGH TIDE FOR DCNRSB
|
||
|
||
DCNRIF::BLOCK 1 ;INPUT RESERVATION FAILURES
|
||
DCNROF::BLOCK 1 ;OUTPUT RESERVATION FAILURES
|
||
DCNCNG: DEC 5 ;CONGESTION MESSAGE BLOCK THRESHOLD
|
||
DCNUCG: DEC 7 ;UNCONGESTION MESSAGE BLOCK THRESHOLD
|
||
|
||
IFN FTOPS10,<
|
||
EV96.0::0 ;DON'T LOG EVENT 96.0
|
||
DCNTIM: ^D10 ;DCNJB0 COUNTDOWN TIMER (SECONDS)
|
||
>; END IFN FTOPS10
|
||
|
||
IFN FTTRACE!FTMINTrace,<
|
||
|
||
;;NOTE - ALL THESE VALUES MUST BE SET BY SNOOP. THERE IS NO CHECKING
|
||
;WHATSOEVER THAT THE MONITOR DOES ON THEM - IT MERELY USES THEM.
|
||
|
||
ZERBPT::BLOCK 1 ;FIRST BYTE POINTER IN USER'S BUFFER
|
||
CURBPT::BLOCK 1 ;CURRENT BYTE POINTER
|
||
MAXBYT::BLOCK 1 ;MAXIMUM NUMBER OF BYTES TO USE IN BUFFER
|
||
LASBYT::BLOCK 1 ;LAST BYTE TO USE IN BUFFER (.GT. MAXBYT)
|
||
CURBYT::BLOCK 1 ;CURRENT BYTE POSITION IN BUFFER
|
||
TRAJOB::BLOCK 1 ;NUMBER OF JOB DOING THE TRACE
|
||
S.ETRA::BLOCK 1 ;ERROR TRACE BITS
|
||
S.TRAC::BLOCK 1 ;THE ORDINARY TRACE MASK
|
||
|
||
> ;END IFN FTTRACE!FTMINTrace
|
||
|
||
XRESCD
|
||
SUBTTL Definitions -- Memory Manager Tables
|
||
|
||
;Memory Management Definitions
|
||
|
||
;$NAM - Three-character name of block type
|
||
;$SIZ - Size of block in words, DNGRBL overhead added in DEFBLK macro
|
||
;$CNT - Number of blocks
|
||
;$CON - Flag saying this block type is subject to congestion control
|
||
|
||
DEFINE BLKDFS,<
|
||
;; $NAM, $SIZ, $CNT, $CON
|
||
IFN FTD36MM,<
|
||
DEFBLK (SBL, ^D7, ^D145, ) ;;SMALL BLOCKS
|
||
DEFBLK (ABL, ^D31, ^D250, ) ;;ARBITRARY BLOCKS
|
||
DEFBLK (BBL, ^D78, ^D140, ) ;;SLIGHTLY LARGER ARB. BLOCKS
|
||
;Increase LBL's by 15. for multinode CI testing /mp
|
||
DEFBLK (LBL, ^D510, ^D35, ) ;;LARGE BLOCKS
|
||
;; (These must fit on 1 page)
|
||
IFE FTHMMEM,<
|
||
DEFBLK (VBL, ^D2058, ^D3, ) ;;VERY LARGE BLOCKS
|
||
>
|
||
IFN FTHMMEM,< ;;One extra for MRQTAB
|
||
DEFBLK (VBL, ^D2058, ^D4, ) ;;VERY LARGE BLOCKS
|
||
>
|
||
>;END IFN FTD36MM
|
||
; DEFBLK (EBL, ^D60, ^D4, ) ;;EVENT BLOCKS
|
||
DEFBLK (MBL, MB.LEN, ^D100, CONGEST ) ;;MESSAGE BLOCKS
|
||
DEFBLK (UBL, 0, ^D80, CONGEST ) ;;USER-DATA BLOCKS
|
||
>;END DEFINE BLKDFS
|
||
|
||
IFE FTD36MM,<VBLSIZ==^D2058> ;NEEDED IN DNSWDS
|
||
|
||
;The following page(s) expand this macro to define the tables and symbols
|
||
;used by the memory manager (DNINIM, DNGRBL and DNFRBL)
|
||
IFE FTLSTCOR,<OVHWDS==1>
|
||
IFN FTLSTCOR,<OVHWDS==4>
|
||
|
||
;Now define symbols for $SIZ and $CNT
|
||
|
||
DEFINE DEFBLK($nam,$siz,$cnt),<
|
||
$nam'SIZ==:$siz+OVHWDS ;;SIZE OF BLOCKS IN DECIMAL WORDS + OVERHEAD
|
||
$nam'CNT==:$cnt ;;NUMBER OF BLOCKS
|
||
..CORS==..CORS+<$nam'SIZ*$cnt>
|
||
>;END DEFINE DEFBLK
|
||
|
||
..CORS==0 ;INITIALIZE TOTAL MEMORY COUNTER
|
||
BLKDFS ;DEFINE SYMBOLS
|
||
|
||
IFN CH.LEN-CH.SIZ-1,<PRINTX ? CHBLKS defined wrong>
|
||
IFN CH.NUM-CH.SIZ, <PRINTX ? CHBLKS defined wrong>
|
||
IFN CH.CON-CH.SIZ, <PRINTX ? CHBLKS defined wrong>
|
||
|
||
DEFINE DEFBLK($nam,$siz,$cnt,$con),<
|
||
..CON==0 ;;ASSUME NO CONGESTION CONTROL ON THIS BLK TYPE
|
||
IFNB <$con>,<..CON==1> ;;IF CONTROLLED, SET 1-BIT FLAG
|
||
$nam'CB: BLOCK CH.LEN-2
|
||
EXP <FLD(<$cnt>,CHLWM)>
|
||
EXP <FLD(<..con>,CHCON)>!<FLD(<$nam'SIZ>,CHSIZ)>!<FLD(<$cnt>,CHNUM)>
|
||
PURGE ..CON
|
||
>;END DEFINE DEFBLK
|
||
|
||
RESDT
|
||
|
||
CHBLKQ: CHBLKN ;FOR GETTAB PURPOSES. DO NOT MOVE
|
||
CHBLKS::!BLKDFS ;VECTOR OF CH BLOCKS
|
||
CHBLKN==<.-CHBLKS>/CH.LEN ;NUMBER OF CH BLOCKS WE HAVE
|
||
|
||
IFN FTHMMEM,<
|
||
MRQTAB::BLOCK 1 ;Pointer to memory request table
|
||
MRQMAX: BLOCK 1 ;Maximum table address
|
||
> ;END FTHMMEM
|
||
|
||
XRESCD
|
||
SUBTTL MSDs -- Initialize MS pointer for MB input
|
||
|
||
;DNGINI - Initialize MS for input (DNGxxx routines)
|
||
;
|
||
; Call:
|
||
; T1/ Pointer to Input Message Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1,T2,MS
|
||
;
|
||
;Note: We are assuming that someone has set up the dynamic byte
|
||
;pointer and the count when the message came in (usually the DLL will
|
||
;have done this). The DNGxxx routines use the dynamic byte pointer and
|
||
;count to go through the message.
|
||
;
|
||
;Callers assume that is it OK to call this routine more than
|
||
;once on a given message.
|
||
;
|
||
;This routine works for MB's only.
|
||
|
||
INTERNAL DNGINI
|
||
XRESCD
|
||
DNGINI:
|
||
XMOVEI MS,IN.MSD(T1) ;POINT TO THE INPUT MSD
|
||
RET ; AND RETURN
|
||
SUBTTL MSDs -- Initialize MS for input
|
||
|
||
;DNGMSI - Initialize an MSD for a raw (empty) buffer
|
||
;
|
||
; Call:
|
||
; T1/ MSD address
|
||
; T2/ Buffer Address
|
||
; T3/ Buffer Length in bytes
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1,MS
|
||
;
|
||
|
||
XRESCD
|
||
DNGMSI::
|
||
MOVE MS,T1 ;MAKE MS POINT TO MSD
|
||
SETZRO MDNXT,(MS) ;INPUT MSD's CAN'T BE CHAINED
|
||
MOVX T1,VGNPTR ;BUILD A VIRGIN BYTE POINTER
|
||
STOR T1,MDAUX,(MS) ;STORE THE BYTE POINTER FOR LATER PEOPLE
|
||
STOR T1,MDPTR,(MS) ; AND STORE THE DYNAMIC BYTE POINTER
|
||
STOR T2,MDALA,(MS) ;STORE BUFFER ADDRESS
|
||
SETZRO MDBYT,(MS) ;NOTHING RECEIVED YET
|
||
STOR T3,MDALL,(MS) ;SET BUFFER LENGTH
|
||
RET ; AND RETURN
|
||
SUBTTL MSDs -- Set up MSD for input on received buffer
|
||
|
||
;DNGMSS - Set up an initialized MSD to point to received data
|
||
;
|
||
; Call:
|
||
; T1/ MSD address
|
||
; T2-T3/ 2 word global pointer to data in receive buffer
|
||
; T4/ Receive data length in bytes
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1,MS
|
||
;
|
||
|
||
XRESCD
|
||
DNGMSS::
|
||
MOVE MS,T1 ;MAKE MS POINT TO MSD
|
||
STOR T4,MDBYT,(MS) ;SET RECEIVED BYTE COUNT
|
||
LOAD T1,MDALA,(MS) ;GET RAW BUFFER ADDRESS
|
||
SUB T3,T1 ;GET WORD OFFSET TO RECEIVE DATA IN BUFFER
|
||
ADDI T2,(T3) ;ADD OFFSET IN E-field OF POINTER
|
||
TXZ T2,1B12 ;CLEAR 2 word global bit
|
||
TLO T2,T6 ;SET STANDARD INDEX FOR VGNPTR
|
||
STOR T2,MDPTR,(MS) ;STORE POINTER
|
||
RET ; AND RETURN
|
||
SUBTTL MSDs -- Initialize MSD for output
|
||
|
||
;DNPINI - Initialize MSD ptr and count for output (DNPxxx routines)
|
||
;
|
||
; Call:
|
||
; T1/ Pointer to MSD to initialize
|
||
;It is assumed that the byte pointer wanted starts at the allocated
|
||
;address of the MSD (MDALA).
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS, LEAVING T1 ALONE
|
||
;
|
||
; Uses: T1,T2,MS
|
||
;
|
||
;The DNPxxx routines will use the byte pointers and byte count in the
|
||
;MSD. There are two byte pointers, one which is updated all the time
|
||
;and one which is left alone for future people to use.
|
||
|
||
XRESCD
|
||
DNPINI::
|
||
MOVE MS,T1 ;MAKE MS POINT TO MSD
|
||
MOVX T2,VGNPTR ;BUILD A VIRGIN BYTE POINTER
|
||
STOR T2,MDAUX,(MS) ;STORE THE BYTE POINTER FOR LATER PEOPLE
|
||
STOR T2,MDPTR,(MS) ; AND STORE THE DYNAMIC BYTE POINTER
|
||
SETZRO MDBYT,(MS) ;JUST IN CASE
|
||
RET ;ONLY RETURN
|
||
|
||
|
||
;DNPINR is a variant of DNPINI for re-initializing an MSD which is to
|
||
;have data added to it.
|
||
|
||
XRESCD
|
||
DNPINR::
|
||
MOVE MS,T1 ;MAKE MS POINT TO MSD
|
||
RET ;THAT'S ALL FOR A RE-INITIALIZATION
|
||
|
||
SUBTTL DNSBP -- Byte routines -- Store a byte pointer
|
||
|
||
;DNSBP - Store a byte pointer into an MSD
|
||
;
|
||
; Call:
|
||
; T1 & T2/ Byte pointer of any type, except OWGBP, indexed or indirect
|
||
; T3/ Pointer to MSD to modify
|
||
;
|
||
;DNSBP makes the indicated MSD point to the same byte as the passed byte
|
||
;pointer.
|
||
|
||
INTERNAL DNSBP
|
||
XRESCD
|
||
DNSBP: LDB T4,[POINT 6,T1,5] ; Fetch P field of byte pointer
|
||
CAILE T4,44 ; One word global?
|
||
BUG.(HLT,COMBBP,D36COM,SOFT,<DNSBP called with OWGBP>,,<
|
||
|
||
Cause: DNSBP was called with a one-word global byte pointer. DNSPB is
|
||
only set up to handle local one-word and two-word byte pointers,
|
||
without indexing or indirection.
|
||
|
||
Action: Either change the caller to pass a two-word byte pointer or upgrade
|
||
DNSBP to handle OWGBPs.
|
||
>)
|
||
TXZN T1,1B12 ; Two word byte pointer?
|
||
HRRZ T2,T1 ; No, one word pointer. Fetch Y field.
|
||
OPSTR <SUB T2,>,MDALA,(T3) ; Compute Y field for MDPTR
|
||
HRR T1,T2 ; Install it
|
||
TXZ T1,37B17 ; Clear indexing and indirection
|
||
TXO T1,<(T6)> ; Use index AC T6
|
||
STOR T1,MDPTR,(T3) ; Save the byte pointer
|
||
RET
|
||
|
||
SUBTTL DNF2WG -- Byte routines -- Fetch a two word global from an MSD
|
||
|
||
;DNF2WG - Fetch a two word global byte pointer from an MSD
|
||
;
|
||
; Call:
|
||
; T1/ Pointer to MSD
|
||
; Return: T1 & T2/ Two word global byte pointer
|
||
;
|
||
|
||
INTERNAL DNF2WG
|
||
XRESCD
|
||
DNF2WG: LOAD T2,MDALA,(T1) ; Fetch Y field for byte pointer
|
||
LOAD T1,MDPTR,(T1) ; Fetch P & S fields
|
||
TXC T1,<1B12+<(T6)>> ; Clear AC and @, set two word global
|
||
RET
|
||
|
||
SUBTTL MSDs -- Byte routines -- Get a byte
|
||
|
||
;DNG1BY - Get one byte from message
|
||
;
|
||
; Call:
|
||
; MS/ Pointer to current MSD in use
|
||
;
|
||
; Return:
|
||
; RET ;RAN OUT OF BYTES
|
||
; RETSKP ;SUCCESS: T1 CONTAINING BYTE
|
||
;
|
||
; Uses: T1,MS
|
||
|
||
INTERNAL DNG1BY
|
||
XRESCD
|
||
DNG1BY: LOAD T6,MDALA,(MS) ;;SET UP INDEX FOR MDPTR
|
||
OPSTRM <SOS T1,>,MDBYT,(MS) ;;UPDATE THE COUNT
|
||
JUMPL T1,RTN ;;RETURN IF WE RAN OUT
|
||
OPSTRM <ILDB T1,>,MDPTR,(MS) ;;GET THE NEXT BYTE
|
||
RETSKP ;TO SENDER
|
||
SUBTTL MSDs -- Byte routines -- Get two bytes
|
||
|
||
;DNG2BY - Get two bytes from message
|
||
;
|
||
; Call:
|
||
; MS/ Pointer to current input MSD
|
||
;
|
||
; Return:
|
||
; RET ;WHEN WE'RE OUT OF BYTES
|
||
; RETSKP ;SUCCESS: WITH T1 CONTAINING THE 16 BIT BYTE
|
||
;
|
||
; Uses: T1,T2,MS
|
||
|
||
INTERNAL DNG2BY
|
||
XRESCD
|
||
DNG2BY: LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
MOVX T1,-2 ;WE NEED TWO BYTES
|
||
OPSTRM <ADDB T1,>,MDBYT,(MS) ;UPDATE STRING COUNT
|
||
JUMPL T1,RTN ;IF THERE ISN'T ENOUGH ROOM, LEAVE
|
||
OPSTRM <ILDB T1,>,MDPTR,(MS) ;GET THE LOW BYTE
|
||
OPSTRM <ILDB T2,>,MDPTR,(MS) ;GET THE NEXT BYTE
|
||
LSH T2,^D8 ;PLACE IT IN THE HIGH POSITION
|
||
IOR T1,T2 ;MAKE UP 16-BIT VALUE
|
||
RETSKP ; AND RETURN TO SENDER
|
||
|
||
SUBTTL MSDs -- Byte routines -- Get HI-ORDER 4 bytes of Ethernet Addr
|
||
|
||
;DNGHIO - Get high order four bytes of Ethernet address from message
|
||
;
|
||
; Call:
|
||
; MS/ Pointer to current input MSD
|
||
;
|
||
; Return:
|
||
; RET ;WHEN WE'RE OUT OF BYTES
|
||
; RETSKP ;SUCCESS: WITH
|
||
; T1/ Ethernet Address, bytes 0,1,2,3 left justified
|
||
;
|
||
; Uses: T1,T2,T3,MS
|
||
|
||
INTERNAL DNGHIO
|
||
XRESCD
|
||
DNGHIO: STKVAR <STG>
|
||
SETZM STG
|
||
MOVX T2,<POINT 8,STG> ;POINT TO 4 BYTE STRING
|
||
LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
HRLZI T3,<-4> ;SET UP LOOP COUNT
|
||
DNGHI1: OPSTRM <SOS T1,>,MDBYT,(MS) ;;UPDATE THE COUNT
|
||
JUMPL T1,RTN ;;RETURN IF WE RAN OUT
|
||
OPSTRM <ILDB T1,>,MDPTR,(MS) ;GET CURRENT BYTE
|
||
IDPB T1,T2 ;OUTPUT CURRENT BYTE
|
||
AOBJN T3,DNGHI1 ;DO ALL 4 BYTES
|
||
MOVE T1,STG ;MAKE 4 BYTE STRING ON STACK
|
||
RETSKP ;AND GIVE HIM A GOOD RETURN
|
||
ENDSV.
|
||
|
||
SUBTTL MSDs -- Byte routines -- Get six byte Ethernet Address
|
||
|
||
;DNGENA - Get six byte Ethernet address from message
|
||
;
|
||
; Call:
|
||
; MS/ Pointer to current input MSD
|
||
;
|
||
; Return:
|
||
; RET ;WHEN WE'RE OUT OF BYTES
|
||
; RETSKP ;SUCCESS: WITH
|
||
; T1/ Ethernet Address, bytes 0,1,2,3 left justified
|
||
; T2/ Ethernet Address, bytes 4,5 left justified
|
||
;
|
||
; Uses: T1,T2,T3,MS
|
||
|
||
INTERNAL DNGENA
|
||
XRESCD
|
||
DNGENA: STKVAR <STG1,STG2>
|
||
SETZM STG1 ;MAKE FOR CLEAN RESULT
|
||
SETZM STG2
|
||
MOVX T2,<POINT 8,STG2> ;POINT TO 6 BYTE STRING
|
||
LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
HRLZI T3,<-6> ;SET UP LOOP COUNT
|
||
DNGEN1: OPSTRM <SOS T1,>,MDBYT,(MS) ;;UPDATE THE COUNT
|
||
JUMPL T1,RTN ;;RETURN IF WE RAN OUT
|
||
OPSTRM <ILDB T1,>,MDPTR,(MS) ;GET CURRENT BYTE
|
||
IDPB T1,T2 ;OUTPUT CURRENT BYTE
|
||
AOBJN T3,DNGEN1 ;DO ALL 6 BYTES
|
||
DMOVE T1,STG2 ;MAKE 6 BYTE STRING ON STACK
|
||
RETSKP ;AND GIVE HIM A GOOD RETURN
|
||
ENDSV.
|
||
|
||
SUBTTL MSDs -- Byte routines -- Get two bytes from specified position
|
||
;DNG2BS - Get two bytes from message at a specified position
|
||
;
|
||
; Call: T1/ Beginning byte position
|
||
; MS/ Pointer to current input MSD
|
||
;
|
||
; Return:
|
||
; RET ;WHEN WE'RE OUT OF BYTES
|
||
; RETSKP ;SUCCESS: WITH T1 CONTAINING THE 16 BIT BYTE
|
||
;
|
||
; Uses: T1,T2,T3,MS
|
||
DNG2BS::LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
;Need to check if went past end of message
|
||
;This code only checks for buffer exceeded
|
||
; MOVX T1,-2 ;WE NEED TWO BYTES
|
||
; OPSTRM <ADDB T1,>,MDBYT,(MS) ;UPDATE STRING COUNT
|
||
; JUMPL T1,RTN ;IF THERE ISN'T ENOUGH ROOM, LEAVE
|
||
MOVEI T2,2(T1)
|
||
OPSTRM <SUB T2,>,MDALL,(MS)
|
||
JUMPG T2,RTN ;IF THERE ISN'T ENOUGH ROOM, LEAVE
|
||
OPSTRM <ADJBP T1,>,MDAUX,(MS) ;ADJUST TO SPECIFIED BYTE POSITION
|
||
MOVE T3,T1 ;SAVE ADJUSTED POINTER FOR USE
|
||
ILDB T1,T3 ;GET THE LOW BYTE
|
||
ILDB T2,T3 ;GET THE NEXT BYTE
|
||
LSH T2,^D8 ;PLACE IT IN THE HIGH POSITION
|
||
IOR T1,T2 ;MAKE UP 16-BIT VALUE
|
||
RETSKP ; AND RETURN TO SENDER
|
||
SUBTTL MSDs -- Byte routines -- Get an extensible field
|
||
|
||
;DNGEBY - Get an extensible field from message
|
||
;
|
||
; Call:
|
||
; MS/ Pointer to current input MSD
|
||
;
|
||
; Return:
|
||
; RET ;IF WE RAN OUT OF BYTES
|
||
; RETSKP ;SUCCESS: WITH T1 CONTAINING THE BYTE
|
||
;
|
||
; Uses: T1-T4,MS
|
||
|
||
XRESCD
|
||
DNGEBY::
|
||
LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
SETZ T1, ;BUILD BYTE IN T1
|
||
MOVE T3,[POINT 7,T1,35] ;MAKE BYTE POINTER FOR BUILDING BYTE
|
||
DNGEB1: OPSTRM <SOS T4,>,MDBYT,(MS) ;DECREMENT THE COUNT
|
||
JUMPL T4,RTN ;GIVE ERROR RETURN IF WE'RE OUT
|
||
OPSTRM <ILDB T2,>,MDPTR,(MS) ;GET THE NEXT BYTE
|
||
DPB T2,T3 ;PUT IT IN WORD WE'RE BUILDING
|
||
TRNN T2,200 ;IS IT EXTENSIBLE
|
||
RETSKP ;NO, RETURN
|
||
ADD T3,[7B5] ;CONTINUE BUILDING
|
||
JRST DNGEB1 ; BY LOOPING
|
||
SUBTTL MSDs -- Byte routines -- Get a byte, skip if non-extensible
|
||
|
||
;DNGSBY - Get a byte, giving non-skip return if extensible
|
||
;
|
||
; Call:
|
||
; MS/ Pointer to current input MSD
|
||
;
|
||
; Return:
|
||
; RET ;WE GOT AN EXTENSIBLE BYTE OR RAN OUT OF BYTES
|
||
; RETSKP ;T1 CONTAINING THE BYTE
|
||
;
|
||
; Uses: T1,MS
|
||
|
||
INTERNAL DNGSBY
|
||
XRESCD
|
||
DNGSBY: LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
OPSTRM <SOS T1,>,MDBYT,(MS) ;DECREMENT THE COUNT
|
||
JUMPL T1,RTN ;IF WE'RE OUT, GIVE ERROR RETURN
|
||
OPSTRM <ILDB T1,>,MDPTR,(MS) ;YUP, GET NEXT ONE
|
||
TRNN T1,200 ;IS IT EXTENSIBLE?
|
||
AOS (P) ;GIVE GOOD RETURN
|
||
RET ;RETURN
|
||
SUBTTL MSDs -- Byte routines -- Put a byte into message
|
||
|
||
;DNP1BY - Place one byte into message
|
||
;
|
||
; Call:
|
||
; T1/ The byte
|
||
; MS/ Pointer to current output MSD
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1,MS
|
||
|
||
INTERNAL DNP1BY
|
||
XRESCD
|
||
DNP1BY: LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
OPSTRM <IDPB T1,>,MDPTR,(MS) ;PUT BYTE IN MESSAGE
|
||
INCR MDBYT,(MS) ;INCREMENT THE COUNT
|
||
RET ;RETURN TO SENDER
|
||
SUBTTL MSDs -- Byte routines -- Put two bytes in message
|
||
|
||
;DNP2BY - Place two bytes into message stream
|
||
;
|
||
; Call:
|
||
; T1/ 2 bytes (a PDP-11 word)
|
||
; MS/ Pointer to current output MSD
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1,MS
|
||
|
||
XRESCD
|
||
DNP2BY::
|
||
IFN DBGS2,<SAVEAC <T6>> ;*LLMOP*
|
||
LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
OPSTRM <IDPB T1,>,MDPTR,(MS) ;OUTPUT FIRST PART OF WORD
|
||
LSH T1,-^D8 ;SHIFT A BYTE
|
||
OPSTRM <IDPB T1,>,MDPTR,(MS) ;OUTPUT NEXT PART
|
||
MOVEI T1,2 ;WE DID TWO BYTES
|
||
OPSTRM <ADDM T1,>,MDBYT,(MS) ;INCREMENT THE COUNT
|
||
RET ;RETURN TO SENDER
|
||
|
||
SUBTTL MSDs -- Byte routines -- Put two bytes to specified position
|
||
;DNP2BS - Put two bytes in message at a specified position
|
||
;
|
||
; Call: T1/ Beginning byte position
|
||
; T2/ 2 bytes (a PDP-11 word)
|
||
; MS/ Pointer to current input MSD
|
||
;
|
||
; Return:
|
||
; RET ;WHEN WE'RE OUT OF BYTES
|
||
; RETSKP ;SUCCESS: WITH T1 CONTAINING THE 16 BIT BYTE
|
||
;
|
||
; Uses: T1,T2,T3,MS
|
||
|
||
XRESCD
|
||
DNP2BS::
|
||
LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
; MOVEI T3,2(T1)
|
||
; OPSTRM <SUB T3,>,MDALL,(MS)
|
||
; JUMPG T3,RTN ;IF THERE ISN'T ENOUGH ROOM, LEAVE
|
||
OPSTRM <ADJBP T1,>,MDAUX,(MS) ;ADJUST TO SPECIFIED BYTE POSITION
|
||
IDPB T2,T1 ;PUT THE LOW BYTE
|
||
LSH T2,-^D8 ;SHIFT TO HI BYTE
|
||
IDPB T2,T1 ;PUT THE NEXT BYTE
|
||
RET ; AND RETURN TO SENDER
|
||
|
||
SUBTTL MSDs -- Byte routines -- Put four bytes in message
|
||
|
||
;DNP4BY - Place four byte value into message stream
|
||
;
|
||
; Call:
|
||
; T1/ 4 bytes (a PDP-11 double word)
|
||
; MS/ Pointer to current output MSD
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1,MS
|
||
|
||
INTERNAL DNP4BY
|
||
XRESCD
|
||
DNP4BY: LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
HRLZI T2,<-4> ;SET UP LOOP COUNT
|
||
DNP4B1: OPSTRM <IDPB T1,>,MDPTR,(MS) ;OUTPUT FIRST BYTE OF WORD
|
||
LSH T1,-^D8 ;SHIFT TO NEXT BYTE
|
||
OPSTRM <AOS>,MDBYT,(MS) ;INCREMENT THE COUNT
|
||
AOBJN T2,DNP4B1 ;DO ALL BYTES IN WORD
|
||
RET ;RETURN TO SENDER
|
||
|
||
SUBTTL MSDs -- Byte routines -- Put HI-ORDER 4 bytes of Ethernet Addr
|
||
|
||
;DNPHIO - Put high order four bytes of Ethernet address in message
|
||
;
|
||
; Call:
|
||
; T1/ Ethernet Address, bytes 0,1,2,3 left justified
|
||
; MS/ Pointer to current output MSD
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1,T2,MS
|
||
|
||
INTERNAL DNPHIO
|
||
XRESCD
|
||
DNPHIO: STKVAR <STG>
|
||
MOVEM T1,STG ;MAKE 4 BYTE STRING ON STACK
|
||
MOVX T2,<POINT 8,STG> ;POINT TO 4 BYTE STRING
|
||
LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
HRLZI T3,<-4> ;SET UP LOOP COUNT
|
||
DNPHI1: ILDB T1,T2 ;GET CURRENT BYTE
|
||
OPSTRM <IDPB T1,>,MDPTR,(MS) ;OUTPUT CURRENT BYTE
|
||
OPSTRM <AOS>,MDBYT,(MS) ;INCREMENT THE COUNT
|
||
AOBJN T3,DNPHI1 ;DO ALL 4 BYTES
|
||
RET ;AND GIVE HIM A GOOD RETURN
|
||
ENDSV.
|
||
|
||
SUBTTL MSDs -- Byte routines -- Put six byte Ethernet Address
|
||
|
||
;DNPENA - Put six byte Ethernet address in message
|
||
;
|
||
; Call:
|
||
; T1/ Ethernet Address, bytes 0,1,2,3 left justified
|
||
; T2/ Ethernet Address, bytes 4,5 left justified
|
||
; MS/ Pointer to current output MSD
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1,T2,MS
|
||
|
||
INTERNAL DNPENA
|
||
XRESCD
|
||
DNPENA: STKVAR <STG1,STG2>
|
||
DMOVEM T1,STG2 ;MAKE 6 BYTE STRING ON STACK
|
||
MOVX T2,<POINT 8,STG2> ;POINT TO 6 BYTE STRING
|
||
LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
HRLZI T3,<-6> ;SET UP LOOP COUNT
|
||
DNPEN1: ILDB T1,T2 ;GET CURRENT BYTE
|
||
OPSTRM <IDPB T1,>,MDPTR,(MS) ;OUTPUT CURRENT BYTE
|
||
OPSTRM <AOS>,MDBYT,(MS) ;INCREMENT THE COUNT
|
||
AOBJN T3,DNPEN1 ;DO ALL 6 BYTES
|
||
RET ;AND GIVE HIM A GOOD RETURN
|
||
ENDSV.
|
||
|
||
SUBTTL MSDs -- Byte routines -- Put an extensible field into message
|
||
|
||
;DNPEBY - Put extensible byte into message stream
|
||
;
|
||
; Call:
|
||
; T1/ Byte
|
||
; MS/ Pointer to current input MSD
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1,T2,MS
|
||
|
||
INTERNAL DNPEBY
|
||
XRESCD
|
||
DNPEBY:
|
||
DO.
|
||
LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
CAIG T1,177 ;IS IT BIG ENUF FOR AN EXTENSIBLE BYTE?
|
||
CALLRET DNP1BY ;NO, OUTPUT THE REST AS ONE BYTE
|
||
LSHC T1,-7 ;PUSH BYTE OVER TO T2
|
||
ROT T2,7 ;LINE IT UP
|
||
TRO T2,200 ;LIGHT UP "EXTENSIBLE" BIT
|
||
OPSTRM <IDPB T2,>,MDPTR,(MS) ;PUT BYTE IN STREAM
|
||
INCR MDBYT,(MS) ;INCREMENT COUNT
|
||
LOOP.
|
||
ENDDO.
|
||
|
||
SUBTTL MSDs -- Byte routines -- Put some zero bytes
|
||
|
||
;DNPZB - Put (T1) bytes of zeros into a message
|
||
;
|
||
; Call:
|
||
; MS/ Pointer to current MSD
|
||
; T1/ Number of zeros to put
|
||
;
|
||
; Return:
|
||
; RET
|
||
;
|
||
; Uses: T1,MS
|
||
|
||
INTERNAL DNPZB
|
||
XRESCD
|
||
DNPZB: JUMPE T1,RTN ;Nothing to do if zero
|
||
OPSTRM <ADDM T1,>,MDBYT,(MS) ;Adjust the byte count
|
||
LOAD T6,MDALA,(MS) ;Set up index for MDPTR
|
||
SETZ T2, ;Datum is a zero
|
||
DNPZB1: OPSTRM <IDPB T2,>,MDPTR,(MS) ;Put byte in message
|
||
SOJG T1,DNPZB1 ;Put as many as requested
|
||
RET
|
||
|
||
SUBTTL MSDs -- Byte routines -- Skip some bytes
|
||
|
||
;DNSKBY - Skip (T1) bytes in input message
|
||
;
|
||
; Call:
|
||
; MS/ Pointer to current input MSD
|
||
; T1/ Number of Bytes to Skip
|
||
;
|
||
; Return:
|
||
; RET ;WHEN WE RAN OUT OF BYTES
|
||
; RETSKP ;ON SUCCESS
|
||
;
|
||
; Uses: T1,T2,MS
|
||
|
||
INTERNAL DNSKBY
|
||
XRESCD
|
||
DNSKBY: JUMPE T1,RSKP ;Success return if no bytes to skip
|
||
LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
MOVN T2,T1 ;GET THE NEGATIVE COUNT
|
||
OPSTRM <MOVNS>,MDBYT,(MS) ;NEGATE COUNT
|
||
OPSTRM <SUBB T2,>,MDBYT,(MS) ;SUBTRACT THE NUMBER OF BACKSPACES
|
||
JUMPL T2,RTN ;IF WE'RE OUT, GIVE ERROR RETURN
|
||
OPSTR <ADJBP T1,>,MDPTR,(MS) ;ADJUST THE BYTE POINTER
|
||
STOR T1,MDPTR,(MS) ;STORE THE POINTER BACK
|
||
RETSKP ;WE'RE OK
|
||
SUBTTL MSDs -- Byte routines -- Go Backwards some number of bytes
|
||
|
||
;DNBKBY - Go backwards (T1) bytes in input message
|
||
;
|
||
; Call:
|
||
; T1/ Number of bytes to go backwards over
|
||
; MS/ Pointer to input MSD
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1,MS
|
||
;
|
||
;Note: It is your responsiblity to make sure that you do not go
|
||
;backwards over an MSD boundary. If you do the program will not work.
|
||
|
||
INTERNAL DNBKBY
|
||
XRESCD
|
||
DNBKBY: LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
OPSTRM <ADDM T1,>,MDBYT,(MS) ;ADJUST THE BYTE COUNT
|
||
MOVN T1,T1 ;GET NEGATIVE COUNT
|
||
OPSTR <ADJBP T1,>,MDPTR,(MS) ;ADJUST THE BYTE POINTER
|
||
FIXADJ T1 ;COMPENSATE FOR BUG IN BP EA CALC
|
||
STOR T1,MDPTR,(MS) ;STORE THE POINTER BACK
|
||
RET ;TO SENDER
|
||
SUBTTL MSDs -- Read and Goto Position
|
||
|
||
;DNRPOS - Read the current position in the input data
|
||
;
|
||
; Call:
|
||
; MS/ Pointer to input MSD
|
||
;
|
||
; Return:
|
||
; RET ;Always, T1 holds full-word of position
|
||
; ; which can be fed to DNGPOS
|
||
;
|
||
; Uses: T1
|
||
;
|
||
;Note that DNRPOS is called far more frequently than DNGPOS, so
|
||
;DNRPOS is simple, where DNGPOS is complicated.
|
||
|
||
INTERNAL DNRPOS
|
||
XRESCD
|
||
DNRPOS: LOAD T1,MDBYT,(MS) ;LOAD UP 'BYTES TO GO'
|
||
RET ;THAT WAS EASY
|
||
|
||
|
||
|
||
;NSP's message trace facility (TRCMSG) makes illicit use of
|
||
;the MSD fields and of the nature of the position value returned
|
||
;by DNRPOS.
|
||
|
||
|
||
|
||
;DNGPOS - Go to a position in the input data spec'd by caller
|
||
;
|
||
; Call:
|
||
; T1/ POSition word returned from DNRPOS
|
||
; MS/ Pointer to input MSD
|
||
;
|
||
; Return:
|
||
; RET
|
||
;
|
||
; Uses: T1,T2
|
||
;
|
||
;Caller passes a value returned from DNRPOS (above). No other
|
||
;routines are expected to understand the contents of the POSition word.
|
||
;This routine should be called for INPUT MESSAGES ONLY.
|
||
|
||
INTERNAL DNGPOS
|
||
XRESCD
|
||
DNGPOS: LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
TLNN MS,770000 ;MAKE SURE LEFT HALF ISN'T GARBAGE
|
||
OPSTR <CAMGE MS,>,CHBOT,+MBLCB ;MAKE SURE WE HAVE AN MS
|
||
BUG.(CHK,COMDNP,D36COM,SOFT,<DNGPOS called with bad MS>,,<
|
||
|
||
Cause: The ac MS points to memory not used by message blocks.
|
||
This was found during range checking.
|
||
|
||
Action: Trace back to the caller and find out why there is a bad pointer.
|
||
>,RTN)
|
||
LOAD T2,MDBYT,(MS) ;GET CURRENT 'BYTES TO GO'
|
||
STOR T1,MDBYT,(MS) ;STORE SAVED 'BYTES TO GO'
|
||
SUB T2,T1 ;DERIVE BYTES TO BACK UP
|
||
OPSTR <ADJBP T2,>,MDPTR,(MS) ;BACK UP THE BYTE POINTER
|
||
FIXADJ T2 ;COMPENSATE FOR BUG IN BP EA CALC
|
||
STOR T2,MDPTR,(MS) ;STORE THE UPDATED BYTE POINTER
|
||
RET
|
||
|
||
;DNGOPS - Go to a position in the input data spec'd by caller
|
||
;
|
||
; Call:
|
||
; T1/ POSition word returned from DNRPOS
|
||
; MS/ Pointer to input MSD
|
||
;
|
||
; Return:
|
||
; RET
|
||
;
|
||
; Uses: T1,T2
|
||
;
|
||
;Caller passes a value returned from DNRPOS (above). No other
|
||
;routines are expected to understand the contents of the POSition word.
|
||
;This routine should be called for OUTPUT MESSAGES ONLY.
|
||
|
||
INTERNAL DNGOPS
|
||
XRESCD
|
||
DNGOPS: LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
TLNN MS,770000 ;MAKE SURE LEFT HALF ISN'T GARBAGE
|
||
OPSTR <CAMGE MS,>,CHBOT,+MBLCB ;MAKE SURE WE HAVE AN MS
|
||
BUG.(CHK,COMODP,D36COM,SOFT,<DNGOPS called with bad MS>,,<
|
||
|
||
Cause: The ac MS points to memory not used by message blocks.
|
||
This was found during range checking.
|
||
|
||
Action: Trace back to the caller and find out why there is a bad pointer.
|
||
>,RTN)
|
||
LOAD T2,MDBYT,(MS) ;GET CURRENT 'BYTES TO GO'
|
||
STOR T1,MDBYT,(MS) ;STORE SAVED 'BYTES TO GO'
|
||
SUBM T1,T2 ;DERIVE BYTES TO BACK UP
|
||
OPSTR <ADJBP T2,>,MDPTR,(MS) ;BACK UP THE BYTE POINTER
|
||
FIXADJ T2 ;COMPENSATE FOR BUG IN BP EA CALC
|
||
STOR T2,MDPTR,(MS) ;STORE THE UPDATED BYTE POINTER
|
||
RET
|
||
|
||
SUBTTL MSDs -- Link a Message Segment into a Message Block
|
||
|
||
;DNLMSS - Link message segment into MB
|
||
;
|
||
; Call:
|
||
; T1/ Pointer to MSD that will point to segment
|
||
; T2/ Pointer to previous MSD
|
||
; T3/ Pointer to data (segment)
|
||
; T4/ Count of bytes in data
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1-T4
|
||
|
||
INTERNAL DNLMSS
|
||
XRESCD
|
||
DNLMSS: JUMPE T3,DNLMS1 ;IF NO POINTER IS SPECIFIED, JUST LINK PREVIOUS
|
||
STOR T3,MDAUX,(T1) ;STORE THE BYTE POINTER
|
||
STOR T3,MDPTR,(T1) ; AND THE DYNAMIC BYTE POINTER
|
||
STOR T4,MDBYT,(T1) ;STORE THE BYTE COUNT
|
||
STOR T4,MDALL,(T1) ; AND THE ALLOCATED LENGTH
|
||
DNLMS1: STOR T1,MDNXT,(T2) ;LINK PREVIOUS MSD TO US
|
||
RET ;RETURN
|
||
SUBTTL MSDs -- Copy message block
|
||
|
||
;DNCPMS - Gather message blocks MSDs into a new message block
|
||
;
|
||
; Call:
|
||
; MB/ Pointer to message block to copy
|
||
;
|
||
; Return:
|
||
; RET ;ERROR IN COPYING
|
||
; RETSKP ;T1 POINTING TO NEW MESSAGE BLOCK
|
||
; ; MB STILL POINTING TO OLD BLOCK
|
||
; Uses: T1-T5
|
||
;
|
||
;Note that the byte pointers in MDPTR and MDAUX are indexed by
|
||
;(T6), see comment at VGNPTR definition, above. Since we are
|
||
;using two msg blks here, one of the byte ptrs has to have its
|
||
;X field changed to T3.
|
||
|
||
INTERNAL DNCPMS
|
||
XRESCD
|
||
DNCPMS: SAVEAC <P1,P2> ;P1 WILL POINT TO NEW MESSAGE BLOCK
|
||
|
||
;First, allocate a new message block
|
||
|
||
MOVE T1,MB ;POINTER TO SOURCE MSG BLK
|
||
CALL DNLENG ;HOW MANY BYTES IN IT?
|
||
CALL DNGMSG ;GET A NEW MSG BLK FOR THAT MANY
|
||
RET ;CAN'T RETURN FAILURE TO CALLER
|
||
MOVE P1,T1 ;SAVE POINTER TO NEW MSG BLK
|
||
|
||
;Now we can fill in the new message block with data as if
|
||
;it had come from the outside world: all in IN.MSD.
|
||
|
||
SETZ T4, ;WE'LL COLLECT BYTE COUNT HERE
|
||
OPSTR <SKIPN T5,>,MBFMS,(MB) ;GET PTR TO FIRST MSD
|
||
JRST DNCPM6 ;LEAVE NOW IF NO DATA TO COPY
|
||
DNCPM1: OPSTR <SKIPN T3,>,MDNXT,(T5) ;REMEMBER ADDR OF LAST MSD IN T5
|
||
JRST DNCPM2 ;DON'T COUNT LAST MSD IN CHAIN
|
||
OPSTR <ADD T4,>,MDBYT,(T5) ;COUNT THIS MSD'S DATA
|
||
MOVE T5,T3 ;MOVE TO NEXT MSD
|
||
JRST DNCPM1 ;THERE IS A NEXT, GO COUNT IT
|
||
|
||
DNCPM2: LOAD T6,MDAUX,(T5) ;INDEXED 8-BIT BYTE PTR TO BEG OF SOURCE
|
||
HRRZ T2,T6 ;ISOLATE OFFSET IN RH OF BYTE PTR
|
||
TLNE T6,700000 ;IS IT 041000,,xxx?
|
||
JRST DNCPM3 ;NO, NO PROBLEM
|
||
TLO T6,400000 ;YES, MAKE IT 4410xx,nnn+1
|
||
HRRI T6,1(T6) ;NON-CARRYING ADD TO RH, TLO JUST MADE IFIW
|
||
DNCPM3: OPSTR <ADD T2,>,MDALA,(T5) ; WHICH WAS INDEXED BY T6=MDALA
|
||
MOVEI T3,3(T4) ;GET BYTES BEFORE THIS MSD, ROUNDED UP
|
||
ASH T3,-2 ;CALCULATE WORDS FOR ALL BUT LAST MSD
|
||
HRR T6,T3 ;SAVE INDEXED BYTE PTR TO BEG OF DEST
|
||
OPSTR <ADD T3,>,MDALA,+IN.MSD(P1) ;ADD ALLOC ADDR IN DEST MSD
|
||
|
||
LOAD T1,MDBYT,(T5) ;GET # OF BYTES IN LAST MSD
|
||
ADDI T1,3+3 ;ADD 3 BEFORE + 3 AFTER FOR BLT MISALIGNMENT
|
||
ASH T1,-2 ;CALC # OF WORDS TO BLT
|
||
CALL XBLTAT ;(T1,T2,T3)COPY MONITOR TO MONITOR
|
||
;Calc dest start byte ptr into T5, byte pointer indexed by T3 for MOVSLJ
|
||
|
||
MOVE T3,T4 ;GET # BYTES BEFORE BLT DATA
|
||
OPSTR <ADD T3,>,MDBYT,(T5) ;GET TOTAL LENGTH OF NEW MESSAGE
|
||
STOR T3,MDBYT,+IN.MSD(P1) ;STORE IN NEW MSD
|
||
JUMPE T4,[ ;DON'T CHANGE 441006,,0 TO 041006,,-1
|
||
STOR T6,MDPTR,+IN.MSD(P1)
|
||
JRST DNCPM6] ;ALL DONE
|
||
MOVN T5,T4 ;NEGATE # OF BYTES BEFORE BLT'D DATA
|
||
ADJBP T5,T6 ;(T6) BYTE PTR TO START OF MSG
|
||
FIXADJ T5 ;COMPENSATE FOR BUG IN BP EA CALC
|
||
STOR T5,MDPTR,+IN.MSD(P1) ;NEW BEG PTR, STILL INDEXED BY T6
|
||
TLZ T5,17 ;GET RID OF T6 INDEX FOR USE BELOW
|
||
TLO T5,T3 ;REPLACE IT WITH T3 INDEX
|
||
LOAD T3,MDALA,+IN.MSD(P1) ;WE'LL INDEX DEST BPT WITH T3
|
||
|
||
;MB will now point to source MSDs instead of source msg blk
|
||
|
||
LOAD P2,MBFMS,(MB) ;PICK UP PTR TO FIRST MSD
|
||
DNCPM5: TMNN MDNXT,(P2) ;IS THIS THE LAST MSD?
|
||
JRST DNCPM6 ;YES, ALREADY BLT'D, DON'T MOVSLJ IT
|
||
LOAD T1,MDBYT,(P2) ;LENGTH OF DATA IN THIS MSD
|
||
LOAD T2,MDAUX,(P2) ;BYTE PTR TO BEG OF DATA
|
||
LOAD T6,MDALA,(P2) ;BYTE PTR IN T2 IS INDEXED BY T6
|
||
MOVE T4,T1 ;COPY SOURCE LENGTH TO DEST LENGTH
|
||
EXTEND T1,[MOVSLJ] ;PREPEND HEADER TO USER DATA
|
||
BUG.(CHK,COMMTS,D36COM,SOFT,<New message block too short>,,<
|
||
|
||
Cause: A MOVSLJ instruction in D36COM has failed.
|
||
|
||
>,RTN)
|
||
LOAD P2,MDNXT,(P2) ;GET PTR TO NEXT MSD IN CHAIN
|
||
JRST DNCPM5 ;GO COPY NEXT IF ITS NOT LAST
|
||
|
||
DNCPM6: XMOVEI T1,IN.MSD(P1) ;GET POINTER TO INPUT MSD IN NEW MSG
|
||
STOR T1,MBFMS,(P1) ;STORE AS FIRST MSD IN MSD CHAIN
|
||
MOVE T1,P1 ;T1 PTS TO NEW MSG BLK FOR CALLER
|
||
RETSKP ;RETURN SUCCESS
|
||
SUBTTL MSDs -- Calculate length of a whole message
|
||
|
||
;DNLENG - Find length of message left
|
||
;
|
||
; Call:
|
||
; T1/ Pointer to Message Block
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS WITH T1 CONTAINING COUNT
|
||
;
|
||
; Uses: T1,T2
|
||
|
||
INTERNAL DNLENG
|
||
XRESCD
|
||
DNLENG:
|
||
SETZ T2, ;KEEP COUNTER IN T2
|
||
LOAD T1,MBFMS,(T1) ;GET POINTER TO FIRST MSD IN MSG BLK
|
||
|
||
DNLEN1: OPSTR <ADD T2,>,MDBYT,(T1) ;ADD UP THE COUNT
|
||
LOAD T1,MDNXT,(T1) ;GET THE NEXT MSD
|
||
JUMPN T1,DNLEN1 ;LOOP IF WE GOT SOME MORE
|
||
MOVE T1,T2 ;PUT IT WERE WE WANT IT
|
||
RET ;OTHERWISE RETURN
|
||
SUBTTL MSDs -- Calculate Length of Message Segment
|
||
|
||
;DNSLNG - Figure out length of MS segment
|
||
;
|
||
; Call:
|
||
; T1/ Pointer to input MSD
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS WITH LENGTH IN T1
|
||
;
|
||
; Uses: T1,T2
|
||
;
|
||
;Use this instead of looking at the count yourself, so that we can
|
||
;wedge the byte count somewhere with extended byte pointers.
|
||
|
||
INTERNAL DNSLNG
|
||
XRESCD
|
||
DNSLNG: LOAD T1,MDBYT,(T1) ;GET OUR BYTE COUNT
|
||
RET ; AND RETURN
|
||
SUBTTL MSDs -- DNMINI - Initialize an allocated message block
|
||
;DNMINI - Initialize a message block
|
||
;
|
||
;Call
|
||
; T1/ Pointer to message block
|
||
; T2/ Number of user bytes desired
|
||
;Return
|
||
; RET ;ON ALLOCATION FAILURE FOR USER DATA BLOCK
|
||
; ; (WILL DE-ALLOCATE MESSAGE BLOCK)
|
||
; RETSKP ;SUCCESS, VIRGIN MESSAGE BLOCK WITH USER DATA
|
||
|
||
INTERNAL DNMINI
|
||
XRESCD
|
||
DNMINI: TDZA T3, ;FLAG AN UNPRIVED CALL
|
||
DNMINP: SETO T3, ;FLAG A PRIVED CALL
|
||
SAVEAC <P1,P2,P3>
|
||
MOVEI P2,3+3(T2) ;SAVE NUMBER OF USER DATA BYTES
|
||
; NEEDED, WITH LEEWAY BEFORE & AFTER FOR
|
||
; BYTE MISALIGNMENT FROM BLT'D DATA
|
||
; IN ROUTINES LIKE DNCU2M, DNCPMS
|
||
MOVE P3,T3 ; Save privelege flag
|
||
SKIPN P1,T1 ;SAVE PTR TO MSG BLK
|
||
BUG.(CHK,COMMZP,D36COM,SOFT,<DNMINI was passed a zero pointer>,,<
|
||
|
||
Cause: Some caller probably meant to ask for zero bytes of user data in T2
|
||
and mistakenly put the count in T1, which is supposed to be the
|
||
pointer to the message block to refresh.
|
||
|
||
Action: Find caller on the stack and fix it.
|
||
|
||
>,RTN)
|
||
XMOVEI T2,UD.DAT(P1) ;PTR TO LITTLE USER DATA BFR IN MSG BLK
|
||
LOAD T1,MDALA,+UD.MSD(P1) ;GET MSD'S PTR TO USER DATA
|
||
JUMPE T1,DNMIN1 ;JUMP IF NO USER DATA BLK PTR
|
||
CAME T1,T2 ;ARE THESE THE SAME?
|
||
JRST DNMIN2 ;NO, WE HAVE A SEPARATE USER DATA BLOCK
|
||
DNMIN1: CAIG P2,UDH.LN ;NO SEPARATE BLOCK, DO WE WANT ONE?
|
||
JRST DNMIN4 ;NO, LITTLE USER DATA BLOCK IS GOOD ENOUGH
|
||
XMOVEI T1,UBLCB ;YES, PTR TO CH FOR USER DATA BLKS
|
||
LOAD P2,CHSIZ,(T1) ;Get size of UBL
|
||
SUBI P2,OVHWDS ; Allowance for overhead word(s)
|
||
IMULI P2,4 ;Convert to bytes for caller
|
||
MOVE T2,P3 ; Get privilege flag
|
||
CALL DNGRBA ;(T1,T2)GO GET BIG UD BLK (T6 IS PRIV FLAG)
|
||
RET ;WE LOSE
|
||
|
||
IFN FTLSTCOR,<
|
||
MOVE T2,-4(P) ;GET CALLER'S PC
|
||
MOVEM T2,(T1) ;PUT INTO FIRST HEADER WORD
|
||
MOVE T2,['D36INI'] ;PUT TEST THING
|
||
MOVEM T2,1(T1) ; IN SECOND HEADER WORD
|
||
ADDI T1,2 ;POINT PAST HEADER WORDS
|
||
>;END IFN FTLSTCOR
|
||
|
||
STOR T1,MDALA,+UD.MSD(P1) ;STORE ALLOCATED ADDRESS OF USER DATA
|
||
JRST DNMIN5 ;WE ARE WARM AND FUZZY NOW
|
||
|
||
DNMIN2: CAILE P2,UDH.LN ;WE HAVE A BLK, DO WE NEED IT?
|
||
JRST DNMIN5 ;YES, WE ARE ALL WARM AND FUZZY
|
||
|
||
IFN FTLSTCOR,<
|
||
SUBI T1,2 ;ACCOUNT FOR THE HEADER WORDS
|
||
>;END IFN FTLSTCOR
|
||
|
||
XMOVEI T2,UBLCB ;POINTER TO CH FOR USER DATA BLOCKS
|
||
CALL DNFRBL ;(T1,T2)RELEASE THE USER DATA BLOCK
|
||
XMOVEI T2,UD.DAT(P1) ;PTR TO PLACE WE CAN FIT USER DATA IN
|
||
DNMIN4: STOR T2,MDALA,+UD.MSD(P1) ;STORE ALLOCATED ADDRESS OF USER DATA
|
||
DNMIN5: STOR P2,MDALL,+UD.MSD(P1) ;STASH AWAY ALLOCATED LENTGH OF STRING
|
||
|
||
XMOVEI T1,NM.HDR(P1) ;GET POINTER TO NSP HEADER AREA
|
||
STOR T1,MDALA,+NM.MSD(P1) ;STORE IT IN ALLOCATED ADDRESS FIELD
|
||
MOVX T1,NMH.LN ;GET THE NSP HEADER AREA LENGTH (IN BYTES)
|
||
STOR T1,MDALL,+NM.MSD(P1) ;STORE AWAY THE ALLOCATED LENGTH
|
||
|
||
XMOVEI T1,RM.HDR(P1) ;GET POINTER TO RTR HEADER AREA
|
||
STOR T1,MDALA,+RM.MSD(P1) ;STORE POINTER IN ALLOCATED ADDRESS FIELD
|
||
MOVX T1,RMH.LN ;GET LENGTH OF HEADER AREA (IN BYTES)
|
||
STOR T1,MDALL,+RM.MSD(P1) ;STORE ALLOCATED LENGTH FOR SOMEONE
|
||
|
||
SETZRO MDBYT,+UD.MSD(P1) ;NO BYTES IN USER DATA MSD YET
|
||
SETZRO MDBYT,+NM.MSD(P1) ;NO BYTES IN NSP MSD YET
|
||
SETZRO MDBYT,+RM.MSD(P1) ;NO BYTES IN ROUTER MSD YET
|
||
|
||
MOVX T1,VGNPTR ;BUILD A VIRGIN BYTE PTR
|
||
STOR T1,MDAUX,+UD.MSD(P1) ;STASH AWAY BYTE POINTER TO USER DATA
|
||
STOR T1,MDPTR,+UD.MSD(P1) ;STASH AWAY IN DYNAMIC POINTER
|
||
STOR T1,MDAUX,+NM.MSD(P1) ;STORE IN NSP STRING POINTER FIELD
|
||
STOR T1,MDPTR,+NM.MSD(P1) ;AND IN THE DYNAMIC BYTE POINTER AREA
|
||
STOR T1,MDAUX,+RM.MSD(P1) ;STORE IT IN STRING POINTER
|
||
STOR T1,MDPTR,+RM.MSD(P1) ;AND IN THE DYNAMIC BYTE POINTER
|
||
|
||
;Link all of the MSD's to their header areas
|
||
|
||
SETZRO MDNXT,+UD.MSD(P1) ;NO FORWARD PTR FROM USER DATA MSD
|
||
SKIPE T1,P2 ;ANY USER DATA?
|
||
XMOVEI T1,UD.MSD(P1) ;YES, GET POINTER TO USER DATA MSD
|
||
STOR T1,MDNXT,+NM.MSD(P1) ;STORE USER DATA OR ZERO AS NEXT TO NSP
|
||
XMOVEI T1,NM.MSD(P1) ;POINT TO THE NSP MSD
|
||
STOR T1,MDNXT,+RM.MSD(P1) ;POINT RTR'S NEXT POINT TO NSP MSD
|
||
XMOVEI T1,RM.MSD(P1) ;POINT TO THE START OF THE RTR MSD
|
||
STOR T1,MBFMS,(P1) ;STORE THAT AS THE FIRST MSD POINTER
|
||
|
||
;Here to fix up the msg blk
|
||
|
||
SETZM MB.FLG(P1) ;CLEAR OUT COMMON FLAGS WORD
|
||
SETZM MB.CHN(P1) ;ASSUME NO LOOPBACK CHANNEL
|
||
SETZM NM.FLG(P1) ;CLEAR OUT LLINKS' FLAGS WORD
|
||
IFN NM.FLG-NM.CNT,<SETZM NM.CNT(P1)> ;SEND COUNT IF IN DIFFERENT WORD
|
||
SETZM RM.FLG(P1) ;CLEAR OUT ROUTER'S FLAGS WORD
|
||
SETZM RM.ICP(P1) ;CLEAR INPUT CIRCUIT POINTER
|
||
SETZM RM.OCP(P1) ;CLEAR OUTPT CIRCUIT POINTER
|
||
SETZM RM.MK1(P1) ;CLEAR OUT THE EVENT MARK TO INDICATE NO ROUTER HEADER
|
||
RETSKP ;RETURN SUCCESS
|
||
|
||
SUBTTL MSDs -- DNCMSD - Copy MSD chain to contiguous block
|
||
|
||
;DNCMSD - copy a MSD chain to a contiguous block
|
||
;
|
||
;Call: T1/ 30-bit pointer of destination block
|
||
; T2/ # of bytes in destination block
|
||
; MB/ message block address
|
||
; CALL DNCMSD
|
||
; +1 return: not room to copy message
|
||
; +2 return: success with -
|
||
; T1/ BP to destination string without any address information
|
||
; T2/ # of pad bytes required to word-align
|
||
; T3/ total # of bytes (excluding pad) in message
|
||
|
||
INTERNAL DNCMSD
|
||
XRESCD
|
||
DNCMSD: SAVEAC <P1,P2,T5,T6>
|
||
STKVAR <PRECNT,TOTCNT,DSTBLK,DSTCNT,NRPAD,DSTPTR>
|
||
;PRECNT is the sum of bytes in all MSDs except the last one
|
||
;TOTCNT is the total number of bytes in the message
|
||
;DSTBLK is address of destination block
|
||
;DSTCNT is the number of bytes the destination block can accomodate
|
||
;NRPAD is the number of pad bytes needed to word-align the message
|
||
;DSTPTR is the destination byte pointer as returned to the user
|
||
MOVEM T1,DSTBLK ;Save destination address
|
||
MOVEM T2,DSTCNT ;Save # of bytes in destination block
|
||
|
||
;Find last MSD and count bytes along the way (into T1)
|
||
LOAD MS,MBFMS,(MB) ;Get first MSD
|
||
SETZ T1, ; and clear count
|
||
DO. ;Loop
|
||
OPSTR <SKIPN T2,>,MDNXT,(MS) ;Is there another MSD?
|
||
EXIT. ; -no, this is the last - exit
|
||
OPSTR <ADD T1,>,MDBYT,(MS) ;Count the # of bytes in this MSD
|
||
MOVE MS,T2 ;Go to next MSD
|
||
LOOP. ; and loop back
|
||
ENDDO.
|
||
MOVEM T1,PRECNT ;Save count of bytes before last MSD
|
||
|
||
;Should we do XBLT or MOVSLJs?
|
||
LOAD T2,MDBYT,(MS) ;Get # of bytes in last MSD
|
||
ADD T1,T2 ;Calculate total # of bytes in message
|
||
MOVEM T1,TOTCNT ; and save that
|
||
CAIG T2,20 ;More than 20 bytes in last MSD?
|
||
JRST COPSLJ ; -no, copy with MOVSLJ
|
||
|
||
;Do XBLT
|
||
|
||
;The bytepointer in a MSD is of the format x41006,,nnn
|
||
LOAD T1,MDAUX,(MS) ;Get the last MSDs pointer
|
||
HRRZ T2,T1 ;Isolate offset
|
||
LDB T1,[POINT 3,T1,2] ;Get "x" from byte pointer
|
||
;The "x" is either 0 (make it into 4, and increase offset), 1,2,3 or 4
|
||
SKIPE T1 ;Is it 0?
|
||
IFSKP. ; then
|
||
MOVX T1,4 ; make it 4
|
||
AOJ T2, ; and increase offset
|
||
ENDIF.
|
||
|
||
IFN FTDEBUG < ;Verify bp only if debugging
|
||
CAILE T1,4 ;Should never be greater than 4
|
||
BUG.(CHK,DNBBP,CIDLL,SOFT,<Bad byte-pointer>,,<
|
||
|
||
Cause: CIDLL while copying a DECnet message to a SCA buffer, saw a
|
||
bytepointer in a MSD where the first three bits are 5,6 or 7.
|
||
|
||
>,RTN)
|
||
>
|
||
|
||
;T2 is the offset from the last MSD bytepointer - make it XBLT source address
|
||
OPSTR <ADD T2,>,MDALA,(MS) ;Thats it!
|
||
|
||
;Since the last MSD do not need to start on a word boundary, there may be
|
||
; room for a couple of bytes there:
|
||
MOVE T1,[EXP 3,2,1,0]-1(T1) ;Get that # of bytes
|
||
MOVE T3,PRECNT ;Get number of bytes before last MSD
|
||
SUB T3,T1 ; and number of bytes that do not fit
|
||
;T3 is the number of bytes before the word where the last MSD starts
|
||
MOVEI T4,3(T3) ;Add 3 and
|
||
ASH T4,-2 ; divide by 4 to get number of words
|
||
;T4 now has number of words before last MSD in destination
|
||
MOVE T5,T4 ;Get word count
|
||
ASH T5,2 ; and make into bytes
|
||
SUB T5,T3 ;Difference is number of pad bytes
|
||
MOVEM T5,NRPAD
|
||
|
||
;Verify that destination block has room for all bytes
|
||
ADD T5,TOTCNT ;Total length is message length + pad bytes
|
||
CAMLE T5,DSTCNT ;Fit?
|
||
RET ; -no, return error
|
||
;Calculate # of words in XBLT
|
||
OPSTR <ADD T1,>,MDBYT,(MS) ;Add # of "spare bytes" in first word
|
||
; with number of bytes in last MSD
|
||
ADDI T1,3 ;Add 3 to
|
||
ASH T1,-2 ; make word count
|
||
;T2 is already loaded
|
||
MOVE T3,DSTBLK ;Load destination block address
|
||
ADD T3,T4 ; and add in offset
|
||
EXTEND T1,[XBLT] ;XBLT...
|
||
|
||
;Now copy all MSDs except the last one with MOVSLJs
|
||
;T1 and T4 is byte count
|
||
;T2 is source byte pointer, indexed by P1 (and not T6)
|
||
;T5 is destination byte pointer, indexed by P2 (and not T6)
|
||
;P1 is source word address (MDALA)
|
||
;P2 is destination block address (DSTBLK)
|
||
LOAD MS,MBFMS,(MB) ;Point to first MSD
|
||
MOVE T5,NRPAD ;Get number of pad bytes
|
||
MOVE T1,[POINT 8,0] ;Make destination pointer without address
|
||
ADJBP T5,T1 ;Make destination pointer point by pad in T5
|
||
FIXADJ T5 ;COMPENSATE FOR BUG IN BP EA CALC
|
||
MOVEM T5,DSTPTR ; and save it for a while
|
||
TLO T5,P2 ;Now insert index through P2
|
||
MOVE P2,DSTBLK ;Load destination block address
|
||
DO. ;Until last MSD do..
|
||
OPSTR <SKIPN>,MDNXT,(MS) ;Is there another MSD?
|
||
EXIT. ; -no, this is the last one - dont copy
|
||
CALL CMSDSG ; Copy one MSD segment
|
||
LOAD MS,MDNXT,(MS) ; and move to next MSD
|
||
LOOP.
|
||
ENDDO.
|
||
|
||
;All done for the XBLT case - just return
|
||
MOVE T1,DSTPTR ;Get destination pointer
|
||
MOVE T2,NRPAD ; and number of pad bytes
|
||
MOVE T3,TOTCNT ; and length of entire message
|
||
RETSKP
|
||
|
||
;COPSLJ - copy all segments with MOVSLJs
|
||
;T1 and T4 is byte count
|
||
;T2 is source byte pointer, indexed by P1 (and not T6)
|
||
;T5 is destination byte pointer, indexed by P2 (and not T6)
|
||
;P1 is source word address (MDALA)
|
||
;P2 is destination block address (DSTBLK)
|
||
;
|
||
COPSLJ: MOVE T1,TOTCNT ;Room for message?
|
||
CAMLE T1,DSTCNT ; ..
|
||
RET ; -no, error return
|
||
LOAD MS,MBFMS,(MB) ;Point to first MSD
|
||
MOVE T5,[POINT 8,(P2)] ;Make destination pointer
|
||
MOVE P2,DSTBLK ;Load destination block address
|
||
DO. ;Until last MSD do..
|
||
CALL CMSDSG ; Copy one MSD segment
|
||
OPSTR <SKIPN MS,>,MDNXT,(MS) ;Move to next MSD if there is one
|
||
EXIT. ; -no, at end, exit
|
||
LOOP.
|
||
ENDDO.
|
||
|
||
;All done for the MOVSLJ case - just return
|
||
MOVSI T1,(POINT 8,0) ;Get LH of destination pointer
|
||
SETZ T2, ;Number of pad bytes
|
||
MOVE T3,TOTCNT ; and length of entire message
|
||
RETSKP
|
||
ENDSV.
|
||
|
||
;CMSDSG - copy a MSD segment
|
||
;
|
||
;Call: T5/ destination byte pointer indexed by P2
|
||
; P2/ destination address
|
||
; MS/ points to current MSD
|
||
;May use T1-T6, P1
|
||
|
||
CMSDSG: LOAD T1,MDBYT,(MS) ;# of bytes to copy
|
||
JUMPE T1,RTN ; -nothing to copy
|
||
LOAD T2,MDAUX,(MS) ;Get byte pointer to source
|
||
TLZ T2,17 ;Clear out index AC
|
||
TLO T2,P1 ; and make it index through P1
|
||
LOAD P1,MDALA,(MS) ;Get source word address to P1
|
||
MOVE T4,T1 ; and move count
|
||
EXTEND T1,[MOVSLJ] ;Copy the bytes
|
||
BUG.(CHK,DNSLJ,CIDLL,SOFT,<MOVSLJ failed>,,<
|
||
|
||
Cause: A MOVSLJ instruction did not skip.
|
||
>)
|
||
RET
|
||
|
||
SUBTTL Buffers -- Copy buffer to a message segment
|
||
|
||
;DNCB2M - Copy buffer to a message segment
|
||
;
|
||
; Call:
|
||
; T1/ Byte Count
|
||
; T2/ 1- or 2-word Byte Pointer to String Block
|
||
; T3/ Optional second word of byte pointer
|
||
; MS/ Pointer to current message segment
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS WITH T2 CONTAINING UPDATED BYTE POINTER
|
||
; ; AND T1, T2 & T3 UPDATED
|
||
;
|
||
; Uses: T1-T6
|
||
;
|
||
;Note that this is used only to copy from a DECnet (monitor) buffer to
|
||
;a DECnet message block.
|
||
|
||
INTERNAL DNCB2M
|
||
XRESCD
|
||
DNCB2M: STKVAR <BYTCNT>
|
||
MOVEM T1,BYTCNT ;Save count of bytes asked to copy
|
||
TXNE T2,1B12 ;IS IT A 2-WORD GLOBAL PTR?
|
||
HRR T2,T3 ;YES, MAKE LOCAL PTR FOR OLD MACHINES
|
||
MOVE T4,T1 ;SET UP THE DESTINATION BYTE COUNT
|
||
LOAD T5,MDPTR,(MS) ; AND THE DESTINATION BYTE POINTER
|
||
LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
CALL BBM2M ;(T1-T6/T1-T6) MOVE BYTES
|
||
TRN ;WON'T HAPPEN
|
||
MOVE T4,BYTCNT ;Number of bytes requested to copy
|
||
SUBI T4,(T1) ;Minus those we didn't send
|
||
OPSTRM <ADDM T4,>,MDBYT,(MS) ;INCREMENT THE BYTE COUNT
|
||
STOR T5,MDPTR,(MS) ;STORE THE UPDATED BYTE POINTER
|
||
RET ;RETURN
|
||
ENDSV.
|
||
|
||
SUBTTL Buffers -- Copy message data to a buffer
|
||
|
||
;DNCM2B - Copy message data to a buffer
|
||
;
|
||
; Call:
|
||
; T1/ Count of bytes
|
||
; T2/ 1- or 2-word Byte Pointer to buffer
|
||
; T3/ Optional second word of byte pointer
|
||
; MS/ Pointer to current message segment
|
||
;
|
||
; Return:
|
||
; RET ;IF LENGTH IS NOT CORRECT
|
||
; RETSKP ;ON SUCCESSFUL COPY WITH T1 AND T2 CONTAINING
|
||
; ; BYTE COUNT AND POINTER
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
INTERNAL DNCM2B
|
||
XRESCD
|
||
DNCM2B: OPSTR <CAMLE T1,>,MDBYT,(MS) ;MESSAGE BIG ENOUGH?
|
||
RET ;NO, LET CALLER DEAL WITH ERROR
|
||
SAVEAC <P1> ;Will contain index AC
|
||
MOVE T4,T1 ;SET UP DESTINATION BYTE COUNT
|
||
DMOVE T5,T2 ; AND DESTINATION BYTE PTR
|
||
TXNE T5,1B12 ;2-WORD BYTE PTR TO MONITOR BUFFER?
|
||
HRR T5,T6 ;YES, MAKE LOCAL FOR OLD MACHINES
|
||
MOVN T2,T1 ;GET NEGATIVE COUNT
|
||
OPSTRM <ADDM T2,>,MDBYT,(MS) ;UPDATE THE BYTE COUNT
|
||
LOAD T2,MDPTR,(MS) ;SET UP THE SOURCE BYTE POINTER
|
||
MOVE P1,T2 ; and save it for restore
|
||
TLZE T2,17 ;IS MDPTR INDEXED?
|
||
TLO T2,T3 ;YES, USE T3, NOT T6
|
||
LOAD T3,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
CALL BBM2M ;(T1-T6/T1-T6) MOVE BYTES
|
||
TRN ;WON'T HAPPEN
|
||
TLZN T2,17 ;MDPTR indexed?
|
||
IFSKP. ; -yes, restore old index AC
|
||
AND P1,[17,,0] ; Clear out everything but old index AC
|
||
TDO T2,P1 ; and put it into byte pointer
|
||
ENDIF.
|
||
STOR T2,MDPTR,(MS) ;STORE BACK THE UPDATED SOURCE BYTE PTR
|
||
MOVE T1,T4 ;UPDATE COUNT FOR CALLER
|
||
DMOVE T2,T5 ;ALSO POSSIBLY 2-WORD BYTE PTR
|
||
RETSKP ;RETURN SUCCESS
|
||
|
||
SUBTTL BYTBLT - Non fancy versions
|
||
IFE FTBYTBLT,<
|
||
BBM2M: JUMPLE T1,RSKP ;RETURN WHEN DONE
|
||
ILDB CX,T2 ;GET A BYTE
|
||
IDPB CX,T5 ;DEPOSIT A BYTE
|
||
SOJA T1,BBM2M ;COUNT DOWN
|
||
>;END IFE FTBYTBLT
|
||
SUBTTL BYTBLT - Fancy version
|
||
|
||
IFN FTBYTBLT,<
|
||
|
||
COMMENT #
|
||
Indirection not permitted
|
||
If a byte pointer passed to this routine is indexed, the index
|
||
register must be T3 for the source, T6 for the destination.
|
||
|
||
Does three special cases:
|
||
1) 8 bit bytes, in "normal" position
|
||
2) packs 8 bit bytes into words
|
||
3) unpacks words into 8 bit bytes
|
||
In all other cases, do an ILDB, IDPB loop
|
||
|
||
CALL BBM2M
|
||
T1/ source count
|
||
T2/ source b.p.
|
||
T3/ optional source b.p. word 2 or index for source b.p.
|
||
T4/ destination count
|
||
T5/ destination b.p.
|
||
T6/ optional destination b.p. word 2 or index for destination b.p.
|
||
returns +1 on failure (bad arguments)
|
||
returns +2 on success
|
||
with T1-T6 updated.
|
||
|
||
Assumes that the 8 bit byte pointers are "normal",
|
||
i.e., as below, or one word global.
|
||
|
||
When the word position is used, it means the number of
|
||
bytes not yet used in the word addressed by the E field of the bp.
|
||
441000,,X - position is 4
|
||
341000,,X - position is 3
|
||
241000,,X - position is 2
|
||
141000,,X - position is 1
|
||
041000,,X - position is 0
|
||
|
||
For 36 bit byte pointers, the count means the number of 8 bit bytes
|
||
|
||
#
|
||
IFN FTOPS10,<
|
||
P4==FREE1 ;EXTRA ACS FOR BYTE BLT
|
||
P5==FREE2
|
||
>; END IFN FTOPS10
|
||
|
||
SMLBLT==30 ;MINIMUM FOR COMPLICATED WAY.
|
||
BP2==1B12 ;2 WORD BP BIT
|
||
BBM2M:: SAVEAC <P1,P2,P3,P4,P5> ;SAVE ACS USED BY THIS ROUTINE
|
||
TRVAR <OWGS,OWGD,<PRG,LPRG>>
|
||
LDB P1,[POINT 6,T2,5] ;GET P OF SOURCE
|
||
LDB P3,[POINT 6,T5,5] ;GET P OF DESTINATION
|
||
CAIG P1,44 ;OWGBP SOURCE ?
|
||
IFSKP.
|
||
CAIG P1,60 ;8 BIT
|
||
CAIL P1,54 ; BYTES ?
|
||
IFSKP.
|
||
MOVEI P2,10 ;YES.
|
||
SUBI P1,54 ;GET
|
||
MOVNS P1 ; POSI-
|
||
ADDI P1,4 ; TION
|
||
SETOM OWGS ;MARK ONE WORD GLOBAL SOURCE
|
||
ELSE.
|
||
MOVEI P2,7 ;NO.
|
||
ENDIF.
|
||
ELSE.
|
||
LDB P2,[POINT 6,T2,11] ;NO. GET S OF SOURCE
|
||
TRNE P1,3 ;IN NORMAL POSITION ?
|
||
JRST BY8LP ;NO. DO SLOWLY.
|
||
LSH P1,-3 ;GET POSITION.
|
||
SETZM OWGS ;MARK NOT ONE WORD GLOBAL SOURCE
|
||
ENDIF.
|
||
CAIG P3,44 ;OWGBP SOURCE ?
|
||
IFSKP.
|
||
CAIG P3,60 ;YES. 8 BIT
|
||
CAIL P3,54 ; BYTES ?
|
||
IFSKP.
|
||
MOVEI P4,10 ;YES.
|
||
SUBI P3,54 ;GET
|
||
MOVNS P3 ; POSI-
|
||
ADDI P3,4 ; TION
|
||
SETOM OWGD ;MARK ONE WORD GLOBAL DEST.
|
||
ELSE.
|
||
MOVEI P4,7 ;NO.
|
||
ENDIF.
|
||
ELSE.
|
||
LDB P4,[POINT 6,T5,11] ;NO. GET S OF SOURCE
|
||
TRNE P3,3 ;IN NORMAL POSITION ?
|
||
JRST BY8LP ;NO. DO SLOWLY.
|
||
LSH P3,-3 ;GET POSITION
|
||
SETZM OWGD ;MARK NOT ONE WORD GLOBAL DEST.
|
||
ENDIF.
|
||
;...
|
||
|
||
;...
|
||
;Dispose of the various cases
|
||
CAIN P2,10 ;8 BIT SOURCE
|
||
CAIE P4,44 ; AND 36 BIT DESTINATION ?
|
||
TRNA ;NO.
|
||
JRST IN36 ;YES. GO DO IT.
|
||
CAIN P2,44 ;36 BIT SOURCE AND
|
||
CAIE P4,10 ; 8 BIT DESTINATION ?
|
||
TRNA ;NO.
|
||
JRST OUT36 ;YES.
|
||
CAMGE T4,T1 ;IS THERE ROOM ?
|
||
RET ;NO. BOMB OUT.
|
||
SUB T4,T1 ;YES. OBTAIN RETURNED COUNT.
|
||
CAIG T1,SMLBLT ;JUST A FEW BYTES ?
|
||
JRST BY8LP ;YES. DO IT EASILY
|
||
CAMN P2,P4 ;BYTE SIZES EQUAL AND
|
||
CAIE P2,10 ; 8 BIT BYTES ?
|
||
JRST BY8LP ;NO. DO IT THE SLOW WAY.
|
||
;Here when 8 bit bytes and using a fast method.
|
||
;Convert source position and byte pointer if necessary.
|
||
IFE. P1 ;IS IT 0 ?
|
||
MOVEI P1,4 ;YES. CONVERT IT TO 4
|
||
SKIPN OWGS ;ONE WORD GLOBAL ?
|
||
IFSKP.
|
||
TLZ T2,600000 ;YES. CONVERT POINTER
|
||
TLO T2,540000
|
||
ELSE.
|
||
TLO T2,440000 ;NO. CONVERT POINTER
|
||
ENDIF.
|
||
TXNN T2,BP2 ;2 WORD BYTE POINTER ?
|
||
IFSKP.
|
||
AOS T3 ;YES.
|
||
ELSE.
|
||
HRRZ CX,T2 ;NO.
|
||
AOS CX
|
||
HRR T2,CX
|
||
ENDIF.
|
||
ENDIF.
|
||
;Convert dest. position and byte pointer if necessary.
|
||
IFE. P3 ;IS IT 0 ?
|
||
MOVEI P3,4 ;YES. CONVERT
|
||
SKIPN OWGD ;ONE WORD GLOBAL ?
|
||
IFSKP.
|
||
TLZ T5,600000 ;YES. CONVERT POINTER
|
||
TLO T5,540000
|
||
ELSE.
|
||
TLO T5,440000 ;NO. CONVERT POINTER
|
||
ENDIF.
|
||
TXNN T5,BP2 ;2 WORD BYTE POINTER ?
|
||
IFSKP.
|
||
AOS T6 ;YES.
|
||
ELSE.
|
||
HRRZ CX,T5 ;NO.
|
||
AOS CX
|
||
HRR T5,CX
|
||
ENDIF.
|
||
ENDIF.
|
||
;BLT or BYTE BLT ?
|
||
CAME P1,P3 ;POSITIONS MATCH ?
|
||
JRST BY8SLW ;(T1-T6,P1-P4) NO. BYTE BLT.
|
||
;...
|
||
|
||
;...
|
||
;BLT - Here when positions match. transfer 0-3 bytes slowly, blt, then
|
||
;transfer the last 0-3 bytes slowly.
|
||
BBBLT: CAIN P1,4 ;POSITION = 4 ? (WORD ALIGNED)
|
||
IFSKP.
|
||
SUB T1,P1 ;NO. MOVE SOME BYTES. UPDATE COUNT.
|
||
BBBLT1: ILDB P5,T2 ;DO
|
||
IDPB P5,T5 ; THOSE
|
||
SOJG P1,BBBLT1 ; BYTES
|
||
MOVEI P5,1 ;REMEMBER WE WERE HERE.
|
||
ELSE.
|
||
SETZ P5, ;WE DIDN'T MOVE BYTES.
|
||
ENDIF.
|
||
;Get source address
|
||
MOVE P2,T2
|
||
SKIPN OWGS ;ONE WORD GLOBAL ?
|
||
IFSKP.
|
||
TLZ P2,770000 ;YES. 30 BITS, NO INDIRECTION OR INDEXING
|
||
ELSE.
|
||
TXNN P2,BP2 ;NO. 2 WORD B.P. ?
|
||
IFSKP.
|
||
XMOVEI P2,(T3) ;YES. GET ADDRESS
|
||
ELSE.
|
||
TLZ P2,777740 ;NO. ONE WORD LOCAL
|
||
TXO P2,<XMOVEI P2,> ;OBTAIN
|
||
XCT P2 ; ADDRESS
|
||
ENDIF.
|
||
ENDIF.
|
||
ADD P2,P5 ;ADD IN IF THE B.P. WAS AT THE END OF A WORD.
|
||
;get destination address
|
||
MOVE P3,T5
|
||
SKIPN OWGD ;ONE WORD GLOBAL ?
|
||
IFSKP.
|
||
TLZ P3,770000 ;YES. 30 BITS, NO INDIRECTION OR INDEXING
|
||
ELSE.
|
||
TXNN P3,BP2 ;NO. 2 WORD B.P. ?
|
||
IFSKP.
|
||
XMOVEI P3,(T6) ;YES. GET ADDRESS
|
||
ELSE.
|
||
TLZ P3,777740 ;NO. ONE WORD LOCAL
|
||
TXO P3,<XMOVEI P3,> ;OBTAIN
|
||
XCT P3 ; ADDRESS
|
||
ENDIF.
|
||
ENDIF.
|
||
ADD P3,P5 ;ADD IN IF THE B.P.S WERE AT THE END OF A WORD.
|
||
MOVE P1,T1 ;SAVE REMAINING BYTE COUNT
|
||
LSH T1,-2 ;CONVERT TO WORD COUNT
|
||
EXCH P2,T2 ;SAVE SOURCE BYTE POINTER (WORDS 1 & 2)
|
||
EXCH P3,T3 ; SET UP FOR XBLT
|
||
CALL XBLTA ;(T1,T2,T3) MOVE IT.
|
||
MOVE T1,P1 ;UPDATE
|
||
LSH T1,-2 ; THE
|
||
MOVE T2,P2 ; BYTE
|
||
MOVE T3,P3 ; POINTERS BY THAT MANY WORDS
|
||
CALL UPDBPW ;(T1,T2,T3,T5,T6/T2,T3,T5,T6)
|
||
MOVE T1,P1 ;REMAINING BYTE
|
||
ANDI T1,3 ; COUNT
|
||
; CALLRET BY8LP ;FINISH OFF THOSE FEW BYTES.
|
||
|
||
;Transfer bytes the easy & slow way
|
||
;CALL BY8LP
|
||
;T1/ Byte count
|
||
;T2,T3/ Source bp
|
||
;T5,T6/ Destination bp
|
||
;RETURNS +2 ALWAYS
|
||
;Uses T1-T6,CX
|
||
BY8LP: JUMPE T1,RSKP
|
||
BY8LP1: ILDB CX,T2
|
||
IDPB CX,T5
|
||
SOJG T1,BY8LP1
|
||
RETSKP
|
||
|
||
;Update byte pointers by words
|
||
;Call UPDBPW
|
||
;T1/ Word count
|
||
;T2,T3/ Source byte pointer
|
||
;T5,T6/ Destination byte pointer
|
||
;Returns +1 always with T2,T3,T5,T6 updated
|
||
;Uses CX
|
||
;Preserves all other ACs
|
||
UPDBPW: TXNN T2,BP2 ;TWO WORD BP ?
|
||
IFSKP.
|
||
ADD T3,T1 ;YES.
|
||
ELSE.
|
||
HRRZ CX,T2 ;NO. DO IT THIS WAY SO
|
||
ADD CX,T1 ; NEGATIVE OFFSET IN B.P.
|
||
HRR T2,CX ; WORKS
|
||
ENDIF.
|
||
TXNN T5,BP2 ;TWO WORD BP ?
|
||
IFSKP.
|
||
ADD T6,T1 ;YES.
|
||
ELSE.
|
||
HRRZ CX,T5 ;NO. DO IT THIS WAY SO
|
||
ADD CX,T1 ; NEGATIVE OFFSET IN B.P.
|
||
HRR T5,CX ; WORKS
|
||
ENDIF.
|
||
RET
|
||
|
||
;Here when byte positions do not match
|
||
;Call BY8SLW
|
||
;T1/ Byte count
|
||
;T2,T3/ Source byte pointer
|
||
;T4/ Remaining byte count already updated
|
||
;T5,T6/ Destination byte pointer
|
||
;P1/ Source position
|
||
;P3/ Dest. position
|
||
;Returns +1 always with
|
||
;T2,T3,T5,T6 updated.
|
||
;uses P1-P5
|
||
;uses the TRVAR OWGS, OWGD
|
||
BY8SLW: SUB T1,P3 ;UPDATE COUNT
|
||
;COMPUTE (SOURCE-DESTINATION MOD 4)
|
||
SUB P1,P3 ; WHAT SOURCE POSITION
|
||
CAIG P1,0 ; WILL BE AFTER
|
||
ADDI P1,4 ; FILLING FIRST WORD OF DEST.
|
||
BY8BL1: ILDB P5,T2 ;FILL IN FIRST WORD OF DESTINATION
|
||
IDPB P5,T5
|
||
SOJG P3,BY8BL1
|
||
;at this point the destination position is 4, and the
|
||
;source position is 1, 2, or 3.
|
||
MOVE P4,T1 ;SAVE COUNT
|
||
MOVE P2,T2 ;AND BYTE
|
||
MOVE P3,T3 ; POINTER
|
||
MOVEI T1,LPRG ;GET COPY OF
|
||
XMOVEI T2,PROTO ;PROTOTYPE BYTE BLT
|
||
XMOVEI T3,PRG ;ON THE STACK
|
||
CALL XBLTA
|
||
MOVE T1,P4 ;RESTORE COUNT AND BYTE POINTER
|
||
MOVE T2,P2
|
||
MOVE T3,P3
|
||
;Alter the program on the stack (TRVAR PRG)
|
||
CAIN P1,3 ;POSITION NOT 3 ?
|
||
IFSKP.
|
||
XMOVEI P2,PRG ;YES. MUST ALTER. ADDRESS OF BYTBLT ROUTINE
|
||
MOVE P3,3(P2) ;GET FIRST INSTRUCTION TO BE ALTERED
|
||
XCT PROT1-1(P1) ;ALTER IT.
|
||
MOVEM P3,3(P2) ;STICK IT IN THE PROGRAM.
|
||
MOVE P3,4(P2) ;GET SECOND INSTRUCTION TO BE ALTERED
|
||
TXZ P3,17B12 ;CLEAR AC FIELD
|
||
TXO P3,11B12 ;SET IT TO P2
|
||
MOVEM P3,4(P2) ;STICK IT IN THE PROGRAM.
|
||
ENDIF.
|
||
;...
|
||
|
||
;...
|
||
;Get source address
|
||
MOVE P3,T2
|
||
SKIPN OWGS ;ONE WORD GLOBAL ?
|
||
IFSKP.
|
||
TLZ P3,770000 ;YES. 30 BITS, NO INDIRECTION OR INDEXING
|
||
ELSE.
|
||
TXNN P3,BP2 ;NO. 2 WORD B.P. ?
|
||
IFSKP.
|
||
XMOVEI P3,(T3) ;YES. GET ADDRESS
|
||
ELSE.
|
||
TLZ P3,777740 ;NO. ONE WORD LOCAL
|
||
TXO P3,<XMOVEI P3,> ;OBTAIN
|
||
XCT P3 ; ADDRESS
|
||
ENDIF.
|
||
ENDIF.
|
||
;Get destination address
|
||
MOVE P4,T5
|
||
SKIPN OWGD ;ONE WORD GLOBAL ?
|
||
IFSKP.
|
||
TLZ P4,770000 ;YES. 30 BITS, NO INDIRECTION OR INDEXING
|
||
ELSE.
|
||
TXNN P4,BP2 ;NO. 2 WORD B.P. ?
|
||
IFSKP.
|
||
XMOVEI P4,(T6) ;YES. GET ADDRESS
|
||
ELSE.
|
||
TLZ P4,777740 ;NO. ONE WORD LOCAL
|
||
TXO P4,<XMOVEI P4,> ;OBTAIN
|
||
XCT P4 ; ADDRESS
|
||
ENDIF.
|
||
ENDIF.
|
||
AOS P4 ;SINCE B.P. WAS AT END OF WORD
|
||
;Set up word count for shifting program.
|
||
MOVE P5,T1 ;GET BYTE COUNT
|
||
LSH P5,-2 ;CONVERT TO WORD COUNT
|
||
CALL PRG ;(P3,P4,P5)GO SHIFT AWAY
|
||
;Finish up.
|
||
MOVE P1,T1 ;UPDATE
|
||
LSH T1,-2 ; BYTE
|
||
CALL UPDBPW ; POINTERS (T1,T2,T3,T5,T6/T2,T3,T5,T6)
|
||
MOVE T1,P1 ;GET REMAINING
|
||
ANDI T1,3 ; BYTE COUNT
|
||
JRST BY8LP ;FINISH IT OFF
|
||
|
||
;Alteration table for the LSHC instruction in PRG.
|
||
PROT1: HRRI P3,-^D8
|
||
HRRI P3,-^D16
|
||
|
||
;Prototype 8 bit byte blt, where bytes are aligned, and source and destination
|
||
;are not in phase, and the destination position is 4.
|
||
;The E field of PROTO+3 will be be ^D12, -^D8 or -^D16
|
||
;The AC field of PROTO+4 will be be T1 or T2
|
||
;This routine, as written, will do the transfer for source position = 3.
|
||
;The low order 4 bits of the destination words will be randomized.
|
||
;P3/ address of source
|
||
;P4/ address of destination
|
||
;P5/ word count
|
||
;Uses P1-P5
|
||
;Assumes that the count is positive.
|
||
PROTO: DMOVE P1,(P3) ;GET SOME SOURCE
|
||
AOS P3 ;UPDATE SOURCE ADDRESS
|
||
LSH P1,-4 ;RIGHT JUSTIFY FIRST SOURCE WORD
|
||
LSHC P1,^D12 ;E FIELD FILLED IN AT RUN TIME - ALIGN SOURCE
|
||
MOVEM P1,(P4) ;AC FIELD FILLED IN AT RUN TIME - FILL DEST.
|
||
AOS P4 ;UPDATE DESTINATION ADDRESS
|
||
SOJG P5,PRG ;LOOP, THE TOP OF THIS ROUTINE IS REALLY PRG.
|
||
RET
|
||
LPRG==.-PROTO
|
||
ENDTV.
|
||
|
||
;pack 8 bit bytes into 36 bit words
|
||
;JRST IN36
|
||
;T1/ # of 8 bit bytes
|
||
;T2,T3/ 8 bit byte pointer
|
||
;T4/ # of 8 bit bytes
|
||
;T5,T6/ 36 bit byte pointer
|
||
;Indirection not permitted
|
||
;If a byte pointer passed to this routine is indexed, the index
|
||
;register must be T3 for the source, T6 for the destination.
|
||
;Uses P1-P5
|
||
;Returns +2 on success, with T1-T6 updated
|
||
;Returns +1 on failure (no room)
|
||
IN36: MOVE P4,T1 ;COMPUTE # OF WORDS
|
||
LSH P4,1 ; WORDS = BYTES * 2 / 9
|
||
IDIVI P4,11
|
||
ANDI P5,3 ;ANY REMAINDER ?
|
||
IFN. P5
|
||
AOS P4 ;YES. NEED ONE MORE WORD.
|
||
ENDIF.
|
||
CAMGE T4,T1 ;ENOUGH ROOM ?
|
||
RET ;NO.
|
||
SUB T4,T1 ;YES. UPDATE # OF 8 BIT BYTES LEFT IN BUFFER.
|
||
;Get destination address
|
||
TXNN T5,BP2 ;2 WORD B.P. ?
|
||
IFSKP.
|
||
XMOVEI P3,(T6) ;YES. GET ADDRESS
|
||
ELSE.
|
||
MOVE P3,T5 ;NO. ONE WORD
|
||
TLZ P3,777740 ; LOCAL, MASK OFF P & S
|
||
TXO P3,<XMOVEI P3,> ;OBTAIN
|
||
XCT P3 ; ADDRESS
|
||
ENDIF.
|
||
;update destination pointer
|
||
TXNN T5,BP2 ;2 WORD BYTE POINTER ?
|
||
IFSKP.
|
||
ADD T6,P4 ;YES. UPDATE IT.
|
||
ELSE.
|
||
HRRZ CX,T5 ;NO. UPDATE ONE WORD BYTE POINTER
|
||
ADD CX,P4
|
||
HRR T5,CX
|
||
ENDIF.
|
||
;loop
|
||
IN36A: SETZB P1,P2 ;INIT WORDS
|
||
MOVEI P5,11 ;ASSUME ENOUGH ROOM
|
||
CAIGE T1,11 ;ENOUGH ROOM FOR 2 WORDS OF BYTES ?
|
||
MOVE P5,T1 ;NO. GET SMALLER COUNT
|
||
;subloop
|
||
IN36B: LSHC P1,10 ;SHIFT BYTES
|
||
ILDB CX,T2 ;GET NEXT BYTE FROM NET BUFFER
|
||
DPB CX,[POINT 8,P2,35] ;STASH IT
|
||
SOJG P5,IN36B ;DO THEM ALL
|
||
SUBI T1,11 ;UPDATE REMAINING BYTE COUNT
|
||
IFL. T1 ;SOME ODD BYTES AT THE END ?
|
||
LSHC P1,-4 ;YES. ALIGN ODD WORD
|
||
MOVEM P2,(P3) ;STORE ODD WORD AND DONE.
|
||
ELSE.
|
||
DMOVEM P1,(P3) ;STORE BOTH WORDS
|
||
ADDI P3,2 ;INCREMENT DESTINATION POINTER
|
||
JUMPG T1,IN36A ;DO MORE IF NEEDED
|
||
ENDIF.
|
||
;end loop. update destination byte pointer
|
||
SETZ T1, ;WE TRANSFERRED ALL THOSE BYTES.
|
||
RETSKP ;ALL DONE
|
||
|
||
;unpack 36 bit bytes into 8 bit bytes
|
||
;JRST OUT36
|
||
;T1/ # of 8 bit bytes in the 36 bit byte buffer
|
||
;T2,T3/ 36 bit byte pointer
|
||
;T4/ size in words of 8 bit byte buffer
|
||
;T5,T6/ 8 bit byte pointer
|
||
;Returns +2 on success, with T1-T6 updated
|
||
;Returns +1 on failure (no room)
|
||
;Uses P1-P5
|
||
;Indirection not permitted
|
||
;If a byte pointer passed to this routine is indexed, the index
|
||
;register must be T3 for the source, T6 for the destination.
|
||
OUT36: STKVAR <WCNT>
|
||
MOVE P1,T1 ;Get request count
|
||
CAILE T1,^D9 ;If nine or less just transfer them
|
||
IFSKP.
|
||
SETZM WCNT ;All bytes transferred
|
||
ELSE.
|
||
IDIVI P1,^D9 ;Number of 8 bit bytes in two words
|
||
IMULI P1,^D9 ;Compute the number that fit on word boundary
|
||
EXCH P1,T1
|
||
SUB P1,T1 ;P1 will contain number we can't copy
|
||
MOVEM P1,WCNT ;Remember that
|
||
ENDIF.
|
||
;Get source address
|
||
TXNN T2,BP2 ;2 WORD B.P. ?
|
||
IFSKP.
|
||
XMOVEI P1,(T3) ;YES. GET ADDRESS
|
||
ELSE.
|
||
MOVE P1,T2 ;NO. ONE WORD
|
||
TLZ P1,777740 ; LOCAL, MASK OFF P & S
|
||
TXO P1,<XMOVEI P1,> ;OBTAIN
|
||
XCT P1 ; ADDRESS
|
||
ENDIF.
|
||
MOVE P2,T1 ;COMPUTE # OF WORDS
|
||
LSH P2,1 ; WORDS = BYTES * 2 / 9
|
||
IDIVI P2,11
|
||
ANDI P3,3 ;ANY REMAINDER ?
|
||
IFN. P3
|
||
AOS P2 ;YES. NEED ONE MORE WORD.
|
||
ENDIF.
|
||
CAMGE T4,T1 ;ENOUGH ROOM ?
|
||
RET ;NO.
|
||
SUB T4,T1 ;YES. UPDATE # OF 8 BIT BYTES LEFT IN BUFFER.
|
||
TXNN T2,BP2 ;2 WORD BYTE POINTER ?
|
||
IFSKP.
|
||
ADD T3,P2 ;YES. UPDATE IT.
|
||
ELSE.
|
||
HRRZ CX,T2 ;NO. UPDATE ONE WORD BYTE POINTER
|
||
ADD CX,P2
|
||
HRR T2,CX
|
||
ENDIF.
|
||
;outer loop
|
||
OUT36A: CAIL P2,2 ;HAVE AT LEAST 2 MORE WORDS?
|
||
IFSKP.
|
||
MOVE P3,(P1) ;NO. GET LAST WORD
|
||
SETZ P4, ;AND THE OTHER IS NULL.
|
||
MOVEI P5,5 ;5 MORE BYTES TO MOVE
|
||
ELSE.
|
||
DMOVE P3,(P1) ;GET TWO MORE WORDS
|
||
ADDI P1,2 ;INCREMENT
|
||
MOVEI P5,11 ;MOVE 9 BYTES
|
||
ENDIF.
|
||
SUBI P2,2 ;TAKE TWO WORDS WORTH OF BYTES.
|
||
;inner loop
|
||
OUT36B: ROTC P3,10 ;GET NEXT BYTE RIGHT JUSTIFIED
|
||
IDPB P4,T5 ;STORE IT
|
||
SOJG P5,OUT36B ;DO ALL BYTES
|
||
JUMPG P2,OUT36A ;GO DO MORE DATA
|
||
;finish up.
|
||
MOVE T1,WCNT ;Number of bytes we didn't transfer
|
||
RETSKP
|
||
ENDSV.
|
||
IFN FTOPS10,<PURGE P4,P5>
|
||
|
||
> ;END IFN FTBYTBLT
|
||
|
||
SUBTTL Buffers -- Copy user buffer to a message segment
|
||
|
||
;DNCU2M - Copy user buffer to a message segment
|
||
;
|
||
; Call:
|
||
; T1/ User Byte Count
|
||
; T2/ User Byte Pointer
|
||
; T3/ Optional second word of byte pointer, not implemented yet
|
||
; for user mode
|
||
; MS/ Pointer to current message segment
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS, WITH T2 CONTAINING UPDATED BYTE PTR
|
||
; ; AND T1 CONTAINING UPDATED BYTE COUNT
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
XRESCD
|
||
DNCU2M::TSTS6
|
||
TORESCD ;Run in section 1 because of PXCT
|
||
IFN FTOPS10,<
|
||
TXZ T2,1B12 ;DON'T ALLOW USER 2-WORD BPTs
|
||
LOAD T4,MDBYT,(MS) ;GET COUNT OF BYTES ALREADY IN MSG BLK
|
||
OPSTRM <ADDM T1,>,MDBYT,(MS) ;INCREMENT THE BYTE COUNT
|
||
JUMPG T4,DNCUM0 ;CAN'T BLT IF SOME ALREADY THERE
|
||
|
||
HLRZ T4,T2 ;GET P & S FIELDS OF USER BPT
|
||
CAIE T4,441000 ;IS IT A STANDARD 8-BIT PTR?
|
||
CAIN T4,341000 ;IN ANY OF THE 4 POSITIONS?
|
||
JRST DNCUMB ;YES, WE CAN BLT
|
||
CAIE T4,241000 ;TWO MORE
|
||
CAIN T4,141000 ; NORMAL ONES TO CHECK
|
||
JRST DNCUMB ;YES, WE CAN BLT
|
||
CAIN T4,041000 ;NO, STANDARD 'NEXT-WORD' BPT?
|
||
JRST [ TLO T2,400000 ;YES, MAKE IT 441000,,N+1
|
||
HRRI T2,1(T2) ; . . .
|
||
JRST DNCUMB] ;AND BLT THE DATA
|
||
DNCUM0:
|
||
>;END OF IFN FTOPS10
|
||
|
||
;Here if we must do a byte-wise copy
|
||
|
||
IFN FTOPS20,<OPSTRM <ADDM T1,>,MDBYT,(MS)> ;INCREMENT THE BYTE COUNT
|
||
|
||
LOAD T6,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
LOAD T5,MDPTR,(MS) ; AND THE DESTINATION BYTE POINTER
|
||
SKIPG T4,T1 ;SET UP THE DESTINATION BYTE COUNT
|
||
RET ;IF NON-POSITIVE, WE'RE DONE
|
||
DNCUM1: XCTBU [ILDB CX,T2] ;GET THE BYTE FROM USER BUFFER
|
||
IDPB CX,T5 ;PUT IT IN THE MESSAGE BLOCK
|
||
SOJG T1,DNCUM1 ;LOOP UNTIL DONE
|
||
STOR T5,MDPTR,(MS) ;STORE THE UPDATED BYTE POINTER
|
||
RET ;RETURN
|
||
|
||
IFN FTOPS10,<
|
||
;Here if we can BLT the user data
|
||
|
||
DNCUMB: HLLZ T4,T2 ;PICK UP ADJUSTED USER BPT'S P&S FIELDS
|
||
TLO T4,T6 ;MDAUX IS INDEXED BY T6
|
||
STOR T4,MDAUX,(MS) ;STORE NEW BEG-OF-MSG BYTE POINTER
|
||
MOVE T5,T1 ;GET BYTE LENGTH AGAIN
|
||
ADJBP T5,T4 ;FIGURE BYTE PTR AT END OF NEW DATA
|
||
STOR T5,MDPTR,(MS) ;STORE NEW END-OF-MSG BYTE POINTER
|
||
|
||
LDB T4,[POINT 3,T2,2] ;PICK UP WORD ALIGNMENT FROM BYTE POINTER
|
||
MOVNS T4 ;NEGATE
|
||
ADDI T4,7(T1) ;CALCULATE MESSAGE WORD COUNT
|
||
ASH T4,-2 ;...
|
||
IFN FTXMON,<
|
||
HRRZ T5,T2 ;SOURCE ADDR, USER ALWAYS IN SECTION 0
|
||
LOAD T6,MDALA,(MS) ;ALLOCATED ADDRESS OF MONITOR DATA BLK
|
||
XCT 2,[EXTEND T4,[XBLT]] ;COPY FROM USER TO MONITOR
|
||
>;END IFN FTXMON
|
||
IFE FTXMON,<
|
||
LOAD T5,MDALA,(MS) ;DESTINATION ADDR IN MONITOR SPACE
|
||
HRL T5,T2 ;SOURCE ADDR IN USER SPACE
|
||
ADDI T4,-1(T5) ;MAKE DEST END ADDRESS IN SECTION 0
|
||
XCT 1,[BLT T5,(T4)] ;COPY USER TO MONITOR
|
||
>;END IFE FTXMON
|
||
MOVE T4,T1 ;GET LENGTH (BYTES) AGAIN
|
||
ADJBP T4,T2 ;MAKE NEW USER BPT
|
||
MOVEM T4,T2 ;PUT BACK FOR CALLER
|
||
SETZM T1 ;UPDATED BYTE COUNT FOR CALLER
|
||
RET ;ONLY RETURN
|
||
>;END OF IFN FTOPS10
|
||
|
||
SUBTTL Buffers -- Copy message data to a user buffer
|
||
|
||
;DNCM2U - Copy message data to a user buffer
|
||
;
|
||
; Call:
|
||
; T1/ Count of bytes
|
||
; T2/ Pointer to data
|
||
; T3/ Optional second word of byte pointer
|
||
; MS/ Pointer to current message segment
|
||
;
|
||
; Return:
|
||
; RET ;IF LENGTH IS NOT CORRECT
|
||
; RETSKP ;ON SUCCESSFUL COPY WITH T1 AND T2 CONTAINING
|
||
; ; BYTE COUNT AND POINTER
|
||
;
|
||
; Uses: T1-T6
|
||
|
||
XRESCD ;Previous context executes run in section 1
|
||
DNCM2U::TSTS6
|
||
TORESCD
|
||
IFN DBGS2,<SAVEAC <T5,T6>> ;*LLMOP*
|
||
TXNE T2,1B12 ;2-WORD BYTE PTR?
|
||
HRR T2,T3 ;YES, MAKE LOCAL FOR OLD MACHINES
|
||
MOVE T4,T1 ;SET UP DESTINATION BYTE COUNT
|
||
DMOVE T5,T2 ;AND DESTINATION BYTE POINTER
|
||
OPSTR <CAMLE T1,>,MDBYT,(MS) ;MESSAGE BIG ENOUGH?
|
||
RET ;NO, LET CALLER DEAL WITH ERROR
|
||
MOVN T2,T1 ;SET UP NEGATIVE COUNT
|
||
OPSTRM <ADDM T2,>,MDBYT,(MS) ;UPDATE THE BYTE COUNT
|
||
LOAD T2,MDPTR,(MS) ;SET UP THE SOURCE BYTE POINTER
|
||
TLZE T2,17 ;IS MDPTR INDEXED?
|
||
TLO T2,T3 ;YES, USE T3, NOT T6
|
||
LOAD T3,MDALA,(MS) ;SET UP INDEX FOR MDPTR
|
||
JRST DNCMU2 ;START IN MIDDLE OF LOOP
|
||
DNCMU1: ILDB CX,T2 ;GET THE BYTE FROM MESSAGE BLOCK
|
||
XCTBU [IDPB CX,T5] ;PLACE BYTE IN USER BUFFER
|
||
DNCMU2: SOJGE T4,DNCMU1 ;DO UNTIL DONE
|
||
STOR T2,MDPTR,(MS) ;STOR THE UPDATED BP TO MESSAGE
|
||
MOVE T1,T4 ;UPDATE COUNT FOR CALLER
|
||
DMOVE T2,T5 ; ALSO POSSIBLY 2-WORD BYTE PTR
|
||
RETSKP ;RETURN SUCCESS
|
||
SUBTTL Core manager -- Smear a block of memory with value
|
||
;DNSWDS - Smear a value into a block of words
|
||
;
|
||
;Call: T1/ Address of start of block
|
||
; T2/ Address of end of block
|
||
; T3/ Value to put in block (typically zero)
|
||
; CALL DNSWDS
|
||
; Normal Return
|
||
;
|
||
;Changes T1,T2,T3,T4
|
||
|
||
INTERNAL DNSWDS
|
||
XRESCD
|
||
DNSWDS: MOVEM T3,(T1) ;STORE THE VALUE TO BE SMEARED
|
||
MOVE T3,T2 ;ADDR OF EO BLOCK INTO T3
|
||
MOVE T2,T1 ;ADDR OF BEG OF BLK INTO T2
|
||
SUBM T3,T1 ;NUMBER OF WORDS TO COPY INTO T1
|
||
XMOVEI T3,1(T2) ;CALC SMEARING DESTINATION ADDR
|
||
CAILE T1,VBLSIZ ;IS THIS A LEGITIMATE SMEAR?
|
||
BUG.(CHK,COMSTB,D36COM,SOFT,<Smear request too big>,,<
|
||
|
||
Cause: The caller has requested that a very large block be smeared.
|
||
|
||
Action: Find out what the caller really wanted to smear and fix the call.
|
||
|
||
>,DNSWD1)
|
||
CALLRET XBLTAT ;(T1,T2,T3)COPY MONITOR TO MONITOR
|
||
|
||
DNSWD1: MOVEI T1,VBLSIZ ;TRY TO RECOVER FROM OVERSIZE SMEAR
|
||
CALLRET XBLTAT ;(T1,T2,T3)COPY MONITOR TO MONITOR
|
||
SUBTTL Core manager -- Copy some words
|
||
|
||
;DNCPYW - Copy words using a BLT or a XBLT
|
||
;
|
||
; Call:
|
||
; T1/ From
|
||
; T2/ To
|
||
; T3/ Count
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
; Uses:
|
||
|
||
INTERNAL DNCPYW
|
||
XRESCD
|
||
DNCPYW: EXCH T1,T3 ;CHANGE TO T1/COUNT, T2/TO, T3/FROM
|
||
EXCH T2,T3 ;CHANGE TO T1/COUNT, T2/FROM, T3/TO
|
||
CALLRET XBLTAT ;(T1,T2,T3)COPY MONITOR TO MONITOR
|
||
SUBTTL Core manager -- Get Some Words
|
||
|
||
;DNGWDP - Get memory-Lowest priority - process context
|
||
;DNGWDN - Get memory-normal priority
|
||
;DNGWDH - Get memory-Highest priority
|
||
;DNGWDS - Get some words, not zeroed
|
||
;
|
||
; Call:
|
||
; T1/ Count of words we want
|
||
;
|
||
; Return:
|
||
; RET ;ON ALLOCATION FAILURE
|
||
; RETSKP ;WITH T1 POINTING TO WORDS
|
||
;
|
||
;
|
||
;Note: The count of words allocated is stored in the word before the
|
||
;returned pointer.
|
||
|
||
XRESCD
|
||
DNGWDS::
|
||
|
||
IFE FTD36MM,<
|
||
IFN FTOPS20,<
|
||
DNGWDH::MOVEI T2,.RESP1 ;Get memory-High priority
|
||
JRST GTWRDS
|
||
DNGWDN::SKIPA T2,[.RESP2] ;Get memory-normal priority
|
||
DNGWDP::MOVEI T2,.RESP3 ;Get memory-Process context (process can be
|
||
; descheduled)
|
||
>
|
||
IFN FTOPS10,<
|
||
DNGWDH::
|
||
DNGWDN::
|
||
DNGWDP::
|
||
>>
|
||
IFN FTD36MM,<
|
||
DNGWDH::
|
||
DNGWDN::
|
||
DNGWDP::
|
||
>
|
||
GTWRDS:
|
||
SAVEAC <P1,T6> ;NOTE - THIS ROUTINE "KNOWS" HOW MANY ACS ARE
|
||
; SAVED, AND USES THIS KNOWLEDGE TO LOOK AT
|
||
; THE STACK. SEE FTLSTCORE.
|
||
IFE FTD36MM,<
|
||
IFN FTOPS20,<
|
||
STKVAR <MEMPRI> ; Priority to get memory from ASGRES
|
||
MOVEM T2,MEMPRI ; Save it
|
||
>>
|
||
HRRZ P1,T1 ;SAVE THE COUNT
|
||
MOVEI T2,1(T1) ;T2 GETS NUMBER OF WORDS.
|
||
IFN FTLSTCOR, ADDI T2,2 ;Overhead for check words
|
||
IFN FTD36MM,<
|
||
OPSTR <CAMLE T2,>,CHSIZ,+VBLCB ;WILL A LARGE A-BLOCK SATISFY REQUEST?
|
||
BUG.(CHK,COMATB,D36COM,SOFT,<A-Block request too big>,,<
|
||
|
||
Cause: For the time being, until we get a real memory-manager for non
|
||
message-block requests, we only support requests for memory
|
||
up to the size of a VBL block, see DEFBLK macro.
|
||
|
||
Action: Wait for the real memory manager or make the size of VBLs bigger
|
||
than they are now.
|
||
|
||
>,RTN)
|
||
> ;End FTD36MM
|
||
IFN FTHMMEM,<
|
||
SKIPN T6,MRQTAB ; Get address of our memory request table
|
||
IFSKP.
|
||
ADD T6,P1 ; Index by request amount
|
||
CAML T6,MRQMAX ; Have we goone too far?
|
||
IFSKP.
|
||
AOS (T6) ; Increment the count of requests this size
|
||
HRRZ T3,(T6) ; Get current outstanding requests
|
||
HLRZ T4,(T6) ; Get the previous high water mark
|
||
CAMLE T3,T4 ; Is this higher?
|
||
HRLM T3,(T6) ; Yes, it becomes new high water mark
|
||
ENDIF.
|
||
ENDIF.
|
||
> ;END FTHMMEM
|
||
IFN FTD36MM,<
|
||
XMOVEI T1,VBLCB
|
||
OPSTR <CAMG T2,>,CHSIZ,+LBLCB ;SEE IF IT MIGHT BE A LARGE BLOCK
|
||
XMOVEI T1,LBLCB ;YES, POINTER TO CH FOR LARGE A-BLOCKS
|
||
OPSTR <CAMG T2,>,CHSIZ,+BBLCB ;HOW ABOUT A LARGE-MEDIUM BLOCK?
|
||
XMOVEI T1,BBLCB ;YES, POINTER TO CH FOR LARGE-MEDIUM A-BLOCKS
|
||
OPSTR <CAMG T2,>,CHSIZ,+ABLCB ;HOW ABOUT A MEDIUM BLOCK?
|
||
XMOVEI T1,ABLCB ;YES, POINTER TO CH FOR MEDIUM A-BLOCKS
|
||
OPSTR <CAMG T2,>,CHSIZ,+SBLCB ;HOW ABOUT A SMALL BLOCK?
|
||
XMOVEI T1,SBLCB ;YES, POINTER TO CH FOR SMALL A-BLOCKS
|
||
STOR P1,CHREQ,(T1) ;;; Remember amount requested
|
||
CALL DNGRBL ;ALLOCATE AN A-BLOCK (DON'T ZERO IT)
|
||
RET ;TELL CALLER WE LOST
|
||
>;END IFN FTD36MM
|
||
IFE FTD36MM,<
|
||
IFN FTOPS20,<
|
||
MOVE T1,T2 ; Number of words needed
|
||
HRL T1,MEMPRI ; Use priority requested by user
|
||
MOVEI T2,.RESNP ; from the DECnet extended pool
|
||
XCALL (MSEC1,ASGRES)
|
||
> ;End FTOPS20
|
||
IFN FTOPS10,<
|
||
MOVEI T3,DCNACB## ; Get DECnet allocation control block
|
||
MCALL (RG,MSEC1,GTXWDS##) ; Go allocate memory
|
||
>
|
||
RET ; Tell caller we failed to get memory
|
||
>;END IFE FTD36MM
|
||
IFN FTLSTCOR,<
|
||
IFE FTD36MM!FTOPS10,<
|
||
MOVE T2,-6(P) ;STKVAR uses 2 more
|
||
CAMN T2,[XADDR. DNGTAG] ;IS THIS A CALL FROM GET ZERO WORDS?
|
||
MOVE T2,-11(P) ;YES, GET ADDRESS OF HIS CALLER
|
||
>
|
||
IFN FTD36MM!FTOPS10,<
|
||
MOVE T2,-3(P) ;GET CALLING PC
|
||
CAMN T2,[XADDR. DNGTAG] ;IS THIS A CALL FROM GET ZERO WORDS?
|
||
MOVE T2,-6(P) ;YES, GET ADDRESS OF HIS CALLER
|
||
>
|
||
MOVEM T2,(T1) ;SAVE CALLER'S PC AT START OF BLOCK
|
||
AOJ T1, ;POINT PAST WHERE WE SAVED THE PC
|
||
> ;END IFN FTLSTCOR
|
||
MOVEM P1,(T1) ;STORE COUNT IN RH OF OVERHEAD WORD
|
||
MOVSI T2,'D36' ;MAKE A TEST THINGY
|
||
HLLM T2,(T1) ;STORE IN LEFT HALF OF FIRST WORD
|
||
AOJ T1, ;RETURN POINTER TO USER PART OF BLOCK
|
||
IFN FTLSTCOR,<
|
||
MOVE T2,T1 ; Get address of user data
|
||
ADD T2,P1 ; Point to 1 word past end of requested buffer
|
||
MOVE T3,['D36COM'] ; Get value to check against
|
||
MOVEM T3,(T2) ; Write value into last word in block
|
||
> ;End IFN FTLSTCOR
|
||
RETSKP ;RETURN SUCCESS
|
||
ENDSV.
|
||
SUBTTL Core manager -- Get Some Zeroed Words
|
||
|
||
;DNGWDZ - Just like DNGWDS but the words are smeared to zero.
|
||
; Note that this is quite a lot more expensive than DNGWDS.
|
||
;
|
||
; Call:
|
||
; T1/ Count of words we want
|
||
;
|
||
; Return:
|
||
; RET ;ON ALLOCATION FAILURE
|
||
; RETSKP ;WITH T1 POINTING TO WORDS
|
||
;
|
||
; Uses: T1-T4
|
||
;
|
||
;Note: The count of words allocated is stored in the word before the
|
||
;returned pointer.
|
||
|
||
XRESCD
|
||
DNGWDZ::
|
||
|
||
IFE FTD36MM,<
|
||
IFN FTOPS20,<
|
||
DNGWZH::MOVEI T2,.RESP1
|
||
JRST DNGWZ1
|
||
DNGWZN::SKIPA T2,[.RESP2]
|
||
DNGWZP::MOVEI T2,.RESP3
|
||
>
|
||
IFN FTOPS10,<
|
||
DNGWZH::
|
||
DNGWZN::
|
||
DNGWZP::
|
||
>>
|
||
IFN FTD36MM,<
|
||
DNGWZH::
|
||
DNGWZN::
|
||
DNGWZP::
|
||
>
|
||
DNGWZ1: SAVEAC P1 ;TO HOLD THE COUNT
|
||
;(NOTE, GTWRDS KNOWS HOW MANY ACS ARE SAVED)
|
||
MOVE P1,T1 ;SAVE THE COUNT
|
||
CALL GTWRDS ;GET SOME WORDS
|
||
DNGTAG: RET ;PROPOGATE ERROR RETURN
|
||
;Zero the words.
|
||
MOVE T2,T1 ;ADDRESS OF BLOCK
|
||
ADDI T2,-1(P1) ;POINT TO LAST WORD IN BLOCK
|
||
SETZ T3, ;WHAT TO SMEAR IT WITH
|
||
MOVE P1,T1 ;SAVE ADDRESS OF BLOCK
|
||
CALL DNSWDS ;SMEAR ZEROES INTO BLOCK
|
||
MOVE T1,P1 ;RESTORE ADDRESS OF BLOCK FOR CALLER
|
||
RETSKP ; AND GIVE GOOD RETURN
|
||
SUBTTL Core manager -- Free Some Words
|
||
|
||
;DNFWDS - Free what DNGWDS took away
|
||
;
|
||
; Call:
|
||
; T1/ Pointer to words allocated by DNGWDS
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
;
|
||
; Uses: T1,T2
|
||
|
||
INTERNAL DNFWDS
|
||
XRESCD
|
||
DNFWDS: SOSG T1 ;POINT T1 TO HEADER WORD
|
||
BUG.(CHK,COMFWZ,D36COM,SOFT,<Tried to free words at zero>,,<
|
||
|
||
Cause: DNFWDS was called with a 0 pointer.
|
||
|
||
Action: Find the caller on the stack and determine why it has no valid
|
||
pointer to free space.
|
||
>,RTN)
|
||
|
||
HLRZ T3,(T1) ;GET THINGY TO CHECK AGAINST.
|
||
CAIN T3,'D36' ;IS IT WHAT WE PUT THERE?
|
||
IFSKP.
|
||
MOVE T2,(P) ; Get caller's address
|
||
BUG.(HLT,COMMMS,D36COM,SOFT,<Bad pointer passed to memory manager>,<<T1,BUFFER>,<T2,CALLER>>,<
|
||
|
||
Cause: When DNGWDS gives out a block of memory, a check word is left
|
||
right before the first word of memory given to the user. This
|
||
word contains the length of the block in the right half, and a "check"
|
||
quantity in the left to verify that this block is what is expected.
|
||
This bug means that this word has either been trashed, or the
|
||
pointer we have been passed is bad.
|
||
|
||
Action: First determine if the pointer is bad, if the check word is trashed,
|
||
or if the check word is 63D. If the check word is 63D the memory has
|
||
already been returned and we are trying to return it again. If the
|
||
check word is trashed then possible the owner trashed it or the user
|
||
of the memory block previous to this one wrote too far. If FTD36MM=0
|
||
then the owner of the memory block is recorded in the block's header.
|
||
For more detail see FREE.MAC.
|
||
|
||
Data: BUFFER - Address of faulty buffer
|
||
CALLER - Address of caller that provided the buffer
|
||
|
||
>,RTN)
|
||
ENDIF.
|
||
MOVEI T2,'63D' ; Destroy check word left half
|
||
HRLM T2,(T1) ; in case freed more than once
|
||
HRRZ T2,(T1) ;GET COUNT OF WORDS BEING RETURNED
|
||
IFN FTLSTCOR,<
|
||
MOVE T3,T1 ; Get address of current position in block
|
||
ADDI T3,1(T2) ; Point to first free location after requested
|
||
MOVE T3,(T3) ; Get test string
|
||
CAMN T3,['D36COM'] ; Does it match?
|
||
IFSKP.
|
||
MOVE T3,-1(T1) ; Get owner's PC
|
||
BUG. (CHK,COMCWT,D36COM,SOFT,<Check word trashed>,<<T1,MEMADR>,<T3,OWNER>>,<
|
||
|
||
Cause: DNFWDS called with memory to return that had check word at end of
|
||
requested buffer trashed.
|
||
|
||
Action: See what routine called with the bad block and find out why the
|
||
check word was smashed.
|
||
>)
|
||
ENDIF.
|
||
> ;End IFN FTLSTCOR
|
||
|
||
IFN FTHMMEM,<
|
||
SKIPN T3,MRQTAB ;Pointer to request table
|
||
IFSKP.
|
||
ADD T3,T2 ;Index to proper place
|
||
CAMGE T3,MRQMAX ;Be sure we don't go too far
|
||
SOS (T3) ; and decrement request count
|
||
ENDIF.
|
||
> ;END FTHMMEM
|
||
AOJ T2, ;ADD IN WORD OF OVERHEAD
|
||
IFN FTLSTCORE,<
|
||
ADDI T2,2 ;Account for check words
|
||
SOJ T1, ;DECREMENT POINTER TO OUR BLOCK.
|
||
SETZM (T1) ;ERASE NAME OF OWNER OF BLOCK
|
||
>;END IFN FTLSTCORE
|
||
IFN FTD36MM,<
|
||
MOVE T3,T2 ;COPY SIZE OF RETURNING BLOCK
|
||
XMOVEI T2,VBLCB ;ASSUME LARGEST BLOCK SIZE
|
||
OPSTR <CAMG T3,>,CHSIZ,+LBLCB ;SEE IF IT MIGHT BE A LARGE BLOCK
|
||
XMOVEI T2,LBLCB ;YES, POINTER TO CH FOR LARGE A-BLOCKS
|
||
OPSTR <CAMG T3,>,CHSIZ,+BBLCB ;HOW ABOUT A LARGE-MEDIUM BLOCK?
|
||
XMOVEI T2,BBLCB ;YES, POINTER TO CH FOR LARGE-MEDIUM A-BLOCKS
|
||
OPSTR <CAMG T3,>,CHSIZ,+ABLCB ;HOW ABOUT A MEDIUM BLOCK?
|
||
XMOVEI T2,ABLCB ;YES, POINTER TO CH FOR MEDIUM A-BLOCKS
|
||
OPSTR <CAMG T3,>,CHSIZ,+SBLCB ;HOW ABOUT A SMALL BLOCK?
|
||
XMOVEI T2,SBLCB ;YES, POINTER TO CH FOR SMALL A-BLOCKS
|
||
CALLRET DNFRBL ;T1/ BLOCK TO FREE, T2/ CH BLOCK TO PUT IT ON
|
||
>;END IFN FTD36MM
|
||
|
||
IFE FTD36MM,<
|
||
IFN FTOPS20,<
|
||
XCALLRET (MSEC1,RELRES) ;Release memory
|
||
>
|
||
IFN FTOPS10,<
|
||
EXCH T1,T2 ;CORE1 WANTS T1/COUNT, T2/ADDRESS
|
||
MOVEI T3,DCNACB## ;GET ADDRESS OF DECNET ALLOCATION CONTROL BLOCK
|
||
MCALL (RG,MSEC1,GVXWDS##) ;LET GO OF OUR CORE.
|
||
RET
|
||
>
|
||
>;END IFE FTD36MM
|
||
SUBTTL Core manager -- Get a DECnet-36 message block
|
||
;DNGMSG - Get a virgin message block and enough user data space for us
|
||
;
|
||
;Call:
|
||
; T1/ Number of user data bytes needed.
|
||
;Return
|
||
; RET ;ON ALLOCATION FAILURE
|
||
; RETSKP ;T1 POINTS TO MESSAGE BLOCK, AND UD.MSD POINTS
|
||
; ; TO USER DATA FIELD, WHEREVER ALLOCATED
|
||
|
||
XRESCD
|
||
DNGMSG::
|
||
TRACE COM,Getting virgin message
|
||
SAVEAC P1
|
||
MOVE P1,T1 ;SAVE COUNT OF USER DATA BYTES REQ'D
|
||
XMOVEI T1,MBLCB ;POINTER TO CH FOR MESSAGE BLOCKS
|
||
CALL DNGRBL ;(T1/T1)GO GET THE BLOCK
|
||
RET ;COULDN'T GET IT, RETURN AN ERROR
|
||
IFN FTLSTCOR,<
|
||
MOVE T2,-2(P) ;GET CALLER'S PC
|
||
MOVEM T2,(T1) ;PUT INTO FIRST HEADER WORD
|
||
MOVE T2,['D36MSG'] ;PUT TEST THING
|
||
MOVEM T2,1(T1) ; IN SECOND HEADER WORD
|
||
ADDI T1,2 ;POINT PAST HEADER WORDS
|
||
>;END IFN FTLSTCOR
|
||
MOVE T2,P1 ;GET BACK NUMBER OF USER BYTES DESIRED
|
||
MOVE P1,T1 ;SAVE ADDR OF BLOCK
|
||
SETZRO MDALA,+UD.MSD(P1) ;TELL DNMINI WE HAVE NO USER DATA NOW
|
||
CALL DNMINI ;(T1,T2)MAKE THE MSG BLK SHINY NEW
|
||
JRST DNGMS1 ;ERROR. RETURN MESSAGE BLOCK FIRST
|
||
MOVE T1,P1 ;PUT MB ADDRESS WHERE USER CAN FIND IT
|
||
RETSKP ;GOOD RETURN, TELL CALLER WE WON
|
||
|
||
DNGMS1: MOVE T1,P1 ;GET ADDR OF MSG BLOCK WE WANT TO RETURN
|
||
|
||
IFN FTLSTCOR,<
|
||
SUBI T1,2 ;POINT TO START OF BLOCK
|
||
HLRZ T2,1(T1) ;GET TEST THING
|
||
CAIN T2,'D36' ;TEST IT.
|
||
IFSKP.
|
||
MOVE T2,(T1) ;FAILED. GET ALLOCATOR'S ADDRESS
|
||
MOVE T3,1(T1) ;GET TEST THING
|
||
MOVE T4,-2(P) ;GET CALLER'S PC
|
||
BUG.(HLT,COMMS3,D36COM,SOFT,<Bad pointer passed to memory manager>,<<T1,BLKADR>,<T2,ALCADR>,<T3,TESTWD>,<T4,CALLER>>,<
|
||
|
||
Cause: A header word is trashed or there is a bad pointer.
|
||
|
||
Action: Check DNMINI to see why it trashed the check word
|
||
|
||
Data: BLKADR - Block address
|
||
ALCADR - Address of allocator
|
||
TESTWD - Test thing
|
||
CALLER - Address of caller to memory management
|
||
>)
|
||
RET
|
||
ENDIF.
|
||
SETZM 1(T1) ;CLEAR TEST THING.
|
||
SETZM (T1) ;CLEAR ALLOCATOR'S PC
|
||
>;END IFN FTLSTCOR
|
||
|
||
XMOVEI T2,MBLCB ;POINTER TO CH FOR MESSAGE BLOCKS
|
||
CALLRET DNFRBL ;RELEASE THE BLOCK, AND GIVE BAD RETURN
|
||
;Get emergency message block. Same as DNGMSG except it BUGs on failure.
|
||
|
||
INTERNAL DNGEMS
|
||
XRESCD
|
||
DNGEMS:
|
||
TRACE COM,Getting virgin emergency buffer
|
||
SAVEAC P1
|
||
MOVE P1,T1 ;SAVE NUMBER OF USER DATA BYTES NEEDED
|
||
XMOVEI T1,MBLCB ;POINTER TO CH FOR MESSAGE BLOCKS
|
||
CALL DNGRBP ;GET BLOCK, PRIV'D TO USE EMERGENCY BLKS
|
||
RET ;PROPOGATE ERROR RETURN, CALLER WILL BUG
|
||
IFN FTLSTCOR,<
|
||
MOVE T2,-2(P) ;GET CALLER'S PC
|
||
MOVEM T2,(T1) ;PUT INTO FIRST HEADER WORD
|
||
MOVE T2,['D36EMS'] ;PUT TEST THING
|
||
MOVEM T2,1(T1) ; IN SECOND HEADER WORD
|
||
ADDI T1,2
|
||
>;END IFN FTLSTCOR
|
||
MOVE T2,P1 ;GET BACK NUMBER OF USER BYTES DESIRED
|
||
MOVE P1,T1 ;SAVE ADDR OF BLOCK HERE, JUST IN CASE
|
||
SETZRO MDALA,+UD.MSD(P1) ;TELL DNMINI WE HAVE NO USER DATA NOW
|
||
CALL DNMINP ;PRIV'D ENTRY TO GET USER-DATA BUFFER
|
||
RET ;PROPOGATE ERROR RETURN, CALLER WILL BUG
|
||
SETONE MBEBF,(P1) ;MARK THIS AS AN EMERGENCY BUFFER FOR ROUTER
|
||
MOVE T1,P1 ;PUT MB ADDRESS WHERE USER CAN FIND IT
|
||
RETSKP ;GOOD RETURN, TELL CALLER WE WON
|
||
SUBTTL Core manager -- Free a DECnet-36 message block
|
||
;DNFMSG - Give back what DNGMSG gave us
|
||
;
|
||
;Call
|
||
; T1/ Pointer to message block to return
|
||
;Return
|
||
; RET ;ALWAYS
|
||
;
|
||
;Note - If MDALA points to other than UD.DAT we will assume that MDALA
|
||
; is a pointer to a separate user data block, and we will return
|
||
; that block as well.
|
||
|
||
INTERNAL DNFMSG
|
||
XRESCD
|
||
DNFMSG:
|
||
IFN FTPARANOID,<
|
||
CAML T1,MBLCB ;THIS MUST COME FROM THE MBL BLOCKS
|
||
IFSKP.
|
||
MOVE T2,0(P) ;IT DIDN'T. CALLER'S PC
|
||
BUG.(HLT,COMMPR,D36COM,SOFT,<Message pointer check>,<<T1,ACLADR>,<T2,CALLER>>,<
|
||
|
||
Cause: DNFMSG caller tried to return a piece of memory not in the
|
||
range of message blocks.
|
||
|
||
Action: See stack for caller and find why it is trying to return
|
||
a bad message block.
|
||
|
||
>)
|
||
RET
|
||
ENDIF.
|
||
>;END IFN FTPARANOID
|
||
|
||
IFN FTLSTCOR,<
|
||
SUBI T1,2 ;POINT TO START OF BLOCK
|
||
HLRZ T2,1(T1) ;GET TEST THING
|
||
CAIN T2,'D36' ;TEST IT
|
||
IFSKP.
|
||
MOVE T2,(T1) ;FAILED. GET ALLOCATOR'S ADDRESS
|
||
MOVE T3,1(T1) ;TEST THING
|
||
MOVE T4,0(P) ;CALLER'S PC
|
||
BUG.(HLT,COMMS1,D36COM,SOFT,<Bad pointer passed to memory manager>,<<T1,BLKADR>,<T2,ALCADR>,<T3,TESTWD>,<T4,CALLER>>,<
|
||
|
||
Cause: A header word is trashed or there is a bad pointer.
|
||
|
||
Data: BLKADR - Address of memory block
|
||
ALCADR - Allocator's address
|
||
TESTWD - Test Word
|
||
CALLER - Caller to memory management
|
||
>)
|
||
RET
|
||
ENDIF.
|
||
ADDI T1,2 ;GET PAST THE HEADER WORDS
|
||
>;END IFN FTLSTCOR
|
||
|
||
XMOVEI T2,UD.DAT(T1) ;GET EXTENDED POINTER TO UD.DAT
|
||
OPSTR <SKIPE T3,>,MDALA,+UD.MSD(T1) ;GET ALLOCATED ADDRESS OF USER DATA
|
||
CAMN T3,T2 ;IF MDALA ISN'T US, RELEASE HIM
|
||
JRST DNFMS0 ;THE UBL IS NOT SEPARATE, JUST RELEASE MBL
|
||
PUSH P,T1 ;SAVE POINTER TO MBL
|
||
MOVE T1,T3 ;POINTER TO SEPARATE USER-DATA BLOCK
|
||
IFN FTLSTCOR,<
|
||
SUBI T1,2 ;POINT TO START OF BLOCK
|
||
HLRZ T2,1(T1) ;GET TEST THING
|
||
CAIN T2,'D36' ;TEST IT.
|
||
IFSKP.
|
||
MOVE T2,(T1) ;FAILED. GET ALLOCATOR'S ADDRESS
|
||
MOVE T3,1(T1) ;TEST THING
|
||
MOVE T4,-1(P) ;CALLER'S PC
|
||
BUG.(HLT,COMMS2,D36COM,SOFT,<Bad pointer passed to memory manager>,<<T1,BLKADR>,<T2,ALCADR>,<T3,TESTWD>,<T4,CALLER>>,<
|
||
|
||
Cause: A header word is trashed or there is a bad pointer.
|
||
|
||
Data: BLKADR - Address of memory block
|
||
ALCADR - Allocator's address
|
||
TESTWD - Test Word
|
||
CALLER - Caller to memory management
|
||
>)
|
||
POP P,T1
|
||
RET
|
||
ENDIF.
|
||
SETZM 1(T1) ;CLEAR TEST THING.
|
||
SETZM (T1) ;CLEAR ALLOCATOR'S PC
|
||
>;END IFN FTLSTCOR
|
||
|
||
XMOVEI T2,UBLCB ;POINTER TO CH FOR USER DATA BLOCKS
|
||
CALL DNFRBL ;RELEASE THE USER-DATA BLOCK
|
||
POP P,T1 ;GET BACK POINTER TO MESSAGE BLOCK
|
||
DNFMS0:
|
||
|
||
IFN FTLSTCOR,<
|
||
SUBI T1,2 ;THE HEADER WORDS
|
||
SETZM (T1) ;CLEAR ALLOCATOR'S ADDRESS
|
||
SETZM 1(T1) ;CLEAR TEST THING
|
||
>;END IFN FTLSTCOR
|
||
|
||
XMOVEI T2,MBLCB ;POINTER TO CH FOR MESSAGE BLOCKS
|
||
CALLRET DNFRBL ;FREE THE MESSAGE BLOCK ITSELF
|
||
SUBTTL Core manager -- Fixed size block allocation entry points
|
||
|
||
repeat 0, < ;DNGEBL and DNFEBL will be removed completely when code is proven
|
||
|
||
;DNGEBL - Get an event block
|
||
;DNGEBP - (Doesn't exist)
|
||
;
|
||
;Call:
|
||
;
|
||
;Return:
|
||
; RET ;ON ALLOCATION FAILURE
|
||
; RETSKP ;WITH T1 POINTING TO BLOCK
|
||
|
||
DNGEBL::XMOVEI T1,EBLCB ;POINTER TO CH FOR EVENT BLOCKS
|
||
CALLRET DNGRBL ;ALLOCATE THE BLOCK (DON'T ZERO IT)
|
||
;DNFEBL - Free an event data block
|
||
;Call
|
||
; T1/ Pointer to block to be returned to free pool
|
||
;Return
|
||
; RET ;Always.
|
||
;
|
||
;DNFEBL is called by NTMAN
|
||
|
||
DNFEBL::XMOVEI T2,EBLCB ;POINTER TO CH FOR EVENT BLOCKS
|
||
CALLRET DNFRBL ;DE-ALLOCATE THE BLOCK
|
||
> ;End repeat 0
|
||
|
||
SUBTTL Core manager -- Memory manager initialization code
|
||
|
||
;DNINIM - Initialize fixed core block memory manager.
|
||
;Call:
|
||
;
|
||
;Return:
|
||
; RET always.
|
||
|
||
XSWAPCD
|
||
DNINIM::
|
||
IFN FTOPS10,<
|
||
SAVEAC <T5,T6,P1> ;GET US A FEW PRESERVED REGISTERS
|
||
MOVE T1,DCNVFF ;GET POINTER TO DECNET CORE
|
||
>;END IFN FTOPS10
|
||
|
||
IFN FTOPS20,<
|
||
SAVEAC <T5,T6,P1,P2> ;GET US A FEW PRESERVED REGISTERS
|
||
MOVSI T1,DNBSE1 ;GET BUFFER ADDRESS (START OF DECnet SECTION)
|
||
MOVE P2,T1 ;SAVE START OF BUFFER ALLOCATION
|
||
>;END IFN FTOPS20
|
||
|
||
|
||
;T1 contains pointer to next available word of pool
|
||
;P1 contains length of memory init table CHBLKN
|
||
|
||
MOVX P1,CHBLKN ;POINT PAST END OF CH BLOCKS
|
||
DNINM2: SOJL P1,DNINM4 ;POINT TO PREVIOUS CH BLOCK
|
||
MOVE T3,P1 ;WHICH CH ARE WE WORKING ON
|
||
IMULI T3,CH.LEN ;POINTER TO WHICH CH WITHIN CHBLKS
|
||
XMOVEI T4,CHBLKS ;POINTER TO CHBLKS VECTOR
|
||
ADD T4,T3 ;POINTER TO OUR CURRENT CH BLOCK
|
||
LOAD T6,CHNUM,(T4) ;GET NUMBER OF BLOCKS FOR THIS TYPE
|
||
STOR T6,CHAVL,(T4) ;SAVE NUMBER OF BLOCKS AVAILABLE
|
||
JUMPLE T6,DNINM2 ;(JUST IN CASE OF DEFINING 0 BLOCKS FOR A TYPE)
|
||
LOAD T5,CHSIZ,(T4) ;GET SIZE OF BLOCKS FOR THIS TYPE
|
||
IFN FTFIXCOR,<
|
||
CALL DNINCH ;(T1/T1)CHECK THAT BLOCK STAYS ON PAGE
|
||
>; End of FTFIXCOR
|
||
STOR T1,CHBOT,(T4) ;SAVE START OF POOL FOR THIS TYPE OF BLOCKS
|
||
STOR T1,CHPTR,(T4) ;SAVE POINTER TO FIRST FREE BLOCK
|
||
DNINM3: MOVE T2,T1 ;SAVE POINTER TO BLOCK
|
||
ADD T1,T5 ;POINT TO NEXT BLOCK
|
||
IFN FTFIXCOR,<
|
||
CALL DNINCH ;(T1/T1)CHECK THAT BLOCK STAYS ON PAGE
|
||
>; End of IFN FTFIXCOR
|
||
STOR T1,FBNXT,(T2) ;STORE POINTER TO NEXT BLOCK
|
||
SOJG T6,DNINM3 ;DO ANOTHER BLOCK
|
||
SETZRO FBNXT,(T2) ;LAST BLOCK HAS END OF LIST INSTEAD OF POINTER
|
||
JRST DNINM2 ;GO DO ANOTHER TYPE OF CORE BLOCK
|
||
|
||
DNINM4:
|
||
|
||
IFN FTOPS10,<
|
||
MOVEM T1,DCNVFF ;SAVE ADDRESS OF DECNET FIRST FREE
|
||
>; END IFN FTOPS10
|
||
IFN FTOPS20,< ;LOCK DOWN THE PAGES WE'VE JUST ALLOCATED
|
||
MOVE P1,T1 ;SAVE FINAL ADDRESS IN P1
|
||
TLZ P1,-1 ;CLEAR ANY SECTION NUMBER
|
||
ADDI P1,777 ;ROUND UP TO FULL PAGE
|
||
LSH P1,-11 ;CONVERT TO NUMBER OF PAGES
|
||
MOVE T1,P2 ;GET BACK ADDRESS OF START OF ALLOCATION
|
||
XCALL (MSEC1,FPTA) ;GET THE PAGE TABLE
|
||
MOVEM T1,P2 ;SAVE FIRST PAGE NUMBER
|
||
DNINM6: XCALL (MSEC1,MLKPG) ;LOCK THE PAGE IN MEMORY
|
||
AOS T1,P2 ;STEP TO NEXT PAGE
|
||
SOJG P1,DNINM6 ;LOCK IT TOO IF ITS NEEDED
|
||
>;END IFN FTOPS20
|
||
IFN FTHMMEM,<
|
||
MOVEI T1,VBLSIZ ;Reserve a very large block for memory request
|
||
CALL DNGWDS ; table
|
||
SETZ T1, ;
|
||
MOVEM T1,MRQTAB ;Save for DNGWDS/DNFWDS
|
||
> ;END FTHMMEM
|
||
CALL DNNMSG ;(/T1)RETURN LESSER OF # MBLs & # UBLs
|
||
MOVEM T1,DCNTSB ;STORE AS TOTAL SYSTEM BUFFERS
|
||
CALLRET CHKCNG ;(T1)CHECK CONGESTION THRESHOLDS
|
||
|
||
;Local subroutine to check that a block is wholly contained in a page
|
||
;only called from DNINIM, right here.
|
||
; T1/ Proposed starting address of new block
|
||
; T5/ Length of new block
|
||
|
||
;Preserves T2,T4,T5,T6
|
||
IFN FTFIXCOR,<
|
||
DNINCH: CAILE T5,1000 ;BLOCK LESS THAN A PAGE IN LENGTH
|
||
RET ;NO, CAN'T FIT IT IN A PAGE ANYWAY
|
||
MOVX T3,777 ;MASK FOR ADDRESSES WITHIN A PAGE
|
||
AND T3,T1 ;GET BLK'S OFFSET W/IN PAGE
|
||
ADD T3,T5 ;WILL BLOCK
|
||
TRNN T3,777000 ; CROSS PAGE BOUNDARY?
|
||
RET ;NO, LEAVE ADDRESS ALONE
|
||
ADDI T1,777 ;YES, ROUND
|
||
TRZ T1,777 ; UP TO NEXT PAGE
|
||
RET ;ONLY RETURN
|
||
>; End of IFN FTFIXCOR
|
||
|
||
XRESCD ;Back to resident
|
||
|
||
SUBTTL Core manager -- Increment count of emergency buffers
|
||
|
||
;DNGEBF - Used to define the number of buffers to be saved for emergencies
|
||
;Call
|
||
; T1/ Number of buffers to reserve
|
||
;Return
|
||
; RET ;Not enough buffers to let you do this
|
||
; RETSKP ;Extra emergency buffers saved
|
||
|
||
XRESCD
|
||
DNGEBF::
|
||
TRACE COM,Reserving buffers for emergencies
|
||
SYSPIF ;DELICATE STUFF, MAKE SURE NO ONE TOUCHES US
|
||
CAML T1,DCNTSB ;#ASKING FOR ALL THE BUFFERS?
|
||
JRST DONRET ;#YES, LOSE
|
||
ADDM T1,DCNEMR ;#RAISE EMERGENCY THRESHOLD
|
||
ADDM T1,DCNCNG ;# AND CONGESTION THRESHOLD
|
||
ADDM T1,DCNUCG ;# AND UNCONGESTION THRESHOLD
|
||
MOVNS T1 ;#LOWER SCLINK'S LIMITS
|
||
ADDB T1,DCNTSB ;#TOTAL SYSTEM BUFFERS
|
||
CALL CHKCNG ;#(T1)CHECK CONGESTION THRESHOLDS
|
||
SYSPIN ;#ALLOW INTERRUPTS AGAIN
|
||
RETSKP ;TELL CALLER WE RESERVED HIS BUFFERS
|
||
|
||
|
||
;CHKCNG check that congestion thresholds still make sense
|
||
; after other levels have been shifted
|
||
;
|
||
;Call: SYSPIF still from changing other thresholds, if needed
|
||
; T1/ Contents of DCNTSB
|
||
|
||
CHKCNG: CAMGE T1,DCNCNG ;#COMPARE WITH DECLARED CONGEST THRESHOLD
|
||
MOVEM T1,DCNCNG ;#CONGEST TOO LARGE, REPLACE WITH DCNTSB
|
||
CAMGE T1,DCNUCG ;#COMPARE WITH DECLARED UNCONGEST THRESHOLD
|
||
MOVEM T1,DCNUCG ;#UNCONGEST TOO LARGE, REPLACE WITH DCNTSB
|
||
MOVE T1,DCNUCG ;#GET UN-CONGESTION THRESHOLD
|
||
SUBI T1,2 ;#ASSURE A MARGIN OF AT LEAST 2
|
||
CAMGE T1,DCNCNG ;# BETWEEN CONGESTION & UNCONGESTION
|
||
MOVEM T1,DCNCNG ;# TO PREVENT KAF FLIPPING BETWEEN CNG & UCG
|
||
RET ;#ONLY RETURN FROM CHKCNG
|
||
SUBTTL Core manager -- Return number of blocks available (for router)
|
||
;DNNMSG - Return MIN(UBL,MBL) available.
|
||
;Call
|
||
;Return
|
||
; +1, T1/ Number of blocks available for router
|
||
;Note - This is probably innacurate. Re-do later accounting for emergency
|
||
;reserves and allocations to session control.
|
||
|
||
INTERNAL DNNMSG
|
||
XRESCD
|
||
DNNMSG: LOAD T1,CHAVL,+UBLCB ;GET NUMBER OF USER DATA BLOCKS AVAILABLE
|
||
OPSTR <CAMLE T1,>,CHAVL,+MBLCB ;MAKE SURE WE HAVE MORE MBL'S
|
||
LOAD T1,CHAVL,+MBLCB ;NOPE, MBL'S ARE LEAST COMMON, USE THEM.
|
||
RET ;RETURN
|
||
SUBTTL Core manager -- Get a Block from a Free Pool
|
||
|
||
;DNGRBL - Get the first block from free pool, if enough are left
|
||
;DNGRBP - Same, Privileged to get emergency blocks
|
||
;DNGRBA - Same, but T2 is zero for non-priv'd, -1 for priv'd
|
||
;Call
|
||
; T1/ Pointer to CH block for this type of block
|
||
;Return
|
||
; RET ;ON ALLOCATION FAILURE
|
||
; RETSKP ;WITH T1 CONTAINING ADDRESS OF BLOCK
|
||
|
||
DNGRBL: TDZA T2,T2 ;ZERO MEANS NO PRIVS FOR EMERGENCY BLKS
|
||
DNGRBP: MOVEI T2,1 ;NON-ZERO MEANS WE HAVE PRIVS
|
||
DNGRBA: SAVEAC <P1,P2>
|
||
IFN FTPARANOID,<
|
||
STKVAR <S1,S2> ;Scratch storage
|
||
>
|
||
DMOVE P1,T1 ;SAVE POINTER TO CH BLOCK & PRIV FLAG
|
||
SYSPIF ;#CODE BELOW CANNOT BE INTERRUPTED
|
||
LOAD T1,CHAVL,(P1) ;#GET CURRENTLY AVAILABLE BLOCK COUNT
|
||
JE CHCON,(P1),DNGRB2 ;#JUMP IF BLK TYPE NOT CONGESTION CONTROLLED
|
||
CAMG T1,DCNCNG ;#WILL WE GO BELOW CONGESTION THRESHOLD?
|
||
SKIPE DCNCON ;#YES, WERE WE ALREADY CONGESTED?
|
||
JRST DNGRB1 ;#NO, DON'T ANNOUNCE CONGESTION TWICE
|
||
SETOM DCNCON ;#YES, SET CONGESTION FLAG
|
||
SYSPIN
|
||
TRACE COM,DNGRBL congested
|
||
CALL NSPCG ; TELL NSP THAT WE ARE GETTING CONGESTED
|
||
SYSPIF
|
||
LOAD T1,CHAVL,(P1) ;#GET NEW AVAIL COUNT AFTER NSPCG CALL
|
||
DNGRB1: CAMG T1,DCNEMR ;#WILL WE GO BELOW EMERGENCY THRESHOLD?
|
||
JUMPE P2,DONRET ;#YES, DON'T GIVE HIM THE BLOCK UNLESS PRIV'D
|
||
DNGRB2: JUMPLE T1,DONRET ;#NO, FAIL IF THERE ARE NO MORE BLOCKS
|
||
OPSTRM <SOS>,CHAVL,(P1) ;#DECREMENT AVAILABLE BLOCKS
|
||
LOAD T1,CHLWM,(P1) ;;; Get the low water mark so far
|
||
LOAD T2,CHAVL,(P1) ;;; and current available
|
||
CAMLE T1,T2 ;;; Have we gone lower
|
||
STOR T2,CHLWM,(P1) ;;; Yes, remember new mark
|
||
OPSTR <SKIPN T1,>,CHPTR,(P1) ;#GET PTR TO FIRST AVAILABLE BLOCK
|
||
BUG.(CHK,COMIEL,D36COM,SOFT,<Illegal end of list pointer>,,<
|
||
|
||
Cause: CHAVL, the available count, indicated there was at least one block
|
||
on the free list, but the first pointer was zero.
|
||
|
||
Action: A forward pointer in a block which was returned some time ago was
|
||
probably smashed.
|
||
|
||
>,DONRET)
|
||
LOAD T2,FBNXT,(T1) ;#GET PTR TO NEXT AVAILABLE BLOCK
|
||
IFN FTPARANOID,<
|
||
JUMPE T2,DNGRB3 ;IF NEXT POINTER IS ZERO, IT'S OK
|
||
MOVEM T1,S1 ;SAVE POINTER TO CURRENT BLOCK
|
||
MOVEM T2,S2 ;SAVE POINTER TO NEXT BLOCK
|
||
MOVE T1,T2 ;GET POINTER TO NEXT BLOCK
|
||
MOVE T2,P1 ;GET POINTER TO CH BLOCK
|
||
CALL DNCHFB ;CHECK THE NEXT BLOCK
|
||
JRST DONRET ;;; We don't ever expect to get here cause
|
||
;;; DNCHFB BUGHLT's if error
|
||
MOVE T1,S1
|
||
MOVE T2,S2
|
||
DNGRB3:
|
||
>;END OF IFN FTPARANOID
|
||
STOR T2,CHPTR,(P1) ;#POINT PAST BLOCK WE NOW HAVE
|
||
SYSPIN ;#ALLOW INTERRUPTS AGAIN
|
||
IFN FTPARANOID,<
|
||
MOVE T2,P1 ;COPY PTR
|
||
CALL DNCHFB ;CHECK PTR TO CORE WE HAVE BEEN GIVEN
|
||
RET ;IN CASE WE FIND OUR BUG
|
||
>;END OF IFN FTPARANOID
|
||
IFN FTLSTCOR,<
|
||
LOAD T2,CHSIZ,(P1) ; Get size of this block in words
|
||
ADD T2,T1 ; Point to 1 word past end
|
||
MOVE T3,['D36COM'] ; Get value to check against
|
||
MOVEM T3,-1(T2) ; Write value into last word in block
|
||
> ;End IFN FTLSTCOR
|
||
RETSKP ;RETURN SUCCESS
|
||
ENDSV.
|
||
;DNFRBL - Free a block
|
||
|
||
;Call: T1/ Ptr to block to be freed
|
||
; T2/ Ptr to CH block for free list
|
||
; CALL DNFRBL
|
||
; Only Return
|
||
|
||
DNFRBL: SAVEAC <P1,P2>
|
||
DMOVE P1,T1 ;T1/ SAVE ADDR OF BLOCK TO BE RETURNED
|
||
;T2/ SAVE ADDR OF CH BLOCK
|
||
IFN FTPARANOID,<
|
||
CALL DNCHFB ;CHECK PTR TO CORE WE HAVE BEEN GIVEN
|
||
RET ;IN CASE WE FIND OUR BUG
|
||
>;END OF IFN FTPARANOID
|
||
IFN FTLSTCOR,<
|
||
MOVE T1,P1 ; Get back address of block
|
||
LOAD T2,CHSIZ,(P2) ; Get allocated size of block
|
||
ADDI T1,-1(T2) ; Point to last word
|
||
MOVE T1,(T1) ; Get test string
|
||
CAMN T1,['D36COM'] ; Does it match?
|
||
IFSKP.
|
||
MOVE P2,-3(P) ; Caller's PC
|
||
BUG. (CHK,COMEBT,D36COM,SOFT,<End of memory block trashed>,<<P1,MEMADR>,<P2,CALLER>>,<
|
||
|
||
Cause: DNFRBL called with block to return that had its last word smashed.
|
||
|
||
Action: See who called with the bad block and find out why the last word
|
||
was smashed.
|
||
>)
|
||
RET
|
||
ENDIF.
|
||
> ;End FTLSTCOR
|
||
SYSPIF ;#KEEP DATA BASE CLEAN WHILE WE CHANGE IT
|
||
LOAD T2,CHPTR,(P2) ;#ADDRESS OF CURRENT FIRST AVAIL BLOCK
|
||
STOR T2,FBNXT,(P1) ;#SAVE IN OUR FREE BLOCK
|
||
STOR P1,CHPTR,(P2) ;#FIRST AVAIL BLOCK IS NOW US
|
||
OPSTRM <AOS>,CHAVL,(P2) ;#INCREMENT THE NUMBER OF AVAIL BLOCKS
|
||
SKIPN DCNCON ;#IS SYSTEM CONGESTED?
|
||
JRST DONRET ;#NO, SYSPIN AND RETURN
|
||
TMNN CHCON,(P2) ;#IS BLK TYPE CONGESTION CONTROLLED?
|
||
JRST DONRET ;#NO, SYSPIN AND RETURN
|
||
|
||
;Here if system is congested, whether or not we are returning a message blk.
|
||
|
||
LOAD T1,CHAVL,+UBLCB ;#YES, GET NUMBER OF USER DATA BLOCKS AVAILABLE
|
||
OPSTR <CAMLE T1,>,CHAVL,+MBLCB ;#MAKE SURE WE HAVE MORE MBL'S
|
||
LOAD T1,CHAVL,+MBLCB ;#NOPE, MBL'S ARE LEAST COMMON, USE THEM.
|
||
CAMGE T1,DCNUCG ;#ARE WE AT UNCONGESTION THRESHOLD?
|
||
JRST DONRET ;#NO, SYSPIN AND RETURN
|
||
MOVE T1,DCNTSB ;#YES, CHECK SCTL'S RESERVATION COUNTER
|
||
SUB T1,DCNRSB ;#SUBTRACT RESERVED FROM TOTAL BUFFERS
|
||
CAMGE T1,DCNUCG ;#DIFFERENCE ABOVE UNCONGEST THRESH TOO?
|
||
JRST DONRET ;#NO, MUST HAVE RESERVED SMALL BFRS IN MSG BLK
|
||
SETZM DCNCON ;#YES, NO LONGER CONGESTED
|
||
SYSPIN ;END OF CRITICAL SECTION
|
||
CALLRET NSPCR ;TELL NSP & SCTL THE NEWS
|
||
|
||
|
||
DONRET::SYSPIN ;GENERAL SYSPIN/RET FOR D36COM
|
||
RET
|
||
|
||
SUBTTL DNMCUB - Check for trashed UBL
|
||
;Call:
|
||
; T1/ Address of UBL
|
||
;
|
||
; BUGCHK's if trashed UBL detected
|
||
|
||
IFN FTLSTCOR,<
|
||
DNMCUB::XMOVEI T2,UBLCB ; Address of UBL core block
|
||
LOAD T2,CHSIZ,(T2) ; Get allocated size of block
|
||
ADDI T1,-3(T2) ; Point to last word
|
||
MOVE T1,(T1) ; Get test string
|
||
CAME T1,['D36COM'] ; Does it match?
|
||
BUG. (CHK,D36UBT,D36COM,SOFT,<End of UBL trashed>,,<
|
||
|
||
Cause: DNADLL called with message received that had its last word smashed.
|
||
|
||
Action: See who called DNADLL with a bad block. Look for too short a
|
||
buffer from DNADLL or a message too long from driver or a message
|
||
beginning one or more words too far into buffer.
|
||
>)
|
||
RET
|
||
> ;End IFN FTLSTCOR
|
||
|
||
SUBTTL Core manager -- Checking routines for debugging only
|
||
|
||
IFN FTCORBUG,<
|
||
|
||
;DNCHCH - Check CH pointer for validity. Debugging routine only
|
||
;Call
|
||
; T1/ CH pointer to check.
|
||
;Return
|
||
; RET ;If we find our BUG
|
||
; RETSKP ;If the CH is kosher
|
||
|
||
|
||
DNCHCH: SAVEAC <T1,T2,T3,T4> ;SAVE SOME ACS
|
||
SYSPIF ;TURN OFF INTERRUPTS FOR A WHILE
|
||
XMOVEI T2,CHBLKS ;GET POINTER TO VALID CH BLOCKS
|
||
MOVE T3,T2 ;COPY IT
|
||
ADDI T3,CH.LEN*<CHBLKN-1> ;POINTER TO LAST VALID BLOCK
|
||
CAMG T1,T3 ;ARE WE BEYOND GOOD BLOCKS?
|
||
CAMGE T1,T2 ;OR BELOW GOOD BLOCKS?
|
||
BUG.(CHK,COMCHO,D36COM,SOFT,<CH pointer out of range>,,<
|
||
|
||
Cause: In the core block checking routines, the internal pointer
|
||
to the CH begstr applying to this type of block is bad.
|
||
|
||
This may mean that your executable code has been trashed.
|
||
>,DNCHX)
|
||
MOVE T4,T1 ;SAVE A COPY OF CH POINTER
|
||
SUB T1,T2 ;GET RELATIVE ADDRESS WITH BLOCKS
|
||
IDIVI T1,CH.LEN ;FIND OUT IF WE ARE ON A BOUNDARY
|
||
SKIPE T2 ;IF NO REMAINDER, THE ADDRESS IS GOOD
|
||
BUG.(CHK,COMCHB,D36COM,SOFT,<CH pointer off by a few>,,<
|
||
|
||
Cause: A pointer internal to the core management routines is off
|
||
by a few words. This probably means that an AC has been
|
||
trashed by adding to it or XORing some bits.
|
||
>,DNCHX)
|
||
LOAD T1,CHAVL,(T4) ;GET NUMBER OF AVAILABLE BLOCKS
|
||
OPSTR <CAMLE T1,>,CHNUM,(T4) ;COMPARE AGAINST TOTAL NUMBER OF BLOCKS
|
||
BUG.(CHK,COMCHA,D36COM,SOFT,<Number of available FB blocks to large>,,<
|
||
|
||
Cause: When checking the CH begstr for a type of block, we noticed that
|
||
we have more blocks available than we started out with. Since
|
||
DNCHFB is supposed to defend against this, what probably has
|
||
happened is that CHNUM has been trashed.
|
||
>,DNCHX)
|
||
JN CHBOT,(T4),DNCHX1 ;MAKE SURE WE HAVE BEEN INITIALIZED
|
||
BUG.(CHK,COMMMI,D36COM,SOFT,<Memory manager must be initialized>,,<
|
||
|
||
Cause: The field CHBOT, which indicates where a free core pool starts,
|
||
is zero. This field gets set when the core manager initializes.
|
||
|
||
Action: If DNINIM has already been called, check it to make sure it is
|
||
initializing all CH blocks.
|
||
>,DNCHX)
|
||
|
||
DNCHX1: AOS (P) ;GIVE SKIP RETURN
|
||
DNCHX: SYSPIN ;GIVE UP INTERLOCK
|
||
RET ; AND RETURN
|
||
|
||
>;END OF IFN FTCORBUG
|
||
SUBTTL Core manager -- Check pointer for validity
|
||
IFN FTPARANOID,<
|
||
|
||
;DNCHFree Block - Check Free Block pointer for validity.
|
||
;
|
||
;Call:
|
||
; T1/ Free Block pointer to check.
|
||
; T2/ CH pointer for this Free Block
|
||
; Note, call when you think the Free Block is NOT on the free list
|
||
;Return:
|
||
; RET ;When we find our bug
|
||
; RETSKP ;If Free Block is kosher
|
||
|
||
DNCHFB: SAVEAC <T1,T2,T3,T4,P1,P2,FL,FREE2>
|
||
DMOVE P1,T1 ;Save FB & CH pointers
|
||
IFN FTCORBUG,<
|
||
MOVE T1,T2 ;GET AC DNCHCH WANTS
|
||
CALL DNCHCH ;CHECK THE CH POINTER TO MAKE SURE
|
||
RET ;OOPS
|
||
>; END IFN FTCORBUG
|
||
|
||
LOAD T3,CHBOT,(P2) ;GET ADDRESS OF START OF POOL
|
||
IFE FTFIXCOR,< ;these checks don't work on page-aligned
|
||
; pools.
|
||
LOAD T4,CHNUM,(P2) ;GET NUMBER OF BLOCKS
|
||
SOJ T4, ;BACK DOWN BY ONE, TO GET HIGHEST NUMBER BLOCK
|
||
OPSTR <IMUL T4,>,CHSIZ,(P2) ;MULTIPLY BY SIZE
|
||
ADD T4,T3 ;ADD IN LOW ADDR, GET HIGHEST LEGAL ADDR FOR FB
|
||
CAMG P1,T4 ;RANGE CHECK THE FB POINTER
|
||
>; End of IFE FTFIXCOR
|
||
CAMGE P1,T3 ;NOT ABOVE MAX, CHECK FOR BELOW MAX
|
||
BUG.(HLT,COMFBO,D36COM,SOFT,<FB pointer is out of range>,,<
|
||
|
||
Cause: A free block pointer being checked is not pointing to the
|
||
free core allocated for this type of block.
|
||
|
||
Action: Find out who supplied this pointer.
|
||
>,RTN)
|
||
IFE FTFIXCOR,< ;these checks don't work on page-aligned
|
||
; pools.
|
||
MOVE T1,P1 ;GET BACK FB POINTER
|
||
SUB T1,T3 ;CONVERT POINTER TO RELATIVE ADDR
|
||
OPSTR <IDIV T1,>,CHSIZ,(P2) ;CONVERT TO ABSOLUTE NUMBER OF BLOCK
|
||
SKIPE T2 ;MAKE SURE WE WERE ON A BLOCK BOUNDARY
|
||
BUG.(HLT,COMFBT,D36COM,SOFT,<FB pointer is off by a few>,,<
|
||
|
||
Cause: A free block pointer is off by a few words. This probably means
|
||
that the user of this pointer had added a constant, and forgot
|
||
to restore it when giving back the block.
|
||
|
||
Action: Trace the user of this pointer, and make sure the pointer is
|
||
valid when given to the memory manager.
|
||
>,RTN)
|
||
|
||
>; End of IFE FTFIXCOR
|
||
|
||
IFN FTCORBUG,<
|
||
;Check the entire FB data structure, making sure all pointers in blocks
|
||
; are good, and this block isn't already on the free list.
|
||
|
||
SYSPIF ;TURN OFF INTERRUPTS
|
||
LOAD FREE2,CHAVL,(P2) ;GET NUMBER OF BLOCKS WE THINK ARE ON LIST
|
||
LOAD T1,CHPTR,(P2) ;GET POINTER TO FIRST FB BLOCK
|
||
DNCHF1: JUMPE T1,DNCHF2 ;AT END OF LIST, EXIT
|
||
IFE FTFIXCOR,< ;these checks don't work on page-aligned
|
||
; pools.
|
||
CAMG T1,T4 ;IS IT ABOVE HIGH RANGE?
|
||
>; End of IFE FTFIXCOR
|
||
CAMGE T1,T3 ;OR BELOW LOW RANGE?
|
||
BUG.(CHK,COMAFB,D36COM,SOFT,<A free block pointer is bad>,,<
|
||
|
||
Cause: There is a block on a free list whose address is not in the
|
||
range expected for this list. The offending pointer is in P1.
|
||
|
||
Action: Somebody back on the stack is probably returning a block to the
|
||
wrong free list or is returning a junk pointer.
|
||
>,DNCHX)
|
||
MOVE FL,T1 ;SAVE FOR DURATION OF ROUTINE
|
||
|
||
IFE FTFIXCOR,< ;these checks don't work on page-aligned
|
||
; pools.
|
||
SUB T1,T3 ;RELATIVE POINTER
|
||
OPSTR <IDIV T1,>,CHSIZ,(P2) ;CONVERT TO ABSOLUTE BLOCK NUMBER
|
||
SKIPE T2 ;MAKE SURE WE WERE ON A BLOCK BOUNDARY
|
||
BUG.(CHK,COMFBB,D36COM,SOFT,<FB in data base is off by a few>,,<
|
||
|
||
Cause: DNCHFB has found a block on a free list, most likely just returned
|
||
to it, whose address is not on a block boundary for blocks on
|
||
this free list. The offending pointer is in P1.
|
||
|
||
Action: Somebody back on the stack is probably returning a junk pointer,
|
||
either a real pointer to a block which has been incremented or
|
||
decremented or a completely junk pointer.
|
||
|
||
>,DNCHX)
|
||
>; End of IFE FTFIXCOR
|
||
CAMN FL,P1 ;MAKE SURE THIS ISNT THE BLOCK I HAVE
|
||
BUG.(CHK,COMFBF,D36COM,SOFT,<FB is already on free list>,,<
|
||
|
||
Cause: The block that P1 points at is already on the free list and
|
||
is being returned again.
|
||
|
||
Action: Somebody back on the stack is returning a block which is already
|
||
free. Either that caller is in error or some previous returner
|
||
is in error.
|
||
>,DNCHX)
|
||
|
||
LOAD T1,FBNXT,(FL) ;GET NEXT POINTER IN THE LIST
|
||
SOJA FREE2,DNCHF1 ;AND TRY AGAIN
|
||
|
||
DNCHF2: SKIPE FREE2 ;ASSURE WE CHECKED RIGHT NUMBER OF BLOCKS
|
||
BUG.(CHK,COMFBA,D36COM,SOFT,<FB available count is wrong>,,<
|
||
|
||
Cause: DNCHFB walked a free list and found a different number of
|
||
blocks on the list than the header indicated.
|
||
|
||
Action: Somebody probably smashed a forward pointer in a block which was
|
||
returned some time ago. Find out who.
|
||
>,DNCHX)
|
||
SYSPIN ;TURN THEM BACK ON
|
||
>;END OF IFN FTCORBUG
|
||
|
||
RETSKP ;INDICATE ALL WARM AND FUZZY
|
||
|
||
|
||
;DNCHMB - Check a message block pointer. Called from ROUTER.
|
||
;Call
|
||
; MB/ Pointer to message block
|
||
;Return
|
||
; Always. Will BUG if an error, but will return.
|
||
|
||
INTERNAL DNCHMB
|
||
XRESCD
|
||
DNCHMB: SAVEAC <T1,T2> ;WE ARE GOING TO USE THESE ACS
|
||
MOVE T1,T3 ;MESSAGE BLOCK POINTER
|
||
IFN FTLSTCOR,<
|
||
SUBI T1,2 ;ALLOW FOR HEADER WORDS
|
||
>;END IFN FTLSTCOR
|
||
XMOVEI T2,MBLCB ;POINTER TO THE CH STRUCTURE WE CARE ABOUT.
|
||
JRST DNCHFB ;GO AND DO COMPLETE CHECKS FOR THE POINTER
|
||
|
||
>;END OF IFN FTPARANOID
|
||
SUBTTL Time -- Get current time in ms.
|
||
|
||
;DNGTIM - Get a timestamp in the proper units into T1
|
||
;
|
||
;Call: CALL DNGTIM
|
||
; Normal Return with time in T1
|
||
;Changes T1,T2
|
||
|
||
TIMBAS==:^D1000 ;FRACTIONS OF A SECOND WITH WHICH TIME
|
||
;IS REPRESENTED. USED BY OTHER
|
||
;ROUTINES WHICH MANIPULATE TIMERS
|
||
INTERNAL DNGTIM
|
||
XRESCD
|
||
DNGTIM:
|
||
IFN FTOPS10,<
|
||
MOVE T1,SYSUTM## ;GET MILLISECONDS OF SYSTEM UPTIME
|
||
>;End of IFN FTOPS10
|
||
|
||
IFN FTOPS20,<
|
||
MOVE T1,TODCLK ;GET MILLSECONDS OF SYSTEM UPTIME
|
||
>;End of IFN FTOPS20
|
||
|
||
RET
|
||
|
||
SUBTTL Network management -- NTPARM - parameters
|
||
|
||
;NTPARM - network management operations for parameters
|
||
;
|
||
;This routine will make it easier to implement the 'set', 'read' and 'clear'
|
||
; network management functions.
|
||
;
|
||
;Call: T1/ address of parameter table
|
||
; T2/ length of parameter table (i.e. # of parameters defined)
|
||
; T3/ requested function (NF.SET, NF.RED or NF.CLR)
|
||
; P1/ address of NF block
|
||
; CALL NTPARM
|
||
; +1 return on error with T1/ network management error code
|
||
; +2 return on success
|
||
;
|
||
;The PARAMETER macro that is used to define the parameter table contains
|
||
; instructions to be executed to set, read and clear a parameter. NTPARM
|
||
; expects this instruction (that of course may be a CALL) to:
|
||
; - always return +1
|
||
;
|
||
;When the instruction is executed, P1 will contain the NF address and T2
|
||
; on set: the new value
|
||
; on clear: the default value specified in the table
|
||
; on read: should return with the new value
|
||
;
|
||
; NTPARM will not touch any AC except T1-T4
|
||
;
|
||
|
||
INTERNAL NTPARM
|
||
XSWAPCD
|
||
NTPARM: STKVAR <TABADR,TABLEN,FUNC,BUFLAG>
|
||
MOVEM T1,TABADR ;Save table address
|
||
MOVEM T2,TABLEN ; and table length
|
||
SETZM FUNC ;Assume function is READ (FUNC EQ 0)
|
||
CAIN T3,NF.SET ;Is it SET?
|
||
SETOM FUNC ; -yes, set FUNC EQ -1
|
||
CAIN T3,NF.CLR ;Or CLEAR?
|
||
MOVEM T3,FUNC ; -yes, move value GT 0 to FUNC
|
||
ASSUME NF.CLR,GT,0
|
||
|
||
;Loop over parameter table, AC usage is:
|
||
; T2/ parameter #
|
||
; T3/ loop index
|
||
; T4/ address of PA block
|
||
|
||
LOAD T2,NFPRM,(P1) ;Get parameter number
|
||
SETZ T3, ;Begin at index 0
|
||
DO. ;LOOP
|
||
CAML T3,TABLEN ; Done all entries
|
||
RNMXER (NF.UPT) ; -no match, return error
|
||
MOVE T4,TABADR ; Get table address
|
||
ADD T4,T3 ; and make pointer to current table entry
|
||
MOVE T4,(T4) ; and make pointer to PA block
|
||
OPSTR <CAMN T2,>,PAPNR,(T4) ;Correct parameter number?
|
||
EXIT. ; -yes, exit loop
|
||
AOJA T3,TOP. ; -no, loop back and try next index
|
||
ENDDO.
|
||
|
||
TMNN PABEX,(T4) ;Is NTMAN supplied buffer ok?
|
||
IFSKP.
|
||
SETOM BUFLAG ; Indicate buffer is expected
|
||
TMNE NFBFF,(P1) ; Is buffer present?
|
||
IFSKP.
|
||
BUG. (CHK,NTNBFS,D36COM,SOFT,<No buffer supplied>,,<
|
||
|
||
Cause: The routine NTPARM was called to handle a network management parameter.
|
||
The caller of NTPARM said that it expects the call from NTMAN to
|
||
supply a buffer for the parameters to be read from or stored into.
|
||
None was supplied.
|
||
>)
|
||
RNMXER (NF.MPE) ; Return "management program error"
|
||
ENDIF.
|
||
ELSE.
|
||
;Verify that buffer flag is clear (this routine handles only single value
|
||
; returns)
|
||
SETZM BUFLAG ; No buffer, data appears in argument block
|
||
TMNN NFBFF,(P1) ;Buffer flag set?
|
||
IFSKP. ; -yes,
|
||
BUG.(CHK,NTBSUP,D36COM,SOFT,<Buffer supplied>,,<
|
||
|
||
Cause: The routine NTPARM was called to handle a network management parameter.
|
||
The routine can only handle returns of a single value, but NTMAN had
|
||
supplied a multi-word buffer.
|
||
>)
|
||
RNMXER (NF.MPE) ; and return "management program error"
|
||
ENDIF.
|
||
ENDIF.
|
||
;Here when buffers are checked and table address is selected
|
||
MOVX T1,NF.FCS ;This will be a flag (sigh) to indicate error
|
||
SKIPL FUNC ;Is it SET?
|
||
IFSKP. ; -yes,
|
||
TMNE PANST,(T4) ;Can this parameter be set
|
||
RNMXER (NF.OPF) ;No, return error
|
||
LOAD T2,NFBUF,(P1) ; No, get new value and check it
|
||
TMNE PADRC,(T4) ;Have we been told not to range check this
|
||
IFSKP. ;value?
|
||
OPSTR <CAML T2,>,PAMIN,(T4) ; Less than the minimum?
|
||
OPSTR <CAMLE T2,>,PAMAX,(T4) ; or greater than the maximum?
|
||
RNMXER (NF.IPV) ; Yes, bad value
|
||
ENDIF.
|
||
OPSTR <XCT>,PASET,(T4) ; Execute instruction to do SET (If the
|
||
; execute calls a routine it is not obliged
|
||
; to use T2)
|
||
ELSE.
|
||
SKIPG FUNC ; -no, is it CLEAR
|
||
IFSKP. ; -yes,
|
||
TMNE PANCL,(T4) ;Can this parameter be cleared?
|
||
RNMXER (NF.OPF) ;No, return error
|
||
LOAD T2,PADEF,(T4) ; Load default value as promised
|
||
OPSTR <XCT>,PACLR,(T4) ; execute instruction to do CLEAR (If the
|
||
; executed intruction calls a routine the
|
||
; the routine is not obliged to use T2
|
||
ELSE. ; -no, it is READ
|
||
OPSTR <XCT>,PARED,(T4) ; Get value
|
||
SKIPL BUFLAG ; If buffer present data is already stored
|
||
STOR T2,NFBUF,(P1) ; and return it in NF block
|
||
ENDIF.
|
||
ENDIF.
|
||
ASSUME NF.NDP,EQ,0
|
||
JUMPLE T1,RTN ; If T1 is negative (error) or 0 (no data),
|
||
; then return error
|
||
RETSKP ;All done, return
|
||
|
||
ENDSV.
|
||
XRESCD
|
||
|
||
SUBTTL Network management -- NTCTRS - counters
|
||
|
||
;NTCTRS - network management operations for counters
|
||
;
|
||
;This routine will make it easier to implement the 'show' and 'show and zero'
|
||
; network management functions.
|
||
;
|
||
;Call: T1/ address of counter table
|
||
; T2/ length of counter table (i.e. # of counters defined)
|
||
; T3/ requested function (NF.SHO or NF.SZC)
|
||
; P1/ address of NF block
|
||
; CALL NTCTRS
|
||
; +1 return on error with T1/ network management error code
|
||
; +2 return on success
|
||
;
|
||
;The COUNTER macro that is used to define the counter table contains
|
||
; instructions to be executed to read and to clear a counter. NTCTRS
|
||
; expects this instruction (that of course may be a CALL) to:
|
||
; - always return +1
|
||
; - return the counter value in T1
|
||
; - not destroy any accumulators, including T2-T4
|
||
;When the instruction is executed, P1 will contain the NF address. NTCTRS
|
||
; will not touch any AC except T1-T4
|
||
;
|
||
;If the read/read & clear operation has to be interlocked, then the caller
|
||
; is responsible for interlocking before calling NTCTRS.
|
||
|
||
INTERNAL NTCTRS
|
||
XSWAPCD
|
||
NTCTRS: STKVAR <TABADR,TABLEN,DOCLR>
|
||
MOVEM T1,TABADR ;Save counter table address
|
||
MOVEM T2,TABLEN ; and length of table
|
||
SETZM DOCLR ;Assume read-only operation
|
||
CAIN T3,NF.SZC ;Is it zero also?
|
||
SETOM DOCLR ; -yes, flag clear should be done
|
||
|
||
;Verify that the 'buffer present' flag is set
|
||
TMNE NFBFF,(P1) ;Is it set?
|
||
IFSKP. ; -no, bugcheck and return error
|
||
BUG.(CHK,NTNBUF,D36COM,SOFT,<No buffer supplied>,,<
|
||
|
||
Cause: NTMAN requested a show counter operation, but did not supply a
|
||
buffer to store the counters in.
|
||
>)
|
||
RNMXER (NF.MPE) ; and return "management program error"
|
||
ENDIF.
|
||
|
||
;Verify that buffer is large enough for all counters in table
|
||
MOVE T1,TABLEN ;Get # of counters
|
||
ASH T1,1 ; and we use two words for each counter
|
||
OPSTR <CAMG T1,>,NFBLN,(P1) ;Compare with supplied size
|
||
IFSKP. ; -too big,
|
||
BUG.(CHK,NTBTSM,D36COM,SOFT,<Buffer too small>,,<
|
||
|
||
Cause: NTMAN requested a show counter operation, but did not supply a
|
||
buffer large enough to store all the counters.
|
||
>)
|
||
RNMXER (NF.MPE) ; -and return "management program error"
|
||
ENDIF.
|
||
STOR T1,NFBLN,(P1) ;Store # of words we are going to write...
|
||
|
||
;Loop over all counters, AC usage is:
|
||
; T2/ address of counter buffer
|
||
; T3/ index into counter table
|
||
; T4/ pointer to current CT block
|
||
|
||
LOAD T2,NFBUF,(P1) ;Get buffer address
|
||
SETZ T3, ;Start at index 0
|
||
DO. ;LOOP
|
||
CAML T3,TABLEN ; Done all counters yet?
|
||
RETSKP ; -yes, return suceess
|
||
MOVE T4,TABADR ; Get address of counter table
|
||
ADD T4,T3 ; and add in index
|
||
MOVE T4,(T4) ; and make pointer to CT block
|
||
LOAD T1,CTHDR,(T4) ; Get counter header (width,,nr)
|
||
MOVEM T1,(T2) ; and store in buffer
|
||
OPSTR <XCT>,CTRED,(T4) ; Read the value of the counter
|
||
MOVEM T1,1(T2) ; and store in buffer
|
||
ADDI T2,2 ; Update buffer pointer with 2
|
||
TMNN CTBMF,(T4) ; Is this a bit mapped counter?
|
||
IFSKP.
|
||
SETONE KBBMF,-2(T2) ; Yes, set the flag for NTMAN
|
||
OPSTR <XCT>,CTBMP,(T4) ;Get the bit map
|
||
MOVEM T1,(T2) ; and store for NTMAN
|
||
AOJ T2, ; and advance the buffer pointer
|
||
ENDIF.
|
||
|
||
SKIPE DOCLR ; Should the counter be cleared?
|
||
OPSTR <XCT>,CTCLR,(T4) ; -yes, do so!
|
||
AOJA T3,TOP. ; Update loop index and loop back
|
||
ENDDO.
|
||
;Will never get here
|
||
ENDSV.
|
||
|
||
XRESCD
|
||
|
||
SUBTTL Trace -- Interface for exec-mode trace.
|
||
IFN FTTRACE!FTMINTrace,<
|
||
;.TCRLF -- TYPE OUT AN END OF LINE
|
||
;.TTABC -- TYPE OUT A TAB
|
||
;.TRBRK -- TYPE OUT A RIGHT BRACKET (CLOSE BRACKET PAIR)
|
||
;.TSPAC -- TYPE OUT A SPACE CHARACTER
|
||
|
||
.TCRLF::MOVEI T1,"M"-100 ;CARRIAGE RETURN
|
||
PUSHJ P,.TCHAR ;PRINT THE CHARACTER OUT
|
||
MOVEI T1,"J"-100 ;LION FEED
|
||
PJRST .TCHAR ;FINISH OFF
|
||
|
||
.TTABC::MOVEI T1,"I"-100
|
||
PJRST .TCHAR ;TYPE OUT A TAB
|
||
.TRBRK::MOVEI T1,"]" ;RIGHT BRACKET
|
||
PJRST .TCHAR ;TYPE IT OUT
|
||
.TSPAC::MOVEI T1," " ;SPACE
|
||
PJRST .TCHAR ;TYPE IT OUT TOO.
|
||
|
||
;.TDECW -- TYPE OUT SIGNED DECIMAL NUMBER
|
||
;.TOCTW -- TYPE OUT SIGNED OCTAL NUMBER
|
||
;.TRDXW -- TYPE OUT SIGNED NUMBER (RADIX IN T3)
|
||
; (IF RADIX .GT. 9, WILL USE ALPHAS AFTER DIGITS)
|
||
;CALL: MOVE T1,NUMBER
|
||
; PUSHJ P,.TOCTW/.TDECW/.TRDXW
|
||
;USES T1, T2, T3
|
||
|
||
.TOCTW::SKIPA T3,[10] ;INITIALIZE FOR OCTAL RADIX
|
||
.TDECW::MOVEI T3,^D10 ;INITIALIZE FOR DECIMAL RADIX
|
||
|
||
.TRDXW::JUMPGE T1,TRDXW1 ;CHECK FOR NEGATIVE
|
||
PUSH P,T1 ;SAVE NUMBER FROM .TCHAR
|
||
MOVEI T1,"-" ;YES--GET MINUS
|
||
PUSHJ P,.TCHAR ;PRINT IT
|
||
POP P,T1 ;RESTORE OUR NUMBER
|
||
MOVMS T1 ;GET MAGNITUDE
|
||
TRDXW1: IDIV T1,T3 ;DIVIDE BY RADIX
|
||
PUSH P,T2 ;SAVE REMAINDER
|
||
SKIPE T1 ;SEE IF ANYTHING LEFT
|
||
PUSHJ P,TRDXW1 ;YES--LOOP BACK WITH PD LIST
|
||
POP P,T1 ;GET BACK A DIGIT
|
||
ADDI T1,"0" ;CONVERT TO ASCII
|
||
CAILE T1,"9" ;SEE IF OVERFLOW DIGITS
|
||
ADDI T1,"A"-"9"-1 ;YES--SWITCH TO ALPHABETICS
|
||
PJRST .TCHAR ;TYPE IT AND RETURN
|
||
SUBTTL Trace -- SCAN's output routines
|
||
;.TSTRG -- TYPE ASCIZ STRING
|
||
;CALL: MOVEI T1,LOCTN. OF STRING
|
||
; PUSHJ P,.TSTRG
|
||
;USES T1
|
||
|
||
.TSTRG::HRLI T1,(POINT 7) ;CONVERT ADDRESS TO POINTER
|
||
TRNN T1,-1 ;SEE IF SOMETHING THERE
|
||
POPJ P, ;NO--RETURN EMPTY HANDED
|
||
PUSH P,T1 ;STORE IN SAFE PLACE [501]
|
||
TSTRG1: ILDB T1,(P) ;GET NEXT CHARACTER [501]
|
||
JUMPE T1,[ ;RETURN WHEN DONE [501]
|
||
POP P,T1 ;PUT T1 BACK
|
||
POPJ P,] ;RETURN
|
||
PUSHJ P,.TCHAR ;OUTPUT CHARACTER
|
||
JRST TSTRG1 ;LOOP UNTIL DONE
|
||
SUBTTL Trace -- Routine store character in shared buffer
|
||
;.TCHAR -- TYPE OUT A CHARACTER
|
||
;CALL: MOVEI T1,CHARACTER
|
||
; PUSHJ P,.TCHAR
|
||
;This routine is the meat of the trace facility - Each character goes
|
||
;through here, being deposited in the user buffer according to a
|
||
;carefully established protocol. If any changes are made, make very
|
||
;sure D36TRC is capable of handling them.
|
||
;*#* Note 0:T2 Will be set by putting a snoop breakpoint at DCNTRA.
|
||
;*#* Note 1: The AOS SOS here assumes that any PI excursion will take less
|
||
; time than the user would to read the entire buffer
|
||
;*#* Note 2: The wrapping of the buffer must be done with SYSPIF, since
|
||
; we could have the other cpu use an invalid byte pointer
|
||
; while we are resetting stuff
|
||
|
||
XP TAKBYT,0
|
||
XP LSTBYT,2
|
||
|
||
.TCHAR::SETZ T2, ;CLEAN OUT OUR AC. SNOOP WILL SET VALUE
|
||
DCNTRA: SKIPN T2 ;GET ADDRESS OF USER'S BLOCK, AND MAKE SURE
|
||
POPJ P, ; WE HAVE A USER'S BLOCK. IF NOT, RETURN NOW.
|
||
;(*#* Note 0 *#*)
|
||
;RESERVE A BYTE
|
||
AOS T3,TAKBYT(T2) ;BUMP NUMBER OF BYTES IN BUFFER TAKEN
|
||
CAML T3,MAXBYT ;IS THIS GOING TO FIT?
|
||
JRST [ SOS TAKBYT(T2) ;NO, BUMP THE COUNT BACK DOWN
|
||
AOS LSTBYT(T2) ;BUMP COUNT OF LOST BYTES
|
||
POPJ P,] ;RETURN QUIETLY (*#* Note 1 *#*)
|
||
;WE HAVE OUR BYTE RESERVED. LET'S PUT IT IN THE BUFFER
|
||
SYSPIF ;(*#* Note 2 *#*)
|
||
AOS T3,CURBYT ;#INCREMENT CURRENT BYTE POSITION IN BUFFER
|
||
CAML T3,LASBYT ;#DO WE HAVE TO WRAP AROUND?
|
||
JRST [ SETZM CURBYT ;#RESET CURRENT BYTE POSITION
|
||
MOVE T3,ZERBPT ;#GET BYTE POINTER TO THE ZEROTH BYTE IN BUFFER
|
||
MOVEM T3,CURBPT ;#SAVE AS CURRENT BYTE POINTER
|
||
JRST .+1]
|
||
IDPB T1,CURBPT ;#DEPOSIT THE BYTE IN THE USER'S BUFFER
|
||
SYSPIN ;ALLOW OTHER CPU IN
|
||
CAIE T1,12 ;IS THIS A LINE FEED?
|
||
RET ;NO, JUST RETURN
|
||
MOVE T1,TRAJOB ;YES, GET JOB NUMBER OF TRACER
|
||
JRST WAKJOB## ;WAKE HIM UP
|
||
|
||
>;END OF IFN FTTRACE!FTMINTR
|
||
SUBTTL TOPS10 -- AC save routines
|
||
|
||
;These routines are defined in MACSYM.REL, but we normally don't load
|
||
;with that, so here they are:
|
||
|
||
IFN FTOPS10,<
|
||
|
||
.SAV1:: PUSH P,.FPAC
|
||
CALL 0(.SAC)
|
||
TRNA
|
||
AOS -1(P)
|
||
POP P,.FPAC
|
||
RET
|
||
|
||
.SAV2:: PUSH P,.FPAC+0
|
||
PUSH P,.FPAC+1
|
||
CALL 0(.SAC)
|
||
TRNA
|
||
AOS -2(P)
|
||
POP P,.FPAC+1
|
||
POP P,.FPAC+0
|
||
RET
|
||
|
||
.SAV3:: PUSH P,.FPAC+0
|
||
PUSH P,.FPAC+1
|
||
PUSH P,.FPAC+2
|
||
CALL 0(.SAC)
|
||
TRNA
|
||
AOS -3(P)
|
||
POP P,.FPAC+2
|
||
POP P,.FPAC+1
|
||
POP P,.FPAC+0
|
||
RET
|
||
|
||
.SAV4:: ADJSP P,4
|
||
DMOVEM .FPAC+0,-3(P)
|
||
DMOVEM .FPAC+2,-1(P)
|
||
CALL 0(.SAC)
|
||
TRNA
|
||
AOS -4(P)
|
||
DMOVE .FPAC+0,-3(P)
|
||
DMOVE .FPAC+2,-1(P)
|
||
ADJSP P,-4
|
||
RET
|
||
|
||
>;END OF IFN FTOPS10
|
||
SUBTTL Kontroller data
|
||
|
||
DEFINE KNMMCS,<
|
||
; Symbol,Name,Cost, Maximum receive block size
|
||
KNMMAC LD.TST,TST, 1, 0 ;TST DEVICE
|
||
KNMMAC LD.DTE,DTE, 3, <^D576> ;DTE DEVICE
|
||
KNMMAC LD.KDP,KDP, 4, <^D576> ;KDP DEVICE
|
||
KNMMAC LD.DDP,DDP, 5, <^D576> ;DDP DEVICE
|
||
KNMMAC LD.CIP,CI, 2, <^D576> ;CI DEVICE
|
||
IFN FTOPS20,<
|
||
KNMMAC LD.ETH,NI, 1, <^D1504-%RTEHS> ;NI DEVICE
|
||
>; END IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
KNMMAC LD.ETH,ETH, 1, <^D1504-%RTEHS> ;ETHERNET CHANNEL
|
||
>; END IFN FTOPS10
|
||
KNMMAC LD.DMR,DMR, 2, <^D576> ;DMR DEVICE
|
||
>;END OF KNMMCS
|
||
|
||
DEFINE KNMMAC(sym,name,cost,bsize),<
|
||
IFN <.-KONNAM-sym>,<PRINTX ?nam device incorrectly defined at KONNAM>
|
||
ASCII /name/
|
||
>;END OF KNMMAC
|
||
|
||
RESCD
|
||
IFN FTOPS10,<RESDT>
|
||
KONNAM::KNMMCS
|
||
IFN <.-KONNAM-LD.MAX-1>,<PRINTX ?Incorrect number of kontrollers defined>
|
||
IFN FTOPS10,<RESCD>
|
||
|
||
DEFINE KNMMAC(sym,name,cost,bsize),<EXP cost>
|
||
KONCST::KNMMCS
|
||
|
||
DEFINE KNMMAC(sym,name,cost,bsize),<EXP bsize>
|
||
MXLBSZ::KNMMCS
|
||
XRESCD
|
||
|
||
|
||
SUBTTL Initialization routines -- Compute Core Requirements
|
||
|
||
|
||
;DCNCCR computes the total DECnet core requirements.
|
||
;Call:
|
||
; PUSHJ P,DCNCCR
|
||
;Returns:
|
||
; T1/ Size of DECnet core
|
||
|
||
IFN FTOPS10,<
|
||
INTERNAL DCNCCR
|
||
XRENT DCNCCR
|
||
|
||
SAVEAC <P1> ;SAVE P1
|
||
SETZ P1, ;START WITH ZERO
|
||
|
||
PUSHJ P,D36CCR ;COMPUTE D36COM'S CORE REQUIREMENTS
|
||
ADD P1,T1 ;ADD TO TOTAL
|
||
PUSHJ P,SCTCCR## ;COMPUTE SCLINK'S CORE REQUIREMENTS
|
||
ADD P1,T1 ;ADD TO TOTAL
|
||
PUSHJ P,NSPCCR## ;COMPUTE LLINK'S CORE REQUIREMENTS
|
||
ADD P1,T1 ;ADD TO TOTAL
|
||
PUSHJ P,RTRCCR## ;COMPUTE ROUTER'S CORE REQUIREMENTS
|
||
ADD P1,T1 ;ADD TO TOTAL
|
||
PUSHJ P,DNDCCR## ;COMPUTE DNADLL'S CORE REQUIREMENTS
|
||
ADD P1,T1 ;ADD TO TOTAL
|
||
|
||
MOVE T1,P1 ;GET TOTAL CORE REQUIREMENTS
|
||
MOVEM T1,DCNTCR ;SAVE FOR STATISTICS
|
||
RET ;AND RETURN
|
||
>; END IFN FTOPS10
|
||
;D36CCR computes D36COM's core requirements.
|
||
;Call:
|
||
; PUSHJ P,D36CCR
|
||
;Returns:
|
||
; T1/ Size of D36COM core
|
||
|
||
IFN FTOPS10,<
|
||
D36CCR: SAVEAC <P1> ;SAVE P1
|
||
SETZ P1, ;START WITH ZERO
|
||
|
||
LOAD T1,IBBSZ,+IBBLK ;GET REQUESTED SIZE OF BUFFERS
|
||
ADDI T1,%RTEHS+3 ;ADD IN MAXIMUM ROUTER OVERHEAD
|
||
LSH T1,-2 ;CONVERT TO WORDS
|
||
ADDI T1,OVHWDS ;ALLOWANCE FOR OVERHEAD WORD(S)
|
||
STOR T1,CHSIZ,+UBLCB ;SAVE IN CH BLOCK
|
||
LOAD T1,IBMXB,+IBBLK ;GET NUMBER OF BUFFERS TO BUILD
|
||
STOR T1,CHNUM,+UBLCB ;SAVE IN CH BLOCK
|
||
MOVE T2,T1 ;GET NUMBER OF UBLS
|
||
LSH T2,-2 ;INCREASE THE NUMBER OF MBLS
|
||
ADD T1,T2 ;BY ONE FOURTH OF THE NUMBER OF UBLS
|
||
STOR T1,CHNUM,+MBLCB ;AND SAVE IT
|
||
MOVEI T3,CHBLKN ;GET NUMBER OF CH BLOCKS
|
||
XMOVEI T4,CHBLKS ;AND ADDRESS OF CH BLOCKS
|
||
D36CC1: LOAD T1,CHNUM,(T4) ;GET NUMBER OF THIS TYPE OF FREE BLK
|
||
LOAD T2,CHSIZ,(T4) ;SIZE OF THIS TYPE OF FREE BLK
|
||
IMUL T1,T2 ;MULTIPLY TO GET WORDS REQ'D
|
||
ADD P1,T1 ;ADD INTO TOTAL
|
||
ADDI T4,CH.LEN ;STEP TO NEXT CH BLOCK
|
||
SOJG T3,D36CC1 ;LOOP OVER ALL CH BLOCKS
|
||
MOVE T1,P1 ;GET MEMORY REQUIREMENTS
|
||
RET ;AND RETURN
|
||
>; END IFN FTOPS10
|
||
SUBTTL Initialization routines
|
||
|
||
|
||
;The DECnet initialization routine
|
||
|
||
XNENT D36INI
|
||
|
||
IFN FTOPS20,<
|
||
SKIPN [DCN] ;Is DECnet turned on?
|
||
RET ; -no, just return
|
||
>
|
||
|
||
SAVEAC <T5,T6> ;SAVE SOME ACS
|
||
MOVX T1,1 ;Set D36IFG
|
||
MOVEM T1,D36IFG ; to +1 to indicate DECnet is initializing
|
||
IFN FTOPS10,<
|
||
PUSHJ P,M10INI ;INIT -10 MEMORY MANAGEMENT
|
||
MOVE T1,DCNNAM## ;GET DECNET NODE NAME
|
||
STOR T1,IBNAM,+IBBLK ;STORE SIXBIT NODE NAME
|
||
MOVE T1,DCNNUM## ;GET DECNET NODE NUMBER (ADDRESS)
|
||
MOVEM T1,RTRADR ;SAVE FOR ALL OF DECNET TO SEE
|
||
MOVE T2,DCNHOM## ;GET DECNET HOME AREA NUMBER
|
||
MOVEM T2,RTRHOM ;SAVE THIS TOO
|
||
STOR T2,RN%ARE,T1 ;COMBINE BOTH AREA AND NODE NUMBERS
|
||
STOR T1,IBADR,+IBBLK ;FILL IN INITIALIZATION BLOCK
|
||
MOVE T1,DCNRTY## ;GET ROUTER TYPE
|
||
STOR T1,IBRTR,+IBBLK ;SAVE
|
||
MOVE T1,DCNCOR ;GET ADDRESS WHERE DECNET CORE ALLOCATION
|
||
MOVEM T1,DCNVFF ;SET UP AS ADDRESS OF DECNET FIRST FREE
|
||
>
|
||
LOAD T1,IBADR,+IBBLK ;Make sure local node index
|
||
LDB T1,[POINTR(T1,RN%NOD)] ; and
|
||
OPSTR <CAMLE T1,>,IBMXA,+IBBLK ; MAXIMUM ADDRESS are consistent
|
||
BUG.(CHK,COMBNN,D36COM,SOFT,<Bad local node number>,,<
|
||
|
||
Cause: The node number set with the NODE command in the CONFIG file
|
||
is higher than the DECNET MAXIMUM-ADDRESS value set in the same file.
|
||
DECnet cannot initialize.
|
||
|
||
Action: Make the startup file consistent.
|
||
>,RTN)
|
||
LOAD T1,IBDBL,+IBBLK ; Get default buffers per link
|
||
LSH T1,1 ; Allow that many for transmit and receive
|
||
STOR T1,PDDQT,+DNDEFS ; and save it for SCJSYS
|
||
IFN FTOPS20,<
|
||
LOAD T1,IBBSZ,+IBBLK ; Get requested block size
|
||
ADDI T1,%RTEHS+3 ; Add maximum Router overhead
|
||
IDIVI T1,4 ; Convert to words
|
||
IFE FTLSTCOR,<AOJ T1,> ; Allowance for overhead word
|
||
IFN FTLSTCOR,<ADDI T1,4> ; Overhead words for trace of lost blks
|
||
STOR T1,CHSIZ,+UBLCB ; Save as size to build UBLs
|
||
LOAD T1,IBMXB,+IBBLK ; Get maximum number of UBL's to build
|
||
STOR T1,CHNUM,+UBLCB ; Save it for initializer
|
||
MOVE T2,T1 ; Get number of UBLs
|
||
LSH T2,-2 ; Increase the number of MBLs
|
||
ADD T1,T2 ; by one fourth of the number of UBLs
|
||
STOR T1,CHNUM,+MBLCB ; and save it
|
||
>; END IFN FTOPS20
|
||
CALL DNINIM ;GO INITIALIZE OUR MEMORY MANAGER
|
||
CALL SCTINI ;CALL SC WHO WILL CALL NSP AND SO ON
|
||
BUG.(CHK,COMCID,D36COM,SOFT,<Couldn't initalize DECNET>,,<
|
||
|
||
Cause: SCTINI has found some reason to object about the DECnet environment.
|
||
See SCTINI for the reasons it will take a non-skip return.
|
||
|
||
>,RTN)
|
||
XCALL (MSEC1,NRTINI) ;INITIALIZE DECnet NRT AS WELL
|
||
TRN ;EAT UP ANY POSSIBLE SKIP RETURN
|
||
CALL RTRON ;TURN ON ROUTER (WHICH TURNS ON DECNET)
|
||
TRN ;EAT ANY POSSIBLE SKIP RETURN
|
||
IFN FTOPS20,XCALL (MSEC1,SCJINI) ;(20)INITIALIZE SCJSYS
|
||
IFN FTOPS10,<
|
||
MOVE T1,DCNTCR ;GET TOTAL CORE REQUIREMENTS
|
||
ADD T1,DCNCOR ;ADD BASE ADDRESS OF DECNET CORE
|
||
CAME T1,DCNVFF ;SHOULD MATCH CURRENT FINAL FIRST FREE ADDRESS
|
||
BUG.(CHK,COMCAW,D36COM,SOFT,<Core allocation wrong>,,,RTN)
|
||
>; END IFN FTOPS10
|
||
SETOM D36IFG ;Flag that DECnet is now initialized
|
||
RET ;RETURN
|
||
|
||
IFN FTOPS10,<
|
||
;INITIALIZE MEMORY MANAGEMENT STUFF FOR THE -10
|
||
|
||
M10INI: XMOVEI P4,DCNACB## ;GET ADDRESS OF DECNET ALLOCATION CONTROL BLOCK
|
||
XMOVEI P3,DCNAHB ;AND ADDRESS OF ALLOCATION HEADER BLOCK
|
||
XMOVEI P2,DCNAEB ;AND ADDRESS OF ALLOCATION EXTENT BLOCK
|
||
MOVEM P3,ACBAHB(P4) ;LINK BLOCKS TOGETHER
|
||
SETZM AHBNXT(P3) ;...
|
||
MOVEM P2,AHBAEB(P3) ;...
|
||
SETZM AEBNXT(P2) ;...
|
||
MOVE T1,ACBCSZ(P4) ;GET CHUNK SIZE IN WORDS
|
||
MOVEM T1,AHBCSZ(P3) ;INITIALIZE ALLOCATION HEADER BLOCK
|
||
MOVE T1,ACBSEC(P4) ;GET SECTION NUMBER OF ALLOCATION
|
||
MOVEM T1,AHBSEC(P3) ;INITIALIZE ALLOCATION HEADER BLOCK
|
||
MOVE T1,ACBINI(P4) ;GET INITIAL ALLOCATION AMOUNT IN WORDS
|
||
MOVEM T1,AHBFRE(P3) ;INITIALIZE ALLOCATION HEADER BLOCK
|
||
MOVEM T1,AHBLWM(P3) ;...
|
||
MOVEM T1,AHBINI(P3) ;...
|
||
MOVEM T1,AHBCUR(P3) ;...
|
||
MOVEM T1,AEBFRE(P2) ;INITIALIZE ALLOCATION EXTENT BLOCK
|
||
MOVEM T1,AEBLWM(P2) ;...
|
||
MOVEM T1,AEBSIZ(P2) ;...
|
||
MOVE T1,ACBTHR(P4) ;GET THRESHOLD ALLOCATION AMOUNT IN WORDS
|
||
MOVEM T1,AHBTHR(P3) ;INITIALIZE ALLOCATION HEADER BLOCK
|
||
MOVE T1,ACBINC(P4) ;GET INCREMENTAL ALLOCATION AMOUNT IN WORDS
|
||
MOVEM T1,AHBINC(P3) ;INITIALIZE ALLOCATION HEADER BLOCK
|
||
MOVE T1,ACBMIN(P4) ;GET MINIMUM ALLOCATION AMOUNT IN WORDS
|
||
MOVEM T1,AHBMIN(P3) ;INITIALIZE ALLOCATION HEADER BLOCK
|
||
MOVE T1,ACBMAX(P4) ;GET MAXIMUM ALLOCATION AMOUNT IN WORDS
|
||
MOVEM T1,AHBMAX(P3) ;INITIALIZE ALLOCATION HEADER BLOCK
|
||
SETZM AHBPND(P3) ;CLEAR PENDING ALLOCATION AMOUNT
|
||
MOVE T1,AEBSIZ(P2) ;GET SIZE OF ALLOCATION EXTENT
|
||
IDIV T1,AHBCSZ(P3) ;COMPUTE NUMBER OF CHUNKS
|
||
ADDI T1,^D35 ;COMPUTE SIZE OF BITMAP
|
||
IDIVI T1,^D36 ; (REMAINDER IN T2)
|
||
PUSH P,T2 ;SAVE FOR A MOMENT
|
||
PUSHJ P,INICOR## ;ALLOCATE CORE
|
||
MOVN T3,T1 ;CREATE AOBJN POINTER TO BITMAP
|
||
HRLS T3 ;...
|
||
HRR T3,T2 ;GET START ADDRESS OF ALLOCATED CORE
|
||
MOVEM T3,AEBBMP(P2) ;SAVE AOBJN POINTER TO BITMAP
|
||
ADD T1,T2 ;COMPUTE LAST WORD IN BITMAP
|
||
POP P,T2 ;GET REMAINDER BACK
|
||
SUBI T2,^D35 ;CALCULATE NUMBER OF BITS TO MARK OFF
|
||
MOVNS T2 ; IN LAST WORD OF BITMAP
|
||
SETO T4, ;START WITH A COMPLETE MASK
|
||
LSH T4,(T2) ;COMPUTE MASK OF BITS TO KEEP
|
||
SETCAM T4,-1(T1) ;MARK OFF APPROPRIATE BITS IN LAST WORD
|
||
;FOLLOWING CODE ALLOCATES SPACE FOR DECNET BUFFERS
|
||
IFE FTXMON,<
|
||
PUSHJ P,DCNCCR ;GET TOTAL WORDS REQUIRED IN T1
|
||
ADD T1,DCNAEB+AEBSIZ ;PLUS SIZE OF BITMAP POOL
|
||
PUSHJ P,INICOR## ;ALLOCATE CORE
|
||
MOVEM T2,DCNAEB+AEBADR ;SAVE BITMAP POOL ADDRESS
|
||
ADD T2,DCNAEB+AEBSIZ ;OFFSET TO START OF USABLE CORE
|
||
MOVEM T2,DCNCOR ;SAVE ADDRESS OF DECNET CORE
|
||
> ;END IFE FTXMON
|
||
IFN FTXMON,<
|
||
PUSHJ P,DCNCCR ;GET TOTAL DECNET WORDS REQ'D IN T1
|
||
ADD T1,DCNAEB+AEBSIZ ;ADD AMOUNT FOR BITMAP POOL
|
||
MOVEI T2,PG.BDY(T1) ;ROUND UP TO PAGE BOUNDARY
|
||
TRZ T2,PG.BDY ;...
|
||
MOVEI T1,(MS.DCN) ;SECTION NUMBER
|
||
PUSHJ P,GFWNZN## ;ASK ONCMOD FOR THE CORE
|
||
HALT . ;** FOR NOW
|
||
MOVEM T1,DCNAEB+AEBADR ;SAVE AS ADDRESS OF BITMAP POOL
|
||
ADD T1,DCNAEB+AEBSIZ ;OFFSET PAST BITMAP POOL
|
||
MOVEM T1,DCNCOR ;SAVE AS STARTING ADDRESS OF DECNET CORE
|
||
> ;END IFN FTXMON
|
||
POPJ P, ;RETURN
|
||
|
||
> ;END IFN FTOPS10
|
||
SUBTTL DCNJIF - DECnet Once-a-jiffy check
|
||
|
||
INTERNAL DCNJIF
|
||
XRENT DCNJIF
|
||
|
||
CALL RTRJIF ;Call ROUTER
|
||
IFN FTOPS10,<
|
||
SKPCPU (0) ;On policy CPU?
|
||
RET ;No, return now
|
||
>; END IFN FTOPS10
|
||
|
||
CALL DNDJIF ;Call DNADLL
|
||
CALLRET NSPJIF ;And LLINKS
|
||
SUBTTL DCNSEC - DECnet Once-a-second check
|
||
|
||
INTERNAL DCNSEC
|
||
XRENT DCNSEC
|
||
|
||
IFN FTOPS20,<
|
||
MOVEI T1,^D1000 ;Get milliseconds in dcnsec interval
|
||
MOVEM T1,DCNTIM ;Initialize count-down in stg
|
||
> ;END IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
SOSG DCNTIM ;Time for XDCNJB checks?
|
||
CALL XDCNJB ;Yes, do periodic checks
|
||
>; END IFN FTOPS10
|
||
|
||
CALL RTRSEC ;Call ROUTER's second routine
|
||
CALLRET SCTSEC ;Call SCLINK's second routine and return
|
||
|
||
SUBTTL DCNJB0 - DECnet periodic checks
|
||
|
||
INTERNAL DCNJB0
|
||
XNENT DCNJB0
|
||
|
||
IFN FTOPS10,<
|
||
MOVEI T1,^D10 ;Reset DCNJB0 interval
|
||
MOVEM T1,DCNTIM ;...
|
||
>; END IFN FTOPS10
|
||
CALLRET NSPJB0 ;Call NSP periodic check and return
|
||
|
||
SUBTTL DCNMOV - SET MEMORY OFFLINE Support
|
||
|
||
|
||
IFN FTOPS10,<
|
||
IFN FTLOCK,<
|
||
INTERNAL DCNMOV
|
||
XNENT DCNMOV
|
||
|
||
CALL SCTMOV## ;Have SCLINK move any name/address pages
|
||
RET
|
||
>; END IFN FTLOCK
|
||
>; END IFN FTOPS10
|
||
SUBTTL NMX -- Privilege checking routine.
|
||
|
||
INTERNAL NMXPRV
|
||
XSWAPCD
|
||
NMXPRV:
|
||
LLMPRV:: ;USED BY LLMOP
|
||
IFN FTOPS10,<
|
||
MOVSI T1,JP.POK ;PRIVILEGE BIT.
|
||
MCALL (RG,MSEC1,PRVBIT##) ;ASK MONITOR IF ALLOWED.
|
||
RETSKP ;HE IS
|
||
RET ;RETURN TO USER
|
||
>
|
||
IFN FTOPS20,<
|
||
MOVE T1,CAPENB ;ENABLED CAPABILITES
|
||
TXNN T1,<SC%WHL+SC%OPR> ;WHEEL OR OPERATOR?
|
||
RNMXER (CAPX1) ;NO, RETURN LACK OF PRIVS
|
||
RETSKP
|
||
>
|
||
SUBTTL NMX -- Time stamp a queued even block
|
||
;NMXTIM - Time stamp a queued event block.
|
||
;Call
|
||
; TOPS-20:
|
||
; T1/ Todclk of event.
|
||
;Return
|
||
; RET always,
|
||
; T1/ Number of julian half days,
|
||
; T2/ Number of seconds into current half day,
|
||
; T3/ Number of milliseconds into current second.
|
||
|
||
INTERNAL NMXTIM
|
||
XSWAPCD
|
||
NMXTIM:
|
||
IFN FTOPS10,<
|
||
MOVE T1,DATE## ;GET CURRENT UDT (IN DAYS,,FRACTION)
|
||
MOVE T2,TIME## ;GET CURRENT TIME (IN JIFFIES SINCE MIDNIGHT)
|
||
LSH T1,-^D17 ;TRUNCATE TO NUMBER OF HALF DAYS.
|
||
SUBI T1,124210_1 ;CONVERT DAYS SINCE 1858 TO DAYS SINCE 1977
|
||
MOVE T3,[^D60*^D60*^D12]
|
||
IMUL T3,TICSEC## ;SECONDS SINCE HALF-DAY
|
||
TRNE T1,1 ;IS THIS THE SECOND HALF OF A DAY?
|
||
SUB T2,T3 ;YES, RECORD SECONDS SINCE HALF-DAY
|
||
IDIV T2,TICSEC## ;CONVERT JIFFIES INTO SECONDS.
|
||
IMULI T3,^D1000 ;CONVERT TO NUMBER OF MILLISECONDS*TICSEC
|
||
IDIV T3,TICSEC## ;CONVERT TO NUMBER OF MILLISECONDS.
|
||
SKIPL T2 ;MAKE SURE WE HAVE A POSITIVE NUMBER OF SECONDS
|
||
TDNE T1,[XWD -1,600000] ;MAKE SURE NO DATE OVERFLOW
|
||
BUG.(HLT,COM911,D36COM,SOFT,<The date is past 9 November 2021>,,<
|
||
|
||
Cause: The 2 byte julian half-day field in an event message is limited
|
||
to 9 november 2021. The routine above has calculated the julian
|
||
half-day, and has found that it overflowed.
|
||
|
||
I doubt very much that the date itself has really gone past 2021.
|
||
Probably someone smashed an AC or the routine to get the time
|
||
from the monitor is returning junk.
|
||
>)
|
||
RET
|
||
>;END IFN FTOPS10
|
||
|
||
IFN FTOPS20,<
|
||
; Enter here with Todclk in T1
|
||
SAVEAC <Q1,Q2>
|
||
STKVAR <ROUND> ;rounding flag
|
||
SETZM ROUND ;intialize
|
||
;duplicate of LGTAD, except no rounding, and save the leftover
|
||
MUL T1,[1B17] ;shift binary point
|
||
DIV T1,JFDAY ;time since startup in T1, remainder in T2
|
||
HLRZ Q1,T2 ;convert remainder to ms, and save
|
||
HRRZ Q2,T2 ;save the pittance that is left
|
||
ADD T1,TADIDT ;data & time in T1 internal format
|
||
; (except leftover ms)
|
||
;find out if ODCNV% will round up.
|
||
HRRZ T3,T1 ;get time
|
||
MULI T3,FULDAY ; will ODCNV%
|
||
DIV T3,[1B17] ; round up
|
||
CAIL T4,400000 ; one second ?
|
||
SETOM ROUND ;it will. remember this
|
||
;compute leftover milliseconds.
|
||
HRRZ T3,T1 ;get time again
|
||
MUL T3,JFDAY ;convert back to ms
|
||
ADD T4,Q2 ; add that pittance to least sig. word
|
||
DIV T3,[1B17] ; end of computation.
|
||
MOVE Q2,T3 ;save it
|
||
IDIVI T3,^D1000 ; modulo
|
||
IMULI T3,^D1000 ; one
|
||
SUB Q2,T3 ; thousand
|
||
ADD Q1,Q2 ;total leftover milliseconds
|
||
;get date & time
|
||
MOVE T2,T1 ;convert internal time to years, Julian
|
||
MOVX T4,<IC%JUD> ; days & seconds
|
||
ODCNV% ;(T2,T4/T2,T4)
|
||
;...
|
||
|
||
;...
|
||
;convert date to Julian half days
|
||
HLRZ T1,T2 ;get year
|
||
CAIL T1,FYEAR ;range
|
||
CAIL T1,FYEAR+YRTABL ; check
|
||
BUG.(CHK,NMXTBG,JNTMAN,SOFT,<NMXTIM table obsolete>,,<
|
||
|
||
Cause: The table used by NMXTIM is obsolete.
|
||
|
||
Action: Create a new table.
|
||
|
||
>,RTN)
|
||
MOVE T1,YEARTB-FYEAR(T1) ;get number of days before this year
|
||
HRRZS T2 ;isolate days
|
||
SOS T2 ;don't count today.. it's not over yet.
|
||
ADD T1,T2 ;total days
|
||
LSH T1,1 ; half days
|
||
;diddle milliseconds & seconds
|
||
HRRZ T2,T4 ;seconds since midnight
|
||
MOVE T3,Q1 ;milliseconds in T3
|
||
CAIGE T3,^D1000 ;too many milliseconds ?
|
||
IFSKP.
|
||
SUBI T3,^D1000 ;yes. make them small.
|
||
AOS T2 ;increment seconds
|
||
ENDIF.
|
||
SKIPN ROUND ;did ODCNV% round up ?
|
||
IFSKP.
|
||
SOSL T2 ;yes. take that second away. cross half day ?
|
||
IFSKP.
|
||
SOS T1 ;yes. take away a half day,
|
||
MOVEI T2,HLFDAY-1 ; and make a lot of seconds
|
||
ENDIF.
|
||
ENDIF.
|
||
NMXTM1: CAIGE T2,HLFDAY ;too many seconds ?
|
||
IFSKP.
|
||
SUBI T2,HLFDAY ;yes. make them small.
|
||
AOS T1 ;increment half days
|
||
JRST NMXTM1 ;and try again.
|
||
ENDIF.
|
||
RET
|
||
ENDSV. ;end STKVAR
|
||
|
||
FULDAY=^D<24*3600> ;the number of seconds in a day
|
||
HLFDAY=^D<12*3600> ;the number of seconds in a half day
|
||
;this table gives the number of julian days since (& including) JAN 1 1977
|
||
; for the years FYEAR (=1982) to FYEAR+YRTABL-1
|
||
FYEAR=^D1982 ;the first year in this table
|
||
YEARTB: ^D1826
|
||
^D2191
|
||
^D2556
|
||
^D2922
|
||
^D3287
|
||
^D3652
|
||
^D4017
|
||
^D4383
|
||
^D4748
|
||
^D5113
|
||
^D5478
|
||
^D5844
|
||
^D6209
|
||
^D6574
|
||
^D6939
|
||
^D7305
|
||
^D7670
|
||
^D8035
|
||
^D8400
|
||
|
||
YRTABL=.-YEARTB
|
||
XRESCD
|
||
>
|
||
SUBTTL TOPS20 -- User mode checking routines.
|
||
IFN FTOPS20,<
|
||
;CHKBPT - Check out a byte pointer the user has passed us.
|
||
;Byte size must be null or 8 bit bytes.
|
||
;Returns +1 on failure with error in T1
|
||
;Returns +2 on success preserving T1 & T2
|
||
;Uses T3
|
||
|
||
INTERNAL CHKBPT
|
||
XRESCD
|
||
CHKBPT: JUMPE T1,RSKP ;IF NULL, THAT IS O.K.
|
||
LDB T3,[POINT 6,T1,11] ;GET THE USER'S BYTE SIZE
|
||
CAIN T3,^D8 ;8 BIT BYTES?
|
||
RETSKP ;YES, ALL O.K.
|
||
MOVX T1,NEADC% ;NO, RETURN AN ERROR
|
||
RET
|
||
> ;END IFN FTOPS20
|
||
SUBTTL End of D36COM
|
||
|
||
IFN FTOPS20, TNXEND
|
||
IFN FTOPS20,<
|
||
|
||
;Hack for section testing
|
||
INTERNAL $TSTS6
|
||
RESCD
|
||
;Come here with JSP CX,$TSTS6
|
||
$TSTS6: PUSH P,CX ;Save return address
|
||
XHLLI CX,.
|
||
HLRZS CX
|
||
CAIN CX,XCDSEC
|
||
JRST $TSTS7
|
||
PUSH P,T1
|
||
MOVE T1,(P)
|
||
BUG. (CHK,NISEC6,D36COM,SOFT,<Not in section 6>,<<T1,CALADR>>,<
|
||
|
||
Cause: Code that should be running in section 6 is not.
|
||
|
||
Data: CALADR - Address of routine not in section 6
|
||
>)
|
||
POP P,T1
|
||
$TSTS7: POP P,CX
|
||
JRST (CX)
|
||
> ;END IFN FTOPS20
|
||
|
||
IFN FTOPS10,<
|
||
RESDT
|
||
D36LOW::!
|
||
XRESCD
|
||
>; END IFN FTOPS10
|
||
END
|