;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; ; D O R A D O C o n t r o l P r o g r a m ; ; B o o t s t r a p C o d e ; ;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ; filed on DoradoBoot.masm ; E. McCreight ; last modified May 15, 1981 5:09 PM .EXPORT LoadDoradoCode,DoIRTableInst .EXPORT StartDoradoAtInitmap .EXPORT SetCP~AndDoIRTableInst,SetCPAndDoIRTableInst .EXPORT SendIMBlockToDorado,SendAHunk .EXPORT SendViaMIR,IRTable .EXPORT CPRegToLink#,IMLHRSTK.0Is0#,IMLHRSTK.0Is1# .EXPORT IMRHBLOCKIs0#,IMRHBLOCKIs1# .EXPORT Return#,QFromCPReg#,ALUFM[0]FromQ# .EXPORT SetHoldTaskSim# .EXPORT BootBlocks,Boot0Block,Boot1Block .EXPORT IMAddress,HunksLeft,Hunk,MicroHalf,ExtraBits,ViaCP .IMPORT InitMap .IMPORT StdClockSet,StdClockSpeedH,StdClockSpeedL .IMPORT ReadMufflerField,ClockSpeedMufField .IMPORT InitManifolds,MaxInitManifold,DoIOReset .IMPORT Boot0Data,Boot0IMLoc,Boot0Length,Boot0Checksum .IMPORT Boot0BreakpointCount,Boot0BreakpointAddrTable .IMPORT Boot0GoLoc .IMPORT Boot1Data,Boot1IMLoc,Boot1Length,Boot1Checksum .IMPORT Boot1BreakpointCount,Boot1BreakpointAddrTable .IMPORT ClearDMManifold,AllowCBHolds,SetManifold .IMPORT Micro,CDatum,ToCPRegH,ToCPRegL .IMPORT SetCPReg~,SetCPReg,DoDoradoMicroInst .IMPORT SetCPReg0,SetCPReg1 .IMPORT RunDoradoInstructionStream,StopDorado .IMPORT PacifyWatchdog,Delay .IMPORT WaitForCPControl,EnableMidas .IMPORT SetProblem,ClearProblem,CouldntBootDorado .SHORT Micro,CDatum,ToCPRegH,ToCPRegL .PREDEFINE "MCS6502PREDEFS.SR" .GETNOLIST "DoradoIO.mdefs" .LOC BootData .SHORT BootData ; Note: these next two must appear together, because we copy ; them as a block to the Dorado. IMAddress: .BLK 2 ; the address where the data goes, ; high-order byte first HunksLeft: .BLK 2 ; number of 17-byte hunks of an IM ; block left to send, high-order byte first InitManifoldsLeft: .BLK 1 NoopsToGo: .BLK 1 ; number of remaining No-ops for reset Hunk: .BLK 2 ; address where the Rom data is coming from ExtraBits: .BLK 1 ; byte containing 1 bit per 2 bytes of IM ; data Checksum: .BLK 2 ; low-order byte first BreakpointsLeft: .BLK 1 NextBreakpoint: .BLK 2 ; IM address, high-order byte first BPAddrTable: .BLK 2 ; low-order byte first MicroHalf: .BLK 1 ; 40 if left half, 41 if right half ViaCP: .BLK 1; 0 if bootstrap loader not yet running in Dorado ; These parameter blocks describe data blocks to be transferred ; to the running Dorado processor. They are probably (although ; not necessarily) located in Rom, and they probably (although ; not necessarily) consist of packed microinstructions to ; be put into IM. We allow for several blocks because we ; may want to re-configure the processor between ; transfers; for example, to turn on/off parity errors. .LOC BootBlockTable BootBlocks: Boot0Block: .ADR Boot0Data ; in microcomputer memory Boot0IMLocation: .ADR Boot0IMLoc ; first IM location Boot0HunkCount: .ADR Boot0Length ; in 17-byte hunks Boot0RomChecksum: .ADR Boot0Checksum Boot0BPCount: Boot0BreakpointCount Boot0BPAddrTable: .ADR Boot0BreakpointAddrTable ; two bytes/breakpoint, ; high-order byte first, in decreasing address order Boot1Block: .ADR Boot1Data .ADR Boot1IMLoc .ADR Boot1Length .ADR Boot1Checksum Boot1BreakpointCount .ADR Boot1BreakpointAddrTable .LOC BootCode ; This is a set of Dorado microinstructions that are ; jammed into IM and executed for their side effects. ; Each is 5 bytes long and conforms to the format ; in DoDoradoMicroInst: ; 0: RSTK.0,P015,JCN.7,P1631,0,0,0,0 ; 1: RSTK.1,RSTK.2,RSTK.3,ALUF.0,BLOCK,FF.0,FF.1,FF.2 ; 2: ALUF.1,ALUF.2,ALUF.3,BSEL.0,FF.3,FF.4,FF.5,FF.6 ; 3: BSEL.1,BSEL.2,LC.0,LC.1,FF.7,JCN.0,JCN.1,JCN.2 ; 4: LC.2,ASEL.0,ASEL.1,ASEL.2,JCN.3,JCN.4,JCN.5,JCN.6 .RDX 2 IRTable: ; General note: these are hand-coded and should be thoroughly ; checked for accuracy. Make sure never to select BSEL=MD (0) ; because that can cause holds. Nop#: ; Nop; ; RSTK[0],ALUF[0],BSEL[1],LC[0],ASEL[4],FF[77],JCN[201] 01^6.+(11^4.) 0000^4.+0001 0000^4.+1111 0100^4.+1100 0100^4.+0000 IFUReset#: ; IFUReset; ; RSTK[0],ALUF[0],BSEL[1],LC[0],ASEL[4],FF[136],JCN[201] 01^6.+(10^4.) 0000^4.+0010 0000^4.+1111 0100^4.+0100 0100^4.+0000 CPRegToLink#: ; B_RWCPReg,LocalJump[1]; ; RSTK[0],ALUF[17],BSEL[0],LC[0],ASEL[4],FF[176],JCN[201] 00^6.+(11^4.) 0001^4.+0011 1110^4.+1111 0000^4.+0100 0100^4.+0000 IMLHRSTK.0Is0#: ; IMLHR0'POK_RWCPReg; ; RSTK[1],ALUF[17],BSEL[0],LC[0],ASEL[4],FF[176],JCN[177] 01^6.+(10^4.) 0011^4.+0011 1110^4.+1111 0000^4.+0011 0100^4.+1111 IMLHRSTK.0Is1#: ; IMLHR0POK_RWCPReg; ; RSTK[3],ALUF[17],BSEL[0],LC[0],ASEL[4],FF[176],JCN[177] 00^6.+(10^4.) 0111^4.+0011 1110^4.+1111 0000^4.+0011 0100^4.+1111 CPRegToIM#: IMRHBLOCKIs0#: ; IMRHB'POK_RWCPReg; ; RSTK[0],ALUF[17],BSEL[0],LC[0],ASEL[4],FF[176],JCN[177] 00^6.+(10^4.) 0001^4.+0011 1110^4.+1111 0000^4.+0011 0100^4.+1111 IMRHBLOCKIs1#: ; IMRHBPOK_RWCPReg; ; RSTK[2],ALUF[17],BSEL[0],LC[0],ASEL[4],FF[176],JCN[177] 01^6.+(10^4.) 0101^4.+0011 1110^4.+1111 0000^4.+0011 0100^4.+1111 Return#: ; TaskingOff,Return; ; RSTK[0],ALUF[17],BSEL[1],LC[0],ASEL[4],FF[142],JCN[107] 01^6.+(10^4.) 0001^4.+0011 1110^4.+0001 0100^4.+0010 0100^4.+0011 QFromCPReg#: ; Q_RWCPReg; ; RSTK[0],ALUF[17],BSEL[3],LC[0],ASEL[4],FF[176],JCN[201] 00^6.+(11^4.) 0001^4.+0011 1110^4.+1111 1100^4.+0100 0100^4.+0000 TFromCPReg#: ; requires ALUFM[0]=B ; T_RWCPReg; ; RSTK[0],ALUF[0],BSEL[0],LC[1],ASEL[4],FF[176],JCN[201] 01^6.+(11^4.) 0000^4.+0011 0000^4.+1111 0000^4.+0100 1100^4.+0000 ALUFM[0]FromQ#: ; ALUFMEM_Q,ALUF[0]; ; RSTK[0],ALUF[0],BSEL[3],LC[0],ASEL[4],FF[262],JCN[201] 00^6.+(11^4.) 0000^4.+0101 0000^4.+1001 1100^4.+0100 0100^4.+0000 SetMcr#: ; LoadMcr[T,T]; ; RSTK[0],ALUF[0],BSEL[2],LC[0],ASEL[6],FF[126],JCN[201] 00^6.+(11^4.) 0000^4.+0010 0000^4.+1011 1000^4.+0100 0110^4.+0000 SetHoldTaskSim#: ; HoldSim_RWCPReg (more or less); ; RSTK[0],ALUF[17],BSEL[2],LC[0],ASEL[4],FF[176],JCN[201] 01^6.+(11^4.) 0001^4.+0011 1110^4.+1111 1000^4.+0100 0100^4.+0000 .RDX 16 ; Routine to run the Boot0 code block in the Dorado, and then ; hand it the Boot1 code block in CPReg byte by byte. LoadDoradoCode: ; Prevent Midas from taking over the machine during a bootstrap ; operation, assuming that Midas is obeying standard politeness ; conventions. JSR WaitForCPControl JSR StopDorado ; Check whether the clock speed is faster than the standard ; startup clock speed. If so, slow it down. LDYI 7 LDXI ClockSpeedMufField JSR ReadMufflerField CMPI StdClockSet BEQ ClockSpeedOK BCC ClockSpeedOK ; Set the standard clock speed LDXI StdClockSpeedH JSR SetManifold LDXI StdClockSpeedL JSR SetManifold ; Wait for the clock to settle. LDXI 2. JSR Delay ; At this point all the power supplies are on and the ; voltages and currents are within acceptable limits. ; Initialize all manifold registers, clear IO reset. ClockSpeedOK: LDXI InitManifolds LDAI MaxInitManifold STA InitManifoldsLeft SetupManifoldLoop: JSR SetManifold INX INX ; two bytes per manifold entry DEC InitManifoldsLeft BPL SetupManifoldLoop JSR PrepareProcessor ; Set up ALUFM[0] with a 25o, which is the logical ; function B. LDXI 25o LDAI QFromCPReg#-IRTable JSR SetCPAndDoIRTableInst LDAI ALUFM[0]FromQ#-IRTable JSR DoIRTableInst ; Do an IFU reset to stop the IFU from polluting the MAR mux. LDAI IFUReset#-IRTable JSR DoIRTableInst ; Enter the Boot0 loader into the IM LDXI Boot0Block-BootBlocks LDAI 0 ; Dorado not running loader JSR SendIMBlockToDorado ; Make sure there is no "ACK" in the Dorado-to-micro ; manifold communication register. LDXI ClearDMManifold JSR SetManifold ; Put into Link the address of the first instruction in the Boot0 ; microcode. LDYI Boot0GoLoc,#HighAddrByte LDXI Boot0GoLoc,#LowAddrByte LDAI CPRegToLink#-IRTable JSR SetCP~AndDoIRTableInst ; Put a 1 in CPReg[0] to synchronize microcomputer-microprocessor ; CPReg communications. LDAI 0 STA ToCPRegL LDAI 80 STA ToCPRegH JSR SetCPReg ; force a 1 in CPReg[0] to synchronize comm ; Allow CB holds LDXI AllowCBHolds JSR SetManifold ; Start the Boot0 loader running in the Dorado. LDAI Return#,#HighAddrByte STA Micro+1 LDAI Return#,#LowAddrByte STA Micro JSR RunDoradoInstructionStream ; Send the Boot0 loader a block of code for it to load into IM. LDXI Boot1Block-BootBlocks LDAI 1 ; Dorado now running loader JSR SendIMBlockToDorado LDAI CouldntBootDorado JSR ClearProblem ; Now see if Dorado has sent us an "ACK", as it were, ; for the whole block. LDYI 65. ; give the Dorado about 250 ms to complete init LDXI 0 WaitForACK: LDA MiscByte ANDI 0f CMPI 01 ; "ACK" BEQ HeSentACK DEX ; 15 us inner loop BNE WaitForACK DEY BNE WaitForACK LDAI CouldntBootDorado JSR SetProblem ; we failed. Notify user. ; Now let Midas have access to the Dorado once again. HeSentACK: JMP EnableMidas ; Routine to re-start the Dorado at IM location InitMap. StartDoradoAtInitmap: JSR WaitForCPControl JSR PrepareProcessor ; Put into Link the address of the InitMap. LDYI InitMap,#HighAddrByte LDXI InitMap,#LowAddrByte LDAI CPRegToLink#-IRTable JSR SetCP~AndDoIRTableInst ; Start the Dorado running at InitMap. LDAI Return#,#HighAddrByte STA Micro+1 LDAI Return#,#LowAddrByte STA Micro JSR RunDoradoInstructionStream JMP EnableMidas ; Subroutine to get the Dorado's attention and get it reset. PrepareProcessor: JSR StopDorado LDXI DoIOReset JSR SetManifold ; Do a lot of microinstructions to clear out the cobwebs. Those ; microinstructions clear out the hold and task simulator. LDAI 40. STA NoopsToGo DoYetAnotherNoop: LDXI 0 LDYI 0 LDAI SetHoldTaskSim#-IRTable JSR SetCPAndDoIRTableInst DEC NoopsToGo BNE DoYetAnotherNoop ; Clear out MCR to DisHold, NoWakeups. LDXI 103o LDYI 0 LDAI TFromCPReg#-IRTable JSR SetCPAndDoIRTableInst LDAI SetMcr#-IRTable JSR DoIRTableInst ; Turn off tasking LDAI Return#-IRTable JSR DoIRTableInst RTS ; Routine to do an IRTable instruction, perhaps setting ; the CP register first. The offset ; is in A. SetCP~AndDoIRTableInst: STX ToCPRegL STY ToCPRegH PHA JSR WaitForCPControl JSR SetCPReg~ PLA JMP DoIRTableInstAndNop SetCPAndDoIRTableInst: STX ToCPRegL STY ToCPRegH PHA JSR WaitForCPControl JSR SetCPReg PLA DoIRTableInstAndNop: ; the Nop holds CPReg constant through T3 of ; the previous instruction JSR DoIRTableInst LDAI Nop#-IRTable JMP BasicDoIRTableInst DoIRTableInst: JSR WaitForCPControl BasicDoIRTableInst: CLC ADCI IRTable,#LowAddrByte STA Micro LDAI 0 ADCI IRTable,#HighAddrByte STA Micro+1 JSR DoDoradoMicroInst JMP EnableMidas ; Routine to pass the Dorado a block of microinstructions. ; X indexes a table of pointers (to first bytes) and lengths ; (in hunks). A is zero if we must load IM by manually executing ; instructions in MIR, and non-zero if we can send stuff ; to an executing Dorado program through CPReg. SendIMBlockToDorado: STA ViaCP LDAX Boot0IMLocation ; low-order byte STA IMAddress+1 LDAX Boot0IMLocation+1 ; high-order byte STA IMAddress LDAX Boot0HunkCount ; low-order byte STA HunksLeft+1 LDAX Boot0HunkCount+1 ; high-order byte STA HunksLeft LDAX Boot0RomChecksum ; low-order byte STA Checksum LDAX Boot0RomChecksum+1 ; high-order byte STA Checksum+1 LDAX Boot0BPCount STA BreakpointsLeft LDAX Boot0BPAddrTable ; low-order byte STA BPAddrTable LDAX Boot0BPAddrTable+1 ; high-order byte STA BPAddrTable+1 JSR SetupNextBreakpoint LDA ViaCP ; don't send a count if nobody's listening BEQ FinishSendIMBlockSetup ; First tell the Dorado where the hunks go, how many are ; coming. LDAI IMAddress,#HighAddrByte STA Hunk+1 LDAI IMAddress,#LowAddrByte STA Hunk LDYI 0 STY ExtraBits LDAI 40 STA MicroHalf JSR SendAHalfMicroInstruction ; IMAddress JSR SendAHalfMicroInstruction ; HunksLeft FinishSendIMBlockSetup: LDAX Boot0Block STA Hunk LDAX Boot0Block+1 STA Hunk+1 SendAnotherHunk: JSR SendAHunk JSR PacifyWatchdog LDA Hunk CLC ADCI 17. STA Hunk BCC NoMicroCarry INC Hunk+1 NoMicroCarry: DEC HunksLeft+1 BNE SendAnotherHunk DEC HunksLeft BPL SendAnotherHunk LDA ViaCP ; don't send a checksum if nobody's listening BEQ FinishSendIMBlock LDA Checksum SEC ; good parity JSR SetCPReg1 ; set low-order byte of parity word LDA Checksum+1 JSR SetCPReg0 ; high-order byte signals that CPReg is good FinishSendIMBlock: RTS SetupNextBreakpoint: TYA PHA LDY BreakpointsLeft DEY TYA ASLA ; 2 bytes/entry TAY LDA@Y BPAddrTable ; high-order address byte STA NextBreakpoint INY LDA@Y BPAddrTable ; low-order address byte STA NextBreakpoint+1 PLA TAY RTS ; A hunk is a ; sequence of 17 bytes containing four microinstructions ; packed as follows, from high- to low-order bit in each byte: ; Byte 0: 0RSTK.0, 0BLOCK, 1RSTK.0, 1BLOCK, ; 2RSTK.0, 2BLOCK, 3RSTK.0, 3BLOCK ; Byte 1: 0RSTK.1, 0RSTK.2, 0RSTK.3, 0ALUF.0, ; 0ALUF.1, 0ALUF.2, 0ALUF.3, 0BSEL.0 ; Byte 2: 0BSEL.1, 0BSEL.2, 0LC.0, 0LC.1, ; 0LC.2, 0ASEL.0, 0ASEL.1, 0ASEL.2 ; Byte 3: 0FF.0, 0FF1, 0FF.2, 0FF.3, ; 0FF.4, 0FF.5, 0FF.6, 0FF.7 ; Byte 4: 0JCN.0, 0JCN.1, 0JCN.2, 0JCN.3, ; 0JCN.4, 0JCN.5, 0JCN.6, 0JCN.7 ; ... ; ... ; Byte 14: 3RSTK.1, 3RSTK.2, 3RSTK.3, 3ALUF.0, ; 3ALUF.1, 3ALUF.2, 3ALUF.3, 3BSEL.0 ; Byte 15: 3BSEL.1, 3BSEL.2, 3LC.0, 3LC.1, ; 3LC.2, 3ASEL.0, 3ASEL.1, 3ASEL.2 ; Byte 16: 3FF.0, 3FF1, 3FF.2, 3FF.3, ; 3FF.4, 3FF.5, 3FF.6, 3FF.7 ; Byte 17: 3JCN.0, 3JCN.1, 3JCN.2, 3JCN.3, ; 3JCN.4, 3JCN.5, 3JCN.6, 3JCN.7 ; We assume without checking that the Dorado will take the ; data as fast as we slap it into the CP register. The ; presence of new data is signalled by a change in ; the high-order bit of the CP register. The Dorado will ; have a minimum of 25 usec from a change in the high-order bit ; of CPReg until the data in the low-order ; byte of CPReg goes away. Data will be sent at about ; 200 usec per microinstruction. SendAHunk: LDA ViaCP BEQ DontGetCPControlYet JSR WaitForCPControl DontGetCPControlYet: LDYI 0 LDA@Y Hunk ; pick up the first byte INY STA ExtraBits SendAnotherInstruction: LDAI 40 ; left half STA MicroHalf LDA IMAddress+1 ; low-order byte CMP NextBreakpoint+1 BNE UseMicroHalf LDA IMAddress ; high-order byte CMP NextBreakpoint BNE UseMicroHalf LDA BreakpointsLeft ; is it really real? BEQ UseMicroHalf LDAI 2 ; set a breakpoint ORA MicroHalf STA MicroHalf UseMicroHalf: JSR SendAHalfMicroInstruction LDA MicroHalf ORAI 1 ; right half STA MicroHalf JSR SendAHalfMicroInstruction LDA MicroHalf ANDI 2 ; set a breakpoint? BEQ NotThisInstruction DEC BreakpointsLeft JSR SetupNextBreakpoint NotThisInstruction: INC IMAddress+1 BNE DontStepHighIMAddress INC IMAddress DontStepHighIMAddress: CPYI 17. ; 2 us BNE SendAnotherInstruction ; 3 us LDA ViaCP BEQ DontReturnCPControl JSR EnableMidas DontReturnCPControl: RTS SendAHalfMicroInstruction: LDA ViaCP BEQ SendViaMIR LDA@Y Hunk ; 5 us INY ; 2 us STA MCPBusH ; 4 us LDAI 80+ABMux1 ; good parity ; 2 us STA MCPBusL ; 4 us INC MCPBusL ; strobe it into CPReg low-order bits ; 5 us DEC MCPBusL ; 5 us LDAI 0 ; 2 us STA MCPBusH ; 4 us LDAI ABMux0 ; 2 us STA MCPBusL ; 4 us INC MCPBusL ; strobe it into CPReg high-order bits ; 5 us DEC MCPBusL ; 5 us LDA@Y Hunk ; 5 us INY ; 2 us STA MCPBusH ; 4 us LDAI 80+ABMux1 ; good parity ; 2 us STA MCPBusL ; 4 us INC MCPBusL ; strobe it into CPReg low-order bits ; 5 us DEC MCPBusL ; 5 us LDA MicroHalf ; 3 us ASL ExtraBits ; 5 us ROLA ; 2 us STA MCPBusH ; 4 us LDAI ABMux0 ; 2 us STA MCPBusL ; 4 us INC MCPBusL ; strobe it into CPReg high-order bits ; 5 us DEC MCPBusL ; 5 us RTS IMStoreTable: IMLHRSTK.0Is0#-IRTable ; 0 instructions in IRTable that do IMLHRSTK.0Is1#-IRTable ; 1 useful stores into IM IMRHBLOCKIs0#-IRTable ; 2 IMRHBLOCKIs1#-IRTable ; 3 ; This stores in IM by executing instructions out of MIR, ; one at a time. We don't bother to set breakpoints here. SendViaMIR: TYA PHA LDX IMAddress+1 ; low-order IM address byte LDY IMAddress ; high-order IM address byte LDAI CPRegToLink#-IRTable JSR SetCP~AndDoIRTableInst PLA TAY LDA@Y Hunk INY STA ToCPRegH LDA@Y Hunk INY STA ToCPRegL TYA PHA JSR SetCPReg~ LDA MicroHalf ANDI 1 ASL ExtraBits ROLA TAX LDAX IMStoreTable JSR DoIRTableInst ; CPReg can change before T3 PLA TAY RTS .END (635)