mirror of
https://github.com/livingcomputermuseum/Darkstar.git
synced 2026-03-02 02:01:00 +00:00
39 lines
24 KiB
Plaintext
39 lines
24 KiB
Plaintext
head 1.1;
|
||
branch 1.1.1;
|
||
access ;
|
||
symbols start:1.1.1.1 Xerox:1.1.1;
|
||
locks ; strict;
|
||
comment @;; @;
|
||
|
||
|
||
1.1
|
||
date 2001.08.12.22.22.19; author freier; state Exp;
|
||
branches 1.1.1.1;
|
||
next ;
|
||
|
||
1.1.1.1
|
||
date 2001.08.12.22.22.19; author freier; state Exp;
|
||
branches ;
|
||
next ;
|
||
|
||
|
||
desc
|
||
@@
|
||
|
||
|
||
|
||
1.1
|
||
log
|
||
@Initial revision
|
||
@
|
||
text
|
||
@{
|
||
----------- Dandelion Processor Program - I/O Processor -----------
|
||
|
||
DESCRIPTION: Boot Program: IOP code.
|
||
Last modification by Roy RXO : January 28, 1982 4:04 PM
|
||
|
||
File: BootMain.asm
|
||
Stored: [Iris]<WMicro>DLion>
|
||
Written by Roy RXO .
|
||
Dennis DEG , 2-Sep-84 15:16:53, add copyright notice.
|
||
}
|
||
|
||
{ Copyright (C) 1980, 1981, 1982 by Xerox Corporation. All rights reserved.}
|
||
|
||
|
||
; Modification History:
|
||
|
||
; Version 1.0
|
||
; - Created (September 8, 1980 2:24 PM)
|
||
; - Added HNH 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
|
||
@
|
||
|
||
|
||
1.1.1.1
|
||
log
|
||
@first add
|
||
@
|
||
text
|
||
@@
|