;----------- Dandelion Processor Program - I/O Processor -----------
; DESCRIPTION: Boot Program: IOP code.
; Last modification by Roy Ogus: January 28, 1982 4:04 PM
; File: BootMain.asm
; Stored: [Iris]<Workstation>Boot30>BootEPromRAM.dm
; Written by Roy Ogus.
; Modification History:
; Version 1.0
; - Created (September 8, 1980 2:24 PM)
; - Added hooks for diagnostic booting, AltBoot handling (November 10, 1980 12:32 PM)
; - Data area as definitions (November 10, 1980 12:32 PM)
; Version 1.1
; - Created (November 11, 1980 2:33 PM)
; - Complemented Control store data in WriteCS (November 11, 1980 2:33 PM)
; Version 2.0
; - Created (November 12, 1980 12:51 PM)
; - Floppy Streaming (November 12, 1980 12:51 PM)
; - Removal of BootSubs into separate file (November 13, 1980 9:53 AM)
; - Separate Floppy/Rigid soft Go (November 18, 1980 1:08 PM)
; - Link table (November 18, 1980 1:08 PM)
; - Link to PreBoot (December 3, 1980 11:09 AM)
; - CSImageStart, FloppyBuffer variables added (December 3, 1980 11:09 AM)
; - Byte swapping from Floppy (December 4, 1980 11:09 AM)
; Version 2.1
; - Created (December 8, 1980)
; - Shortened CSImage to 256 locations (December 8, 1980)
; - Floppy buffer is 5 sectors (December 8, 1980)
; Version 2.2
; - Created (December 22, 1980 4:01 PM)
; - New MP numbers (December 22, 1980 5:13 PM)
; - General CSImage size (December 22, 1980 5:13 PM)
; - Diagnostic Floppy bypasses (January 4, 1981 6:34 PM)
; Version 2.3 (not used)
; Version 2.4
; - Renamed main program file BootMain.asm (June 17, 1981 1:08 PM)
; - 2D, 2S floppy booting added (June 18, 1981 1:29 PM)
; Version 3.0
; - Trident0 hook added to FinishPhase0 (November 24, 1981 3:25 PM)
; - FinishPhase0 redone according to new BootType allocation (December 11, 1981 3:10 PM)
; - Set interrupt state moved to BootInit, changed start code (January 13, 1982 4:22 PM)
; - Add links to FloppyInitE and DoSeekCmd, use RestoreCom (January 14, 1982 1:39 PM)
; - Double count check simplification in DoLoadIOP, Do IgnoreBlock (January 28, 1982 3:58 PM)
; DEFNITIONS:
get "SysDefs"
get "BootDefs"
; EXPORTS:
EXP StartNextPhase ; For BootSubs
EXP DoBootPhase ; For IOPInitial
EXP BootGo,BootGoExt,SetInt ; For Burdock command file and debugging
EXP EndPhase0,EndPhase0Floppy,EndPhaseNot0 ; For debugging
EXP MoveLinkTableExt ; For debugging
; IMPORTS (from BootSubs):
IMP BootInit,CheckAltBootDevice
IMP StartNextRead,GetNextWord
IMP InitCSTPCImage,TransferCSImage,TransferTPCImage
IMP WriteCS
IMP SetupUregisters,InformCPBootDevice,ReadMainMem
IMP CheckCPStopped,StartCPKernel,StartCP
IMP ByteToWord
IMP FloppyInit, FloppyInitE,DoSeekCmd
IMP PhaseToMP,PutMP,ClearMPanel,IncrMP,DeltaMP,ErrorReport
IMP InitCPCmd,WriteCPword,ReadCPWord,Delay
IMP StartPreBoot ; From StartIOPBootRAM or StartIOPBootProm
;
{ This code constitutes the IOP code that will reside in the IOP EProm. This code will
be bound with the .bin form of the Phase0 CP microcode that will be loaded by the IOP
into Control Store. This microcode will read the Initial microcode from the boot device
into main memory, in the case of rigid disk booting. In the case of Floppy booting, the IOP will
read the Initial microcode and Initial IOP code from the floppy. The IOP will then interpret the
loaded boot file and (conditionally) restart the CP executing Initial. In the next phase,
the Pilot microcode, the Germ, and Domino will be read into main memory, and subsequently read
and placed by the IOP.}
{Notes:
Boot file in Main memory should not cross 64K boundary
Maximum of 16 loadU blocks in Phase 0 boot file.
Allocation in RAM for Testing:
Phase0 boot file 2000H (Overlaid by Domino)
IOPInitial 3000H (Overlaid by Domino)
Boot code start 4000H
Floppy Buffer (5 sector) 51D0H
CSImage 5BD0H
Variables 5ED0H-5F63H
Link Table 5F76H-5F9FH
User stack 5FA0H - 5FCEH
Allocation in Prom:
IOP Kernel 0H
Boot code start 40H
(Boot code+Phase0 boot file)
PreBoot code start 1800H
Floppy Buffer (5 sectors) 51D0H
CSImage 5BD0H
Variables 5ED0H-5F63H
Link Table 5F76H-5F9FH
User stack 5FA0H - 5FCEH
}
;------------------------------------------------------
; RAM storage (definitions in BootDefs definitions file).
; LINK table.
; These are fixed locations for used by external programs.
; This table is copied into RAM at start of boot for use by other programs.
; Location of LinkTable in RAM defined by StartLinkTable in BootDefs.asm.
; Note that the entry for MoveLinkTable is not used in the RAM location, since it will not
; be there before the subroutine is called. This entry is to be called directly in the EProm.
TopLinkTable:
BootGoExt:
jmp BootGo ; 0: Boot entry point
DoBootPhaseExt:
jmp DoBootPhase ; 1: Start of Boot file interpreter
GetNextWordExt:
jmp GetNextWord ; 2: Get the next word from the boot file
BootInitExt:
jmp BootInit ; 3: Boot initialization subroutine
ReadMainMemExt:
jmp ReadMainMem ; 4: Read a word of main memory
InitCPCmdExt:
jmp InitCPCmd ; 5: Start a CPport Read or Write
WriteCPwordExt:
jmp WriteCPword ; 6: Write a CP word
ReadCPWordExt:
jmp ReadCPWord ; 7: Read a CP word
ClearMPanelExt:
jmp ClearMPanel ; 8: Clear maintenance panel
IncrMPExt:
jmp IncrMP ; 9: Increment maintenance panel
PutMPExt:
jmp PutMP ; 10: Put a number in the Maintenance panel
DelayExt:
jmp Delay ; 11: Delay subroutine
ErrorReportExt:
jmp ErrorReport ; 12: Error Report loop
MoveLinkTableExt:
jmp MoveLinkTable ; 13: Start of MoveLinkTable subroutine
FloppyInitExt:
jmp FloppyInitE ; 14: External entry point of FloppyInit subroutine
DoSeekCmdExt:
jmp DoSeekCmd ; 15: External entry point of DoSeekCmd subroutine
EndLinkTable:
;
;------------------------------------------------------
; Boot Start locations:
; EProm entry point (from Kernel, or from RST 0):
; Note: The PreBoot code will first set BootType to DefaultBoot,
; and then check the AltBoot switches to determine for any other value of BootType.
; For soft testing, the initialization in PreBoot is changed in the command file.
BootGo:
SetInt:
di ; Set to "ei" for Mouse Halts in testing
; Initialize the boot stack.
lxi sp,BootStackStart ; Initialize stack pointer
call BootInit ; Do various system initialization
call MoveLinkTable ; Move the link table to RAM (sub. in this module)
; Note: The LinkTable is moved BEFORE the PreBoot diagnostics are run.
; Call the PreBoot diagnostics.
call StartPreBoot ; Call the PreBoot Diagnostics, read the AltBoot and set BootType
; Return from the PreBoot diagnostics.
; The PreBoot diagnostics should also call the ReadAltBoot subroutine to read in the BootType.
; The PreBoot code should restore the Link table, and call BootInit if RAM was destroyed.
; Start processing the Phase0 boot file.
StartPhase0:
lxi h,MPStartPhase0 ; Set MP = 100, MPOffset to 100
shld MPOffset
call PutMP ; MP = 100
; Go to: DoBootPhase
;
; START of the Boot file interpreter.
{ The boot file interpreter interprets blocks of the Dandelion boot file. The boot file
can be in EProm or CP main memory. During Phase 0, the boot file is in EProm, during
subsequent phases (currently Phase 1 and phase 2), it is in main memory.
The subroutine GetNextWord gets the next 2 bytes from the appropriate place,
depending on the Phase. Because CP memory accesses may be involved, the subroutine
StartNextRead is needed which starts a CP port access if appropriate.
Control store locations less than an address determined by MaxCSImage are written into
a control store image area in IOP memory. This image is transferred to control store just
before the CP is started executing the next phase. TPC values specified in the boot files
are also buffered until the end of the IOP boot phase.
U-register handling: U registers can only be written by the IOP when the CP is executing
(i.e. not dead or stopped). In addition, if rigid disk booting is required, the IOP can only
write the appropriate the U-registers when it is known which rigid disk is on the system.}
{ Phase 0 starts at 100. End Phase 0 starts at 135.
Phase 1 starts at 149. End Phase 1 starts at 190.
Phase 2 starts at 199 End Phase 2 starts at 240.
}
DoBootPhase:
call InitCSTPCImage ; Initialize the CS image and the TPC buffer
StartBootBlock:
lxi h,1 ; Get header word for next block
call StartNextRead ; Initiate the read
lxi h,Header ; Do the read
call GetNextWord
lda HeaderHi ; What is it?
ani BlockTypeMask
jz DoSpecialBlock ; z => a special block type
; Write CONTROL STORE Block.
; It was a control store block. Store count of the number of microinstructions in block.
; A has the number of microinstructions to be read, left justified.
DoCSBlock:
rlc
rlc
rlc
rlc
sta CSInstrCount
mov b,a ; Save Count in B
rlc ; 2*Count in A
add b ; 3*Count = number of words to be read
lxi h,0 ; Number to H,L
mov l,a
call StartNextRead ; Initiate the read of the microinstructions
lhld Header
mov a,h ; Clear BlockType field
ani nBlockTypeMask
mov h,a
shld CSAddress ; Store CS address (BlockType later masked out)
NextCS:
mvi c,3 ; Counter for 3 words
lxi h,CSBuffer ; Point start of CS buffer
GetCSData:
call GetNextWord ; Store in CS buffer (H,L is updated)
dcr c
jnz GetCSData ; nz => still more
; Microinstruction is stored in CSBuffer.
call WriteCS ; Write instruction in the control store or the CS image
; Check for end of CS block.
lda CSInstrCount
dcr a
sta CSInstrCount
jz BootBlockDone ; z => Block is done
; Do next microinstruction.
lhld CSAddress
inx h
shld CSAddress
jmp NextCS
; The current block is completed.
BootBlockDone:
jmp StartBootBlock
; SPECIAL Blocks.
; It was a special block. Do further decoding to determine which one.
; Low part of header determines further decoding.
DoSpecialBlock:
lda Header
cpi 8 ; Check if a TPC block
jc DoTPCBlock ; c => A<8, i.e. TPC
cpi 8 ; Check for Last block
jz DoLastBlock ; z => A=8
cpi 9 ; Check for load IOP memory
jz DoLoadIOP ; z => A=9
cpi 10 ; Check for Load U register
jz DoLoadU ; z => A=10
cpi 11 ; Check for load IOP memory
jz DoIgnoreBlock ; z => A=11
cpi 12 ; Check for Load U register
jz DoSetStartIOP ; z => A=12
UnknownBlock:
mvi c,ErrorUnknownBlock ; ERROR: Unknown special Boot file Block
jmp ErrorReport ; Report the error
; TPC Block.
; Insert the TPC value in the TPC buffer. Clear the empty flag for the slot.
; Slot address is TPCBuffer + 2*(TPC address)
; The TPC's will later be written into the actual TPC's.
; Header (low) contains the TPC address.
DoTPCBlock:
lxi h,1 ; Read next word
call StartNextRead ; Initiate the read
lda Header ; Get the TPC address
rlc ; Form 2*(TPC address)
lxi b,0
mov c,a ; B,C contains 2*(TPC address)
lxi h,TPCBuffer ; Point to the TPC buffer
dad b ; H,L ← TPCBuffer + 2*(TPC address)
call GetNextWord ; Store the value in TPC buffer (clear Empty flag)
jmp BootBlockDone
; IOP memory block.
; The next word contains the IOP starting address, the next the count (in bytes).
; Since there can be an odd number of bytes, maintain 2 counts in the inner loop.
; The wordCount is the (byteCount+1)/2.
DoLoadIOP:
lxi h,2 ; Read next two words
call StartNextRead ; Initiate the read
lxi h,IOPAddress
call GetNextWord ; Store the address
lxi h,IOPCountByte
call GetNextWord ; Store the count (in bytes)
lhld IOPCountByte ; Convert to words after incrementing to round up
inx h
call ByteToWord ; Returned in H,L
shld IOPCountWord ; Store
call StartNextRead ; Initiate the read
jmp DecrIOPCount ; Jump to end of the loop to check for 1 word only
; Inner loop.
GetIOPData:
lhld IOPAddress ; Point to the IOP memory
call GetNextWord ; Store in IOP memory (H,L updated to point to next slot)
shld IOPAddress ; Save pointer
lhld IOPCountByte ; Decrement the byte count by 2
dcx h
dcx h
shld IOPCountByte ; Store back
DecrIOPCount:
lhld IOPCountWord ; Decrement the word count by 1
dcx h
shld IOPCountWord ; Store back
mov a,l ; Check for count = 0
ora h ; Low OR high
jnz GetIOPData ; nz => nonzero
; We have one more word to get from the boot file.
; There might be one or two bytes in it.
; The byte count will be 2 for two bytes left, and 1 for one byte left.
; IOPAddress points to the next IOP memory location.
LastIOPData:
lda IOPCountByte ; Get low part of byte count (assume high part is zero)
cpi 1 ; One more byte?
jz DoLastIOPByte ; z => 1 byte left
cpi 2 ; One more byte?
jz DoLastIOPWord ; z => 1 word left
BadIOPCount:
mvi c,ErrorBadIOPCount ; ERROR: Something wrong with byte count
jmp ErrorReport
; One byte left. Have to read the next word into a buffer (use Header).
DoLastIOPByte:
lxi h,Header ; Point to Header
call GetNextWord ; Store in IOP memory (H,L updated)
lhld IOPAddress ; Store the byte
lda Header ; Get the byte
mov m,a ; Store away the byte
jmp BootBlockDone ; Done with block
; Two bytes left. Do the normal thing.
DoLastIOPWord
lhld IOPAddress ; Point to the IOP memory
call GetNextWord ; Store in IOP memory (H,L updated)
jmp BootBlockDone ; Done with block
; U register block.
; This block specified a load of a U-register block.
; In Phase 0, the pointer to the loadU block is saved for later update of U-registers.
; In Phase not 0, this is ignored (breakpoint).
; Phase 0:
; Save pointer to the LoadU block, increment uBlock counter.
; At end of Phase 0 the blocks are interpreted as follows:
; uBlockType = unconditional => DoWriteUBlock
; uBlockType = BootDevice => DoWriteUBlock
; uBlockType # unconditional => ignore
DoLoadU:
lda Phase ; Check if Phase 0
ora a ; Set flags
jz LoadUPhase0
LoadUNotPhase0:
mvi c,ErrorLoadUNotPhase0 ; ERROR: LoadU not in Phase 0
jmp ErrorReport
; Phase 0 load of U register. Save the pointer, and increment the uBlock count.
; Skip over the rest of the u Block.
LoadUPhase0:
lhld BootAddrIOP ; Get pointer to the rest of the block
xchg ; Move to D,E
lhld uBlockPtr ; Get pointer to next slot in array
mov m,e ; Store low part
inx h
mov m,d ; Store high part
inx h
shld uBlockPtr ; Store back pointer
lxi h,uBlockCnt ; Increment uBlock Count
inr m ; Note: No checking for more than 16 blocks
; Now skip over the rest of the block (17 words).
lhld BootAddrIOP ; Get Boot file pointer again
mvi d,34 ; Counter for 34 bytes
LoadUSkipLoop:
inx h ; Increment the pointer
dcr d
jnz LoadUSkipLoop
; Store back the pointer.
shld BootAddrIOP
jmp BootBlockDone ; Done with block
; IGNORE Block.
; This block is to be skipped over.
; The next word specifies how manywords to be skipped.
DoIgnoreBlock:
lxi h,1 ; Read next word
call StartNextRead ; Initiate the read
lxi h,IgnoreCount ; Read how many words to Skip
call GetNextWord ; Store the count
lhld IgnoreCount ; Read next words to be skipped
call StartNextRead ; Initiate the read
IgnoreLoop:
lxi h,IgnoreData
call GetNextWord ; Throw away the data
lhld IgnoreCount ; Decrement the count
dcx h
shld IgnoreCount
mov a,l ; Check for count = 0
ora h ; Low OR high
jnz IgnoreLoop ; nz => nonzero
; The block is all done.
jmp BootBlockDone ; Done with block
; SET START IOP Block.
DoSetStartIOP:
lxi h,1 ; Read next word
call StartNextRead ; Initiate the read
lxi h,StartIOPAddress ; Read next word into Start IOP address slot
call GetNextWord
jmp BootBlockDone ; Done with block
; LAST BLOCK. This is the end of the boot file. Read the LstBlock Flags and finish the Boot phase.
; Depending on which phase, do the end-of-phase cleanup and start the CP executing if specified.
DoLastBlock:
lxi h,1 ; Read next word
call StartNextRead ; Initiate the read
lxi h,LastBlockFlags ; Read next word into LastBlockFlags
call GetNextWord
lda Phase ; Determine which phase it is
ora a
jz FinishPhase0 ; z => Finish Phase0.
jmp FinishPhaseNot0 ; Finish up a phase other than Phase 0
;
; PHASE 0 termination.
FinishPhase0:
lxi h,MPEndPhase0 ; MP = 135
call PutMP
; Check for diagnostic floppy booting. If so, leave the CP alone.
call CheckDiagFloppy
ora a ; A#0 => Diagnostic floppy booting
jnz GoToPhase1DiagFloppy ; nz => Diagnostic floppy booting
; Not diagnostic floppy booting. Transfer CSimage into low control store, load the TPC's
call TransferImage ; MP = 136, 137
call StartCPKernel ; Start the CP kernel
call IncrMP ; MP = 138
call StartCP ; Issue the ExitKernel command to the CP (unconditional)
call IncrMP ; MP = 139
EndPhase0:
nop
; BootFlags are now: BootMode=0, CPStopped=0.
; The CP has started execution.
; The microcode will determine which boot devices are present, ie. SA1000 or SA4000, Ethernet.
; This is needed to determine which U-registers to load.
; Memory location 0 will be set to non-zero when this is determined.
WaitMem0:
lxi h,0 ; H,L ← address 0
call ReadMainMem ; Read main memory 0
ora a
jz WaitMem0 ; z => still no valid information
sta CPDevices ; Store low byte of Mem 0
call IncrMP ; MP = 140
; The devices present (including rigid disk type) have been determined by the microcode.
; Check whether the Boot device is the rigid disk or not, from BootType.
; BootType determines what boot device is to be used and is defaulted to 0 (rigid disk booting).
Phase0CPStarted:
call CheckAltBootDevice ; Check the BootType and set BootDevice
; Setup the U registers (if any), and transmit Host number, DiagBoot and BootDevice.
call InformCP ; MP = 141
; Check which boot device.
; Ethernet booting: same as rigid disk booting, wait for valid boot file in main memory.
; Floppy disk booting: initialize the floppy disk.
lda BootDevice
cpi BootFloppy ; Is is Floppy booting?
jz GoToPhase1Floppy ; z => Floppy booting
jmp StartNextPhase ; Rigid, Ethernet booting, wait for valid boot file in main memory
; Floppy disk booting.
GoToPhase1DiagFloppy:
mvi a,BootFloppy ; Set boot device to Floppy
sta BootDevice
; Initialize the floppy disk controller and data structures.
GoToPhase1Floppy:
call FloppyInit ; Initialize the floppy hardware
call IncrMP ; MP = 142
; Initialize floppy data structures.
mvi a,BootSourceFloppy
sta BootSource ; BootSource ← Floppy
; Set FloppyBufCnt to zero (empty). This will cause a transfer at the first GetNextWord.
lxi h,0
shld FloppyBufCnt
; Set the disk address to start of Initial:
SetStartInitial:
lxi h,StartInitialCylinder ; Initialize starting cylinder (a word)
shld DCylinder
mvi a,StartInitialSector ; Initialize starting sector
sta Sector
mvi a,StartInitialSide ; Initialize starting side
sta DSide
; Go to next phase.
lxi h,Phase ; Increment phase number
inr m
call PhaseToMP ; Put Phase*50 + 99 in MP
call IncrMP ; Put Phase*50 + 100 in MP
EndPhase0Floppy:
jmp DoBootPhase
;
; START of new rigid disk Phase.
; This is where all rigid disk booting phases after Phase 0 start executing.
StartNextPhase:
lxi h,Phase ; Increment phase number
inr m
call PhaseToMP ; Put Phase*50 + 99 in MP
; MP has Phase*50 + 99 in it. MPOffset is Phase*50 + 100
; Assumes Rigid disk or Etherbooting here.
; Wait for a valid Boot file in main memory. Memory loc. 1 will be non-zero when this occurs.
WaitMem1:
lxi h,1 ; Specify memory location 1
call ReadMainMem ; Read main memory 1
; Check for completion (low byte in A, high byte in B):
; high byte # 0 => Valid completion,
; high byte = 0, low byte # 0 => Error, error code in low byte,
; high byte = 0, low byte = 0 => not completed.
mov c,a ; Save low byte
mov a,b ; Get high byte
ora a
jnz SetNextPhase ; nz => completed
; High byte is zero, check low byte:
mov a,c
ora a
jnz CPError ; nz => Error
; High byte is zero, low byte is zero:
jmp WaitMem1
; A valid boot file is in main memory. Initialize the BootFile Pointer and interpret it.
SetNextPhase:
mvi a,BootSourceCP ; Set the value of BootSource to CP memory
sta BootSource
; Start of BootFile in main memory is at address in B,C:
mov l,c ; Start of Boot file in CP memory
mov h,b
shld BootAddrCP
call IncrMP ; MP = Phase*50 + 100
jmp DoBootPhase ; Go and interpret it
; CP has completed in error. C has the error code.
CPError:
jmp ErrorReport ; ERROR: Error in CP FloppyInitial
; PHASE not zero termination.
FinishPhaseNot0:
call PhaseToMP ; Put Phase*50 + 99 in MP
lxi h,MPEndPhaseNot0+1 ; MP = PhaseNumber*100 + 40
call DeltaMP ; StartPhase+40
; Check for diagnostic floppy booting. If so, leave the CP alone.
call CheckDiagFloppy
ora a ; A#0 => Diagnostic floppy booting
jnz EndPhaseNot0 ; nz => Diagnostic floppy booting
; Not diagnostic floppy booting. Continue with normal sequence.
call CheckCPStopped ; If CP is not stopped, then stop it
call IncrMP ; MP = StartPhase+41
; Transfer CSimage into low control store, load the TPC's
call TransferImage ; MP = StartPhase+42, StartPhase+43
; Now check whether CP is to be started.
CheckStartCP:
lda LastBlockFlagsHi ; Check InhibitStartCP bit in LastBlockFlags
ani InhibitStartCPMask
jnz EndPhaseNot0 ; nz => Do not start the CP
; Start the CP.
call StartCP ; Issue the ExitKernel command to the CP
call IncrMP ; MP = StartPhase+44
EndPhaseNot0:
nop
GoToNextPhase:
; Wait for CP to disable IOP port, and clear memory location 1.
nop
; Go to where specified by StartIOPAddress. This is initialized to StartNextPhase
StartIOP:
lhld StartIOPAddress
pchl ; Go to it
;
; Special SUBROUTINE to move Link table into RAM.
; This subroutine must be in this module.
; Subroutine: MoveLinkTable.
; Copy the Link table from this module to RAM in variable area.
; This is needed since the boot code might be in RAM (soft booting) or Prom.
; The table is copied upwards in memory.
; Copy each item separately.
; Use Header as a counter.
SizeLinkTable equ (EndLinkTable-TopLinkTable)/3 ; No of items in Link table
MoveLinkTable:
lxi h,TopLinkTable ; Source
lxi d,StartLinkTable ; Destination in RAM
mvi a,SizeLinkTable ; Size of table
sta Header
MoveLinkLoop:
mvi c,SizeLink ; Size of an item
MoveItemLoop:
mov a,m ; Get source byte
stax d ; Store at destination
inx h ; Bump pointers
inx d
dcr c ; Check count
jnz MoveItemLoop ; nz => more bytes in link
; The link is moved, do next one.
; Check count.
lda Header
dcr a
sta Header
rz ; z => Done
; Decrement destination pointer by 6.
xchg ; H,L ← Destination pointer, D,E ← source pointer
lxi b,-6
dad b ; H,L ← Destination pointer - 6
xchg ; D,E ← New destination pointer, H,L ← source pointer
jmp MoveLinkLoop
; Subroutine: TransferImage.
; Transfer the CS and TPC images.
TransferImage:
call TransferCSImage ; Transfer image into low control store
call IncrMP ; Increment MP
call TransferTPCImage ; Load the TPC's
jmp IncrMP ; Increment MP
; Jump to IncrMP subroutine and Return.
; Subroutine: InformCP.
; Setup the U registers (if any), and transmit Host number, DiagBoot and BootDevice.
InformCP:
call SetupUregisters ; Set up the U registers (if any)
call InformCPBootDevice ; Tell CP BootDevice, U-registers loaded
jmp IncrMP ; Increment MP
; Jump to IncrMP subroutine and Return.
; Subroutine: CheckDiagFloppy.
; Check DiagBoot and BootType to see if diagnostic floppy booting.
; On exit:
; A # 0 if (DiagBoot#0) AND (BootType=AltDiagFloppyBoot)
; A = 0 otherwise.
CheckDiagFloppy:
lda DiagBoot ; Check DiagBoot first
ora a
rz ; z => DiagBoot = 0, not diag floppy booting
; DiagBoot was not zero. Check if diagnostic floppy booting.
lda BootType ; Check the BootType
xri AltDiagFloppyBoot ; A ← 0 if BootType=AltDiagFloppyBoot
jnz NotDiagFloppyBoot ; nz => BootType#AltDiagFloppyBoot
; BootType=AltDiagFloppyBoot (A=0).
cma ; Complement sense: A#0 if BootType=AltDiagFloppyBoot
ret
NotDiagFloppyBoot:
xra a ; Return A = 0
ret
END BootMain