        .IF     EXTERNAL = 1        .NOLIST        .ENDC        .PAGE        .ABSOLUTE	        ;makes listing look nicer        .PROC   LISAROM,0        .ORG    0	        ; ORG'ED AT 0 BUT RUNS AT $00FE0000;  Reset vectors here to pick up SP and PC valuesBASE        .WORD   $0000	        ;initial SP        .WORD   STKBASE        .WORD   ROMSLCT	        ;initial PC (assumes use of MMU reg 127)        .WORD   BEGIN;  Set up next locations for exception vectorsBUSVCT  .WORD   ROMSLCT		  ; BUS ERROR VECTOR        .WORD   EXCPERRADRVCT  .WORD   ROMSLCT		  ; ADDRESS ERROR        .WORD   EXCPERRILLVCT  .WORD   ROMSLCT		  ; ILLEGAL INSTRUCTION        .WORD   EXCPERRDIV0VCT .WORD   ROMSLCT		  ; DIVIDE BY ZERO ERROR        .WORD   EXCPERRCHKVCT  .WORD   ROMSLCT		  ; CHK INSTRUCTION        .WORD   EXCPERRTRAPVCT .WORD   ROMSLCT		  ; TRAPV INSTRUCTION        .WORD   EXCPERRPRIVCT  .WORD   ROMSLCT		  ; PRIVILEGE VIOLATION        .WORD   EXCPERRTRCVCT  .WORD   ROMSLCT		  ; TRACE OPERATION        .WORD   EXCPERRL10VCT  .WORD   ROMSLCT		  ; OPCODE 1010 DETECTED        .WORD   EXCPERRL11VCT  .WORD   ROMSLCT		  ; OPCODE 1111 DETECTED        .WORD   EXCPERR;------------------------------------------------------------------;  Exception and interrupt vector handler for ROM - resets SP and;  tries a restart;------------------------------------------------------------------EXCPERR MOVEA   #STKBASE,SP     ;reset stack ptr        CLR.L   D7	        ;clear error indicator		        CHG004        BRA     ROMTST	        ;and restart diags		        CHG004        .PAGE;--------------------------------------------------------------------;  Subroutine for saving registers and stack pointers;--------------------------------------------------------------------SAVEREGS        MOVE.L  SP,SUPSTK       ;save sup stack ptrSAVEREG2        MOVE.L  A6,A6SAV        ;save other regs (that aren't reset)        MOVE.L  USP,A6        MOVE.L  A6,USPSAV        MOVE    #A6SAV,A6       ;set ptr for saving regs        MOVEM.L D0-D7/A0-A5,-(A6)        RTS;  use spare bytes for messageSVCMSG  .ASCII  'SERVICE MODE'  ;				        RM000        .BYTE   0	        ;				        RM000        .ORG    $60;  The next set of vectors cover spurious and autovector interruptsSPURVCT .WORD   ROMSLCT		  ; SPURIOUS INTERRUPT        .WORD   EXCPERRLVL1VCT .WORD   ROMSLCT		  ; INTERNAL I/O INTERRUPTS (DISK,VERT TRACE,ETC.)        .WORD   EXCPERRLVL2VCT .WORD   ROMSLCT		  ; KEYBOARD INTERRUPT        .WORD   EXCPERRLVL3VCT .WORD   ROMSLCT		  ; I/O SLOT 2 INTERRUPT        .WORD   EXCPERRLVL4VCT .WORD   ROMSLCT		  ; I/O SLOT 1        .WORD   EXCPERRLVL5VCT .WORD   ROMSLCT		  ; I/O SLOT 0        .WORD   EXCPERRLVL6VCT .WORD   ROMSLCT		  ; RS-232        .WORD   EXCPERRLVL7VCT .WORD   ROMSLCT		  ; NMI        .WORD   NMIEXCP		  ;				        RM010        .IF     EXTERNAL = 1        .LIST        .ENDC        .PAGE        .ORG    $80;-------------------------------------------------------------------------;  Jump Table for calling by external routines;-------------------------------------------------------------------------JMPTBL        JMP     DORESET	        ;go to restart point		        RM000        JMP     INITMON	        ;jump to ROM Monitor        .IF  USERINT = 0        JMP     DSPMSG	        ;display a message        .ELSE        JMP     CONVRTD5        ;convert row ptr and display message        .ENDC        JMP     WRTMMU	        ;write to set of MMU registers        JMP     PROREAD	        ;Profile read a block routine        JMP     TWGREAD	        ;Twiggy read a sector routine        .IF  DIAGS = 1        JMP     RAMTEST	        ;basic memory test        NOP		        ;				        CHG015        RTS		        ;				        CHG015        NOP		        ;				        CHG015        RTS		        ;				        CHG015        .ELSE        NOP        RTS        NOP        RTS        NOP        RTS        .ENDC        JMP     READMMU	        ;read MMU registers        JMP     COPSCMD	        ;Send COPS command        .IF  DIAGS = 1        JMP     READCLK	        ;Read clock setting        .ELSE        NOP        RTS        .ENDC        JMP     DSPDEC	        ;display hex error code in decimal        JMP     CONSET2	        ;for setting contrast        JMP     TONE	        ;to beep speaker        JMP     VFYCHKSM        ;verify checksum        .IF  ROM4K = 0        JMP     WRTSUM	        ;rewrite parameter memory	        CHG017        JMP     RDSERN	        ;go read system serial #        .ENDC;******************** Loop point for ROM test failure ********************************SPIN    BRA.S   SPIN	        ;hang system				        CHG007;*************************************************************************************        .IF     EXTERNAL = 1        .NOLIST        .ENDC;----------------------------------------------------------------------------;  NMI Exception Handler						        RM010;----------------------------------------------------------------------------NMIEXCP CLR.B   SETUP	        ;enable memory access			        RM010        BTST    #1,STATREG      ;parity error?				        RM010        BNE.S   @1	        ;skip if not to ignore			        RM010        MOVE    MEALTCH,ADRLTCH ;save address if yes			        RM010        TST.B   PAROFF	        ;and toggle to clear error bit		        RM010        TST.B   PARON	        ;					        RM010@1      TST.B   SETUPON	        ;return to SETUP state			        RM010        RTE		        ;					        RM010        .PAGE;----------------------------------------------------------------------------;  First do "warm-start" no reset check - scan I/O MMU regs to see if set up;----------------------------------------------------------------------------BEGIN        .IF     NORESET = 1        MOVE    MMU126L,D0      ;check reg 126 for special I/O space        ANDI    #$0FFF,D0       ;ignore don't care bits        CMPI    #IOLMT2,D0      ;for no reset, 126L = $x901  (x = random value)        BNE.S   BEGIN2	        ;skip if not set up        ANDI    #$0FFF,MMU126B  ;else also check 126B = $x000        BNE.S   BEGIN2;  Check OK - set MMU for ROM access and change SETUP before vectoring        MOVE    #MEMLMT,MMU0L   ;set low memory for r/w (to save regs,etc.)        MOVE    #IOLMT2,MMU126L ;set for I/O space access (reset value)        MOVE    #SPLMT,MMU127L  ;set access for ROM space        MOVE    #0,MMU127B        CLR.B   SETUP	        ;enable memory access        MOVE.L  SP,SUPSTK       ;save supervisor stack ptr        MOVEA   #STKBASE,SP     ;move stack pointer for ROM use        BSR.S   SAVEREG2        ;save other registers;  Restore ROM Monitor environment        BSR4    CONSET	        ;go set default contrast        SUBA.L  A2,A2	        ;set for no icons        CLR.L   D0	        ; error codes        SUBA.L  A3,A3	        ;  or messages        BRA     INIT1	        ;exit directly to monitor (avoid resaving regs)        .ENDC;-------------------------------------------------------------------------;  Do second warm-start check to see if contrast should be reset;-------------------------------------------------------------------------BEGIN2  CLR.L   D7	        ;clear for error use        MOVE    MMU127L,D0      ;check reg 127 for ROM space        ANDI    #$0FFF,D0       ;ignore don't care bits        CMPI    #SPLMT,D0       ;expect 127L = $xF00  (x = random value)        BNE.S   ROMTST	        ;skip if not        ANDI    #$0FFF,MMU127B  ;else check if 127B = $x000        BNE.S   ROMTST;  Check OK - set MMU for I/O and ROM access and go set contrast        BSET    #WRMSTRT,D7     ;set warm start indicator        MOVEQ   #0,D0	        ;clear for use        MOVE    #IOLMT,MMU126L  ;set access for I/O space        MOVE    D0,MMU126B        MOVE    #SPLMT,MMU127L  ;set access for ROM spaceBEGIN3  RESET		        ;ensure clean I/O state for "warm-start"        .IF  NEWLISA = 1        BSR4    CONOFF	        ;and go disable contrast        .ELSE        BSR4    CONSET	        ;go set default contrast        .ENDC        .PAGE;-------------------------------------------------------------------------;  Start diagnostics - do ROM checksum test first; expected result = 0;-------------------------------------------------------------------------ROMTST        .IF  DIAGS = 1        CLR.L   D0	        ;clear for checksum use        LEA     BASE,A0	        ;init ROM address ptrs        LEA     LAST,A1DOSUM   ADD     (A0)+,D0        ;read location and add to sum        ROL     #1,D0	        ;rotate to catch multiple bit errors        CMPA.L  A0,A1	        ;loop until done        BNE.S   DOSUM        ADD     (A0)+,D0        ;add checksum word        BNE     SPIN	        ;loop if error			        CHG007        TST.L   D7	        ;in loop mode?        BMI.S   ROMTST	        ;restart test if yes        .ENDC        .PAGE;----------------------------------------------------------------------------;  Next do read/write and address test of MMU supervisor regs;  Register Usage (by this routine and/or its subroutines):;       A0 = MMU reg pointer	        D0 = test pattern;       A1 = last MMU limit reg addr    D1 = contents read from MMU reg;       A2 = MMU address increment      D2 = OR mask of results;       A3 = last MMU base reg addr     D3 = pattern expected at last error;       A4 = used for return address    D4 = final value for MMU reg;       A5 = MMU address of last error  D5 = unused;       A6 = used for return address    D6 = unused;       A7 = stack pointer	        D7 = error indicator (0 = R/W error);----------------------------------------------------------------------------MMUTST        .IF     DIAGS = 1        BSR4    MMUINIT	        ;initialize test variables        BSR6    MMURW	        ;and go do read/write test        BNE.S   MMUERR	        ;abort if error        BSRS4   MMUINIT	        ;reinitialize        BSR6    MMUACHK	        ;and do address test        BNE.S   @2	        ;skip if error        BRA     SETMMU	        ;else go do initial MMU setup@2      NOT     D7	        ;set address error indicator        .PAGE;----------------------------------------------------------------------------;  The following code is used to toggle every address and data line;  going to the MMU if an error in the MMU context 0 tests is found.;  Reset signals indicate read/write or addressing error.;----------------------------------------------------------------------------MMUERR  TST     D7	        ;check error type        BEQ.S   @2        RESET		        ;two reset signals for address error@2      RESET		        ;only one for R/W error;  Toggle every data and address bitMMULP   MOVE.L  #$00028000,A0   ;set MMU limit reg start address        MOVEQ   #1,D1	        ;and starting data pattern        MOVEQ   #7,D2	        ;and loop count        BSRS4   TSTLOOP	        ;go toggle for limit regs        MOVE.L  #$00028008,A0   ;set MMU base reg start address        MOVEQ   #5,D2	        ;and loop count        BSRS4   TSTLOOP	        ;go test base regs        BRA.S   MMUERR	        ;and loop indefinitely;  Subroutine to do reg testingTSTLOOP MOVE.L  A0,D0	        ;save starting addressREGTST  MOVE    D1,(A0)	        ;do write        MOVE    (A0),D3	        ;then read        LSL     #1,D1	        ;update pattern        SWAP    D0	        ;get address        LSL     #1,D0	        ;update and restore        SWAP    D0        MOVE.L  D0,A0        SUBQ    #1,D2	        ;loop until done        BNE.S   REGTST        RTS4		        ;exit        .PAGE;----------------------------------------------------------------------------;  Subroutine to do initial setup for MMU testing;----------------------------------------------------------------------------MMUINIT MOVE    #PATRN2,D0      ;set test pattern        MOVEQ   #0,D1	        ;clear for result/error use        MOVEQ   #0,D2	        ; use MOVEQ for speed        MOVE.L  #ADR128K,A2     ;set up increment value        ORI     #$0710,SR       ;set extend bit and disable interrupts        RTS4        .PAGE;----------------------------------------------------------------------------;  Subroutine to do MMU Read/Write Test for all registers in one context.;  Zero bit set in CCR if no errors.;----------------------------------------------------------------------------MMURW   MOVE.L  #MMUSADRL,A0    ;SET MMU LIMIT START ADDR        MOVE.L  #MMUEADRL,A1    ;SET MMU LIMIT END ADDR        MOVE.L  #MMUEADRB,A3    ;SET MMU BASE END ADDRRWCHK1  BSR4    CHKRW	        ;GO DO READ/WRITE CHECK        NOT     D0	        ;INVERT FOR NEXT PASS        BSRS4   CHKRW	        ;GO DO AGAINRWCHK2  NOT     D0	        ;INVERT BACK TO ORIGINAL PATTERN        BSRS4   CHKRW	        ;ONE MORE TIMERWCHK3  ROXL    #1,D0	        ;SET UP NEW PATTERN        CMPA.L  A0,A1	        ;CHECK IF DONE        BEQ.S   CHKBASE	        ;IF YES GO CHECK FOR BASE REG TESTING        ADDA.L  A2,A0	        ;ELSE BUMP MMU ADDR        BRA.S   RWCHK1CHKBASE CMPA.L  A0,A3	        ;DONE WITH BASE?        BEQ.S   @2	        ;EXIT IF YES        MOVE.L  #MMUSADRB,A0    ;ELSE SET STARTING BASE ADDRESS        MOVEA.L A3,A1	        ; AND ENDING ADDRESS        BRA.S   RWCHK1	        ;GO CHECK BASE REGS@2      TST     D2	        ;check for errors        RTS6		        ;and exit test        .PAGE;----------------------------------------------------------------------------;  Subroutine to do MMU address check;  Leaves limit registers with invalid page value, base regs with 0;----------------------------------------------------------------------------MMUACHK MOVE.L  #MMUSADRL,A0    ;SET MMU LIMIT START ADDR        MOVE.L  #MMUEADRL,A1    ;SET MMU LIMIT END ADDR        MOVE.L  #MMUEADRB,A3    ;SET MMU BASE END ADDR        MOVE    #INVPAG,D4      ;SET FINAL VALUE FOR LIMIT REGSACHK1   MOVE    (A0),D1	        ;READ REG        EOR     D0,D1	        ;CHECK IF EXPECTED        ANDI    #$0FFF,D1       ;MASK DON'T CARES        BNE.S   MADRERR	        ;EXIT IF ERRORMMUSET  MOVE    D4,(A0)	        ;SET FINAL REG VALUE        ROXL    #1,D0	        ;SET UP NEW PATTERN        CMPA.L  A0,A1	        ;CHECK IF DONE        BEQ.S   ACHK2	        ;IF YES GO CHECK FOR BASE REG TESTING        ADDA.L  A2,A0	        ;ELSE BUMP MMU ADDR        BRA.S   ACHK1ACHK2   CMPA.L  A0,A3	        ;DONE WITH BASE?        BEQ.S   @2	        ;EXIT IF YES        MOVE.L  #MMUSADRB,A0    ;ELSE SET STARTING BASE ADDRESS        MOVEA.L A3,A1	        ; AND ENDING ADDRESS        MOVEQ   #0,D4	        ;SET FINAL VALUE FOR BASE REGS        BRA.S   ACHK1	        ;GO CHECK BASE REGS@2      TST     D2	        ;check for errors        RTS6		        ;and exit test;  Handle MMU address errorMADRERR OR      D1,D2	        ;save error bits        BRA.S   MMUSET	        ; and continue test        .ELSE        CLR.L   D2	        ;for error patterns        BRA.S   SETMMU        .ENDC        .PAGE;----------------------------------------------------------------------------; Subroutine to do MMU actual read/write;----------------------------------------------------------------------------CHKRW   MOVE    D0,(A0)	        ;do write        MOVE    (A0),D1	        ;read back        EOR     D0,D1	        ;compare        ANDI    #$0FFF,D1       ;mask don't cares        BNE.S   RWERR	        ;skip if error        RTS4		        ;else return;  Error collectionRWERR   OR      D1,D2	        ;save error bits        RTS4		        ;and return        .PAGE;--------------------------------------------------------------------------;  Now do setup of MMU supervisor registers for RAM and I/O space access.;  Also do read check after write and abort if error.;--------------------------------------------------------------------------;  Do origin registers firstSETMMU  MOVE.L  #MMUSADRB,A0    ;GET MMU PTR        MOVEQ   #0,D0	        ;clear for use        MOVEQ   #0,D1        MOVE    D2,D4	        ;SAVE PREVIOUS RESULTS IF ANY        MOVEQ   #0,D2        MOVEQ   #0,D6        MOVE.L  #ADR128K,A2     ;ADDRESS INCREMENT        MOVE.L  #PAG128K,A3     ;SET UP BASE ADDRESS INCREMENT        MOVEQ   #16,D6	        ;LOOP COUNTLOADORG BSRS4   CHKRW	        ;DO WRITE/READ CHECK        ADD.L   A3,D0	        ;COMPUTE NEXT MEMORY BASE ADDRESS        ADDA.L  A2,A0	        ;BUMP MMU ORG PTR        SUBQ    #1,D6        BNE.S   LOADORG	        ;LOOP UNTIL DONE;  Set base for I/O and special I/O space        MOVEA.L #MMU126B,A0     ;PT TO ORG REG 126        MOVEQ   #0,D0	        ;set data value        BSRS4   CHKRW        ADDA.L  A2,A0	        ;BUMP PTR TO REG 127        BSRS4   CHKRW;  Now do limit registers        MOVEA.L #MMUSADRL,A0    ;GET MMU LIMIT REG PTR        MOVE    #MEMLMT,D0      ;LIMIT FOR 128K MEMORY SEGMENTS        MOVEQ   #0,D1	        ;use as working reg        MOVEQ   #16,D6	        ;LOOP COUNTLOADLMT BSRS4   CHKRW        ADDA.L  A2,A0	        ;BUMP MMU PTR        SUBQ    #1,D6        BNE.S   LOADLMT	        ;LOOP UNITL DONE;  Now do MMU limit reg setup for I/O and Special I/O access        MOVEA.L #MMU126L,A0     ;PT TO LMT REG 126        MOVE    #IOLMT,D0       ;SET FOR I/O SPACE, FULL ACCESS        BSRS4   CHKRW        ADDA.L  A2,A0	        ;BUMP PTR TO REG 127        MOVE    #SPLMT,D0       ;SET FOR SPECIAL I/O, FULL ACCESS        BSRS4   CHKRW        .IF  DIAGS = 1;  Check if errors detected        TST     D2	        ;CHECK ERROR MASK        BNE     MMUERR	        ;ABORT IF ERROR        MOVE    D4,D2	        ;ELSE RESTORE PREVIOUS RESULTS        .ENDC        .PAGE;--------------------------------------------------------------------------;  Complete testing of MMU by checking other context regs.;  Uses reg D6 for context indicator.;--------------------------------------------------------------------------        .IF     DIAGS = 1MMUTST2 MOVEQ   #0,D6	        ;FOR CONTEXT INDICATOR        BSR4    MMUINIT	        ;REINITIALIZE FOR TESTING        TST.B   SEG1ON	        ;SET FOR CONTEXT 1        MOVEQ   #1,D6	        ;SET CONTEXT INDICATOR        BSR4    CONCHK	        ;CHECK IF MMU CONTEXT CHANGED        BEQ     MMUERR2	        ;EXIT IF NO - SEG BIT ERROR        BSR6    MMURW	        ;ELSE GO DO R/W TEST        BNE     MMUERR2	        ;exit if error        TST.B   SEG2ON	        ;SET FOR CONTEXT 3        MOVEQ   #3,D6        BSR4    CONCHK	        ;CHECK IF MMU CONTEXT CHANGED        BEQ.S   MMUERR2	        ;EXIT IF NO - SEG BIT ERROR        BSR6    MMURW	        ;ELSE GO TEST        BNE.S   MMUERR2	        ;exit if error        TST.B   SEG1OFF	        ;SET FOR CONTEXT 2        MOVEQ   #2,D6        BSRS4   CONCHK	        ;CHECK IF MMU CONTEXT CHANGED        BEQ.S   MMUERR3	        ;EXIT IF NO - SEG BIT ERROR        BSRS6   MMURW	        ;ELSE GO TEST        BNE.S   MMUERR3	        ;exit if error        TST.B   SEG2OFF	        ;RESET FOR CONTEXT 0 REGS;  Now do MMU addressing check of remaining context regs        BSR4    MMUINIT	        ;REINITIALIZE        TST.B   SEG1ON	        ;SET FOR CONTEXT 1        MOVEQ   #1,D6        BSR6    MMUACHK	        ;TEST CONTEXT 1        BNE.S   MMUERR2	        ;exit if error        TST.B   SEG2ON	        ;TEST CONTEXT 3        MOVEQ   #3,D6        BSR6    MMUACHK        BNE.S   MMUERR2	        ;exit if error        TST.B   SEG1OFF	        ;TEST CONTEXT 2        MOVEQ   #2,D6        BSR6    MMUACHK        BNE.S   MMUERR3	        ;exit if error        TST.B   SEG2OFF	        ;RESET TO CONTEXT 0        BRA.S   MMULPCHK        ;go check for loop modeMMUERR2 TST.B   SEG1OFF	        ;ENSURE RESET FOR CONTEXT 0MMUERR3 TST.B   SEG2OFF        ROR     #4,D6	        ;get context indicator        OR      D6,D2	        ;save with error bits (if any)        BSET    #MMU,D7	        ;set error indicatorMMULPCHK        TST.L   D7	        ;in loop mode?        BMI.S   MMUTST	        ;restart full MMU test if yes        BRA.S   START	        ;else continue to next test        .PAGE;-------------------------------------------------------------------------;  Subroutine to verify context change made - does comparison to ensure;  destruction of context 0 mapping avoided.  Zero bit set if error.;-------------------------------------------------------------------------CONCHK  MOVE    MMU126L,D4      ;check limit reg for I/O space        ANDI    #$0FFF,D4       ;mask don't care        CMPI    #IOLMT,D4       ;still in same context?        BNE.S   CONOK	        ;exit if not        MOVE    MMU127L,D4      ;else also check reg for ROM space        ANDI    #$0FFF,D4       ;mask don't care        CMPI    #SPLMT,D4       ;also set up?        BNE.S   CONOK	        ;exit if not        MOVE    MMU0L,D4        ;else do final check on reg for memory access        ANDI    #$0FFF,D4        CMPI    #MEMLMT,D4      ;return with match results to callerCONOK   RTS4        .ENDC        .IF  ROM4K = 0        .IF  DIAGS = 0;-------------------------------------------------------------------------;  Initialize other MMU regs for invalid access;-------------------------------------------------------------------------        TST.B   SEG1ON	        ;SET FOR CONTEXT 1        MOVEQ   #1,D6	        ;SET CONTEXT INDICATOR        BSR6    INITMMU        TST.B   SEG2ON	        ;SET FOR CONTEXT 3        MOVEQ   #3,D6        BSR6    INITMMU        TST.B   SEG1OFF	        ;SET FOR CONTEXT 2        MOVEQ   #2,D6        BSR6    INITMMU        TST.B   SEG2OFF	        ;RESET FOR CONTEXT 0 REGS        CLR.L   D6        TST     D2	        ;CHECK IF ERRORS        BEQ.S   START	        ;exit if ok        ROR.L   #8,D6	        ;GET CONTEXT INDICATOR        OR.L    D6,D2	        ;SAVE WITH ERROR BITS        BSET    #MMU,D7	        ;SET ERROR CODE FOR LATER MESSAGE        BEQ.S   START	        ;AND CONTINUE        .PAGE;-------------------------------------------------------------------------;  Routine to init MMU regs;-------------------------------------------------------------------------INITMMU        MOVE.L  #MMUSADRL,A0    ;MMU limit start addr        MOVE.L  #MMUEADRL,A1    ;MMU limit end addr        MOVE.L  #ADR128K,A2     ;increment value        MOVE.L  #MMUEADRB,A3    ;MMU base end addr        MOVE    #INVPAG,D0      ;set pattern for limit regsRWLOOP  BSR4    CHKRW	        ;go initialize and check        CMPA.L  A0,A1	        ;done?        BEQ.S   CHKBASE	        ;if yes go check for base reg testing        ADDA.L  A2,A0	        ;else bump addr        BRA.S   RWLOOPCHKBASE CMPA.L  A0,A3	        ;done with base?        BEQ.S   @2	        ;exit if yes        MOVE.L  #MMUSADRB,A0    ;else set starting base address        MOVEA.L A3,A1	        ; and ending address        CLR.L   D0	        ;set base value        BRA.S   RWLOOP	        ;go do base regs@2      RTS6		        ;AND EXIT TEST        .ENDC		        ;{DIAGS}        .ENDC		        ;{ROM4K}        .PAGE;-------------------------------------------------------------------------;  Reset SETUP bit to enable system access and continue with testing;-------------------------------------------------------------------------START   CLR.B   SETUP	        ;TURN OFF SETUP TO ENTER MAP LAND ...;----------------------------------------------------------------------------;  Now do memory sizing - assumes 128K minimum memory increment;  Register usage:;       A0 = minimum physical address	        D0 = scratch use;       A1 = maximum physical address/scratch   D1 = incr for search address;       A2 = unused			        D2 = unused;       A3 = next base memory addr to test      D3 = inverted sizing test pattern;       A4 = return address		        D4 = sizing test pattern;       A5 = unused			        D5 = retry count;       A6 = saved error mask		        D6 = error mask;----------------------------------------------------------------------------MEMSIZ  CLR.L   D0	        ;setup regs for loop        MOVE.L  D0,A0        MOVE.L  D0,A1        MOVE.L  D0,A3        MOVE.L  D0,A6        MOVEQ   #2,D1	        ;size at 128K boundaries			        RM000        SWAP    D1	        ;						        RM000        MOVE.L  #PATRN,D4       ;set test patterns for sizing			        CHG002        MOVE    D4,D3	        ;use only lower word        NOT     D3	        ;and its inverseCHKLO   BSR4    CHKMEM	        ;first search for low memory address        TST     D6	        ;memory found?        BEQ.S   SAVELO	        ;yes - go save address        NOT     D6	        ;else invert to check if all bits in error        TST     D6	        ;if not, assume memory error        BNE.S   @3	        ; and go save address@2      ADDA.L  D1,A3	        ;else bump search address        MOVEA.L A3,A1	        ;set as next working address        CMPA.L  #MAXADR,A1      ;at max address?        BNE.S   CHKLO	        ;continue search if not;  No memory found - toggle LED and check for I/O board; if no I/O (bus error)	        CHG004;  diagnostics are restarted							        CHG004        MOVE.B  #DEFVID2,VIDLTCH ;set LED on and default video latch setting (PAGE 2F)  CHG004        MOVE    #TNTHSEC,D0	 ;delay for .1 sec				        CHG004@9      SUBQ    #1,D0		 ;						        CHG004        BNE.S   @9		 ;						        CHG004        MOVE.B  #DEFVID,VIDLTCH	 ;reset LED and leave video latch setting	        CHG004        MOVE.L  #VIA1BASE,A0	 ;check for I/O board				        CHG004        TST.B   (A0)		 ;bus error will occur if not installed		        CHG004;  Go into read/write loop if no memory found but I/O installed        BSR2    LOTONE	        ;beep speaker for error        BSR4    CONSET	        ;set contrast        MOVE.L  #ONEMEG-2,A0    ;set default memory address (to span both boards)       CHG002@4      MOVE.L  D4,(A0)	        ;go into read/write loop			        CHG002        MOVE.L  (A0),D3	        ;						        CHG002        BRA.S   @4;  Low memory address found - save and continue@3      NOT     D6	        ;reinvert and        MOVE    D6,A6	        ; save resultsSAVELO  MOVEA.L A3,A0	        ;save low address        CMPA.L  #ONEMEG,A0      ;check for min low address        BLE.S   @1	        ;skip if OK        MOVEA.L #ONEMEG,A0      ;else set at min value (one 512K board in slot 1)        .PAGE;-----------------------------------------------------------------------------;  Now check for high memory address; search to max address of 2 meg;-----------------------------------------------------------------------------@1      MOVEA.L A3,A2	        ;save low address as first high addressTSTHI        ADDA.L  D1,A3	        ;compute next 128K increment        MOVEA.L A3,A1	        ;use as new search value        CMPA.L  #MAXADR,A1      ;done?        BEQ.S   SIZXIT;  Following patch added to detect for wraparound problem of old memory boards        MOVE.L  A0,D0	        ;check low address				        RM015        BNE.S   CHKHI	        ;old memory boards start at address 0		        RM015        CMP     (A1),D3	        ;are we wrapped back to already tested location?        BEQ.S   WRAPXIT	        ;skip if yes (i.e., old memory board)		        RM015;  Else continue with check for high addressCHKHI   BSRS4   CHKMEM	        ;go do memory search        TST     D6	        ;any errors?        BEQ.S   SAVEHI	        ;skip if not to save address        NOT     D6	        ;else invert to see if all bits in error        TST     D6        BEQ.S   TSTHI	        ;skip if yes to ignore address        MOVE    A6,D0	        ;else get previous results        NOT     D6	        ;reinvert and        OR      D6,D0	        ; add new results        MOVE    D0,A6	        ;save for laterSAVEHI  MOVEA.L A3,A2	        ;save as new potential high address        CLR     (A3)	        ;clear test pattern				        RM015        BRA.S   TSTHI	        ; and continue loopWRAPXIT CLR     (A1)	        ;clear test pattern				        RM015SIZXIT  ADDA.L  D1,A2	        ;high address = last valid addr + 128K        MOVEA.L A2,A1	        ;save for later use        BRA.S   RSTMMU	        ;continue on        .PAGE;----------------------------------------------------------------------------;  Subroutine to do memory check for sizing.  If error, tries successive;  memory locations up to retry count (D5).  Returns with error mask in D6.;----------------------------------------------------------------------------CHKMEM  MOVEQ   #RETRYCNT,D5    ; set retry count in case of errors        CLR     D6	        ; clear for error mask@1      MOVE    D4,(A1)	        ; check if true data stores        MOVE    D3,2(A1)        ; and try complement to next location        CMP     (A1),D4        BEQ.S   @2	        ; continue if yes        MOVE    (A1),D0	        ; else get error bits        EOR     D4,D0        OR      D0,D6	        ; and save them@2      CMP     2(A1),D3        ; check second location        BEQ.S   @3	        ; exit if data correct        MOVE    2(A1),D0        ; else read again        EOR     D3,D0	        ; get error bits        OR      D0,D6	        ; save in error mask@3      MOVE    D4,2(A1)        ; now try in reverse order        MOVE    D3,(A1)        CMP     2(A1),D4        ; check second location        BEQ.S   @4	        ; skip if OK        MOVE    2(A1),D0        ; else save error bits        EOR     D4,D0        OR      D0,D6@4      CMP     (A1),D3	        ; and check first        BEQ.S   @5	        ; continue if yes        MOVE    (A1),D0	        ; else get error bits        EOR     D3,D0        OR      D0,D6	        ; and save them@5      TST     D6	        ; any  errors?        BEQ.S   @6	        ; skip if no        TST.L   (A1)+	        ; else bump search address to next pair        SUBQ    #1,D5	        ; decr retry count        BNE.S   @1	        ; continue until count exhausted@6      RTS4		        ; return with results in D6        .PAGE;-------------------------------------------------------------------------; Subroutine to set parms for lo tone from speaker;-------------------------------------------------------------------------LOTONE  MOVEQ   #$60,D0	        ;set frequency        MOVE    #250,D1	        ;and duration        MOVEQ   #4,D2	        ;and volume (medium)        BSR4    TONE2	        ;go do tone        RTS2        .PAGE;---------------------------------------------------------------------------;  Now reset MMU regs according to low and high physical address;  Remainder of MMU regs in context 0 are set to invalid page;;  Register Usage:;       A0 - low physical address       D0 - scratch/value stored in base reg;       A1 - high physical address      D1 - value stored in limit reg;       A2 - MMU base reg ptr	        D2 - unused;       A3 - MMU limit reg ptr	        D3 - holds base reg page incr value;       A4 - used for return address    D4 - used for count of regs to set;       A5 - MMU address increment      D5 - low physical page;       A6 - not used		        D6 - high physical page;---------------------------------------------------------------------------;  First translate memory addresses to 512 byte page values for MMU useRSTMMU        MOVE.L  A0,D5	        ;GET MEMORY ADDRESS VALUES        MOVE.L  A1,D6        MOVEQ   #9,D0	        ;SET SHIFT COUNT        LSR.L   D0,D5	        ;TRANSLATE TO PAGE VALUES        LSR.L   D0,D6;  Now initialize for MMU write operations        MOVEA.L #MMUSADRB,A2    ;SET MMU BASE REG PTR        MOVEA.L #MMUSADRL,A3    ;SET LIMIT REG PTR        MOVE.L  #ADR128K,A5     ;SET INCREMENT VALUE FOR MMU ADDRESSES        MOVE.L  #PAG128K,D3     ;SET INCR VALUE FOR BASE REG CONTENTS        MOVEQ   #126,D4	        ;SET REG COUNT - NO RESETTING OF REGS 126,127        MOVE    D5,D0	        ;SET BASE VALUE        MOVE    #MEMLMT,D1      ;SET LIMIT VALUE;  Remap MMU regs for existing memoryREMAP   BSRS4   WRTMMU	        ;REWRITE SET OF MMU REGS        SUBQ    #1,D4	        ;DECR REG COUNT        ADD.L   D3,D0	        ;BUMP PAGE ADDRESS        CMP.L   D0,D6	        ;CHECK IF AT UPPER LIMIT        BNE.S   REMAP	        ;LOOP IF NO;  Now map remainder of regs for invalid access        CLR     D0	        ;SET NEW BASE REG VALUE        MOVE    #INVPAG,D1      ; AND LIMIT REG VALUEMAPINV  BSRS4   WRTMMU	        ;GO DO REWRITE        SUBQ.L  #1,D4	        ;DECR COUNT        BNE.S   MAPINV	        ;LOOP UNTIL DONE;  Finally reset video page to last page of memory        LSR.L   #6,D6	        ;compute address for video page        SUBQ    #1,D6	        ;decr to last page        MOVE.B  D6,VIDLTCH      ;and set video latch        BRA.S   MEMTST1	        ;SKIP TO NEXT TEST        .IF     EXTERNAL = 1        .LIST        .PAGE        .ENDC;-------------------------------------------------------------------------;  Subroutine to set MMU regs (context 0) - can also be called by external;  routines that provide the following register inputs:;;       A2 = base reg address	        D0 = value for base reg;       A3 = limit reg address	        D1 = value for limit reg;       A5 = reg address increment;-------------------------------------------------------------------------WRTMMU  TST.B   SETUPON	        ;TURN SETUP ON TO ENABLE MMU ACCESS        MOVE    D0,(A2)	        ;SET BASE REG        MOVE    D1,(A3)	        ;SET LIMIT REG        ADDA.L  A5,A2	        ;BUMP MMU PTRS        ADDA.L  A5,A3        CLR.B   SETUP	        ;BACK TO MAP LAND        RTS4		        ;AND BACK TO CALLER        .IF  ROM16K = 1;-------------------------------------------------------------------------;  Subroutine to read MMU regs - for call by external routines.;  Inputs:;       D2 = context to read (0-3);       A2 = base reg address;       A3 = limit reg address;       A4 = return address;       A5 = reg address increment;  Outputs:;       D0 = value of base reg;       D1 = value of limit reg;       A2,A3 incremented by value in A5;  Side Effects:;       D3 trashed;-------------------------------------------------------------------------READMMU MOVE    #$0FFF,D3       ;set mask for result        TST.B   SETUPON	        ;turn setup on to enable MMU access        TST     D2	        ;check context        BEQ.S   @9	        ;skip if context 0        CMP.B   #1,D2	        ;context 1?        BEQ.S   @2        CMP.B   #2,D2	        ;context 2?        BEQ.S   @1        TST.B   SEG2ON	        ;must be context 3        BRA.S   @2	        ;set both seg bits@1      TST.B   SEG2ON	        ;set for context 2        BRA.S   @9@2      TST.B   SEG1ON	        ;set for context 1 and 3;  read the regs@9      MOVE    (A2),D0	        ;read base reg        AND     D3,D0	        ;clear junk        MOVE    (A3),D1	        ;read limit reg        AND     D3,D1	        ;clear junk        ADDA.L  A5,A2	        ;incr ptrs        ADDA.L  A5,A3        TST.B   SEG1OFF	        ;restore to context 0        TST.B   SEG2OFF        CLR.B   SETUP	        ;back to map land        RTS4		        ;and back to caller        .ENDC        .IF     EXTERNAL = 1        .NOLIST        .ENDC        .PAGE;--------------------------------------------------------------------------;  Begin memory testing by checking first 800 hex locations (2K).;  If error here, abort other testing and go into loop since can't relay;  meaningful results.;--------------------------------------------------------------------------MEMTST1 MOVEA.L A0,A2	        ;save memory lo, hi addresses        MOVEA.L A1,A3        .IF  DIAGS = 1        SUBA.L  A0,A0	        ;set test addresses        MOVEA   #LOMEM,A1       ;upper address				        RM000        BSR4    RAMTEST	        ;go do memory test        BEQ.S   INITMEM	        ;skip if OK;  Error in low memory - reset video latch, beep speaker and go into R/W loop        MOVE.L  A2,D0	        ;get low physical address        LSR.L   #8,D0	        ;convert to page value        LSR.L   #7,D0        MOVE.B  D0,VIDLTCH      ;set video latch to bad area        BSR4    CONSET	        ;ensure contrast on        BSR2    LOTONE	        ;beep speaker twice for low memory error        MOVE    #TNTHSEC,D0     ;delay for about 1/10 sec		        RM000TONEDLY SUBQ    #1,D0        BNE.S   TONEDLY        BSR2    LOTONE	        ;do second beep        SUBA.L  A0,A0	        ;loop at first address        MOVE    #PATRN2,D0      ;set pattern for use@2      MOVE    D0,(A0)        MOVE    (A0),D1        BRA.S   @2	        ;loop with random display on screen        .ELSE        MOVEQ   #0,D3	        ;set results reg        MOVEQ   #-1,D0	        ;set for memory "clear" patternCLRMEM  MOVE.L  D0,(A0)+        ;do "clear"        CMPA.L  A0,A1	        ;done?        BNE.S   CLRMEM	        ;loop until yes        .ENDC		        ;{DIAGS};  Now attempt to initialize status areas and save resultsINITMEM MOVEA   #STATUS,A0      ;get ptr to start of status area	        RM000        MOVEQ   #127,D0	        ;set count@2      CLR.L   (A0)+	        ;clear it        DBF     D0,@2	        ;until done        MOVE    D3,MEMRSLT      ;save test results        MOVE    A6,SIZRSLT      ;save sizing results        MOVE.L  A2,MINMEM       ;save min memory address        MOVE.L  A3,MAXMEM       ;save max memory address        SUBA.L  A2,A3	        ;compute total memory        MOVE.L  A3,TOTLMEM      ;and save also        MOVE.L  #HEX32K,A0      ;compute base address for screen        SUBA.L  A0,A3        MOVE.L  A3,SCRNBASE     ;and save        MOVE    D2,MMURSLT      ;and save MMU results also        MOVE.L  #KBDQ,KBDQPTR   ;init COPS buffer pointer for later use        .PAGE;------------------------------------------------------------------------; Initialize exception and trap vectors to catch unexpected errors;------------------------------------------------------------------------INITVCT BSR.S   SETVCTRS        ;init vectors        BRA     SCCSET	        ;continue testing			        CHG027;  Subroutine to set up default vectorsSETVCTRS        LEA     MISC,A0        SUBA.L  A1,A1        MOVEQ   #64,D0@1      MOVE.L  A0,(A1)+        ; fill with unknown ones        SUBQ    #1,D0        BGT     @1        BSR.S   SETBUSVCT       ; then, with special ones		        RM000        LEA     AERR,A0        MOVE.L  A0,ADRVCTR        LEA     IERR,A0        MOVE.L  A0,ILLVCTR        LEA     NMI,A0        MOVE.L  A0,NMIVCT        LEA     TRPERR,A0       ; same routine for line 1010 and 1111        MOVE.L  A0,L10VCTR        MOVE.L  A0,L11VCTR        .IF  USERINT = 0        MOVEQ   #FIRSTROW,D5    ;set default row and        MOVEQ   #FIRSTCOL,D6    ; column cursor ptrs        .ENDC        RTS;-----------------------------------------------------------;  Subroutine to setup bus error vector					        RM000;-----------------------------------------------------------SETBUSVCT        LEA     BERR,A3	        ;setup default vector			        RM000        MOVE.L  A3,BUSVCTR      ;					        RM000        RTS		        ;					        RM000;-----------------------------------------------------------;  Exception Handler routines;-----------------------------------------------------------MISC    MOVE.L  D7,D7SAV        ;save incoming value        MOVEQ   #0,D7        BSET    #MISEXCP,D7     ;set error indicator        BRA.S   EXCP1IERR    MOVE.L  D7,D7SAV        ;save incoming value        MOVEQ   #0,D7        BSET    #ILLEXCP,D7     ;set error indicator        BRA.S   EXCP1NMI     MOVE.L  D7,D7SAV        ;save incoming value        MOVEQ   #0,D7        BSR     TSTSTAT	        ;check status reg for parity error	        CHG015        BNE.S   NOTPE	        ;skip if not        BSET    #MPAR,D7        ;set error indicator        BSR     GETPADDR        ;get and save error address		        CHG015        TST.B   PAROFF	        ;toggle to clear error bit        BTST    #5,D1	        ;video error?				        CHG015        BEQ.S   @1	        ;skip if not				        CHG015        ANDI.L  #VMSK,D1        ;mask if yes				        CHG015@1      MOVE.L  D1,PEADDR       ;save converted error address		        CHG015        BRA.S   EXCP1	        ;go to exitNOTPE   BSET   #CPUINTR,D7      ;else set NMI code        BRA.S   EXCP1	        ; and exitTRPERR  MOVE.L  D7,D7SAV        ;save incoming value        MOVEQ   #0,D7        BSET    #TRPEXCP,D7     ;set error indicator        BRA.S   EXCP1BERR    MOVE.L  D7,D7SAV        ;save incoming value        MOVEQ   #0,D7        BSET    #BUSEXCP,D7     ;set error indicator        BRA.S   EXCP0AERR    MOVE.L  D7,D7SAV        ;save incoming value        MOVEQ   #0,D7        BSET    #ADREXCP,D7     ;set error indicatorEXCP0			        ; GROUP 0 EXCEPTIONS HERE        MOVE    (SP)+,EXCFC     ; SAVE THE EXTRA DATA        MOVE.L  (SP)+,EXCADR        MOVE    (SP)+,EXCIREXCP1			        ; GROUP 1 EXCEPTIONS HERE        MOVE    (SP)+,EXCSR     ; SAVE COMMON INFO        MOVE.L  (SP)+,EXCPC        MOVE    D0,EXCTYPE      ; save error type        BRA     TSTCHK	        ; and go display error        .PAGE;-------------------------------------------------------------------------;  Initialize SCC chip for Applebus use.					 CHG027;  Bus error vector setup in case of problems.;-------------------------------------------------------------------------SCCSET        LEA     NOIO,A3		      ;set bus error vector in case no IO board	 CHG027        MOVE.L  A3,BUSVCTR	      ;						 CHG027        BSR     RSTSCC		      ;go do setup				 CHG027;-------------------------------------------------------------------------; Now test VIA for parallel port and contrast latch.; A read/write test on the timer 1 latches is done, then contrast; is set if OK.;-------------------------------------------------------------------------VIA2TST        .IF  DIAGS = 1VIA2CHK        .IF  ROM16K = 1        LEA     VIA2VCT,A3      ;OK - set up special bus vector        MOVE.L  A3,BUSVCTR        MOVE.L  #<VIA2BASE+T1LL2>,A0  ;set base address of timer low latch        MOVEQ   #8,D0	        ;set offset to high latch        BSRS6   VIATST	        ;and go do test        BEQ.S   @2	        ;if OK, continue        BSET    #VIA2,D7        ;else set error bit        TST.L   D7	        ;check if in loop mode        BMI.S   VIA2CHK	        ;restart if yes        BRA.S   @3	        ;else skip contrast setting        .ENDC@2      TST.L   D7	        ;in loop mode?        BMI.S   VIA2CHK	        ;restart if yes        BSRS4	 CONOFF	        ;go turn off contrast        .ENDC		        ;{DIAGS}@3      BRA.S   SCRNTST	        ;else skip to next test        .IF  DIAGS = 1;------------------------------------------------------------------------;  Bus error handler for VIA #2 use;------------------------------------------------------------------------VIA2VCT MOVEQ   #EVIA2,D0       ;SET ERROR CODE        BSET    #VIA2,D7        ;set indicator        BRA     IOVCT	        ;AND GO HANDLE I/O EXCEPTION        .ENDC		        ;{DIAGS}        .IF  ROM16K = 1        .PAGE;-------------------------------------------------------------------------;   Subroutine to do VIA testing;     A0 = address of first timer latch;     D0 = offset to other latch;-------------------------------------------------------------------------VIATST  MOVE.L  A0,A1	        ;set up address for second latch        ADDA.L  D0,A1        MOVEQ   #0,D0	        ;for error use        CLR.B   D2	        ;clear old data value        MOVE.B	 #0,(A0)        ;and the timer latches        MOVE.B	 #0,(A1)        MOVE    #$FF,D3	        ;set up start value        BSRS4   VIARW	        ;go do read/write test        RTS6		        ;and return;  Subroutine to do read/write test - loops thru all 256 valuesVIARW   CMP.B   (A0),D2	        ;check for old values first        BNE.S   VIAFAIL        CMP.B   (A1),D2        BNE.S   VIAFAIL        MOVE.B  D3,(A0)	        ;set new value in low timer latch        CMP.B   (A1),D2	        ;ensure high latch not affected        BNE.S   VIAFAIL        CMP.B   (A0),D3	        ;verify new low latch setting        BNE.S   VIAFAIL        MOVE.B  D3,(A1)	        ;set new value in high timer latch        CMP.B   (A0),D3	        ;ensure low latch not affected        BNE.S   VIAFAIL        CMP.B   (A1),D3	        ;verify new high latch setting        BNE.S   VIAFAIL        MOVE.B  D3,D2	        ;the new value becomes the old        DBF     D3,VIARW        ;loop thru all 256 values        BRA.S   VIARWENDVIAFAIL ADDQ    #1,D0	        ;set for errorVIARWEND TST    D0	        ;set zero bit indicator        RTS4        .ENDC        .PAGE;--------------------------------------------------------------------------;  Subroutine to set contrast latch - sets for default, off or value in D0;--------------------------------------------------------------------------CONSET  MOVE.B  #$80,D0	        ;set mid range value default        BRA.S   CONSET2CONOFF  MOVEQ   #-1,D0	        ;set for contrast offCONSET2			        ;for external entry        MOVE.L  #VIA2BASE,A0    ;GET 6522 BASE ADDR        MOVE.B  #$84,DDRB2(A0)  ;ENSURE NO STRAY DATA TO CONTRAST        MOVE.B  #4,ORB2(A0)     ; LATCH BY DISABLING DRIVERS        MOVE.B  #$FF,DDRA2(A0)  ;NOW SET PORT A AS OUTPUTS        MOVE.B  D0,ORA2(A0)     ;set contrast value        BSET    #7,ORB2(A0)     ;AND STROBE IT        RTS4		        ;RETURN TO CALLER        .PAGE;-------------------------------------------------------------------------;  Test memory to be used for screen.  The screen can then be;  used for test icon display.  Default choice is last 32K of memory.;  If this is invalid, do backwards scan through memory until a valid;  area is found.;  Assumes:  location SCRNBASE = base address of default screen (set by;   sizing routine);-------------------------------------------------------------------------SCRNTST        .IF  DIAGS = 1        MOVE.L  SCRNBASE,A0     ;get base address of screen        MOVE.L  TOTLMEM,A1      ;set end address        BSR4    RAMTEST	        ;and go do test        BEQ.S   INVTST	        ;continue if no error        BSET    #MEM,D7	        ;else set memory read/write error;  save error results and then start search for good video page        BSR     TSTINIT	        ;initialize for further testing        BSR.S   SCRNSAV	        ;save results        MOVE.L  SCRNBASE,A1     ;set new search end address        MOVE.L  A1,A0        MOVE.L  #HEX32K,A2      ;screen size is 32K        SUBA.L  A2,A0	        ;set new start addr (end-32K)@1      MOVEM.L A0-A2,-(SP)     ;save search addresses        BSR4    RAMTEST	        ;go test        MOVEM.L (SP)+,A0-A2     ;restore addresses (no effect on CCR)        BEQ.S   SCRNOK	        ;skip if OK (non-zero CCR if error)        MOVE.L  A0,D4	        ;else go save results        BSR.S   SCRNSAV        MOVE.L  A0,A1	        ;set next end        SUBA.L  A2,A0	        ; and start addresses        MOVE.L  A0,D0	        ;continue thru all of memory if necessary        BGT.S   @1SCRNERR BRA.S   INVTST	        ;continue testing, leave screen at defaultSCRNOK  MOVE.L  A0,SCRNBASE     ;save new screen base        BSR.S   SETVLTCH        ;and go set video latch        BRA.S   INVTST	        ;and exit to next test;-------------------------------------------------------------------------;  Subroutine to save error results from screen test routine;  Inputs:;       A3 = ptr to base of save result area;       D4 = base address of test area;  Outputs:;       None;  Side Effects:;       D1/D3-D4 trashed;-------------------------------------------------------------------------SCRNSAV MOVEQ   #17,D1	        ;divide base address by 128K        LSR.L   D1,D4        ADD     D4,D4	        ;double for word index to save area        MOVE.L  D3,D1	        ;combine error results        SWAP    D3        OR      D1,D3        OR      D3,0(A3,D4)     ;save and exit        RTS;-------------------------------------------------------------------------;  Subroutine to set the video latch;  Inputs:;       Location SCRNBASE = logical base address for screen;  Outputs:;       None;  Side Effects:;       D0-D1 trashed;-------------------------------------------------------------------------SETVLTCH        MOVE.L  SCRNBASE,D2     ;get logical screen base address        MOVE.L  TOTLMEM,D1      ;get physical amount of memory        SUB.L   D2,D1	        ;compute screen base offset        MOVE.L  MAXMEM,D0       ;get max physical address        SUB.L   D1,D0	        ;compute physical screen base address        LSR.L   #8,D0	        ;convert to page value        LSR.L   #7,D0        MOVE.B  D0,VIDLTCH      ;set latch        RTS		        ;and exit        .PAGE;-------------------------------------------------------------------------;  Now check state of INVID bit to see if inverse video is installed.;  If yes, rewrite last 4 words of screen page to avoid retrace line.;-------------------------------------------------------------------------INVTST        .IF  INVERTCK = 1       ;				        CHG013        MOVEA.L #STATREG,A5     ;set ptr to status register        BTST    #INVIDBIT,(A5)  ;check if inverse video installed        BNE.S   VIA1TST	        ;go on to next test if not;  Inverse video requires zeroing of last bit in video page (32K)        MOVE.L  SCRNBASE,A0     ;get base address of screen        ADD.L   #HEX32K,A0      ;set ptr to end of screen        CLR.L   -(A0)	        ;rewrite last 4 words        CLR.L   -(A0)        .ENDC		        ;{INVERTCK}			        CHG013        .ENDC		        ;{DIAGS};-------------------------------------------------------------------------; Continue testing by now doing COPS VIA test;-------------------------------------------------------------------------VIA1TST        .IF  USERINT = 1;  Draw desktop on screen for test icon display        BSR     DRAWDESK        ;draw the desk        BSR.S   DSPCPURM        ;and CPU ROM id		        CHG001        .ENDC        BSR4    CONSET	        ;set default contrast        .IF  ROM16K = 1VIA1CHK LEA     VIA1VCT,A3      ;first set up bus error vector        MOVE.L  A3,BUSVCTR        MOVE.L  #<VIA1BASE+T1LL1>,A0 ;set base address of timer low latch        MOVEQ   #2,D0	        ;set offset to high latch        BSR6    VIATST	        ;go test        BEQ.S   @2	        ;skip if OK        BSET    #VIA1,D7        ;else set error bit        TST.L   D7	        ;loop?        BMI.S   VIA1CHK	        ;yes - test again        BRA     TSTCHK	        ;else abort further testing@2      TST.L   D7	        ;check for loop mode        BMI.S   VIA1CHK        BRA.S   COPSENBL        ;else go test COPS;------------------------------------------------------------------------;  Subroutine to display CPU ROM id;------------------------------------------------------------------------DSPCPURM        MOVE.B  REV,D0	        ;read ROM rev			        CHG001        MOVEQ   #ROMIDROW,D5    ;setup cursor ptrs		        CHG001        MOVEQ   #ROMIDCOL,D6    ;				        CHG001        BSR     DSPVAL	        ;do display			        CHG001        RTS		        ;				        CHG001        .ENDC        .PAGE;-------------------------------------------------------------------------;  Try turning COPS on so that keyboard commands can be received;-------------------------------------------------------------------------COPSENBL        LEA     COPSVCT,A3      ;set up bus error vector first        MOVE.L  A3,BUSVCTR        BSR.S   CPSINIT	        ;enable COPS        BCS.S   COPSBAD	        ;skip if error        TST.L   D7	        ;looping desired?        BMI.S   COPSENBL        ;go repeat test        MOVE.L  D7,D0	        ;get error indicator        ANDI.L  #CPIOMSK,D0     ;mask off don't care bits        BEQ     RSTSCAN	        ;continue if OK to do reset scan        BRA     TSTCHK	        ;else go report errorCOPSBAD BSET    #IOCOPS,D7      ;else set COPS error        TST.L   D7	        ;looping desired?        BMI.S   COPSENBL        ;go repeat test        BRA     TSTCHK	        ;else abort further testing;-----------------------------------------------------------------------------;  Bus error handler for COPS testing with entry point for other I/O tests;-----------------------------------------------------------------------------COPSVCT MOVEQ   #EIOCOP,D0      ;SET ERROR CODEIOVCT   BSET    #IOEXCP,D7      ;SET I/O EXCEPTION ERROR        BRA     EXCP0	        ;AND GO HANDLE EXCEPTION;-----------------------------------------------------------------------------;  Subroutine to initiialize COPS interface for use;-----------------------------------------------------------------------------CPSINIT MOVEA.L #VIA1BASE,A0    ;GET VIA BASE ADDRESS        MOVE.B  #$01,ACR1(A0)   ;SET PORT A LATCH ENABLE        OR.B    #$09,PCR1(A0)   ;SET HANDSHAKE ENABLE        MOVE.B  #$7F,IER1(A0)   ;CLEAR ALL INTRPT ENABLES        MOVE.B  #$7F,IFR1(A0)   ;AND CLEAR FLAGS;  Now turn COPS on, disabling mouse and NMI keyTURNON  CLR     D0	        ;SET FOR PORT ON CMD        BSR.S   COPSCMD	        ;SEND TO COPS        BCS.S   @1	        ;EXIT IF TIMEOUT ERROR        MOVEQ   #$70,D0	        ;DISABLE MOUSE        BSR.S   COPSCMD        BCS.S   @1        .IF  DEBUG = 0        MOVEQ   #$50,D0	        ;disable NMI key        BSR.S   COPSCMD        BCS.S   @1        MOVEQ   #$60,D0        BSR.S   COPSCMD        .ENDC@1      RTS		        ;AND EXIT        .PAGE;-----------------------------------------------------------------------------;  Subroutine to send cmd to COPS;  Assumes registers:;       D0 = cmd value;  If COPS does not respond, timeout error indicated by setting carry bit.;-----------------------------------------------------------------------------COPSCMD        MOVEM.L D0-D4/A0-A2,-(SP) ;save regs        DISABLE		        ;disable all interrupts        MOVEA.L #VIA1BASE,A0    ;set COPS VIA interface ptr        MOVEA.L A0,A1	        ;save for use as port B output reg address        MOVEA.L A0,A2        ADDA    #DDRA1,A2       ;compute address for port A data direction reg        MOVEQ   #$40,D2	        ;set up constants for later use        MOVEQ   #-1,D3        MOVEQ   #6,D4        MOVE.B  D0,PORTA1(A0)   ;set cmd in data reg (no handshake);---------------------------------------------------------------------------;  First find a ready state (CRDY low);  Each of the following loops take about 32 machine cycles = 6.4 us plus;  a variable amount of time for sync with 6522 (max = 2us);---------------------------------------------------------------------------        MOVE    #$061A,D1       ;set timeout for about 10 ms@3      SUBQ    #1,D1        BEQ.S   @1	        ;exit if timeout        BTST    D4,(A1)	        ;else wait for "ready" (bit 6 = CRDY)        BNE.S   @3;  Now find the next ready state to insure enough time available for data        MULU    #1,D0	        ;kill some time (about 15.2 us) to get                                ; out of previous CRDY        MOVE    #$061A,D1       ;reinit timeout count@4      SUBQ    #1,D1        BEQ.S   @1	        ;exit if timeout        BTST    D4,(A1)	        ;wait for another "ready"        BNE.S   @4        MOVE.B  D3,(A2)	        ; ok, jam out the data;  Now wait for CRDY high and then hold data for COPS to read        MOVE    #$061A,D1       ;set timeout for about 10 ms@5      SUBQ    #1,D1        BEQ.S   @1	        ;exit if timeout        BTST    D4,(A1)	        ;wait for "not-ready"        BEQ.S   @5        MOVEQ   #$A,D0	        ; force about a 40 ms@6      SUBQ    #1,D0	        ;  delay for COPS hold time        BGT.S   @6        CLR.B   (A2)	        ; reset direction reg now        MOVE.B  #$82,IER1(A0)   ;  and, enable CA1        BRA.S   @2	        ; go to normal exit;  Timeout occurred - set error indicator@1      ENABLE		        ;reenable        ORI.B   #$01,CCR        ;set carry bit        BRA.S   @9	        ;skip to exit@2      ENABLE		        ;restore interrupt levels@9      MOVEM.L (SP)+,D0-D4/A0-A2 ;restore regs        RTS		        ;and return to caller        .PAGE;-------------------------------------------------------------------------;  Scan COPS for proper reset codes.  Delay added for normal COPS power-up;  time of about 1.7 seconds.;;  Send reset signal and then scan keyboard/mouse interface.  First "clears";  COPS of any pending codes, and then issues reset.  Works via;  a "state machine" that checks codes received and sets flags as follows:;;       D1 = 0 - reset signal in place;	   = 1 - reset signal removed;;       D3 = 0 - no keyboard codes received => keyboard disconnected;	   = 1 - keyboard disconnect code ($80/$FD) received;		  => ignore, may be old keyboard;	   = 2 - keyboard disconnect/connect codes ($80/$FD/$80/id) received;		  => keyboard connected;;       D4 = 0 - no mouse codes received => mouse connected;	   = 1 - only mouse connect code ($87) received => ignore, may be old sys;	   = 2 - mouse connect/disconnect ($87/$07) codes received;		  => mouse disconnected;--------------------------------------------------------------------------RSTSCAN        MOVE.L  KBDQPTR,A1      ;setup buffer ptrs        MOVEA   #QEND,A2@1      BSR.S   GETJMP	        ;clear COPS queue, saving data        BCC.S   @1        BSR     RSTKBD	        ;do reset of keyboard/mouse interfaces        .IF  ROM4K = 0        CLR.L   D1	        ;init some flags        CLR.L   D3        CLR.L   D4        BSR.S   GETJMP	        ;check for data        BCS.S   RSTXIT	        ;exit if none (may be old keyboard);  State 0 - waiting for reset flag or mouse connect codeRST0    CMPI.B  #RSTCODE,D0     ;reset flag?        BEQ.S   RST1	        ;skip if yes to state 1        CMPI.B  #MSPLG,D0       ;mouse connect code?        BEQ.S   RST2	        ;skip if yes to state 2        CMPI.B  #MSUNPLG,D0     ;mouse disconnect code only?        BNE.S   GET0        MOVEQ   #2,D4	        ;set flag for disconnect stateGET0    BSR.S   GETJMP	        ;go get next code        BCS.S   RSTXIT	        ;exit if no more codes        BRA.S   RST0	        ;else continue scan loop;  State 2 - waiting for mouse unplugged codeRST2    MOVEQ   #1,D4	        ;set flag for mouse connect received        BSR.S   GETJMP	        ;go get next byte        BCS.S   RSTXIT	        ;exit if none or queue full        CMPI.B  #MSUNPLG,D0     ;mouse disconnect code?        BNE.S   RST0	        ;no - return to state 0        MOVEQ   #2,D4	        ;yes - set flag        BRA.S   GET0	        ;and return to state 0;  State 1 - waiting for reset codeRST1    BSR.S   GETJMP	        ;go get next byte        BCS.S   RSTXIT	        ;exit if no more        CMPI.B  #KUNPLG,D0      ;keyboard unplugged code?        BNE.S   @1	        ;skip if not        MOVEQ   #1,D3	        ;else set flag        BRA.S   GET0	        ;and return to state 0@1      CMPI.B  #$DF,D0	        ;id code?        BHI.S   @2	        ;skip if not        MOVE.B  D0,KEYID        ;else save for later use        MOVEQ   #2,D3	        ;update flag        BRA.S   GET0	        ;and return to state 0@2      CMPI.B  #KCERR,D0       ;Keyboard COPS error?        BNE.S   @3	        ;skip if not        BSET    #KBDCOPS,D7     ;else set error indicator@3      CMPI.B  #ICERR,D0       ;I/O COPS error code?        BNE.S   @4	        ;skip if not        BSET    #IOCOPS,D7      ;else set error indicator@4      BRA.S   GET0	        ;continue scan from state 0;  Insert to save code spaceGETJMP  BSR.S   GETDATA	        ;go get COPS data        RTS		        ;and return to caller;  Reset exit - analyze resultsRSTXIT  TST.B   D1	        ;reset signal lifted?        BNE.S   @1	        ;skip if yes        BSR     CLRRST	        ;else remove reset signal        MOVEQ   #1,D1	        ;set "removed flag"        BSR.S   GETDATA	        ;any data?        BCC.S   RST0	        ;go decode if yes@1        .IF  FINKBD = 1        TST.B   D3	        ;any keyboard data detected?        BNE.S   MSCHK	        ;skip if yes - assume keybd connected        BSET    #KBDOUT,D7      ;if none, keyboard is disconnectedMSCHK        TST.B   D4	        ;any mouse data?        BEQ.S   SCANXIT	        ;skip if none - mouse connected@1      SUBQ    #1,D4	        ;flag = 1?        BEQ.S   SCANXIT	        ;ignore if yes        BSET    #MOUSOUT,D7     ;else mouse disconnected        BRA.S   SCANXIT	        ;and go to exit        .ELSE        BRA.S   SCANXIT        .ENDC		        ;{FINKBD};  Error exits - set appropriate indicatorSCANERR BSET    #IOKBD,D7       ;I/O or keyboard failure        BRA.S   SCANXITIOCERR  BSET    #IOCOPS,D7      ;I/O COPS error        .ELSE@1      BSR.S   GETDATA	        ;clear COPS queue        BCC.S   @1        BSR.S   CLRRST	        ;clear reset signal@2      BSR.S   GETDATA	        ;any data?        BCC.S   @2	        ;clear the queue        .ENDC		        ;{ROM4K}SCANXIT MOVE.L  A1,KBDQPTR      ;save queue ptr for later use        .IF  ROM4K = 0        MOVE.L  D7,D0	        ;check error codes        ANDI.L  #SCANMSK,D0     ; for scan errors        TST.L   D0	        ;any found?        BNE     TSTCHK	        ;skip if yes        .ENDC        BRA.S   BEEP	        ;else continue testing        .PAGE;-------------------------------------------------------------------------;  Subroutine to get COPS data;  Assumes registers:;       D0 - scratch use        A0 - VIA address;       D1 - unused	        A1 - Ptr to data save area;       D2 - scratch use        A2 - Ptr to end of data area;  Puts data in save area and also leaves in register D0.;  Carry bit set if timeout error or keyboard queue full.;-------------------------------------------------------------------------GETDATA CMPA.L  A1,A2	        ;check if at end of queue        BEQ.S   @2	        ;exit if yes        MOVE.L  #$1FF,D2        ;else set timeout for about 5 ms        MOVEA.L #VIA1BASE,A0    ;set COPS VIA interface ptr@1      MOVE.B  IFR1(A0),D0     ;check if data avail        BTST    #1,D0        BNE.S   GETIT	        ;skip if yes        SUBQ    #1,D2        BNE.S   @1	        ;else continue@2      ORI.B   #$01,CCR        ;set timeout error        RTSGETIT   MOVE.B  ORA1(A0),D0     ;read data        MOVE.B  D0,(A1)+        ;save it        RTS		        ;and exit with results        .PAGE;-------------------------------------------------------------------------;  Subroutine to do reset of keyboard and mouse interfaces;  Inputs:;       None;  Outputs:;       None;  Side Effects:;       D0/A0 trashed;-------------------------------------------------------------------------RSTKBD  MOVEA.L #VIA1BASE,A0    ;set VIA ptr        BCLR    #0,ORB1(A0)     ;set reset signal        ORI.B   #$01,DDRB1(A0)  ;send it        MOVE.L  #3000,D0        ;do delay for 12 ms        BSR.S   DELAY        RTS;-------------------------------------------------------------------------;  Subroutine to remove reset signal for keyboard and mouse interfaces;  Inputs:;       A0 = ptr to parallel port VIA (set in RSTKBD routine);  Outputs:;       None;  Side Effects:;       D0 trashed;-------------------------------------------------------------------------CLRRST  BSET    #0,ORB1(A0)     ;remove reset signal        BSR.S   KBDDELAY        ;delay for keyboard reset time        RTS;----------------------------------------------------------------------------; Subroutine to delay for count in D0 (each count = 4 us).  Additional; entry points set up for fixed delays.;----------------------------------------------------------------------------        .IF  ROM4K = 0DELAY_1 MOVE.L  #TNTHSEC,D0     ;.1 second delay        BRA.S   DELAYDELAY5  MOVE.L  #FIVESEC,D0     ;5 second delay        BRA.S   DELAYKBDDELAY        MOVE.L  #KBDDLY,D0      ;delay for COPS debounce loop        .ENDCDELAY   SUBQ.L  #1,D0	        ;loop until count = 0        BNE.S   DELAY        RTS        .PAGE;-------------------------------------------------------------------------; Sound starting "tone";-------------------------------------------------------------------------BEEP        BSR.S   CLICK	        ;go click speaker        BRA     VIDTST	        ;then go do video test;-------------------------------------------------------------------------; Subroutine to set parms for speaker "click";-------------------------------------------------------------------------CLICK   MOVE.B  #$A0,D0	        ;set frequency        MOVEQ   #0,D1	        ;and duration        MOVEQ   #8,D2	        ;and volume (medium)		        RM000                                ;then fall thru to tone routine	        RM000;-------------------------------------------------------------------------;  Routine to beep the speaker;  Assumes regs set up as;    D0 = desired frequency ($00 - $AA);    D1 = duration (0 = .5 msec);    D2 = volume (0,2,4,...,E);-------------------------------------------------------------------------TONE    MOVEM.L A0/A4/D3,-(SP)  ;save regs        BSRS4   TONE2	        ;go do tone        MOVEM.L (SP)+,A0/A4/D3  ;restore and exit        RTS;  separate entry point for call without memory usageTONE2   MOVEA.L #VIA1BASE,A0    ;set VIA ptr        ORI.B   #$0E,DDRB1(A0)  ;set volume bits for output        ANDI.B  #$F1,ORB1(A0)   ;clear and then        OR.B    D2,ORB1(A0)     ; set volume bits        ANDI.B  #$E3,ACR1(A0)   ;clear shift mode bits        ORI.B   #$10,ACR1(A0)   ;set shift reg for continuous rotate; check system type        TST.B   DISKROM	        ;test for Lisa 1 board		        CHG014        BPL.S   @3	        ;no changes if yes		        CHG014        BTST    #SLOTMR,DISKROM ;else check if slow timers	        CHG029        BNE.S   @3	        ;skip if yes			        CHG029        MOVE.B  D0,D3	        ;else adjust input parm		        CHG014        LSR.B   #2,D3	        ; by factor of .25		        CHG014        ADD.B   D3,D0	        ;				        CHG014@3      MOVE.B  D0,T2CL1(A0)    ;set frequency        MOVE.B  #$0F,SHR1(A0)   ;set for square wave and trigger;  Do time delay -  enter with count in D1 (about .5 msec per count)@1      MOVE.W  #$00D0,D3       ;set delay constant@2      DBF     D3,@2        DBF     D1,@1SILENCE ANDI.B  #$E3,ACR1(A0)   ;disable tone        RTS4		        ;and return        .IF  DIAGS = 1;-------------------------------------------------------------------------;   Routine to handle I/O board selection errors.  Does check for access;   of other I/O board devices to try to pinpoint error.;-------------------------------------------------------------------------NOIO    BSET    #RS232B,D7      ;set SCC port B access error	        CHG027        MOVE    #STKBASE,SP     ;restore stack pointer;  try access of other I/O board devices        LEA     NOIO2,A3        ;set up new bus error vector        MOVE.L  A3,BUSVCTR        MOVE.L  #VIA2BASE,A0    ;set base address		        CHG027        TST.B   (A0)	        ;try access        BRA     VIA2TST	        ;return to testing if OK	        CHG027NOIO2   BSET    #VIA2,D7        ;set VIA #2 error also		        CHG027        LEA     NOIO3,A3        ;try final access to VIA #1	        CHG027        MOVE.L  A3,BUSVCTR        MOVE.L  #VIA1BASE,A0    ;set base address		        CHG027        TST.B   (A0)        BRA.S   SCRNTST	        ;exit if OK			        CHG027NOIO3   BSET    #CPUSEL,D7      ;most likely CPU board error        BRA     TSTCHK	        ;go report errors		        CHG027        .ENDC