Trailing-Edge
-
PDP-10 Archives
-
BB-H138E-BM
-
6-1-sources/knildr.mac
There are 8 other files named knildr.mac in the archive. Click here to see a list.
; UPD ID= 117, SNARK:<6.1.UTILITIES>KNILDR.MAC.16, 23-Apr-85 17:52:29 by GROSSMAN
;More TCO 6.1.1338 - Update edit # to 9.
; UPD ID= 116, SNARK:<6.1.UTILITIES>KNILDR.MAC.15, 23-Apr-85 17:49:54 by GROSSMAN
;TCO 6.1.1338 - Make BADFIL check ATOFLG.
; UPD ID= 101, SNARK:<6.1.UTILITIES>KNILDR.MAC.14, 20-Mar-85 14:02:11 by GROSSMAN
;Even more TCO 6.1.1226 - Dump the PS block too! Edit # 8
; UPD ID= 100, SNARK:<6.1.UTILITIES>KNILDR.MAC.13, 20-Mar-85 13:08:19 by GROSSMAN
;More TCO 6.1.1226 - Dump PCB and LAR also. Edit # 7.
; UPD ID= 96, SNARK:<6.1.UTILITIES>KNILDR.MAC.12, 13-Mar-85 10:34:42 by GROSSMAN
;More TCO 6.1.1226 - Fix fencepost error in condition code dumper (CCPYLP).
; Edit # 6.
; UPD ID= 94, SNARK:<6.1.UTILITIES>KNILDR.MAC.11, 11-Mar-85 09:40:59 by GROSSMAN
;More TCO 6.1.1246 - Increment edit # to 5.
; UPD ID= 93, SNARK:<6.1.UTILITIES>KNILDR.MAC.10, 11-Mar-85 09:36:05 by GROSSMAN
;TCO 6.1.1246 - Add INFO VER and HELP command.
; UPD ID= 90, SNARK:<6.1.UTILITIES>KNILDR.MAC.9, 3-Mar-85 09:15:36 by GROSSMAN
;TCO 6.1.1226 - Enhance dumper to include 2910 stack, condition codes, and the
;used buffer list. Edit # 4.
; UPD ID= 89, SNARK:<6.1.UTILITIES>KNILDR.MAC.8, 26-Feb-85 10:51:17 by GROSSMAN
;TCO 6.1.1221 - Edit # 3. Make automatic mode dump to SYSTEM: instead of to
;connected directory.
; UPD ID= 65, SNARK:<6.1.UTILITIES>KNILDR.MAC.7, 1-Jan-85 17:04:16 by GROSSMAN
;TCO 6.1.1102 - Edit # 2. Restart the KLNI after reloading or dumping it.
; UPD ID= 49, SNARK:<6.1.UTILITIES>KNILDR.MAC.6, 19-Nov-84 19:14:47 by GROSSMAN
;More TCO 6.1.1060 - Set edit number to 1.
; UPD ID= 48, SNARK:<6.1.UTILITIES>KNILDR.MAC.5, 19-Nov-84 17:03:24 by GROSSMAN
;TCO 6.1.1060 - Support new microcode version # format. Use new NI% JSYS
; symbols.
; UPD ID= 42, SNARK:<6.1.UTILITIES>KNILDR.MAC.4, 13-Nov-84 03:09:51 by GROSSMAN
;Correct assembly errors by using new symbols.
; UPD ID= 41, SNARK:<6.1.UTILITIES>KNILDR.MAC.3, 13-Nov-84 01:32:27 by GROSSMAN
;TCO 6.1.1049 - Remove search of NISYM, as it is no more...
; UPD ID= 30, SNARK:<6.1.UTILITIES>KNILDR.MAC.2, 4-Sep-84 09:14:57 by GROSSMAN
; .REQUIRE MACREL to simplify build procedure.
; Program creation - Stu Grossman - August 1984
TITLE KNILDR - Loader/Dumper for KLNI's
SEARCH MACSYM,MONSYM,JOBDAT
SALL ; Suppress macro expansions
.REQUIRE SYS:MACREL
; AC defs
STDAC.
CHN=P4 ; Always holds the KLNI channel #
; Version numbers
VERWHO==0 ; Customer version number
VERMAJ==1 ; Major version number
VERMIN==0 ; Minor version number
VEREDT==^D9 ; Edit number
; Entry vector
ENTVEC: JRST KNILDR ; Normal start address
JRST KNIATO ; Automatic mode start address
<BYTE (3)VERWHO (9)VERMAJ (6)VERMIN (18)VEREDT> + VI%DEC
SUBTTL Macros
; DIE macro - Used when program encounters a fatal error
;
; DIE (nam,text)
;
; nam - 3 letter suffix for stopcode name. Must be unique.
; text - Long form explanation.
;
DEFINE DIE(nam,text)<JRST [HALTF%]>
; HLPTXT macro - Use this macro as the first instruction for a command.
; The text can then be automatically found by the help routine.
DEFINE HLPTXT(text)<TRN [ASCIZ |text|]>
; Handy macro's for dealing with the COMND% JSYS
; Command line init
DEFINE CMDINI <MOVEI T2,[FLDDB. (.CMINI)]
CALL DOCMND>
; Keyword parser
DEFINE GETKEY (table)<MOVEI T2,[FLDDB. (.CMKEY,,table)]
CALL DOCMND>
; Switch parser
DEFINE GETSWI (table,defalt)<MOVEI T2,[FLDDB. (.CMSWI,,table,,defalt)]
CALL DOCMND>
; Noise
DEFINE NOISE (phrase)<MOVEI T2,[FLDDB. (.CMNOI,,<-1,,[ASCIZ |phrase|]>)]
CALL DOCMND>
; Input file
DEFINE IFILE<MOVEI T2,[FLDDB.(.CMIFI)]
CALL DOCMND>
; Output file
DEFINE OFILE (defalt)<MOVEI T2,[FLDDB. (.CMOFI,,,,defalt)]
CALL DOCMND>
; Number
DEFINE GETNUM (radix)<MOVEI T2,[FLDDB. (.CMNUM,,radix)]
CALL DOCMND>
; Confirm
DEFINE CONFRM <CALL CNFIRM>
; Error message handler
DEFINE ERROR (text) <JRST [HRROI T1,[ASCIZ |text|]
JRST ERRTRM]>
SUBTTL Symbols
; These symbols describe the action that should be taken after dumping or
; reloading the KLNI.
.KYHLT==0 ; Halt the KLNI
.KYPRE==1 ; Preserve the state
.KYSTA==2 ; Start the KLNI
SUBTTL Device control bits
KNI==564 ; Device code for KLIPA
;CONI BITS - LEFT
CI.PPT==1B0 ;PORT PRESENT
CI.DCC==1B2 ;DIAG CSR CHANGE
CI.CPE==1B6 ;CRAM PARITY ERROR
CI.MBE==1B7 ;MBUS ERROR
CI.IDL==1B11 ;IDLE
CI.DCP==1B12 ;DISABLE COMPLETE
CI.ECP==1B13 ;ENABLE COMPLETE
;CONI/CONO BITS - RIGHT
CO.CPT==1B18 ;CLEAR PORT
CO.SEB==1B19 ;SELECT EBUF
CO.LAR==1B21 ;SELECT LAR
CO.SSC==1B22 ;DIAG SINGLE CYCLE
CI.EPE==1B24 ;EBUS PARITY ERROR
CI.FQE==1B25 ;FREE QUEUE ERROR
CI.DME==1B26 ;DATA MOVER ERROR
CO.CQA==1B27 ;COMMAND QUEUE AVAILABLE
CI.RQA==1B28 ;RESPONSE QUEUE AVAILABLE
CO.DIS==1B30 ;DISABLE
CO.ENA==1B31 ;ENABLE
CO.MRN==1B32 ;MICRO-PROCESSOR RUN
DO.LAD==1B0 ;BIT ON IN DATAO TO LOAD RAM ADDRESS REGISTER
DO.MSB==1B13 ;BIT ON IN DATAO TO LOAD HIGH ORDER UWORD
CI.ERR==CI.CPE!CI.MBE!CI.EPE!CI.DME
LSLEN==^D1024 ; Local storage length
CRMLEN==^D4096 ; Length of ucode memory
DEFSTR MICPC,,12,12 ;UPROC PC FIELD WHEN READ VIA A DATAI
; Microword field definitions
; This set of definitions is based on the KLPDDT storage format for CRAM
; locations. Each cram loc takes up two words right justified in bits
; 6-35 of each word.
BEGSTR MW
FILLER 6 ; First twelve bits are ignored
FIELD JMP,12 ; MWJMPFLD Microword Jump Address
FIELD PAR,1 ; MWPAR Microword Parity Bit
FIELD OEN,1 ; MWOUTPUTENA ALU Data Output Enable Bit
FIELD MGC,10 ; MWMGCFLD Magic Number Field
FIELD SRC,3 ; MWSORCEFLD ALU Source Input Field
FIELD FUN,3 ; MWFUNCTFLD ALU Function Field
NXTWRD ; Force us into the next word
FILLER 6 ; Jump to next word
FIELD DST,3 ; MWDESTFLD ALU Destination Output Field
FIELD CCE,1 ; MWCCENA Condition Code Enable Bit
FIELD RAM,1 ; MWRAMODE Local Storage RAM Mode Bit
FIELD PRA,4 ; MWPORTAFLD ALU Port "A" Address Field
FIELD PRB,4 ; MWPORTBFLD ALU Port "B" Address Field
FIELD SKP,5 ; MWSKIPFLD Microword Skip Field
FIELD BUS,3 ; MWBUSCTLFLD Microprocessor Bus Control Field
FIELD CRY,1 ; MWCARRY Microword Carry Input Bit to ALU
FIELD CTL,4 ; MWCTRLFLD Microseqr Control Input Field
FIELD TIM,1 ; MWTIMEFLD Microword Time Field Bit
FIELD UNU,2 ; MWSPARE0 & MWSPARE1 Unused
FIELD MRK,1 ; MWMARKBIT Microword Mark Bit
ENDSTR MW
; Version # fields in the ucode
DEFSTR MWMAJ,136*2+1,^D25,6 ; Major version #
DEFSTR MWMIN,136*2+1,^D29,4 ; Minor version #
DEFSTR MWEDT,137*2+1,^D29,^D10 ; Edit #
; Device code field of an I/O instruction
DEFSTR DVCOD,,9,7
SUBTTL KNILDR - Manual program start address
KNILDR: RESET%
MOVE P,STKAC ; Setup the stack pointer
SETZM ATOFLG ; Indicate we are in manual mode
; Initialize for command scanning
COMLOP: CMDINI ; Initialize the scanner
; Basic command loop
COMRPR: MOVE P,STKAC ; Reset the stack
GETKEY (CMDTBL) ; Parse the initial command
HRRZ T1,(T2) ; Get command routine address
CALL (T1) ; Call the processor
JRST COMLOP ; And jump back again
; Top level command table
DEFINE COMM(comand,flgs)<IFB <flgs>,<XWD [ASCIZ |comand|],.'comand>
IFNB <flgs>,<XWD [CM%FW+flgs
ASCIZ |comand|],.'comand>>
DEFINE ABR(comand,loc)<XWD [CM%FW+CM%ABR+CM%INV
ASCIZ |comand|],loc>
DEFINE NG(comand)<XWD [CM%FW+CM%NOR
ASCIZ |comand|],0>
CMDTBL: XWD CMDTLN,CMDTLN ; Length of command table
COMM DUMP ; Dump KLNI into a file
ABR E,.+4 ; Abbreviation for exit
NG ENABL ; Suppress abbreviations
COMM ENABLE,CM%INV ; Enable magical commands
ABR EX,.+1 ; "
COMM EXIT ; Exit the program
COMM EXTRACT,CM%INV ; Extract symbols from a .ULD file
COMM GET,CM%INV ; Get microcode from a file
COMM HALT ; Stop the KLNI
COMM HELP ; Obtain help
COMM INFORMATION ; Information about KLNI's
COMM LOAD ; Load microcode into the KLNI
COMM START ; Start the KLNI
ABR T,.+1 ; Abbreviation for TAKE
; COMM TAKE ; Take a command file
COMM TRANSLATE,CM%INV ; Translate a dump into human readable form
CMDTLN==.-CMDTBL-1
REPAR: JRST COMRPR
.TAKE:
.EXIT: HLPTXT <
EXIT - Exit the program.>
CONFRM ; Wait for the CRLF
HALTF%
RET
SUBTTL GET Command
; This command will read a .ULD file and put it's microcode into the buffer
; starting at location CRAM.
;
; Command format:
; KNILDR>GET (MICROCODE FROM FILE) FOO.ULD
;
.GET: HLPTXT <
GET - Reads the microassembler output and saves it in this core image.
After doing a GET, you should EXIT and SAVE the program to make
it permanent.>
SAVEAC P1
NOISE MICROCODE FROM FILE
IFILE ; Parse an input file
MOVE P1,T2 ; Put JFN in a safe place
CONFRM ; Eat the CRLF
MOVE T1,P1 ; Get JFN
MOVE T2,[FLD(7,OF%BSZ)+OF%RD] ; Open file for read, 7 bit bytes
OPENF% ; Open the file
ERJMP BADFIL
SETZM BUFCNT ; Reset the input buffer count
SETZM MICVAL ; Clear the valid micorcode flag
SETZM LINNUM ; Start line numbers at 1
SETZM NUMMIC ; Reset number of microwords read
SETZM CRAM ; Clear first word of CRAM buffer
MOVE T1,[CRAM,,CRAM+1] ; Prepare to BLT
BLT T1,CRAM+CRMLEN-1 ; the CRAM buffer away
MOVEM P1,JFN ; Put JFN in a safe place
SUBTTL .ULD file parsing routines
SAVEAC <P1,P2,P3>
NEWLIN: AOS LINNUM ; Increment the line counter
CALL REDCHR ; Read the first character of the line
JRST FILDON ; End of file
CAIN T1,";" ; Comment?
JRST COMENT ; Yes, eat the comment
CAIE T1,"[" ; Location indicator?
JRST FILDON ; Nope, we are done
CALL REDNUM ; Read in the PC
JRST FILERR ; Bad place to end the file
CAIE T2,"]" ; Did the PC terminate correctly?
JRST FILERR ; Nope, complain
CAILE T1,CRMLEN-1 ; Is the PC reasonable?
JRST FILERR ; PC out of range
MOVE P1,T1 ; Save the PC for a moment
LSH P1,1 ; Multiply the PC by 2
CALL REDCHR ; Get the next character
JRST FILERR ; Bad place to end the file
CAIE T1,"=" ; Is it an "="???
JRST FILERR ; Nope, bitch
CALL REDHLF ; Read half of a microword
JRST FILERR ; Bad place to end the file
MOVEM T1,CRAM+1(P1) ; Save the MSB's of the microword
CALL REDHLF ; Read half of a microword
JRST FILERR ; Bad place to end the file
MOVEM T1,CRAM(P1) ; Save the LSB's of the microword
AOS NUMMIC ; Increment the number of uwords loaded
CALL REDCHR ; Get a carriage return
JRST FILERR
CAIE T1,15 ; Carriage return?
JRST FILERR
EATLF: CALL REDCHR ; Get line feed
JRST FILERR
CAIE T1,12 ; Line feed?
JRST FILERR
JRST NEWLIN ; Back to the start of the line
; Here to eat comments
COMENT: CALL REDCHR ; Get a character
JRST FILDON ; End of file, quit
CAIE T1,15 ; Carriage return?
JRST COMENT ; Nope, try again
JRST EATLF ; Yes, go eat the line feed
FILDON: SKIPN NUMMIC ; Did we load any microcode?
JRST FILDO2 ; No, file was probably bogus
SETOM MICVAL ; Microcode is now valid
CALL .TYMPR ; Type out standard prefix
HRROI T1,[ASCIZ |Microcode version |]
PSOUT%
MOVX T1,CRAM ; Get address of ucode
CALL .TYMVR ; Type out the ucode version
HRROI T1,[ASCIZ | loaded]
|]
PSOUT%
FILDO2: CALL .TYMPR ; Type out standard prefix
MOVE T1,NUMMIC ; Get the number of uwords we loaded
CALL .TYDEC ; Type it out
HRROI T1,[ASCIZ | words of microcode loaded]
|]
PSOUT%
FILDO1: MOVE T1,JFN ; Get the JFN
CLOSF% ; Close the file
ERJMP .+1
RET ; All done
FILERR: CALL .TYEPR ; Type out standard prefix
MOVE T1,LINNUM ; Get the errant line number
CALL .TYDEC ; Type the number
HRROI T1,[ASCIZ | in file |]
PSOUT%
MOVX T1,.PRIOU ; Use primary output
MOVE T2,JFN ; Get the JFN
SETZ T3, ; Use default format control
JFNS% ; Print out the file name
HRROI T1,[ASCIZ |
|]
PSOUT% ; Finish off the line
JRST FILDO1 ; And close off the file
; Here when some file I/O error occurs
BADFIL: MOVE T2,T1 ; Get error code
CALL .TYJSE ; Type it out
SKIPN ATOFLG ; Are we in auto mode?
JRST COMLOP ; Nope, abort the command
RET ; Yes, just give error return
SUBTTL DUMP Command
; This command will dump the contents of a KLNI to a file. The local store,
; microcode stack, and ALU registers will be dumped.
;
; Command format:
;
; KNILDR>DUMP (CHANNEL) channel (TO FILE) filename
.DUMP: HLPTXT <
DUMP - This command will dump the variables of a KLNI into a file. It may
be used at any time, even when the KLNI is running.>
SAVEAC <P1,P2>
NOISE CHANNEL
GETNUM ^D10 ; Get the channel #
MOVE CHN,T2 ; Save the channel #
DPB CHN,DEFCHN ; Put the channel number into the filename
NOISE TO FILE
MOVEI T2,[FLD(.CMOFI,CM%FNC)+CM%DPP ; Output filespec
0 ; No data
0 ; No help message
-1,,DEFFIL] ; Pointer to default filespec
CALL DOCMND ; Do the COMND% jsys
MOVEM T2,JFN ; Save the JFN
GETSWI (STASWI,/PRESERVE-STATE)
HRRZ P1,(T2) ; Get the new state indicator
CONFRM ; Get the CRLF
CALL GETCHS ; Get the KLNIs current state
DIE CGS,
MOVE P2,T1 ; Save the state in a safe place
CALL DODUM1 ; Go do the actual dump
DMOVE T1,P1 ; Get the state disp and old state
CALLRET SETDSP ; Set the new state
SUBTTL LOAD command
; This command will reload a KLNI's microcode.
;
; Command format:
;
; KNILDR>LOAD (CHANNEL) channel
.LOAD: HLPTXT <
LOAD - Loads the KLNI's control store from the microcode contained in this
file.>
SAVEAC <P1,P2>
NOISE CHANNEL
GETNUM ^D10 ; Read the channel number
MOVE CHN,T2 ; Save the channel #
GETSWI (STASWI,/PRESERVE-STATE)
CONFRM ; Read the end of a line
HRRZ P1,(T2) ; Get the new state indicator
CALL GETCHS ; Get the current state
DIE CGS
MOVE P2,T1 ; Save the current state
CALL DORELD ; Do the actual reload
DMOVE T1,P1 ; Get the state disp and the old state
CALLRET SETDSP ; Set the state according to the disposition
DEFINE XX(cmdnum,comand)<XWD [ASCIZ |comand|],cmdnum>
STASWI: XWD STATLN,STATLN ; Length of command table
XX .KYHLT,HALT-ETHERNET-CHANNEL
XX .KYPRE,PRESERVE-STATE
XX .KYSTA,START-ETHERNET-CHANNEL
STATLN==.-STASWI-1
SUBTTL START command
; This command will start a KLNI.
;
; Command format:
;
; KNILDR>START (CHANNEL) channel
.START: HLPTXT <
START - Start the specified Ethernet channel.>
NOISE CHANNEL
GETNUM ^D10 ; Read the channel number
MOVE CHN,T2 ; Put it in a safe place
CONFRM
MOVX T1,.EISRN ; New state is RUN
CALL SETCHS ; Set the state
ERROR (Can't set channel state)
RET
SUBTTL HALT command
; This command will stop a KLNI.
;
; Command format:
;
; KNILDR>HALT (CHANNEL) channel
.HALT: HLPTXT <
HALT - Halt the specified Ethernet channel.>
NOISE CHANNEL
GETNUM ^D10 ; Read the channel number
MOVE CHN,T2 ; Put it in a safe place
CONFRM
MOVX T1,.EISOF ; New state is off
CALL SETCHS ; Set the state
ERROR (Can't set channel state)
RET
SUBTTL HELP Command
.HELP: HLPTXT <
HELP - Print this text.>
NOISE WITH KNILDR
CONFRM
SAVEAC P1
HRROI T1,[ASCIZ |
KNILDR is a utility used to perform various maintenance functions for the
NIA20 Ethernet controller. KNILDR can start and stop the NIA20 microcode,
it also can reload the NIA20's microstore. It can also dump the NIA20's
variables for later analysis. KNILDR is also run automatically by TOPS-20
whenever the NIA20 needs to be reloaded or dumped.
|]
PSOUT%
MOVE P1,[-CMDTLN,,CMDTBL+1] ; Get AOBJN pointer to command table
HLPLOP: HLRZ T1,(P1) ; Get the text address
MOVE T1,(T1) ; Get the first word of text
TLNE T1,774000 ; First byte 0?
JRST HLPOK ; Nope, help is on the way
TXNN T1,CM%FW ; Is this a flags word?
JRST HLPOK ; Nope, try helping him
TXNE T1,CM%INV ; Invisible?
JRST HLPNXT ; Yes, then don't help him
HLPOK: HRRZ T1,(P1) ; Get start address of routine
MOVE T1,(T1) ; Get first instruction of routine
HLRZ T2,T1 ; Get the opcode
CAIE T2,(TRN) ; Is it the magic value?
JRST HLPNXT ; Nope, keep trying
TLO T1,-1 ; Make it into a standard BP
PSOUT% ; Output the text
HRROI T1,[ASCIZ |
|]
PSOUT% ; Finish it off with a return
HLPNXT: AOBJN P1,HLPLOP ; Loop through the whole mess
HRROI T1,[ASCIZ |
|]
PSOUT%
RET ; All done!
SUBTTL ENABLE Command
.ENABLE:
NOISE MAGIC MODE
CONFRM
SAVEAC P1
MOVE P1,[-CMDTLN,,CMDTBL+1] ; Get AOBJN pointer to commands
ENABLP: HLRZ T1,(P1) ; Get addr of flags word
MOVE T2,(T1) ; Get the flags word
TLNE T2,774000 ; Possible flags word?
JRST ENBNXT ; Nope, try next command
TXNN T2,CM%FW ; Flags word?
JRST ENBNXT ; Nope, try next command
TXNN T2,CM%INV ; Invisible?
JRST ENBNXT ; Nope, don't bother
TXNE T2,CM%ABR ; Abbreviation?
JRST ENBNXT ; Yes, leave it alone
TXZ T2,CM%INV ; Make it visible
MOVEM T2,(T1) ; Put it back into the table
ENBNXT: AOBJN P1,ENABLP ; Loop through the whole mess
RET
SUBTTL INFORMATION Command
.INFORMATION:
HLPTXT <
INFORMATION -
Get information about various things.>
NOISE ABOUT
GETKEY (INFKEY) ; Get the subcommand
HRRZ T1,(T2) ; Get the routine address
CALLRET (T1) ; Call the sub-command processor
INFKEY: INFTLN,,INFTLN ; Length of command table
COMM VERSION ; Return the microcode version
INFTLN==.-INFKEY-1
.VERSION:
NOISE OF MICROCODE
CONFRM
SKIPN MICVAL ; Is the microcode valid?
ERROR This file does not contain valid microcode.
HRROI T1,[ASCIZ |
This file contains NIA20 microcode version |]
PSOUT%
MOVX T1,CRAM ; Get the address of the ucode
CALL .TYMVR ; Type out the version #
MOVX T1,[ASCIZ |.
|]
PSOUT%
RET ; All done!
SUBTTL EXTRACT Command - Extract symbols from a .ULD file
; This command will read the symbols from a .ULD file, and put them into an
; internal symbol table.
;
; Command format:
; KNILDR>EXTRACT (SYMBOLS FROM FILE) FOO.ULD
;
.EXTRACT:
SAVEAC P1
NOISE SYMBOLS FROM FILE
IFILE ; Parse an input file
MOVE P1,T2 ; Put JFN in a safe place
CONFRM ; Eat the CRLF
MOVE T1,P1 ; Get JFN
MOVE T2,[FLD(7,OF%BSZ)+OF%RD] ; Open file for read, 7 bit bytes
OPENF% ; Open the file
ERJMP BADFIL
SETZM BUFCNT ; Reset the buffer character count
MOVEM P1,JFN ; Put JFN in a safe place
MOVE T1,[POINT 7,[ASCIZ |
FIELD M=<14:23>
|]]
CALL SRCSTR ; Look for the field indicator
HALT . ; Couldn't find the field indicator
TRVAR <<SYMBUF,8>>
EXTRA1: CALL REDCHR ; Read the next character
JRST EXTRA2 ; All done, return
CAIE T1," " ; Did we get a space?
JRST EXTRA2 ; Nope, we're done
MOVE T1,[POINT 7,SYMBUF] ; Get pointer to symbol buffer
CALL REDSYM ; Read in the symbol
HALT .
MOVE P1,T1 ; Save length for a moment
CALL REDNUM ; Read the value
HALT .
CAIE T2,15 ; Did number terminate correctly?
HALT .
XMOVEI T2,SYMBUF ; Get pointer to symbol
MOVE T3,P1 ; Get length of symbol
CALL INSSYM ; Insert the symbol
CALL REDCHR ; Read the line feed
HALT .
CAIE T1,12 ; Is it a line feed?
HALT .
JRST EXTRA1 ; Loop over whole table
HALT .
; Here when done with file
EXTRA2: CALL FILDO1 ; Close the file
RET
SUBTTL TRANSLATE Command
; This command will convert a KLNI binary dump file into a human readable
; text file. Symbols will be used where possible.
;
; Command format:
; KNILDR>TRANSLATE (DUMP FILE) KLNI-0.DUMP (TO) KLNI-0.TXT
;
.TRANSLATE:
SAVEAC <P1,P2,P3>
NOISE DUMP FILE
IFILE ; Parse an input file
MOVE P1,T2 ; Put input JFN in a safe place
NOISE TO FILE
OFILE ; Parse an output file
MOVE P2,T2 ; Save output JFN
CONFRM ; Terminate the line
MOVE T1,P1 ; Get input JFN
MOVE T2,[FLD(^D36,OF%BSZ)+OF%RD] ; Open the file for read
OPENF% ; Open the file
ERJMP BADFIL
MOVE T1,P2 ; Get output JFN
MOVE T2,[FLD(7,OF%BSZ)+OF%WR] ; Open the file for write
OPENF% ; Open the file
ERJMP BADFIL
; First dump the local store, printing out the location symbolically
SETZ P3, ; Reset the location counter
DO.
MOVE T1,P3 ; Get current location
CALL LOKSYM ; Look it up
IFSKP. ; If we found it, print it symbolically
MOVE T4,T1 ; Put pointer in a safe place
DO.
MOVE T1,P2 ; Get output JFN
HRROI T2,1(T4) ; Get address of ASCIZ symbol name
SETZ T3, ; Terminate on 0
SOUT% ; Output the symbol name
MOVE T4,(T4) ; Get next symbol name
JUMPE T4,ENDLP. ; Jump if at end of chain
MOVX T2,"," ; Get a comma
BOUT% ; Output that
JRST TOP. ; And loop over all symbols
ENDDO.
ELSE. ; No symbol for this location
MOVE T1,P2 ; Get output JFN
MOVE T2,P3 ; Get location #
MOVX T3,8 ; Print it in octal
NOUT% ; Output it numerically
HALT .
ENDIF.
HRROI T2,[ASCIZ |/ |] ; Get seperator
SETZ T3, ; Terminate on null
SOUT% ; Output the seperator
MOVE T1,P1 ; Get input JFN
BIN% ; Input the location
MOVE T1,P2 ; Get the output JFN
MOVX T3,<NO%MAG!8> ; Output it in octal
NOUT% ; Output the contents
HALT .
HRROI T2,[ASCIZ |
|]
SETZ T3, ; Terminate on null
SOUT% ; Finish off the line
CAIGE P3,LSLEN-1 ; Did we do it all?
AOJA P3,TOP. ; Nope, loop over the entire mess
ENDDO.
MOVE T1,P2 ; Get the output JFN
CLOSF% ; Close the file
ERJMP BADFIL
MOVE T1,P1 ; Get the input JFN
CLOSF% ; Close input file
ERJMP BADFIL
RET
SUBTTL INSSYM - Insert a symbol into the symbol table
INSSYM: SAVEAC <P1,P2>
DMOVE P1,T1 ; Save value and pointer
SKIPL T1 ; Less than 0?
CAXLE T1,LSLEN ; Or larger than largest?
HALT .
ADDI T3,4+5 ; Round up to full word plus room for fwd ptr
IDIVI T3,5 ; Divide by chars/word
MOVE T1,T3 ; Setup length for GETMEM
CALL GETMEM ; Get some memory
HALT .
MOVE P2,T1 ; Save address
SETZM (P2) ; Clear forward ptr
MOVEI T1,-1(T3) ; Get length
MOVEI T3,1(P2) ; Point to space for symbol name
EXTEND T1,[XBLT] ; Copy the data
SKIPE SYMTAB(P1) ; Is there a symbol there already?
JRST INSSY1 ; Yes, loop down the chain
MOVEM P2,SYMTAB(P1) ; Nope, install the new symbol
RET
INSSY1: HRROI T1,[ASCIZ |
? Symbol conflict |]
PSOUT%
HRROI T1,1(P2)
PSOUT%
MOVX T1,"="
PBOUT%
MOVX T1,.PRIOU
MOVE T2,P1
MOVX T3,8
NOUT%
HALT .
HRROI T1,[ASCIZ |
|]
PSOUT%
; Now find the end of the symbol chain for this value and add this symbol
; to the list.
XMOVEI T1,SYMTAB(P1) ; Get the first entry
CNFLOP: MOVE T1,(T1) ; Get next entry
SKIPE (T1) ; Did we find the end?
JRST CNFLOP ; No, try again
MOVEM P2,(T1) ; Install this item
RET
SYMTAB: BLOCK LSLEN ; Symbol table
SUBTTL LOKSYM - Lookup a value in the symbol table
LOKSYM: MOVE T1,SYMTAB(T1) ; Fetch the symbol name
JUMPE T1,RTN ; Non-skip if no name
RETSKP ; Skip if name exists
SUBTTL REDSYM - Read a symbol
; Call: MOVX T1,BP to place to hold symbol
; CALL REDSYM
; <+1 Symbol terminated prematurely>
; <+2 Symbol read in, length (including 0 terminator) in T1>
;
REDSYM: MOVE T2,T1 ; Get symbol pointer in a safe place
SETZ T3, ; Initial length is 0
REDSY1: CALL REDCHR ; Read a character
RET ; EOF?
CAIE T1,177 ; Delete?
TRNN T1,140 ; Printable character?
RET ; Nope, fail
CAIN T1,"=" ; Did we get the proper terminator?
SETZ T1, ; Yes, turn it into a null
IDPB T1,T2 ; Stuff the character
ADDI T3,1 ; Increment the length
JUMPN T1,REDSY1 ; And loop over the whole mess
MOVE T1,T3 ; Get the length
RETSKP ; All done!
SUBTTL SRCSTR - Search for a string
; Call: MOVX T1,byte pointer to ASCIZ string
; CALL SRCSTR
; <+1 String not found>
; <+2 String found>
SRCSTR: MOVE T2,T1 ; Put BP into a safe place
SRCST1: MOVE T4,T2 ; Get fresh copy of the BP
SRCST2: ILDB T3,T4 ; Get a char from the string
JUMPE T3,RSKP ; If we ran out, we succeeded
CALL REDCHR ; Read a character from the file
RET ; Ran out of file, fail
CAIE T1,(T3) ; Character match?
JRST SRCST1 ; Nope, reset string and try again
JRST SRCST2 ; Yes, keep on going
SUBTTL KNIATO - Automatic program start address
KNIATO: RESET% ; Reset the universe (just in case)
MOVE P,STKAC ; Setup stack pointer
SETOM ATOFLG ; Indicate we are in automatic mode
CALL SRVALL ; Call the main service loop
NOP
SETZM ATOFLG ; No longer in automagic mode
HALTF% ; All done
JRST KNIATO ; Just in case
SUBTTL SRVALL - Main service loop
; Loop through all known KLNI's dumping or reloading them according to their
; channel state.
; Execute the following code once for each channel
SRVALL: SAVEAC P1
CALL ALLCHN
CALL GETCHS ; Get the channel's state
DIE CGS,<Can't get KLNI status>
MOVE P1,STATAB-.EISVG(T1) ; Fetch the bits for this state
TXNE P1,IGN ; Ignore?
RET ; Yes, just return
TXNE P1,DMP ; Do a dump?
CALL DODUMP ; Yes, go do a dump
TXNE P1,RLD ; Reload?
CALL DORELD ; Yes, go do a reload
MOVX T1,.EISRN ; Get the new state
CALL SETCHS ; Start the KLNI
DIE CSS,<Can't set KLNI status>
RET
; This table determines the actions KNILDR will take when the KLNI is in
; various states.
IGN==1B0 ; Ignore this state and do nothing to the KLNI
RLD==1B1 ; Reload the KLNI
DMP==1B2 ; Dump the KLNI
STATAB: IGN ; .EISVG - Virgin - has never run before
RLD ; .EISRE - Reload - reload requested
IGN ; .EISCR - Can't Reload - reload request timed out
IGN ; .EISIN - Init - waiting for response to first command
IGN ; .EISRN - Run - channel is running and can accept commands
DMP ; .EISDP - Dump - a dump has been requested
DMP!RLD ; .EISDR - Dump & Reload - dump followed by a reload request
IGN ; .EISBK - Broken - channel cannot be initialized
IGN ; .EISOF - Off - channel is off
SUBTTL DODUMP - Take a dump of a KLNI
; This routine will dump the contents of a KLNI into a file. The file
; will have the name KLNI-<channel #>.DUMP.
;
; Call: MOVX T1,new-channel-state-indicator
; MOVX CHN,channel #
; CALL DODUMP
; <Return +1 Always>
;
DODUMP: DPB CHN,ADFCHN ; Put the channel # into the filename
MOVX T1,GJ%SHT+GJ%FOU ; Open the file for output
HRROI T2,ADFFIL ; Get pointer to default filespec
GTJFN% ; Get the JFN
DIE (GFD,GTJFN failure during a dump)
MOVEM T1,JFN ; Put the JFN in a safe place
;Here from the DUMP command
DODUM1: CALL .TYMPR ; Type message prefix
HRROI T1,[ASCIZ |Dumping Ethernet channel |]
PSOUT%
MOVE T1,CHN ; Get the channel #
CALL .TYOCT
HRROI T1,[ASCIZ |]
|]
PSOUT%
MOVX T1,.PRIOU ; Get tty output JFN
DOBE ; Wait till console has printed the message
MOVE T1,JFN ; Get the JFN
MOVE T2,[FLD(^D36,OF%BSZ)+OF%WR] ; Open the file for write, PMAPS
OPENF% ; Open the file
ERJMP BADFIL
MOVX T1,WRDBLN ; Get the length of the buffer
MOVEM T1,BUFCNT ; Save it
MOVE T1,[POINT 36,CHRBUF] ; Get pointer to buffer
MOVEM T1,BUFPTR ; Save it
MOVX T1,.EISDP ; Set state to DUMP
CALL SETCHS ; Tell the monitor about it
ERROR <Can't put channel into DUMP state>
CALL SETDEV ; Setup the I/O instructions
USRIO% ; Try to get User I/O
ERROR Can't get user I/O
XCT DEVCNI ; Read the status bits
TXNE T1,CO.MRN ; Is the KLNI still running?
ERROR <Can't dump KLNI, microcode is still running>
CALL RDLAR ; Read the current PC
HALT .
MOVEM T1,SAVUPC ; Save the micro PC
MOVX T1,CI.EPE ; Don't blow up the word, just clear the
; nasty conditions.
XCT DEVCNO ; Tell the hardware about it
SAVEAC <P1>
CALL INICRM ; Initialize the CRAM for dumping
SUBTTL Dump the Condition Codes
SETZ P1, ; Reset the condition code number
CCLOP: MOVE T1,P1 ; Get the condition #
CALL RDCCOD ; Read the code
MOVEM T1,CCSAVE(P1) ; Save the condition code
CAIGE P1,17 ; Did we do them all?
AOJA P1,CCLOP ; Loop over all condition codes
SUBTTL Dump the 2901 registers
HRLZI P1,-21 ; Get AOBJN pointer for 2901 registers
L2901: HRRZ T1,P1 ; Get current register #
CALL RDAC ; Read the 2901 reg
MOVEM T1,ACS(P1) ; Save the register
AOBJN P1,L2901 ; And do all registers
SUBTTL Dump the Local Store
; Note that these routines destroy the contents of 2901 register 0.
HRLZI P1,-LSLEN ; Set up AOBJN pointer for local store
DMPLOP: SETZ T1, ; Clear DIAG SEL EBUF...
XCT DEVCNO ; Tell the hardware about it
MOVX T1,DO.LAD!DO.MSB+FLD(LSUCOD,MICPC) ; Point to MSB's
XCT DEVDTO ; Set the RAR
SETZ T3, ; Clear number of ones
HRRZ T1,P1 ; Get the local store address
CALL PARITY ; Setup MWPAR to generate correct parity
XOR T1,DMPCRM+LSUCOD*2 ; Get MSB's possibly complimenting MWPAR
STOR P1,MWMGC,+T1 ; Setup the magic number field
XCT DEVDTO ; Write loc 0 MSB's
MOVX T1,LSUCOD ; Get the starting PC
CALL STUCOD ; Start the microcode
DIE(EBS,Error bits set during dump)
CALL RDEBUF ; Read the EBUF into T1
HALT .
CALL PUTWRD ; Save the word
AOBJN P1,DMPLOP ; And try again
SUBTTL Copy the AC's from the 2901 into the file
HRLZI P1,-21 ; Get AOBJN ptr to ACs
CPYLOP: MOVE T1,ACS(P1) ; Get an AC
CALL PUTWRD ; Write it to the file
AOBJN P1,CPYLOP ; Loop over all AC's
SUBTTL Dump Used Buffer List
DMPUBL: MOVX T1,11 ; Disable link control reg
MOVX T2,377 ; Disable all bits
CALL WRPLI ; Disable link control
MOVX T1,1 ; Enable link control reg
MOVX T2,64 ; 512*32 memory + Enable Link + Int. loopback
CALL WRPLI ; Setup memory config + internal loopback
MOVX T1,6 ; Transmit action reg
MOVX T2,1 ; Reset transmit buffer address
CALL WRPLI ; Point to start of xmit buffer
MOVX T1,3 ; Write transmit buffer reg
MOVX T2,1 ; Use a multicast address
CALL WRPLI ; Send to multicast so that we receive our
; own transmissions
MOVX P1,200 ; Write 200 bytes
BLDXMB: MOVX T1,3 ; Write xmit buffer reg
MOVE T2,P1 ; Use the current count
CALL WRPLI ; Put in into the xmit buffer
SOJG P1,BLDXMB ; Write 200 bytes into xmit buffer
MOVX T1,6 ; Transmit action reg
MOVX T2,3 ; Write transmit end of frame
CALL WRPLI ; Terminate the buffer
MOVX P1,^D33 ; Transmit 32 times + 1 for good luck
SNDXMB: MOVX T1,6 ; Transmit action reg
MOVX T2,0 ; Transmit frame
CALL WRPLI ; Transmit the frame
MOVX T1,13 ; Read xmit status
CALL RDPLI ; Read the status
HALT .
SKIPE T1 ; Any problems?
JRST [TRC T1,3
TRNN T1,374 ; Any bad bits?
TRNN T1,3
TRNA
JRST FUX
AOS FOO#
JRST SNDXMB]
FUX: SOJG P1,SNDXMB ; Use up the free buffer list
MOVX P1,^D32 ; Read the entire used buffer list
REDUBL: MOVX T1,15 ; Read used buffer list
CALL RDPLI ; Read a used buffer
HALT .
CALL PUTWRD ; Write the entry into the file
SOJG P1,REDUBL ; Loop over all buffers
MOVX T1,11 ; Disable link control reg
MOVX T2,377 ; Disable everything
CALL WRPLI ; Tell the hardware about it
SUBTTL Dump 2910 Stack
MOVEI P1,5 ; Number of time to pop the stack
STKLOP: CALL RDSTAK ; Read the stack
CALL PUTWRD ; Write it out to the file
SOJG P1,STKLOP ; Loop over the whole stack
SUBTTL Copy the dumped condition codes into the file
HRLZI P1,-20 ; Get AOBJN pointer to cond codes
CCPYLP: MOVE T1,CCSAVE(P1) ; Get a cond code
CALL PUTWRD ; Write it out
AOBJN P1,CCPYLP ; Loop over the whole mess
SUBTTL Put the micro PC into the file
MOVE T1,SAVUPC ; Get the saved PC
CALL PUTWRD ; Write it out
SUBTTL Copy the PCB and the PS block into the dump file
MOVE T1,[SQUOZE 0,PCBSTG] ; Start address of PCB
MOVE T2,[SQUOZE 0,PB.LEN] ; Length of PCB
CALL CPYMON ; Copy the PCB into the dump file
JRST DMPEND ; Quit gracefully
MOVE T1,[SQUOZE 0,PRTSTG] ; Start address of port variables
MOVE T2,[SQUOZE 0,PS.LEN] ; Length of block
CALL CPYMON ; Copy the variables into the dump file
JRST DMPEND ; Quit gracefully
; All done with dumping, restore the CRAM locs we used
DMPEND: CALL RESCRM
; All done with the file, flush the output buffer and close the file.
SOS BUFCNT ; Correct for FLUSHO fencepost
CALL FLUSHO ; Flush the output buffer
MOVE T1,JFN ; Get the JFN
CLOSF% ; Close the file
ERJMP .+1
RET
SUBTTL DORELD - Reload a KLNI's microcode
; This routine will reload a KLNI's microcode. The microcode comes from
; a table built into the program. The contents of the table may be altered
; by a command given by a user.
;
; Call: MOVX T1,new-channel-state-indicator
; MOVX CHN,channel #
; CALL DORELD
; <Return +1 Always>
;
DORELD: SKIPN MICVAL ; Is the microcode valid?
ERROR Microcode is not valid
CALL .TYMPR ; Type message prefix
HRROI T1,[ASCIZ |Loading microcode version |]
PSOUT%
MOVX T1,CRAM ; Get address of ucode
CALL .TYMVR ; Type out it's version #
HRROI T1,[ASCIZ | into Ethernet channel |]
PSOUT%
MOVE T1,CHN ; Get the channel #
CALL .TYOCT
HRROI T1,[ASCIZ |]
|]
PSOUT%
MOVX T1,.PRIOU ; Get tty output JFN
DOBE ; Wait till console has printed the message
CALL SETDEV ; Setup the I/O instructions
USRIO% ; Try to get User I/O
ERROR Can't get user I/O
MOVX T1,.EISRE ; Set state to reload
CALL SETCHS ; Set the channel's state
ERROR <Can't stop the channel>
XCT DEVCNI ; Read the status bits
TXNE T1,CO.MRN ; Is the KLNI still running?
ERROR <Can't reload KLNI, microcode still running>
MOVX T1,CO.CPT ; Clear the port
XCT DEVCNO ; Tell the hardware about it
MOVX T1,DO.LAD ; Setup current CRAM address reg
MOVE T2,DEVBKO ; Get the BLKO
IORI T2,T3 ; Setup addr of IOWD
MOVE T3,[IOWD CRMBLN,CRAM] ; Setup IOWD pointer to ucode
RELLOP: XCT DEVDTO ; Set the CRAM address in the KLIPA
ADDX T1,1B13 ; Point to the next micro 1/2 word
XCT T2 ; Load in 1/2 a micro word
JRSTF @[RTN] ; All done, return & clear user I/O
JRST RELLOP ; Loop till done with load
SUBTTL GETCHS - Get the status of a channel
; Read the "substate" of a channel.
;
; Call: MOVX CHN,channel #
; CALL GETCHS
; <Error return>
; <Good return, T1/ channel state>
;
GETCHS: MOVX T1,.EIBMX ; Get length of arg block
STOR T1,EILEN,+NIBLOK ; Save it
MOVX T1,.EIRCI ; Function is Read Channel Info
STOR T1,EIFCN,+NIBLOK ; Save it
STOR CHN,EICHN,+NIBLOK ; Install the channel #
XMOVEI T1,NIBLOK ; Get arg block address
NI% ; Get the status from the monitor
ERJMP [RET] ; Non-ex channel??
LOAD T1,EISST,+NIBLOK ; Get the substate
RETSKP ; And return success
SETCHS: STOR T1,EISST,+NIBLOK ; Save the new state
MOVX T1,.EIBMX ; Get length of arg block
STOR T1,EILEN,+NIBLOK ; Save it
MOVX T1,.EISCS ; Function is Set Channel State
STOR T1,EIFCN,+NIBLOK ; Save it
STOR CHN,EICHN,+NIBLOK ; Install the channel #
XMOVEI T1,NIBLOK ; Get arg block address
NI% ; Get the status from the monitor
ERJMP [RET] ; Non-ex channel??
RETSKP ; And return success
SUBTTL SETDSP - Set KLNI state according to state disposition
; This routine will set the KLNI's state according to the state disposition
; contained in T1.
;
; Call: MOVX T1,state_disposition
; MOVX T2,old_state
; CALL SETDSP
; <Return +1 always>
SETDSP: XCT SETDS1-.KYHLT(T1) ; Get the new state
CALL SETCHS ; Get the new state
TRN
RET
SETDS1: MOVX T1,.EISOF ; New state is off
MOVE T1,T2 ; Preserve the state
MOVX T1,.EISRN ; New state is run
SUBTTL ALLCHN - Co-routine to loop through all channels
ALLCHN: PUSH P,CHN
MOVX CHN,0 ; Fudge up channel 0 for now
CALL @-1(P) ; Call back the caller
NOP
POP P,CHN ; Restore CHN
POP P,(P) ; Pop the caller off the stack
RET ; All done
SUBTTL SETDEV - Setup I/O instructions
; This routine will setup the locations DEVxyz to contain an I/O instruction
; for the correct device.
;
; Call: MOVX CHN,channel #
; CALL SETDEV
; <Return +1 Always>
;
SETDEV: CALL GETION ; Get the device code
DIE CGF,<Call to GETION failed>
STOR T1,DVCOD,DEVCNI ; CONI dev,T1
STOR T1,DVCOD,DEVCNO ; CONO dev,(T1)
STOR T1,DVCOD,DEVDTI ; DATAI dev,T1
STOR T1,DVCOD,DEVDTO ; DATAO dev,T1
STOR T1,DVCOD,DEVBKO ; BLKO dev,0
RET
SUBTTL GETION - Get I/O device # for a given channel #
GETION: MOVX T1,564_-2 ; Fudge this up for now
RETSKP
SUBTTL REDHLF - Read half of a microword
REDHLF: MOVEI T3,^D10 ; Just read 10 digits
SETZ T2, ; Clear receiving buffer
REDHL2: CALL REDCHR ; Read the next character
RET ; EOF??
CAIL T1,"0" ; Is it
CAILE T1,"7" ; numeric?
RET ; Nope, quit now
SUBI T1,"0" ; Turn character into a number
LSH T2,3 ; Make room for the new digit
IOR T2,T1 ; Install the new digit
SOJG T3,REDHL2 ; Loop for rest of digits
MOVE T1,T2 ; Get number into the right place
RETSKP ; All done
SUBTTL REDNUM - Read an octal number from the file
REDNUM: SETZ T2, ; Clear receiving buffer
REDNU2: CALL REDCHR ; Read the next character
RET ; EOF???
CAIL T1,"0" ; Is it
CAILE T1,"7" ; numeric?
JRST REDNU1 ; Nope, terminate
SUBI T1,"0" ; Turn character into a number
LSH T2,3 ; Make room for the new digit
IOR T2,T1 ; Install the new digit
JRST REDNU2 ; And do it all over again
REDNU1: EXCH T1,T2 ; T1 gets number, T2 gets terminator
RETSKP ; Return success
SUBTTL REDCHR - Low level file I/O
REDCHR: SOSGE BUFCNT ; Anything left in the buffer?
JRST REDCH1 ; Nope, try to get another buffer
ILDB T1,BUFPTR ; Get a character from the buffer
RETSKP ; And return
REDCH1: PUSH P,T2 ; Preserve T's
PUSH P,T3
MOVE T1,JFN ; Get JFN
MOVE T2,[POINT 7,CHRBUF] ; Get pointer to character buffer
MOVEM T2,BUFPTR ; Save it
MOVX T3,CHRBLN ; Get length of character buffer
SIN% ; Read the data
SUBI T3,CHRBLN ; Compute negative length of data
MOVNM T3,BUFCNT ; Save the buffer length
POP P,T3
POP P,T2
SKIPN BUFCNT ; Did we read anything this time?
RET ; Nope, give non-skip return
JRST REDCHR ; And fetch the next character
PUTWD1: CALL FLUSHO ; Flush the output buffer
PUTWRD: SOSGE BUFCNT ; Any room left in the buffer?
JRST PUTWD1 ; Nope, write it out
IDPB T1,BUFPTR ; Yes, deposit the byte
RET ; All done
FLUSHO: SAVEAC <T1,T2,T3> ; Preserve all AC's
MOVE T1,JFN ; Get JFN
MOVE T2,[POINT 36,CHRBUF] ; Get pointer to buffer
MOVEM T2,BUFPTR ; Save it
AOS T3,BUFCNT ; Get # of words left in buffer
SUBI T3,WRDBLN ; Compute # of words written
SOUT% ; Write the data
MOVX T1,WRDBLN ; Get the length of the buffer
MOVEM T1,BUFCNT ; Save the buffer length
RET
SUBTTL DOCMND - Do a COMND% JSYS
DOCMND: MOVEI T1,CSB ; Get address of command state block
COMND% ; Do the command
ERJMP [DIE CMF,<COMND% JSYS FAILED>] ; Error, complain
TXNN T1,CM%NOP ; No parse?
RET ; Nope, return to the user
DOCMN1: CALL .TYJSE ; Type out a JSYS error
JRST COMLOP ; Abort the command
SUBTTL Error recovery
; Here to print an error message and terminate a command
ERRTRM: CALL .TYERR ; Type out the error message
SKIPN ATOFLG ; Are we in auto mode?
JRST COMLOP ; No, just abort the command
RET ; Yes, return failure
; Here to type out a JSYS error
.TYJSE: HRROI T1,ERRBUF ; Point to error buffer
HRLI T2,.FHSLF ; Use our process handle
MOVX T3,ERRBLN
ERSTR% ; Print out the error
JFCL
JFCL
HRROI T1,ERRBUF ; Restore pointer to error buffer
; Here to type out a standard error message
.TYERR: PUSH P,T1 ; Preserve error message
CALL .TYEPR ; Type error prpefix
POP P,T1 ; Restore the error message
PSOUT% ; Type out the message
HRROI T1,[ASCIZ |
|]
PSOUT%
RET
.TYEPR: HRROI T1,[ASCIZ | KNILDR: |]
ESOUT% ; Type out the error prefix
RET
.TYMPR: HRROI T1,[ASCIZ |[KNILDR: |] ; Type message prefix
PSOUT%
RET
; Type ucode version
.TYMVR: SAVEAC P1
MOVE P1,T1 ; Save CRAM address
LOAD T1,MWMAJ,(P1) ; Get the major version number
CALL .TYOCT ; Type it out
LOAD T2,MWMIN,(P1) ; Get the minor version number
JUMPE T2,TYMVR1 ; Skip this if its 0
MOVX T1,"." ; Get a .
PBOUT% ; Type out a .
MOVE T1,T2 ; Get the minor version #
CALL .TYOCT ; Type out the minor version #
TYMVR1: LOAD T2,MWEDT,(P1) ; Get the edit #
JUMPE T2,RTN ; Skip this if 0
MOVX T1,"(" ; Get a paren
PBOUT% ; Type it out
MOVE T1,T2 ; Get edit #
CALL .TYOCT ; Type it out
MOVX T1,")" ; Get the other paren
PBOUT% ; Type out the paren
RTN: RET
; Here to do a .CMCFM function
CNFIRM: SAVEAC <T1,T2,T3,T4> ; Preserve all AC's
MOVEI T2,[FLDDB. (.CMCFM)] ; Parse a <CRLF>
CALLRET DOCMND ; Do the COMND% JSYS
SUBTTL .TYxxx
.TYOCT: SKIPA T3,[8] ; Type out an octal number
.TYDEC: MOVX T3,^D10 ; Use radix 10
MOVE T2,T1 ; Get number into the right AC
MOVX T1,.PRIOU ; Get primary output designator
NOUT% ; Type out the number
ERJMP [DIE NOF,<NOUT FAILURE>]
RET
SUBTTL RDCRAM and WRCRAM
;ROUTINE TO READ A CRAM LOCATION
;CALL: MOVx T1,cram-address
; CALL RDCRAM
; <+1 COULDN'T READ CRAM BECAUSE UCODE WAS RUNNING>
; <+2 T1 6-35 CONTAINS CRAM MSB'S, T2 6-35 CONTAINS CRAM LSB'S>
RDCRAM: MOVE T4,T1 ; Save the PC in a safe place
XCT DEVCNI ; Read the port's status
TXNE T1,CO.MRN ; Is the port running?
RET ; Yes, quit now
SETZ T1, ; Get new status bits
XCT DEVCNO ; Make sure CO.LAR is clear
STOR T4,MICPC,T1 ; Put the PC in the right place
TXO T1,DO.LAD!DO.MSB ; Set up to read the MSB's
XCT DEVDTO ; Tell the hardware about it
XCT DEVDTI ; Get contents of high order part of CRAM
TXZ T1,77B5 ; Clear out 0-5 since they are meaningless
MOVE T2,T1 ; Put MSB's in a safe place
SETZ T1, ; Clear PC
STOR T4,MICPC,T1 ; Put the PC into the right place
TXO T1,DO.LAD ; Setup to load a new address
XCT DEVDTO ; Set the new address
XCT DEVDTI ; Get contents of low order part of CRAM
TXZ T1,77B5 ; Clear out 0-5 since they are meaningless
EXCH T1,T2 ; T1 gets MSB's, T2 gets LSB's
RETSKP
;ROUTINE TO WRITE A CRAM LOCATION
;CALL: MOVx T1,cram-address
; MOVx T2,cram-msbs
; MOVx T3,cram-lsbs
; CALL WRCRAM
; <+1 COULDN'T WRITE CRAM BECAUSE UCODE WAS RUNNING>
; <+2 Successful>
WRCRAM: MOVE T4,T1 ; Put PC into the right place
XCT DEVCNI ; Get the status bits
TXNE T1,CO.MRN ; Is the port running?
RET ; Yes, quit now
SETZ T1, ; Get new status
XCT DEVCNO ; Clear CO.LAR
STOR T4,MICPC,T1 ; Put the PC in the right place
TXO T1,DO.LAD!DO.MSB ; Set up to write the MSB's
XCT DEVDTO ; Tell the hardware about it
TXZ T2,77B5 ; Clear out 0-5 since they are meaningless
MOVE T1,T2 ; Get MSB's into T1
XCT DEVDTO ; Write contents of high order part of CRAM
SETZ T1, ; Clear PC
STOR T4,MICPC,T1 ; Get PC again
TXO T1,DO.LAD ; Set up to write the LSB's
XCT DEVDTO ; Tell the hardware about it
TXZ T3,77B5 ; Clear out 0-5 since they are meaningless
MOVE T1,T3 ; Get LSB's into T1
XCT DEVDTO ; Write contents of low order part of CRAM
RETSKP
SUBTTL INICRM - Load up microprograms for dumping things
INICRM: SAVEAC P1
SETZ P1, ; Reset location counter
INILOP: MOVE T1,P1 ; Get current location
CALL RDCRAM ; Read the CRAM
HALT .
MOVE T3,P1 ; Get the loc
LSH T3,1 ; *2
DMOVEM T1,SAVCRM(T3) ; Save the current CRAM contents
DMOVE T2,DMPCRM(T3) ; Get the ucode for this loc
MOVE T1,P1 ; Get the loc into T1
CALL WRCRAM ; Write it into the KLNI
HALT .
CAIGE P1,DMPCLN-1 ; Did we do 'em all?
AOJA P1,INILOP ; Nope, keep going
RET
; Here to restore the CRAM to it's original beauty
RESCRM: SETZ P1, ; Reset location counter
RESLOP: MOVE T2,P1 ; Get the current location
LSH T2,1 ; Create a SAVCRM offset
DMOVE T2,SAVCRM(T2) ; Get the saved CRAM
MOVE T1,P1 ; Get the location again
CALL WRCRAM ; Restore the CRAM
HALT .
CAIGE P1,DMPCLN-1 ; Did we restore everything?
AOJA P1,RESLOP ; Nope, keep going
RET ; All done
DMPCRM:
; Program for dumping local store
LSUCOD==<.-DMPCRM>/2 ; Starting PC
XWD 1,400073 ; 0
XWD 2000,220040
XWD 1,600443 ; 1
XWD 1000,5040
; Program for dumping 2901 AC's 0-17
ACUCOD==<.-DMPCRM>/2 ; Starting PC
XWD 2,600443 ; 2
XWD 1000,5040
; Program for dumping 2901 AC Q
QUCOD==<.-DMPCRM>/2 ; Starting PC
XWD 3,200420 ; 3
XWD 1000,5040
; Program for writing data into the PLI
WPUCOD==<.-DMPCRM>/2 ; Starting PC
XWD 5,73 ; 4
XWD 2000,240040
XWD 0,604043 ; 5
XWD 1000,2340
XWD 0,1400 ; 6
XWD 1000,1340
XWD 7,0 ; 7
XWD 1000,40
; Routine for reading data from the PLI
RPUCOD==<.-DMPCRM>/2 ; Starting PC
XWD 11,402000 ; 10
XWD 1000,2040
XWD 0,1200 ; 11
XWD 1000,1340
XWD 0,430073 ; 12
XWD 2000,2340
XWD 0,200443 ; 13
XWD 1000,5340
XWD 16,400000 ; 14
XWD 1400,150060
XWD 15,0 ; 15
XWD 1000,40
XWD 16,0 ; 16
XWD 1000,40
; Program for reading and popping the top location off the 2910 stack
SKUCOD==<.-DMPCRM>/2 ; Starting PC
XWD 17,0 ; 17
XWD 1000,240
CCUCOD==<.-DMPCRM>/2 ; Starting PC
XWD 21,400000 ; 20
XWD 1000,40
XWD 23,0 ; 21
XWD 1400,60
XWD 22,400000 ; 22
XWD 1000,40
XWD 23,0 ; 23
XWD 1000,40
RDFCOD==<.-DMPCRM>/2 ; Start address
XWD 24,74 ; 24
XWD 1400,120320
DMPCLN==<.-DMPCRM>/2 ; # of uwords of CRAM for dumping
SAVCRM: BLOCK DMPCLN*2 ; Reserve space for holding old CRAM
SUBTTL PARITY - Compute Parity
; Compute the parity of the number in T1. Return with T1 containing MWPAR=1
; if parity would be even. Otherwise, it will be 0.
;
; Call: MOVX T1,number
; CALL PARITY
; <Return +1 always, T1/MWPAR or 0>
PARITY: SETZ T4, ; Clear the counter
PARIT1: MOVN T2,T1 ; Negate the number
TDZE T1,T2 ; Did we find a 1?
AOJA T4,PARIT1 ; Yes, keep on truckin
SETZ T1, ; Assume proper parity
TRNE T4,1 ; Even parity?
MOVX T1,MWPAR ; Nope, odd must have parity bit
RET
SUBTTL STUCOD - Start Microcode at the specified address
; Call: MOVX T1,micro_PC
; CALL STUCOD
; <Return +1, error>
; <Return +2 success>
SINCYC: SKIPA T3,[CO.MRN!CO.SSC] ; Here for single cycle operation
STUCOD: MOVX T3,CO.MRN ; Here for normal start
MOVX T2,DO.LAD ; Get ready to load the RAR
STOR T1,MICPC,+T2 ; Insert the PC into the DATAO word
MOVX T1,CI.EPE ; Clear all the nasty bits
XCT DEVCNO ; Tell the hardware about it
MOVE T1,T2 ; Get the PC
XCT DEVDTO ; Set the RAR
MOVE T1,T3 ; Get the run bit
XCT DEVCNO ; Start the port
SETZ T1, ; Get a 0
XCT DEVCNO ; Stop the port
XCT DEVCNI ; Read the status
TXNE T1,CI.ERR ; Any errors?
RET ; Yes, pass it upwards
RETSKP ; Nope, return success
SUBTTL RDLAR - Read the Latched Address Register
; Call: CALL RDLAR
; <Return +1, error>
; <Return +2 success, T1/ micro PC>
RDLAR: XCT DEVCNI ; Read the CSR
TXNE T1,CO.MRN ; Is it running?
RET ; Yes, that's a no-no
MOVX T1,CO.LAR ; Prepare to
XCT DEVCNO ; read the LAR
XCT DEVDTI ; Read the LAR
LOAD T1,MICPC,+T1 ; Fetch the micro PC
RETSKP ; And return success
SUBTTL RDEBUF - Read the EBUS Buffer
; Call: CALL RDEBUF
; <Return +1, error>
; <Return +2 success, T1/ data from EBUF>
RDEBUF: XCT DEVCNI ; Read the CSR
TXNE T1,CO.MRN ; Is it running?
RET ; Yes, that's a no-no
MOVX T1,CO.SEB ; Prepare to
XCT DEVCNO ; read the EBUF
XCT DEVDTI ; Read the EBUF into T1
RETSKP ; And return success
SUBTTL WRPLI - Write PLI
; This routine will write the data in T2 into the PLI register indicated by T1.
;
; Call: MOVX T1,pli_reg
; MOVX T2,data
; CALL WRPLI
; <+1 Return Always>
;
WRPLI: SAVEAC <P1,P2>
DMOVE P1,T1 ; Save PLI # and data
MOVE T1,P1 ; Get the pli # again
CALL PARITY ; Get proper value for MWPAR
DMOVE T2,DMPCRM+<WPUCOD+2>*2 ; Get word we have to modify
DPB P1,[POINT 6,T2,25] ; Insert PLI # into ucode
TDC T2,T1 ; Fix the parity
MOVX T1,WPUCOD+2 ; Get address to modify
CALL WRCRAM ; Write the CRAM
HALT .
MOVE T1,P2 ; Get the data byte
CALL PARITY ; Get parity bit
DMOVE T2,DMPCRM+WPUCOD*2 ; Get word to stuff data into
STOR P2,MWMGC,+T2 ; Insert the data byte
TDC T2,T1 ; Complement the parity bit
MOVX T1,WPUCOD ; Get address
CALL WRCRAM ; Write the CRAM
HALT .
MOVX T1,WPUCOD ; Get start address
CALL STUCOD ; Start the microcode
HALT .
RET ; All done
SUBTTL RDPLI - Read PLI
; This routine will read the contents of the PLI register addressed by T1 into
; T2.
;
; Call: MOVX T1,pli_reg
; CALL RDPLI
; <+1 Return failure>
; <+2 Return success>
RDPLI: SAVEAC <P1,P2>
MOVE P1,T1 ; Remember the PLI register number
MOVE T1,P1 ; Get the PLI #
CALL PARITY ; Setup T1 with MWPAR
DMOVE T2,DMPCRM+<RPUCOD+1>*2 ; Get the uword
DPB P1,[POINT 6,T2,25] ; Insert PLI # into ucode
TDC T2,T1 ; Complement the parity bit
MOVX T1,RPUCOD+1 ; Address 1
CALL WRCRAM ; Write the CRAM
HALT .
MOVX T1,RPUCOD ; Get the starting PC
CALL STUCOD ; Start the microcode
HALT .
CALL RDEBUF ; Read in the PLI data
HALT .
ANDI T1,377 ; Mask it down to 8 bits
MOVE P1,T1 ; Save the data for a moment
CALL RDLAR ; Read the PC
HALT .
CAIN T1,RPUCOD+6 ; Did a parity error occur?
TXO P1,1B0 ; Yes, say so
MOVE T1,P1 ; Get the data
RETSKP ; And return happily
SUBTTL RDAC - Read a 2901 AC
; Read an AC from the 2901. Specify AC # in T1 (Q=20). Contents
; returned in T1.
;
; Call: MOVX T1,ac#
; CALL RDAC
; <+1 Return Always, T1/ contents of AC>
;
RDAC: SAVEAC P1
MOVE P1,T1 ; Save register # in a safer place
CAIN T1,20 ; Doing the Q register?
IFSKP. ; Nope
CALL PARITY ; Get proper value for MWPAR
DMOVE T2,DMPCRM+ACUCOD*2 ; Get the little microroutine we need
TDC T2,T1 ; Set the parity bit
STOR P1,MWPRA,+T2 ; Install the register number
MOVX T1,ACUCOD ; Get PC of our little routine
CALL WRCRAM ; Install the microroutine
DIE(CD2,Can't load CRAM to dump 2901)
MOVX T1,ACUCOD ; Get the starting PC of the ucode
ELSE. ; Dump the Q register
MOVX T1,QUCOD ; Get the starting PC
ENDIF.
CALL SINCYC ; Startup the port for a single cycle
DIE(R2E,Error reading 2901 register)
CALL RDEBUF ; Read the result into T1
HALT .
RET
SUBTTL RDSTAK - Read (and pop off) the top item on the 2910 stack
; Call: CALL RDSTAK
; <Return +1, Always with T1/ stack item>
RDSTAK: MOVX T1,SKUCOD ; Get the start address
CALL SINCYC ; Single cycle the port
HALT .
CALL RDLAR ; Read the LAR
HALT .
RET
REDTOP: MOVX T1,RDFCOD ; Get the start address
CALL SINCYC ; Step the port
HALT .
CALL RDLAR ; Read the PC
HALT .
RET
SUBTTL RDCCOD - Read Condition Codes
; Read the condition code specified by T1. Return a sixbit code if the
; condition is set, 0 otherwise.
;
; Call: MOVX T1,code#
; CALL RDCCOD
; <Return +1 Always, T1 indicates state of condition>
;
RDCCOD: SAVEAC P1
MOVE P1,T1 ; Put condition # in a safe place
CALL PARITY ; Generate MWPAR
DMOVE T2,DMPCRM+<CCUCOD+1>*2 ; Get the CRAM loc we have to modify
TDC T2,T1 ; Fix the parity bit
STOR P1,MWSKP,+T2 ; Install the condition code
MOVX T1,CCUCOD+1 ; Get the location for this uword
CALL WRCRAM ; Install the word
HALT .
MOVX T1,CCUCOD ; Get the starting address
CALL STUCOD ; Start the microcode
HALT .
CALL RDLAR ; Read the PC
HALT .
MOVE T2,T1 ; Put the PC in a safe place
SETZ T1, ; Assume condition was not set
CAIN T2,CCUCOD+3 ; Is the condition enabled?
MOVE T1,CCTAB(P1) ; Yes, say so
RET ; All done
; Table of short abbreviations for condition codes. Indexed by cond code.
DEFINE X (name)<SIXBIT |name|>
CCTAB: X CBAV ; 0 - CBus AVailable
X GCSR ; 1 - Grant CSR
X FEQ0 ; 2 - last alu Function EQuals 0
X CSRC ; 3 - CSR Changed
X EBPE ; 4 - EBus Parity Error
X RATN ; 5 - Receive ATteNtion
X EOFF ; 6 - End of Frame Found
X XATN ; 7 - Xmit ATteNtion
X ERQS ; 10 - Ebus ReQueSt
X IACT ; 11 - Interrupt ACTive
X MSGN ; 12 - Msb/SiGN bit set
X MVRP ; 13 - MoVeR Parity check
X CBPE ; 14 - CBus Parity Error
X PLPE ; 15 - PLi Parity Error
X CHER ; 16 - CHannel ERror
X CBLW ; 17 - CBus Last Word
SUBTTL GETMEM - Allocate free space
; Call: MOVX T1,# of words desired
; CALL GETMEM
; <+1 No room>
; <+2 Memory pointed at T1>
;
GETMEM: ADD T1,.JBFF ; Compute new .JBFF
EXCH T1,.JBFF ; Get old .JBFF, update .JBFF
RETSKP ; Return success
SUBTTL CPYMON - Copy a chunk of the monitor into the dump file
; Call this routine with the symbol representing the start address of a
; block in T1, and a symbol representing the length of the block in T2.
;
; Call: MOVX T1,symbol1
; MOVX T2,symbol2
; CALL CPYMON
; Error return
; Success return
CPYMON: MOVE P1,T2 ; Save length symbol for a moment
CALL MONSYM ; Lookup the address
RET
EXCH P1,T1 ; Save location
CALL MONSYM ; Lookup the length
RET
MOVN T1,T1 ; Negate the length
HRL P1,T1 ; Form an AOBJN pointer
PCBLOP: HRRZ T1,P1 ; Get address to read
HRLI T1,1 ; Just 1 word at a time
MOVX T2,T1 ; Read it into T1
PEEK% ; Read the monitor
ERJMP RTN ; Quit gracefully
CALL PUTWRD ; Write out the word from the PCB
AOBJN P1,PCBLOP ; Loop over the whole PCB
RETSKP ; Return success
SUBTTL MONSYM - Lookup a symbol in the monitor address space
MONSYM: MOVE T2,T1 ; Get symbol into the correct AC
MOVX T1,.SNPSY ; Convert a symbol to a value
MOVE T3,[SQUOZE 0,NISRV] ; In the module NISRV
SNOOP% ; Snoop it out of the monitor
RET ; Just quit if it fails
MOVE T1,T2 ; Get symbol into correct AC
RETSKP ; Return success
SUBTTL Storage
STKAC: IOWD STKLEN,STACK ; AC for stack
STACK: BLOCK 100
STKLEN==.-STACK
ATOFLG: BLOCK 1 ; Non-zero means we are in auto mode
NIBLOK: BLOCK .EIBMX ; Arg block for NI% jsys
; Command State Block for COMND% JSYS
CSB: XWD 0,REPAR ; No flags,, reparse address
XWD .PRIIN,.PRIOU ; Use primary I/O JFNs
XWD -1,[ASCIZ |KNILDR>|] ; Setup prompt
XWD -1,CMDBUF ; Pointer to command buffer
XWD -1,CMDBUF ; Pointer to next field
EXP CMDLEN ; Length of command buffer
EXP 0 ; No characters to parse yet
XWD -1,ATMBUF ; Pointer to atom buffer
EXP ATMLEN ; Length of atom buffer
EXP GJBLK ; Address of GTJFN block
CMDLEN==^D132 ; Be generous with command length
CMDBUF: BLOCK <CMDLEN+3>/4 ; Command buffer
ATMLEN==^D132 ; Be generous with the atom buffer
ATMBUF: BLOCK <ATMLEN+3>/4 ; Atom buffer
GJBLK: BLOCK 16 ; GTJFN% block for COMND%
DEVCNI: CONI 0,T1 ; Prototype I/O instructions
DEVCNO: CONO 0,(T1)
DEVDTI: DATAI 0,T1
DEVDTO: DATAO 0,T1
DEVBKO: BLKO 0,0
MICVAL: EXP 0 ; Non-zero means microcode is valid
CRAM: BLOCK CRMLEN*2 ; Microcode goes here
CRMBLN==.-CRAM ; Length of CRAM buffer
DEFINE XX (file)<
..CNT==0
IRPC file,<..CNT==..CNT+1
IFIDN <file><->,<STOPI>>
DEFCHN: POINT 3,DEFFIL+..CNT/5,6+7*<..CNT-<<..CNT/5>*5>>
DEFFIL: ASCIZ |file|
>
XX (KLNI-0.DUMP) ; Generate default filename
DEFINE XX (file)<
..CNT==0
IRPC file,<..CNT==..CNT+1
IFIDN <file><->,<STOPI>>
ADFCHN: POINT 3,ADFFIL+..CNT/5,6+7*<..CNT-<<..CNT/5>*5>>
ADFFIL: ASCIZ |file|
>
XX (SYSTEM:KLNI-0.DUMP) ; Generate automatic mode filename
ACS: BLOCK 21 ; Temp holding area for 2901 AC's
CCSAVE: BLOCK 20 ; Temp holding area for cond codes
SAVUPC: BLOCK 1 ; Temp holding area for the LAR
JFN: BLOCK 1 ; JFN goes here
LINNUM: BLOCK 1 ; Current line number of .ULD file
NUMMIC: BLOCK 1 ; Number of microwords loaded
BUFPTR: BLOCK 1 ; Byte pointer to file buffer goes here
BUFCNT: EXP 0 ; # of bytes remaining in buffer
CHRBUF: BLOCK 1000 ; File buffer
WRDBLN==<.-CHRBUF> ; Length of the file buffer in words
CHRBLN==WRDBLN*5 ; Length of the file buffer in bytes
ERRBLN==^D100 ; Make error buffer 100 characters
ERRBUF: BLOCK <ERRBLN+4>/5 ; Buffer for holding JSYS error string
END <3,,ENTVEC>