Lisa_Boot_ROM_RM248
.PAGE
;----------------------------------------------------------------------------
; VIDEO CIRCUITRY TEST
; The following test checks the vertical retrace signal of the
; video circuitry to verify it is toggling.
; Register usage:
; D0 = timeout count A0 = unused
; D1 = unused A1 = unused
; D2 = bit pointer A2 = unused
; D3 = unused A3 = address to disable VTIR
; D4 = unused A4 = address to enable VTIR
; D5 = unused A5 = address of bus status register
;----------------------------------------------------------------------------
VIDTST
.IF ROM4K = 0
.IF USERINT = 1
BSR MAKETEST ;display test icons
MOVEA #CPUSTRT,A1 ;hilite CPU board icon
BSR INVICON
.ENDC
VIDCHK
MOVEA.L #VTIRDIS,A3 ;ADDRESS FOR DISABLING VTIR
MOVEA.L #VTIRENB,A4 ;ADDRESS FOR VTIR ENABLE
MOVEA.L #STATREG,A5 ;STATUS REGISTER LOCATION FOR BYTE OPS
MOVE #$0DF4,D0 ;SET TIMEOUT COUNT FOR ABOUT 20 MS
MOVEQ #VRBIT,D2 ;VR BIT LOCATION
TST (A3) ;RESET THEN
TST (A4) ; ENABLE VTIR
@1 BTST D2,(A5) ;WAIT FOR LOW
BEQ.S @2 ;EXIT IF YES
DBF D0,@1 ;ELSE LOOP (ABOUT 5.6 MS PER LOOP)
BRA.S VIDERR ;AND SET ERROR IF TIMEOUT
@2 TST (A3) ;RESET VTIR
TST (A4) ;THEN RENABLE
BTST D2,(A5) ;SHOULD BE HIGH BY NOW
BEQ.S VIDERR ;GO TO ERROR EXIT IF NOT
TST (A3) ;DISABLE VTIR
BRA.S VIDXIT ;and go to exit
; Error exit
VIDERR BSET #VID,D7 ;SET ERROR INDICATOR
TST.L D7 ;in loop mode?
BMI.S VIDCHK ;restart test if yes
BRA TSTCHK ;else go to error msg routine
; Normal exit
VIDXIT
;----------------------------------------------------------------------------
; Now, try reading of system serial number
;----------------------------------------------------------------------------
MOVEA #SERNUM,A0 ;ptr for save of serial #
BSR.S RDSERN ;go do read
BCC.S VIDERR ;exit if error
TST VTIRDIS ;else disable vertical retrace
TST.L D7 ;check for loop mode
BMI.S VIDCHK ;if not, fall thru to next test
BRA PARTST ;and go on to next test
.PAGE
;--------------------------------------------------------------------------
;
; Routine to read system serial # from video prom.
; Written by Ken Schmal and Ron Hochsprung.
;
; Register Usage:
;
; temporary and iterative D0
; temporary and iterative D1
; temporary and iterative D2
; temporary and iterative D3
; boolean FOUND to be returned D4
; pointer to save area for serial # A0
; SN1 & SN2 pointer A1
; STATUS REGISTER pointer A2
; SCRACH array pointer A3
; SCRACH END pointer A4
; Tag const A5
; static link and stack frame
; base pointer register A6
;
; Returns with carry bit set if all OK.
; All registers except D7 and A0 trashed.
;
;--------------------------------------------------------------------------
RDSERN
MOVEM.L D7/A0,-(SP) ;save regs
; turn off all interrupts
move SR, -(sp) ;save the present status register
ori.w #$0700, SR ;set interrupt to level 7
;--------------------------------------------------------------------------
; now set up registers for the algorithm
;--------------------------------------------------------------------------
move.l #Snum, a1 ;location in MMU of SN1 & SN2
move.l #Statreg,a2 ;Status Register pointer
link a6, #dStack ;make room for SCRACH
lea dScrach(a6), a3 ;get pointer for SCRACH
lea Tag,a4
move.l a0,dSavArry(a6)
;--------------------------------------------------------------------------
; first we get the block out of the vertical half
;--------------------------------------------------------------------------
;
; sync up to the vertical retrace bit
;
GetBits1:
moveq #2, d1 ;vertical retrace is bit #2
move.l #BytesPerRead,dLcnt(a6) ;read this many bytes
clr VTIRDIS ;clear vertical retrace bit
clr VTIRENB ;set vertical retrace interrupt
@1: btst d1, (a2) ;wait until it's true
bne.s @1
;
;------ read the first block ------
;
@3: movem (a1), d0-d7
movem d0-d7, (a3)
addq.l #8, a3
addq.l #8, a3
nop
moveq #dlycnst-1, d0
subq.l #1, dLcnt(a6)
@4: dble d0, @4
bgt.s @3
;--------------------------------------------------------------------------
; then we get the block out of the horizontal half
;--------------------------------------------------------------------------
;
; kill time until we're near the last vertical retrace line
;
GetBits2:
move.l #BytesPerRead, dLcnt(a6);get the last few bytes
move.w #TKiller-1, d0 ;time killer constant
@1: dbra d0, @1 ;loop
;
;------ read the second or last block ------
;
@2: movem (a1), d0-d7
movem d0-d7, (a3)
addq.l #8, a3
addq.l #8, a3
nop
moveq #dlycnst-1, d0
subq.l #1, dLcnt(a6)
@3: dble d0, @3
bgt.s @2
;--------------------------------------------------------------------------
; now we have to find sync bytes and extract the bit stream
;--------------------------------------------------------------------------
clr VTIRDIS ;turn off vertical retrace
moveq #1, d4 ;initialize FOUND to true
GetBytes:
lea dScrach(a6), a3 ;pointer to 1/2 Scrach Array pointer
move.l a3, a4
adda #HalfSize, a4 ;pointer to end of 1/2 Scrach Array RM000
;
; find the first sync byte
;
bsr FindSync
tst.w d4
beq.s Exit ;exit if no sync byte found
;
; now pull out the first block from the bit stream
;
bsr GetNibbles
;
; here we look for the second sync byte.
;
lea dScrach(a6), a3
adda #HalfSize, a3 ;pointer to 2/2 Scrach Array pointer RM000
move.l a3,a4
adda #HalfSize,a4 ;pointer to end of 2/2 Scrach Array RM000
;
bsr FindSync
tst.w d4
beq.s Exit ;again, exit if no sync byte found
;
; now pull out second block from the bit stream
;
bsr GetNibbles
;----------------------------------------------------------------------
; Check the checksum of the read data
;----------------------------------------------------------------------
CheckSum:
move.l dSavArry(a6),a0
clr.w d0
move.b 24(a0),d0
move.w #100,d2
mulu d2,d0
move.b 25(a0),d1
move.w #10,d2
mulu d2,d1
add.w d1,d0
move.b 26(a0),d1
add.w d1,d0
clr.w d1
clr.w d2
clr.w d3
@2: move.b 0(a0,d1),d3
add.w d3,d2
addq.w #1,d1
cmpi.w #24,d1
bne.s @2
move.b 27(a0), d3
add.w d3,d2
subi.w #4 * $F, d2
cmp.w d0,d2
beq.s @3
clr.w d4
@3:
;---------------------------------------------------------------------------
; job well done, lets go home
;---------------------------------------------------------------------------
Exit:
unlk a6
move (sp)+, SR ;restore status reg
MOVEM.L (SP)+,D7/A0 ;and regs
clr VTIRENB ;re-enable interrupts
LSR #1,D4 ;shift to set/reset error indicator
@1 RTS ; and exit
.PAGE
;---------------------------------------------------------------------------
; subroutine to find a sync byte
;---------------------------------------------------------------------------
FindSync:
clr.l d0
moveq #2, d1 ;two passes to find the sync byte
@1: move.w (a3)+, d2 ;
lsl.w #1, d2 ;
roxl.b #1, d0 ;get SN1
cmpa.l a3, a4 ;assure the buffer's circular
bne.s @2 ;
adda.l #-HalfSize, a3 ;if it's at the end then
subq #1, d1 ; check if it's the second try
beq.s @3 ; and exit if so
@2: cmpi.b #$0ff, d0 ;test here if it's a sync byte
bne.s @1 ;no: loop again
lsl.w #4, d0 ;yes: adjust the byte
lsr.b #4, d0 ;
move.w d0, (a0)+ ;save it
rts ;and return
@3: clr.w d4 ;uh, oh. No sync byte.
rts ;clear FOUND and return
;--------------------------------------------------------------------------
; subroutine to pull out a 14 nibble block from the bit stream
;--------------------------------------------------------------------------
GetNibbles:
moveq #BytesPerRead-1, d2 ;
@1: moveq #8, d1 ;8 bits/byte
clr.l d0 ;
@2: lsl (a3)+ ;get SN1 in the next scrach word
roxl.b #1, d0 ;shift it into the save buffer
cmpa.l a3, a4 ;assure a circular bufer
bne.s @3 ;
adda.l #-HalfSize, a3 ;
@3 subq #1, d1 ;decrement bit/byte counter
bne.s @2 ;loop again if still in byte
lsl.w #4, d0 ;separate the nibbles
lsr.b #4, d0 ;
move d0, (a0)+ ;save these nibbles
subq #1, d2 ;decrement byte/SN counter
bne.s @1 ;loop again if still more to go
rts
Tag .word $4b41,$5300
.PAGE
;----------------------------------------------------------------------------
; PARITY CIRCUITRY TEST
; The purpose of this test is to verify the operation of the parity checking
; logic by forcing a parity error and ensuring it is caught.
; Register usage:
; D0 = pattern written A0 = logical address used for test
; D1 = read results A1 = corresponding physical address
; D2 = NMI indicator A2 = save for NMI vector
; D3 = save of memory contents A3 = scratch
; D4 = save of error addr latch A4 = unused
; D5 = unused A5 = address of bus status register
; D6 = unused A6 = unused
;----------------------------------------------------------------------------
PARTST
.ENDC
.IF ROM16K = 1
MOVE.L NMIVCT,A2 ;SAVE STANDARD NMI VECTOR
LEA WWPERR,A3 ;THEN SET UP NEW PARITY ERROR (NMI) VECTOR
MOVE.L A3,NMIVCT
MOVEA.L #STATREG,A5 ;setup status reg ptr for byte ops
TST.B PAROFF ;disable parity initially
CLR.L D2 ;clear regs for result use
CLR.L D4
MOVE #$01FF,D0 ;SET UP PATTERN FOR WRITE
MOVEA #$300,A0 ;SET UP ADDRESS FOR USE (in already verified mem) RM000
MOVE (A0),D3 ;SAVE ITS CONTENTS
MOVEA.L A0,A1 ;COMPUTE CORRESPONDING
ADDA.L MINMEM,A1 ; PHYSICAL ADDRESS
TST.B DG2ON ;ENABLE WRITE WRONG PARITY FUNCTION
MOVE D0,(A0) ;DO WRITE TO CREATE BAD PARITY
TST.B DG2OFF ;DISABLE WWP
TST.B PARON ;ENABLE PARITY ERROR DETECTION
TST D2 ;SHOULDN'T HAVE INTERRUPT YET
BNE.S PARERR ;EXIT IF ERROR
MOVE (A0),D1 ;DO READ - PARITY ERROR SHOULD OCCUR
NOP ;GIVE A LITTLE EXTRA TIME
TST D2 ;NMI RECEIVED?
BEQ.S PARERR ;ERROR IF NO
; Check that parity error and failing address correctly caught
BTST #PBIT,(A5) ;PARITY ERROR BIT SET?
BNE.S PARERR ;EXIT IF NOT
MOVE MEALTCH,D4 ;GET ERROR ADDRESS
TST.B PAROFF ;disable parity to clear error bit
LSL.L #5,D4 ;NORMALIZE THE ADDRESS
CMPA.L D4,A1 ;SAME ADDRESS AS WRITTEN TO?
BNE.S PARERR ;EXIT IF ERROR
MOVE.L A2,NMIVCT ;ELSE RESTORE NMI VECTOR
CLR D0
NOT D0
MOVE D0,(A0) ;"clear" bad parity
TST.B PARON ;reenable parity
BRA.S PARXIT ;and skip to exit
; Error exit
PARERR BSET #PAR,D7 ;SET INDICATOR
TST.L D7 ;in loop mode?
BMI.S PARTST ;restart if yes
TST.B PAROFF ;else ensure parity disabled
MOVE.L A2,NMIVCT ;RESTORE NMI VECTOR
BRA TSTCHK ;AND ABORT FURTHER TESTING
; Normal exit
PARXIT TST.L D7 ;check for loop mode
BMI.S PARTST ;restart test if yes
BSR CHKCPU ;place check over CPU (all tests OK)
BRA.S MEMTST2 ;else go do memory test
; NMI routine for parity error checking
WWPERR MOVEQ #1,D2 ;SET INDICATOR
RTE ;AND RETURN
;------------------------------------------------------------------------
; Bus error handler for VIA #1 use
;------------------------------------------------------------------------
VIA1VCT MOVEQ #EVIA1,D0 ;SET ERROR CODE
BSET #VIA1,D7 ;set indicator
BRA IOVCT ;AND GO HANDLE I/O EXCEPTION
.ENDC ;(ROM16K)
.PAGE
;-------------------------------------------------------------------------
; Now do full memory test with and without parity enabled. If parameter
; memory bit set for extended memory testing, memory tests executed in
; twice. If warm-start, execute only one pass with parity enabled.
; Uses registers:
; A0 = starting address to test D0 = used to consolidate test results
; A1 = ending address to test D1 = scratch
; A2 = unused D2 = address increment
; A3 = save address for results D3 = test results for each 128K
; A4 = return address D4 = max test address
; A5 = unused D5 = pass count
;-------------------------------------------------------------------------
MEMTST2
.IF ROM4K = 0
.IF USERINT = 1
MOVEA #MEMSTRT,A1 ;hilite memory board test icon
BSR INVICON
.ENDC
BSR SETBUSVCT ;restore normal bus error vector RM000
MEMLOOP
LEA PRTYINT1,A1 ;setup up vector for parity intrpt CHG015
MOVE.L A1,NMIVCT ; CHG015
.IF ROM16K = 1
; First check if this is a warm-start CHG006
BTST #WRMSTRT,D7 ;warm-start? CHG006
BEQ.S @0 ;skip if not CHG015
MOVEQ #1,D5 ;else set count for one pass CHG015
BRA.S @3 ;skip to do it CHG015
; Next check parameter memory to see if extended testing desired
@0 BSR CHKPM ;go check parameter memory
BCS.S @1 ;skip if not valid to do only one pass
BTST #6,MEMCODE ;else check extended memory test indicator
BEQ.S @1 ;exit if not set
MOVEQ #2,D5 ;run two passes for extended mode CHG015
BRA.S @2 ;go do it CHG015
@1 MOVEQ #1,D5 ;run one pass for normal mode CHG015
; Run the memory tests
@2 TST.B PAROFF ;first run with parity off CHG015
BSR.S RUNTESTS ;run test pass CHG015
BNE.S TSTDONE ;skip if error CHG015
@3 TST.B PARON ;then run pass with parity on CHG015
BSR.S RUNTESTS ;run test pass CHG015
BNE.S TSTDONE ;exit if error CHG015
SUBQ #1,D5 ;decr pass count CHG015
BNE.S @2 ;continue testing until done CHG015
TSTDONE TST.L D7 ;in loop mode?
BMI.S MEMLOOP ;restart if yes
BTST #MEM,D7 ;memory error?
BNE TSTCHK ;abort if yes
BSR CHKMBRD ;else signal memory OK
LEA NMI,A3 ;restore NMI vector CHG015
MOVE.L A3,NMIVCT ; CHG015
BRA IOTST ;go on to next test
;-----------------------------------------------------------------------
; Subroutine to run the memory tests - saves results as test proceeds
; Zero condition code bit set if no errors.
;-----------------------------------------------------------------------
RUNTESTS
; Do the basic test
BASICTST
BSR.S TSTINIT ;init for new test
CALL3
BSR4 RAMTEST
BEQ.S @1 ;skip if no errors
BSET #MEM,D7 ;else set error indicator
@1 BSR.S SAVRSLT ;save results
BNE.S CALL3 ;loop until done CHG021
BTST #MEM,D7 ;set condition code CHG015
RTS ;and exit
.ELSE
TST.B PARON ;enable parity...
; Do the basic test
BASICTST
BSR.S TSTINIT ;init for new test
CALL3
BSR4 RAMTEST
BEQ.S @1 ;skip if no errors
BSET #MEM,D7 ;else set error indicator
@1 BSR.S SAVRSLT ;save results
BCC.S CALL3 ;and loop until done
TSTDONE LEA NMI,A3 ;restore normal NMI vector
MOVE.L A3,NMIVCT
TST.L D7 ;in loop mode?
BMI.S MEMLOOP ;restart if yes
BTST #MEM,D7 ;memory error?
BNE TSTCHK ;abort if yes
BRA IOTST ;else go on to next test
.ENDC ;{ROM16K}
.PAGE
;----------------------------------------------------------------------
; Subroutine to do initialization for memory tests
;----------------------------------------------------------------------
TSTINIT
MOVEQ #2,D2 ;test in 128K increments RM000
SWAP D2 ; (sets D2 = $20000) RM000
MOVE.L SCRNBASE,D4 ;get max test address (base of screen)
MOVEA #LOMEM,A0 ;set initial start
MOVE.L D2,A1 ; and ending address
MOVEA #MEMRSLT,A3 ;set address of result area RM000
RTS
;----------------------------------------------------------------------
; Subroutine to save results and update ptrs.
;----------------------------------------------------------------------
SAVRSLT MOVE D3,D0 ;get low results
SWAP D3 ;get high results
OR D0,D3 ;combine
OR D3,(A3)+ ; and save
CMP.L A1,D4 ;at max test address?
BEQ.S @1 ;exit if yes
MOVEA.L A1,A0 ;else set new addresses
ADDA.L D2,A1 ; to check next row of memory
CMP.L A1,D4 ;in last segment?
BGE.S @1
MOVE.L D4,A1 ;set at base of video page
@1 RTS
.PAGE
;-----------------------------------------------------------------------------
; BASIC MEMORY TEST - writes pattern and its complement in memory location,
; then verifies by reading. Also does second scan as
; addressing check. Uses long word operations for speed.
; Inputs:
; A0 - Starting address to test
; A1 - Ending address
; A4 - Return address
; Outputs:
; CCR zero bit set if no error
; D3 = OR mask of errors
; Uses registers:
; A0 = current test address D0 = current test pattern
; A1 = ending test address D1 = scratch
; A2 = unused D2 = unused
; A3 = unused D3 = OR mask of errors
; A4 = return address D4 = unused
; A5 = saved start address D5 = unused
; A6 = used for return address D6 = unused
;-----------------------------------------------------------------------------
RAMTEST MOVE.L A0,A5 ;save start address
MOVE.L #PATRN,D0 ;get pattern
NOT.L D0 ;use complement first
MOVEQ #0,D3 ;clear for result use
ORI #$0010,SR ;set extend bit for use with pattern rotate
RAMRW MOVE.L D0,(A0) ;do write
CMP.L (A0),D0 ;verify
BEQ.S RAMCHK2 ;skip if OK
BSRS6 RDERR ;else save error bits
RAMCHK2 NOT.L D0 ;now use inverse
MOVE.L D0,(A0) ;write to check for stuck bits
CMP.L (A0)+,D0 ;verify and bump address
BEQ.S RAMNXT ;skip if OK
SUBQ.L #4,A0 ;else get error address
BSRS6 RDERR ;go save error bits
ADDQ.L #4,A0 ;and restore next test address
RAMNXT ROXL.L #1,D0 ;create new pattern
NOT.L D0 ;invert for test
CMPA.L A0,A1 ;done?
BNE.S RAMRW ;loop if not
; Now do address check - writes memory as all F's during scan
ADRTST MOVE.L #PATRN,D0 ;reinitialize
MOVE.L A5,A0 ;get start address
MOVEQ #0,D1
NOT.L D1 ;final pattern for write
ORI #$0010,SR ;set extend
ADRCHK CMP.L (A0),D0 ;check contents
BEQ.S ADRCLR ;skip if OK
BSRS6 RDERR ;else save errors
ADRCLR MOVE.L D1,(A0)+ ;'clear' and go to next location
ROXL.L #1,D0 ;create next pattern
CMPA.L A0,A1 ;done?
BNE.S ADRCHK ;loop if not
; Check results
TST.L D3 ;set condition codes
RTS4
; Failure routine - save results and continue testing
RDERR MOVE.L (A0),D1 ;do read again
EOR.L D0,D1 ;isolate bad bits
OR.L D1,D3 ;save result
RTS6 ;and return
.PAGE
;------------------------------------------------------------------------------
; Phase 1 Parity error handler for memory tests. Objective for handler is to
; isolate parity error to chip level.
; Assumes:
; D0 = expected data pattern
; A0 = error address or address + 4
; Uses registers:
; D1 = parity error address
; D2 = search size for byte in error
; D3 = low memory address
; A1 = search address
;------------------------------------------------------------------------------
PRTYINT1
BSR.S TSTSTAT ;check if parity error CHG015
BNE NMI ;skip if not CHG015
BSET #MPAR,D7 ;set error indicator CHG015
MOVE.L D0,XPCTDATA ;save data and address CHG015
MOVE.L A0,XPCTADDR ; CHG015
MOVE.L MINMEM,D3 ;get low memory address CHG015
BSR GETPADDR ;read and convert parity address CHG015
BTST #5,D1 ;main mem error? CHG015
BNE.S @1 ;skip if not CHG015
MOVEQ #MSRCHSZ-1,D2 ;setup up search size for main mem CHG015
BRA.S @2 ;skip to do it CHG015
@1 MOVE #VSRCHSZ-1,D2 ;setup for video memory search CHG015
ANDI.L #VMSK,D1 ;mask off undefined info CHG015
@2 MOVE.L D1,PEADDR ;save error address CHG015
; Reset NMI vector and start search for exact address CHG015
LEA PRTYINT2,A1 ;setup new vector CHG015
MOVE.L A1,NMIVCT ; CHG015
SUB.L D3,D1 ;convert to logical address CHG015
MOVE.L D1,A1 ;setup for use CHG015
TST.B PAROFF ;clear parity bit CHG015
TST.B PARON ; CHG015
CLR.L D4 ;clear for use CHG015
@3 MOVE.B (A1)+,D4 ;search for parity error by byte CHG015
DBRA D2,@3 ;loop until found CHG015
; Error did not repeat CHG015
BRA.S PRIXIT ;go save error info and exit CHG015
;-----------------------------------------------------------------------------
; Subroutine to check for parity error
;-----------------------------------------------------------------------------
TSTSTAT BTST #1,STATREG ;check for parity error CHG015
RTS ;return with condition code set CHG015
;-----------------------------------------------------------------------------
; Parity error handler, phase 2.
; Assumes:
; A1 = error address + 1
; D0 = expected data (long)
; D4 = error data (byte)
; Uses registers:
; D1 = error address
; D2 = scratch
;-----------------------------------------------------------------------------
PRTYINT2
BSR.S TSTSTAT ;parity error? CHG015
BNE NMI ;skip if not to handle NMI CHG015
BSR GETPADDR ;get error address CHG015
MOVE.L D1,PEADR2 ;save it CHG015
SUBA.L #1,A1 ;get actual address CHG015
MOVE.L A1,ACTADDR ;save address and data CHG015
MOVE.L D4,ACTDATA ; CHG015
BTST #5,D1 ;video error? CHG015
BNE.S PRIXIT ;skip if yes CHG015
MOVE.L A1,D1 ;get error address CHG015
ANDI.L #ADRMSK,D1 ;setup up rotate count CHG015
MOVE.L D1,D2 ;save it CHG015
BEQ.S @2 ;skip if pre-rotate not needed CHG015
@1 LSL.L #8,D0 ;shift expected data to high byte CHG015
SUBQ #1,D1 ; CHG015
BNE.S @1 ; CHG015
@2 ROL.L #8,D0 ;shift to low byte CHG015
ANDI.L #$FF,D0 ;strip unneeded info CHG015
EOR.B D4,D0 ;isolate bad bits CHG015
BEQ.S PCERR ;skip if no data error CHG015
BTST #0,D2 ;check if high or low byte error CHG015
BNE.S @3 ;skip if low byte CHG015
LSL #8,D0 ;else shift to high byte CHG015
@3 MOVEA #MEMRSLT,A3 ;set ptr to save area CHG015
MOVE.L A1,D4 ;set error address CHG015
MOVE.L D0,D3 ;and error bits CHG015
BSR SCRNSAV ;then go save data CHG015
PRIXIT TST.B PAROFF ;disable parity CHG015
BRA EXCP1 ;and go to exit CHG015
; no data error - must be parity chip failure; decode to chip id CHG015
PCERR MOVE.L A1,D1 ;get error address CHG015
BTST #0,D1 ;check if odd or even CHG015
BEQ.S @1 ;skip if even CHG015
MOVE.B #$14,PCHIP ;bad parity chip in low word CHG015
BRA.S @2 ; CHG015
@1 MOVE.B #9,PCHIP ;bad chip in high word CHG015
@2 MOVEQ #17,D2 ;calculate row address CHG015
LSR.L D2,D1 ; for parity error CHG015
MOVE.B D1,PCHPROW ;save row info CHG015
BRA.S PRIXIT ;and exit CHG015
;-----------------------------------------------------------------------------
; Subroutine to get parity error address
; Returns D1 = error address
;-----------------------------------------------------------------------------
GETPADDR
CLR.L D1 ;clear for use CHG015
MOVE MEALTCH,D1 ;read error latch CHG015
MOVE D1,ADRLTCH ;save it CHG015
LSL.L #5,D1 ;convert to physical address CHG015
RTS ; CHG015
.PAGE
;-----------------------------------------------------------------------------
; Continue with I/O board testing
;-----------------------------------------------------------------------------
IOTST
.ELSE ;{ROM4K}
MOVE.L #FIVESEC,D0 ;delay to allow keyboard input
BSR.S DELAY
.ENDC ;{ROM4K}
.IF USERINT = 1
MOVEA #IOSTRT,A1 ;hilite I/O board test icon
BSR INVICON
.ENDC
.IF FULLSCC = 1
;-------------------------------------------------------------------------------;
; SCC Test (Checks RS232 port controller)
;
; The SCC interrupt vector is written and read with all 8 bit patterns
; to check SCC addressing. An internal loopback test is then done on
; channel B. RM014
;
; The chip is always left in an initial state as follows:
; both channels are reset
; master interrupt enable is reset
; DTR, RTS outputs set high on channel B CHG011
;
; Runs with interrupts off, uses stack. Uses registers:
;
; A0 = SCC address D0 = error indicator
; A2 = scratch D1 = scratch
; D2 = scratch
; D3 = scratch
;
; Errors saved in D0 and stored in low memory as follows:
;
; 0000 0001 -> SCC vector read/write error (accessed via channel A) RM014
; 0000 0010 -> channel B transmit buffer empty timeout RM014
; 0000 0100 -> channel B receive buffer full timeout RM014
; 0000 1000 -> channel B data compare error RM014
;
;-------------------------------------------------------------------------------;
SCCTEST LEA SCCVCT,A3 ;set up bus error vector
MOVE.L A3,BUSVCTR
BSR RSTSCC ;reset and set up A0 for SCC
ADDQ.L #ACTL,A0 ;adjust SCC address for channel A
MOVEQ #0,D1 ;SCC interrupt vector starts out 0
MOVEQ #0,D0 ;no errors
VECTLOOP
MOVE.B #2,(A0) ;test scc write register 2 (interrupt vector)
; via channel A RM014
MOVE (SP),(SP) ;delay
MOVE.B (A0),D2 ;read unmodified vector
CMP.B D1,D2 ;ok?
BEQ.S @1 ;branch if so
MOVEQ #1,D0 ;otherwise set error code
BRA.S SCCEXIT ;and exit
@1 MOVE (SP),(SP)
MOVE.B #2,(A0) ;write next vector value
ADDQ.L #1,D1 ;increment and delay
MOVE.B D1,(A0) ;write it
BNE.S VECTLOOP ;go through 256 values
BRA.S SETSCC ;now go do loopback init
;-----------------------------------------------------------------------
; Now init channel B for max baud rate and internal loopback.
; External transmit is inhibited by setting DTR low.
;-----------------------------------------------------------------------
; Initialization data for SCC: max baud RS-232 async communication
b96data:
.byte 9,$00 ;disable all interupts RM014
.byte 4,$4D ;x16 clk, 2 stop bits, odd parity
.byte 11,$50 ;baud rate gen clk to receiver, transmitter
.byte 12,$00 ;set baud rate to max
.byte 13,$00
.byte 14,$13 ;enable baud rate gen, BR=PCLK, loopback
.byte 3,$C1 ;8 bits/char recv, enable receiver
.byte 5,$EA ;DTR low, 8 bits/char xmit, enable xmit, CRC RM014
b96lth .equ *-b96data
SETSCC LEA B96DATA,A2 ;setup channel B RM014
MOVE.W #B96LTH,D1
SUBQ.L #ACTL,A0 ;set address for channel B
BSR.S WRITESCC ; RM000
; do the loopback test
; RM014
LPTEST MOVEQ #0,D1 ;go thru 256 bytes
MOVEQ #-1,D3 ;set up timeout count
SCCLOOP
BTST #TXBE,(A0) ;wait for transmit buffer empty
BNE.S SCCOUT
DBRA D3,SCCLOOP
ADDQ #2,D0
BRA.S SCCLXIT ;report timeout error
SCCOUT MOVE (SP),(SP)
MOVE.B D1,SCCDATA(A0)
SCCLOOP2
BTST #RXBF,(A0) ;wait for data byte to come in
BNE.S SCCIN
DBRA D3,SCCLOOP2
ADDQ #4,D0
BRA.S SCCLXIT
SCCIN MOVE (SP),(SP)
MOVE.B SCCDATA(A0),D2
CMP.B D1,D2
BNE.S SCCLERR
MOVEQ #-1,D3 ;update timeout count
ADDQ.B #1,D1 ;increment data
BNE.S SCCLOOP ;just do it 256 times
SCCLXIT BRA.S SCCEXIT
SCCLERR ADDQ #8,D0
; exit, saving errors
SCCEXIT MOVE.B D0,SCCRSLT ;save results
BEQ.S @3 ;continue if OK
BTST #0,D0 ;check for chan A error RM014
BEQ.S @1
BSET #RS232A,D7
@1 LSR #1,D0 ;check for chan B error RM014
TST.B D0
BEQ.S @2
BSET #RS232B,D7
@2 BSR.S RSTSCC ;leave SCC at initial condition
TST.L D7 ;looping required?
BMI.S SCCTEST ;restart test if yes
BRA TSTCHK ;else go report error
@3 BSR.S RSTSCC ;leave SCC at initial condition
TST.L D7 ;in loop mode?
BMI.S SCCTEST ;restart test if yes
BRA.S DSKTST ;else continue to next test RM014
.PAGE
;------------------------------------------------------------------------
; WRITESCC: used to initialize a series of SCC registers.
;
; A0 = SCC address for channel to be initialized
; A2 = pointer to an initialization data block as above
; A4 = return address
; D1 = initialization data block size in bytes
;
; A2, D1, D2 are modified.
;
;------------------------------------------------------------------------
WRITESCC
MOVE.B (A0),D2 ;read to make sure SCC is sync'ed up
BRA.S @2 ;delay for timing, too
@1 MOVE.B (A2)+,(A0)
@2 DBRA D1,@1
RTS
;------------------------------------------------------------------------
; Subroutine to initialize SCC. Does reset and zeroes interrupt vector.
;------------------------------------------------------------------------
INITBDATA
.BYTE 2,$00 ;zero interrupt vector
.BYTE 9,$C0 ;reset both channels
INITBLTH .EQU 4 ; CHG011
INITB2 .BYTE 5,$82 ;set DTR, RTS high for Applebus CHG011
INITB2L .EQU 2 ; CHG011
RSTSCC
MOVE.L #SCCBCTL,A0 ;point to SCC base address (chan B)
LEA INITBDATA,A2 ;point to channel B init data
MOVEQ #INITBLTH,D1 ; and set up the length CHG011
BSR.S WRITESCC ;then init channel B
MOVEQ #12,D0 ;delay for SCC reset
BSR DELAY
LEA INITB2,A2 ;setup DTR, RTS outputs CHG011
MOVEQ #INITB2L,D1 ; CHG011
BSR.S WRITESCC ; CHG011
RTS ;and return
;-----------------------------------------------------------------------------
; Bus error routine for SCC testing
;-----------------------------------------------------------------------------
SCCVCT CMPA.L #SCCBCTL,A0 ;accessing channel B?
BNE.S @1 ;skip if no
MOVEQ #ERS232B,D0 ;set error code for chan B
BRA.S @2
@1 MOVEQ #ERS232A,D0 ;set error code for chan A
@2 TST.L D7 ;check if in loop mode
BPL.S @3 ;skip if not
MOVEA #STKBASE,SP ;else restore stack ptr RM000
BRA SCCTEST ;and restart test
@3 BRA IOVCT ;and go handle I/O card bus error
.ENDC
.PAGE
;----------------------------------------------------------------------------
; Test of disk interface - ensure R/W capability to shared RAM, then
; try disable interrupts command. This test will also verify
; the results of the disk controller's own self-test (ROM and RAM test).
;----------------------------------------------------------------------------
DSKTST
.IF DIAGS = 1
LEA DSKVCT,A3 ;set up vector in case of bus timeout
MOVE.L A3,BUSVCTR
MOVE.L #DISKMEM,A0 ;set ptr for shared memory
; Display ROM id CHG001
MOVEQ #ROMIDROW,D5 ;set cursor ptrs CHG001
MOVE #ROMIDCOL+1,D6 ; CHG001
MOVEQ #'/',D0 ;preceed with / char CHG001
BSR DSPVAL ;display it CHG001
MOVE.B ROMV(A0),D0 ;read id CHG001
MOVE.B D0,IOROM ;save in low memory CHG010
MOVEQ #2,D1 ; CHG001
BSR OUTCH ; CHG001
; Read system type CHG009
BSR.S SETTYPE ;determine system type CHG029
; Check disk alive indicator
CLR.L D2 ;clear for use CHG022
MOVE.L #VIA2BASE,A1 ;set ptr to parallel port 6522
ANDI.B #$BF,DDRB2(A1) ;ensure bit 6 is input
MOVE.L #DSKTMOUT,D0 ;set up timeout count for 15 secs
@2 BTST #DSKDIAG,IRB2(A1) ;check indicator
BNE.S @3 ;skip if set
SUBQ.L #1,D0 ;else loop until timeout (about 8 us per loop)
BNE.S @2
MOVEQ #EDISK,D2 ;error if not set CHG022
; Try read operation and check results of self-test
@3
.IF DIAGS = 1
MOVE.B STST(A0),DSKRSLT ;get results of disk self-test CHG022
BNE.S INTERR ;exit if error CHG022
@4 TST.B D2 ;previous error? CHG022
BNE.S INTERR ;exit if yes CHG022
; Then try simple write operation to shared RAM
MOVEQ #$55,D0 ;set up pattern RM000
MOVE.B D0,CMD(A0) ;try write
CMP.B CMD(A0),D0 ;verify
BNE.S INTERR ;exit if error
; Finally try a command to disable interrupts
BSR DSABLDSK ;go issue disable cmd
BCC.S DSKXIT ;skip if OK
.ELSE
BRA.S COPSCHK ;continue
.ENDC
INTERR BSET #DISK,D7 ;else set disk error
TST.L D7 ;restart if in loop mode
BMI.S DSKTST
BRA TSTCHK ;and abort further testing
DSKXIT TST.L D7 ;restart if in loop mode
BMI.S DSKTST
.ENDC
BRA.S COPSCHK ;else go to next test
;-----------------------------------------------------------------------------
; Bus error routine for disk testing
;-----------------------------------------------------------------------------
DSKVCT MOVEQ #EDISK,D0 ;SET ERROR CODE
.IF ROM4K = 0
TST.L D7 ;check if in loop mode
BPL.S @3 ;skip if not
.ENDC
MOVEA #STKBASE,SP ;else restore stack ptr RM000
BRA DSKTST ;and restart test
@3 BRA IOVCT ;GO HANDLE I/O CARD BUS ERROR
;-------------------------------------------------------------------------
; Subroutine for determining system type
; Returns type value in D0 and sets SYSTYPE location in memory
; D0 = 0 - Lisa 1
; 1 - Lisa 2/external disk with slow timers
; 2 - Lisa 2/external disk with fast timers
; 3 - Lisa 2/internal disk (Pepsi) with fast timers
;-------------------------------------------------------------------------
SETTYPE CLR.L D0 ;clear for type usage CHG029
MOVE.B DISKROM,D1 ;read disk id CHG029
TST.B D1 ;check for Lisa 1 CHG029
BPL.S @9 ;skip if yes CHG029
BTST #SLOTMR,D1 ;Lisa 2 with slow timers? CHG029
BEQ.S @1 ;skip if not CHG029
MOVEQ #1,D0 ;else set type CHG029
BRA.S @9 ; CHG029
@1 BTST #FASTMR,D1 ;Lisa 2 with fast timers? CHG029
BEQ.S @2 ;skip if not CHG029
MOVEQ #2,D0 ;else set type CHG029
BRA.S @9 ; CHG029
@2 MOVEQ #3,D0 ;else must be Pepsi with fast timers CHG029
@9 MOVE.B D0,SYSTYPE ;save system type CHG029
RTS ; CHG029
.PAGE
;-------------------------------------------------------------------------
; Scan the keyboard for user commands. Click speaker first to alert user.
;-------------------------------------------------------------------------
COPSCHK LEA COPSVCT,A3 ;set up bus error vector
MOVE.L A3,BUSVCTR
BSR CLICK ;notify user that keyboard about to be scanned
BSR DELAY_1 ;delay for 1/10 sec
MOVEA.L #VIA1BASE,A0 ;set up VIA address
MOVE.B #$C9,PCR1(A0) ;set intrpt control for later use
; also causes second "click"
BSR.S SCANCPS ;go check for keyboard input
BRA CLKTST ;and continue on
;--------------------------------------------------------------------------
; Subroutine to do scan of keyboard COPS
;--------------------------------------------------------------------------
SCANCPS
MOVE.L KBDQPTR,A1 ;set up queue ptrs
MOVEA #QEND,A2
; Scan for keyboard data
KEYSCAN BSR GETDATA ;go check for keyboard input
BCS.S @9 ;exit if no data or queue full
CMPI.B #CMDKEY,D0 ;is it the command key?
BNE.S @1 ;skip if no
BSR GETDATA ;yes - get next char to see if boot cmd
BCS.S @9 ;exit if queue full or no more data
CMPI.B #SHFTKEY,D0 ;check for shift key
BNE.S @2 ;skip if no - go save as boot code
BSR GETDATA ;else keep checking for command sequence
BCS.S @9 ;skip if Q full or no data
CMPI.B #PKEY,D0 ;'P' key for power-cycling
BNE.S @1 ;skip if not
MOVE.B #PC,BOOTDVCE ;set for power-cycle mode
BSET #ALTBOOT,D7 ;set alternate boot
BRA.S KEYSCAN ;and continue scan
@1
.IF USERINT = 1
; do test for downstroke or mouse button (used for burnin cycling)
TST.B D0 ;check keycode
BPL.S @4 ;skip if not downstroke
CMPI.B #ALPHKEY,D0 ;ignore alpha lock key
BEQ.S KEYSCAN
.ENDC
.IF BURNIN = 1
CMP.B #MOUSDWN,D0 ;mouse button?
BNE.S @3 ;skip if not
BSET #MSBUTN,STATFLGS ;else set flag for later use
BRA.S KEYSCAN ;and continue scan
.ENDC
@3
.IF USERINT = 1
BSET #BTMENU,D7 ;set indicator for boot menu
.ENDC
BRA.S KEYSCAN ;and continue scan
; Save code as possible boot id and set indicator
@2 BSR.S XLATE ;translate to boot id code and save
BRA.S KEYSCAN ;and continue keyboard scan
; Check if release of mouse or COMMAND key (in case continuing after error)
@4 CMP.B #MOUSUP,D0 ;mouse release?
BNE.S @5
BCLR #MOUSE,STATFLGS ;clear marker if yes
BRA.S KEYSCAN ;and continue scan
@5 CMP.B #CMDUP,D0 ;Left CMD key release?
BNE.S @6
BCLR #CMDFLG,STATFLGS ;clear marker if yes
@6 BRA.S KEYSCAN ;continue scan
@9 MOVE.L A1,KBDQPTR ;save buffer ptr
RTS ;and return to caller
;---------------------------------------------------------------------
; Subroutine to translate keycodes to boot device codes. Returns
; with boot code in D2 if match found, else D2 = $F for no match.
; Also saves boot id in memory, and sets alternate boot indicator.
; Destroys A3 and D2.
;---------------------------------------------------------------------
XLATE LEA KEYTBL,A3 ;get ptr to keycode table
CLR.L D2 ;clear for counter
@1 CMP.B (A3)+,D0 ;do search until match
BEQ.S @2 ;skip if match
ADDQ #1,D2 ;else bump cntr
TST.B (A3) ;at end?
BNE.S @1 ;if not continue scan
MOVEQ #$7F,D2 ;else set for invalid code
@2
MOVE.B D2,BOOTDVCE ;save as boot device code
BSET #ALTBOOT,D7 ;set indicator
RTS ;and exit
KEYTBL .BYTE KEY1,KEY2,KEY3 ;1,2,3
.BYTE KEY4,KEY5,01 ;4,5,reserved (01 is invalid keycode)
.BYTE KEY6,KEY7,01 ;6,7,reserved
.BYTE KEY8,KEY9,01 ;8,9,reserved
.BYTE 01,01,01 ;reserved
.BYTE 01 ;reserved for power-cycle mode
.BYTE ENTRKEY ;Enter on numeric key pad
; (for Monitor access)
TBLEND .BYTE 0 ;ensure on word boundary
.PAGE
;------------------------------------------------------------------------------
; Try initial clock read and save data for later use
;------------------------------------------------------------------------------
CLKTST
.IF NEWLISA = 1
.IF DIAGS = 1
BSR.S READCLK ;go read clock
TST.L D7 ;restart if in loop mode
BMI.S CLKTST
BTST #CLK,D7 ;any errors?
BNE TSTCHK ;abort if yes
BSR CHKIOBRD ;else mark I/O board OK
BRA.S CONFIG ;and exit to next test
; Subroutine to read clock - destroys regs A0-A2, D0-D1
READCLK DISABLE ;disable all interrupts
MOVEQ #$02,D0 ;set up read clock cmd
BSR COPSCMD ;and send to COPS
BCS.S CLKERR ;exit if error
MOVEA #DATARGS,A2 ;set ptr to end of save area RM000
RDCLK0 MOVEA #CLKDATA-1,A1 ;set ptr to start of save area RM000
BSR.S GETDATA ;go get clock reset code
BCS.S CLKERR ;exit if timeout error
CMP.B #$80,D0 ;is it the reset code?
BNE.S RDCLK0 ;skip if no to continue wait
BSR.S GETDATA ;go check if clock data
BCS.S CLKERR
ANDI.B #$F0,D0 ;mask to check if clock flag
CMP.B #$E0,D0 ;clock data?
BNE.S RDCLK0 ;continue wait if no
MOVEQ #5,D1 ;set expected byte count
RDCLK1 BSR GETDATA ;go read clock data
BCS.S CLKERR ;exit if error
SUBQ #1,D1 ;else loop until all data received
BNE.S RDCLK1
ENABLE ;restore interrupt mask
RTS
; Error exit - set indicator and return
CLKERR BSET #CLK,D7
ENABLE ;restore interrupt mask
ORI.B #$01,CCR ;leave carry bit set
RTS
.ENDC
.ENDC
.PAGE
;-------------------------------------------------------------------------
; Scan I/O slots to determine what cards, if any, are installed and save
; id's of installed cards.
;-------------------------------------------------------------------------
CONFIG
.IF USERINT = 1
MOVEA #XCRDSTRT,A1 ;hilite I/O slot test icon
BSR INVICON
.ENDC
CONFIG2 MOVEQ #1,D4 ;set flag for status check
BSR.S RDSLOTS ; and go scan the slots
.IF DIAGS = 1
TST.L D7 ;restart if in loop mode
BMI.S CONFIG2
.ENDC
BSR CHKXCRD ;mark I/O slots OK
BRA TSTCHK ;exit to check overall results
;-------------------------------------------------------------------------
; Subroutine to scan I/O expansion slots
; Inputs:
; D4 = non-zero if status check to be done, else 0 for no check
; Outputs:
; Saves card id's in locations $298-$29C
; Error bits set in D7 if slot card errors encountered
; Error code saved in location BOOTDATA+1
; Side Effects:
; A5,A6 trashed
;-------------------------------------------------------------------------
RDSLOTS MOVEM.L D1/A1-A3,-(SP) ;save regs
MOVE.L SP,A6 ;save stack ptr
CLR.L D1 ;for result use
MOVEA #IO1ID,A1 ;get ptr to id save area RM000
MOVE.L #SLOT1L,A2 ;get slot 1 address
MOVE.L BUSVCTR,A5 ;save current bus vector value
LEA NOCRD1,A3 ;init bus error vector
MOVE.L A3,BUSVCTR ; in case no card installed
MOVEP (A2),D1 ;read id for slot 1
BSR.S CHKID ;go check id
BCC.S SLOT2 ;skip if OK
BSET #IO1ERR,D7 ;else set error indicator
BRA.S SLOT2 ;and continue
NOCRD1 CLR (A1)+ ;set id for no card
SLOT2 MOVE.L #SLOT2L,A2 ;do same for slot 2
LEA NOCRD2,A3
MOVE.L A3,BUSVCTR
MOVEP (A2),D1 ;read and check id
BSR.S CHKID
BCC.S SLOT3 ;skip if OK
BSET #IO2ERR,D7 ;else set error indicator
BRA.S SLOT3 ;and continue
NOCRD2 CLR (A1)+ ;set id for no card
SLOT3 MOVE.L #SLOT3L,A2 ;and finally for slot 3
LEA NOCRD3,A3
MOVE.L A3,BUSVCTR
MOVEP (A2),D1 ;read and check id
BSR.S CHKID
BCC.S CFGEXIT ;skip if OK
BSET #IO3ERR,D7 ;else set error indicator
BRA.S CFGEXIT ;go to exit
NOCRD3 CLR (A1)+ ;set id for no card
; Restore default bus error vector and SP and continue
CFGEXIT ORI #$0700,SR ;ensure interrupts off
MOVE.L A5,BUSVCTR ;restore from previous saves
MOVE.L A6,SP
MOVEM.L (SP)+,D1/A1-A3 ;and restore regs
RTS ;then exit
;-------------------------------------------------------------------------
; Subroutine to do I/O slot card id check.
; Requires D1 = card id
;-------------------------------------------------------------------------
CHKID
CMP #$FFFF,D1 ;check for prototype card
BEQ.S @9 ;skip if not - treat as no card
MOVE D1,(A1)+ ;else save id
BMI.S @7 ;if bootable go do check
BTST #STBIT,D1 ; or do if status routine exists
BEQ.S @8 ;skip if not
@7 BSR RDIOSLT ;else go check for good board
@8 RTS
@9 CLR (A1)+ ;set id for no card
RTS
.PAGE
;-------------------------------------------------------------------------
; Check test results by checking error indicators in reg D7.
; Output greeting message if system contains memory and all is OK.
; Else output appropriate error messages.
;-------------------------------------------------------------------------
TSTCHK BSR SAVEREGS ;save regs first
LEA TST2,A3 ;setup bus error vector for type check CHG032
MOVE.L A3,BUSVCTR ; CHG032
BSR SETTYPE ;go set system type CHG032
TST2 BSR SETBUSVCT ;restore default bus error vector RM000
MOVEA #STKBASE,SP ; and default stack
BSR SETVLTCH ;and set video latch CHG020
.IF USERINT = 0
BSR CLRSCRN ;clear screen for display
MOVEQ #FIRSTROW,D5 ;set row for display
MOVEQ #FIRSTCOL,D6 ;set col for display
.ELSE
BSR CLRDESK ;clear desktop
.ENDC
MOVE.L D7,D0 ;GET ERROR INDICATORS
ANDI.L #ERRMSK,D0 ;MASK OFF NON-FATAL ERRORS
TST.L D0 ;OK?
BEQ OTHER ;SKIP IF YES
.IF ROM4K = 0
;---------------------------------------------------------------------------
; Errors detected - scan D7 for CPU error indicators
;---------------------------------------------------------------------------
MOVE.L D7,D0 ;get error indicators
ANDI.L #CPUMSK,D0 ;mask off no-CPU errors
TST.L D0 ;any?
BEQ.S EXCHK ;skip if none to check for exception errors
.IF USERINT = 0
LEA CPUMSG,A3 ;ELSE GET MSG PTR
BSR DSPMSGR ;AND DISPLAY IT
.ELSE
LEA CPUBRD,A2 ;set ptr for CPU board icon
.ENDC
; Check for specific error
.IF DIAGS = 1
BTST #CPUSEL,D7 ;check for CPU selection error
BEQ.S @1 ;skip if not
MOVEQ #ECPUSEL,D0 ;else get error code
BSR ERRDISP ;display it
BRA VIA2TST ;and loop on parallel port VIA test
; Sound error tones if not selection error (controls path to speaker)
@1 BSR LOPTCH ;CPU error causes lo,lo,hi tones
BSR LOPTCH
BSR HIPTCH
; Continue check for specific error
BTST #MMU,D7 ;CHECK IF MMU ERROR
BEQ.S @2 ;SKIP IF NO
MOVEQ #EMMU,D0 ;ELSE GET ERROR CODE
BRA.S @9 ;and go output it
@2
.IF NEWLISA = 1
.IF ROM16K = 1
BTST #VID,D7 ;CHECK IF VIDEO ERROR
BEQ.S @3 ;SKIP IF NO
MOVEQ #EVID,D0 ;ELSE GET ERROR CODE
BRA.S @9 ;and go output it
@3 MOVEQ #ECPAR,D0 ;else must be parity ckt error
.ENDC ;{ROM16K}
.ENDC ;{NEWLISA}
.ENDC ;{DIAGS}
@9 BRA TSTXIT ;go to exit
.ENDC ;{ROM4K}
;----------------------------------------------------------------------------
; Scan for exception errors
;----------------------------------------------------------------------------
EXCHK MOVE.L D7,D0 ;mask off non-exception errors
ANDI.L #EXMSK,D0
TST.L D0 ;OK?
BEQ.S IOCHK ;skip if yes to next check
.IF USERINT = 0
LEA EXCPMSG,A3 ;output general error msg
BSR DSPMSGR
.ELSE
; Sound error tones
BSR LOPTCH ;general logic failure causes lo,hi tones
BSR HIPTCH
LEA LISA,A2 ;set ptr for general LISA error
.ENDC
; Scan for details on exception errors
BTST #CPUINTR,D7 ;NMI?
BEQ.S @1
MOVEQ #ECPUINTR,D0 ;set error code
BRA.S @9 ;and go display
@1 BTST #BUSEXCP,D7 ;bus error?
BEQ.S @2
MOVEQ #EBUSEXCP,D0 ;set error code
BRA.S @9
@2 BTST #ADREXCP,D7 ;address error?
BEQ.S @3
MOVEQ #EADREXCP,D0 ;set error code
BRA.S @9
@3 BTST #MISEXCP,D7 ;miscellaneous error?
BEQ.S @4
MOVEQ #EMISEXCP,D0 ;set error code
BRA.S @9
@4 BTST #ILLEXCP,D7 ;illegal instruction error?
BEQ.S @5
MOVEQ #EILLEXCP,D0 ;set error code
BRA.S @9
@5 MOVEQ #ETRPEXCP,D0 ;must be a trap error
@9 BRA TSTXIT ;and go to exit
;-------------------------------------------------------------------------
; Check for I/O errors
;-------------------------------------------------------------------------
IOCHK MOVE.L D7,D0 ;GET ERRORS
ANDI.L #IOMSK,D0 ;MASK OFF NON-IO ERRORS
TST.L D0 ;OK?
BEQ KBDCHK ;SKIP IF YES TO NEXT CHECK
.IF USERINT = 0
LEA IOMSG,A3 ;GET I/O ERROR MSG
BSR DSPMSGR ;OUTPUT IT
.ELSE
LEA IOBRD,A2 ;set ptr for I/O board icon
.ENDC
.IF ROM4K = 0
; Scan for details on I/O errors
.IF ROM16K = 1
BTST #VIA1,D7 ;check for keyboard VIA errors
BEQ.S @1 ;skip if OK
MOVEQ #EVIA1,D0 ;else set error code
BSR.S ERRDISP ;display the error
BRA VIA1CHK ;and loop on VIA #1 test
; Sound error tones if not VIA #1 error (controls the speaker)
@1 BSR LOPTCH ;I/O errors cause lo,hi,lo tones
BSR HIPTCH
BSR LOPTCH
; Continue scan for detailed errors
BTST #VIA2,D7 ;parallel port VIA error?
BEQ.S @2
MOVEQ #EVIA2,D0 ;set error code
BRA.S @19
.ENDC
@2 BTST #IOCOPS,D7
BEQ.S @3
MOVEQ #EIOCOP,D0 ;get error code
BSR.S ERRDISP ;display error
BRA COPSENBL ;and go do loop on COPS test
@3
.IF DIAGS = 1
BTST #CLK,D7
BEQ.S @4
MOVEQ #ECLK,D0 ;ELSE GET ERROR CODE
BRA.S @19
.ENDC
@4
.IF FULLSCC = 1
BTST #RS232A,D7
BEQ.S @6
MOVEQ #ERS232A,D0 ;ELSE GET ERROR CODE
BRA.S @19
@6 BTST #RS232B,D7
BEQ.S @7
MOVEQ #ERS232B,D0 ;ELSE GET ERROR CODE
BRA.S @19
.ENDC
@7 BTST #DISK,D7
BEQ.S @8
MOVEQ #EDISK,D0 ;ELSE GET ERROR CODE
BRA.S @19
@8 BTST #IOEXCP,D7
BEQ.S @9
MOVEQ #EIOEXCP,D0 ;ELSE GET ERROR CODE
BRA.S @19
@9 BTST #IOCOPS2,D7 ;COPS code error?
BEQ.S @10
MOVEQ #EIOCOP2,D0 ;get error code
BRA.S @19
@10 BTST #IOKBD,D7 ;I/O or keyboard error?
BEQ.S @19
MOVEQ #EIOKBD,D0 ;get error code
.ENDC ;{ROM4K}
@19 BRA TSTXIT
;--------------------------------------------------------------------------
; Subroutine to do display for fatal errors
;--------------------------------------------------------------------------
ERRDISP
.IF USERINT = 1
BSR DSPERRICON ;display error
.ENDC
BSR DSPCODE ;output error code
BSET #LOOP,D7 ;set for looping operation
RTS
;--------------------------------------------------------------------------
; Check for keyboard error
;--------------------------------------------------------------------------
KBDCHK BTST #KBDCOPS,D7 ;Keyboard error?
BEQ.S MEMCHK ;skip to next check if not
.IF USERINT = 1
; Sound error tones
BSR HIPTCH ;Keyboard error causes hi,lo,hi tones
BSR LOPTCH
BSR HIPTCH
LEA KEYBDOUT,A2 ;set ptr for keyboard icon
.ENDC
MOVEQ #EKBDCOP,D0 ;set error code
BRA TSTXIT ;and go to exit
;--------------------------------------------------------------------------
; Check for memory errors
;--------------------------------------------------------------------------
MEMCHK
MOVE.L D7,D0 ;GET ERRORS
ANDI.L #MEMMSK,D0 ;MASK OFF NON-memory ERRORS
TST.L D0 ;any errors?
BEQ IOSCHK ;skip if no - must be I/O slot error
.IF USERINT = 0
LEA RAMMSG,A3 ;ELSE GET RAM ERROR MSG
BSR DSPMSGR
.ELSE
; Sound memory error tones
BSR LOPTCH ;memory error causes lo,hi,hi tones
BSR HIPTCH
BSR HIPTCH
; determine which memory card in error if more than one
CMPI.L #HEX512K,TOTLMEM ;more than 1 memory card?
BGT.S SCNRSLTS ;skip if yes
; only one card - check memory addresses to determine slot
MOVE.L MINMEM,D0 ;get low physical address
CHKMADR CMPI.L #ONEMEG,D0 ;address in slot 1?
BLT.S @2 ;skip if not
MOVEQ #1,D1 ;set board id for slot 1
BRA.S @3
@2 MOVEQ #2,D1 ;set board id for slot 2
@3 BRA.S MERRCHK ;and go scan for details
; more than one memory card - scan memory test results to determine which card
SCNRSLTS
BTST #MPAR,D7 ;parity error?
BEQ.S @1 ;skip if not
MOVE.L PEADDR,D0 ;go get error address CHG015
BRA.S CHKMADR ;and check it
; Check for R/W error
@1 MOVEA #MEMRSLT,A0 ;set ptr to OR masks RM000
MOVEQ #8,D0 ;and set counter
@4 TST (A0)+ ;check the rows
BNE.S @5 ;skip if error detected
SUBQ #1,D0 ;else check all masks
BNE.S @4 ;until done
@5 CMP.B #4,D0 ;check where error found
BGT.S @6 ;skip if low memory error
MOVEQ #1,D1 ;high memory on card 1
BRA.S MERRCHK
@6 MOVEQ #2,D1 ;low memory on card 2
.ENDC ;{USERINT}
.IF ROM4K = 0
; scan for error details
MERRCHK BTST #MEM,D7 ;check for main memory R/W error
BEQ.S @2 ;exit if not
MOVEQ #EMEM,D0 ;else display error code
MOVE.B D1,MEMSLOT ;save slot # for board in error
BRA.S MEMERR
@2 MOVEQ #EPAR,D0 ;must be parity error
.ENDC ;{ROM4K}
MEMERR
.IF USERINT = 1
MOVE.L D7,STATUS ;save power-up status
LEA MEMBRD,A2 ;set ptr for memory board icon
BSR DSPNUMICON ;display icon and board slot #
BRA.S TSTXIT2 ;finally exit to monitor
.ELSE
BRA.S TSTXIT
.ENDC ;{USERINT}
;--------------------------------------------------------------------------
; Must be I/O slot errors
;--------------------------------------------------------------------------
IOSCHK
.IF ROM4K = 0
.IF USERINT = 0
LEA IOSMSG,A3 ;ELSE GET RAM ERROR MSG
BSR DSPMSGR
.ELSE
; Sound error tones
BSR HIPTCH ;I/O slot error causes hi,lo,lo tones
BSR LOPTCH
BSR LOPTCH
LEA Xcard,A2 ;set ptr for I/O slot board icon
.ENDC
@1 BTST #IO3ERR,D7 ;check for slot 3 error
BEQ.S @2 ;exit if not
MOVEQ #3,D1 ;else set slot #
BRA.S @4
@2 BTST #IO2ERR,D7 ;slot 2 error?
BEQ.S @3
MOVEQ #2,D1 ;set slot #
BRA.S @4
@3 MOVEQ #1,D1 ;must be slot 1 error
@4 MOVE.B BOOTDATA,D0 ;get error code
BSR DSPNUMICON ;display error icon and slot #
BRA.S TSTXIT2 ;and exit to monitor
.ENDC ;{ROM4K}
TSTXIT
.IF USERINT = 0
MOVE.L D7,STATUS ;save status
BSR DSPCODE ;display error code
BRA MONITOR ;exit to monitor
.ELSE
BSR DSPERRICON ;display error icon
TSTXIT2
MOVE.L D7,STATUS ;save status
BSR DSPCODE ;display the error code
; Save error data in special parameter memory area, then exit to monitor
;****************************
; Delete for LISA 2 CHG034
;****************************
; LEA PMVCT,A3 ;setup bus error vector for PM RM013
; MOVE.L A3,BUSVCTR ; RM013
; BSR.S CHKSTATPM ;check if error already saved
; BCC.S GOTOMON ;skip if yes
; MOVEA.L #STATSTRT,A0 ;set starting ptr
; MOVE.B D0,(A0) ;save error code
; MOVE ADRLTCH,D0 ;save error address latch contents
; MOVEP D0,2(A0)
; MOVE.B MEMSLOT,6(A0) ;save memory slot #
; MOVE.L CLKDATA,D0 ;save clock data
; MOVEP.L D0,8(A0)
; MOVE CLKDATA+4,D0
; MOVEP D0,16(A0)
; CLR.L D0 ;clear remaining area
; MOVEP.L D0,20(A0)
; MOVEQ #STATWRDS-2,D0 ;validate save area
; BSR WRTSUM
GOTOMON BSR SCANCPS ;clear COPS queue
BSR CPSINIT ;reinit interface
BSR CURSORINIT ;init cursor and mouse
BRA MONITOR ;then jump to monitor
;-------------------------------------------------------------------------
; Parameter memory bus error handler RM013
;-------------------------------------------------------------------------
PMVCT MOVEA #STKBASE,SP ;reset stack RM013
BSR SETBUSVCT ;restore bus error vector RM013
BRA.S GOTOMON ;and exit to monitor RM013
;-------------------------------------------------------------------------
; Subroutine to check special parameter memory validity.
; Verify checksum routine sets carry bit if checksum not valid.
;-------------------------------------------------------------------------
;CHKSTATPM CHG034
; MOVEM.L D0-D1/A0,-(SP) ;save regs
; MOVEA.L #STATSTRT,A0 ;set starting ptr
; MOVEQ #STATWRDS-1,D0 ;and # of words to check
; MOVE D0,D1 ;set for shared memory
; BSR VFYCHKSM ;and go do checksum
;@1 MOVEM.L (SP)+,D0-D1/A0 ;restore regs
; RTS
.ENDC
;------------------------------------------------------------------------
; Scan for non-fatal errors
;------------------------------------------------------------------------
OTHER
.IF ROM16K = 1
MOVE.L D7,D0 ;get errors
ANDI.L #OTHRMSK,D0 ;isolate to non-fatal errors
TST.L D0 ;OK?
BEQ.S @9 ;skip if no errors
BTST #KBDOUT,D7 ;Keyboard disconnected?
BEQ.S @1 ;skip if no
.IF USERINT = 0
LEA KBDMSG,A3 ;else output message
BSR DSPMSGR
.ELSE
LEA KEYBDOUT,A2 ;display keyboard icon
BRA.S @2 ;with question mark
.ENDC
@1 ;must be mouse
.IF USERINT = 0
LEA MOUSMSG,A3 ;else output message
BSR DSPMSGR
.ELSE
BSR CHKPM ;check parameter memory before notify
; of mouse disconnect
BCS.S @8 ;ignore error if invalid
BTST #MOUSEON,MEMCODE ;check if should be installed
BEQ.S @8 ;skip if not
LEA MOUSEOUT,A2 ;else display mouse icon
@2 BSR DSPQICON ;with question mark
.ENDC
BRA NOTIFY ;alert user
.ENDC ;{ROM16K}
@8 BCLR #MOUSOUT,D7 ;ignore mouse disconnected error
@9 BRA SYSOK ;system must be OK
.PAGE
;-------------------------------------------------------------------------
; Subroutine to output error code
;-------------------------------------------------------------------------
DSPCODE MOVEM.L D0-D3,-(SP) ;save regs
.IF USERINT = 0
LEA ERRMSG,A3 ;get msg ptr
BSR DSPMSG
.ENDC
.IF NEWTWIG = 0
MOVEQ #2,D1 ;# of digits to display
.ENDC
.IF USERINT = 1
MOVE #CODEROW,D5 ;set screen ptrs for display
MOVE #CODECOL,D6
.ENDC
BRA.S GETDIG ;go do display
.IF NEWTWIG = 1
; Translate up to 4 digit hex error code to decimal
; Second entry point for routine
DSPDEC
MOVEM.L D0-D3,-(SP) ;save regs
GETDIG ANDI.L #$0FFFF,D0 ;clear other digits
MOVEQ #1,D1 ;display 1 char at a time
TST D0 ;is it 0?
BEQ.S @9 ;exit if yes to display it
CLR.L D2 ;clear working regs
CLR.L D3
; display all non-zero digits
@1 DIVU #$A,D0 ;converting to decimal
SWAP D0 ;get remainder
MOVE.B D0,D2 ;save for display
ROR.L #4,D2
ADDQ #1,D3 ;set count
CLR D0 ;clear remainder
SWAP D0 ;get new quotient
TST D0 ;quit when =0
BEQ.S @2 ;skip to do display
BRA.S @1
@2 ROL.L #4,D2 ;get char for output
MOVE.B D2,D0
SUBQ #1,D3 ;decr digit count
BEQ.S @9 ;skip to display last digit
BSR.S OUTCH ;display a digit
BRA.S @2 ;and loop until done
.ENDC
@9 BSR.S OUTCHR ;do output and CR
DSPCXIT MOVEM.L (SP)+,D0-D3 ;restore regs
RTS ;and return
;-------------------------------------------------------------------------
; Subroutine to invoke code display routine, then do CR
;-------------------------------------------------------------------------
OUTCHR BSR.S OUTCH ;output digits
.IF USERINT = 0
ADDQ #1,D5 ;bump to next char row
.ELSE
ADD #CHRSPC,D5 ;bump to next char row
.ENDC
MOVEQ #1,D6 ;and do CR
RTS
.PAGE
;-------------------------------------------------------------------------
; Subroutines to enable display of hex codes
; Requires D0 = value to display
; D1 = # of digits to display
;-------------------------------------------------------------------------
OUTCH MOVEM.L D0-D2,-(SP) ;save regs
MOVEQ #8,D2 ;set max digits to display
@1 CMP.B D1,D2 ;check digits desired
BEQ.S @2 ;and skip if match
ROL.L #4,D0 ;else skip over digit
SUBQ #1,D2 ;update count
BRA.S @1 ;and loop until match
@2 ROL.L #4,D0 ;rotate to next digit
BSR.S OUTNIB ;go output one digit
SUBQ #1,D1 ;decr count
BNE.S @2 ;loop until done
MOVEM.L (SP)+,D0-D2 ;restore and exit
RTS
; The following routine does conversion to ASCII to enable display
OUTNIB MOVE.L D0,-(SP) ;SAVE REG
ANDI #$000F,D0 ;ISOLATE DIGIT TO DISPLAY
CMPI.B #9,D0 ;CHECK IF NUMERIC
BHI.S ALPHA ;SKIP IF NOT
ORI.B #$30,D0 ;CONVERT TO ASCII
BRA.S DSPCH ;AND GO DISPLAY
ALPHA SUBI.B #9,D0 ;CONVERT FOR
ORI.B #$40,D0 ; ASCII
DSPCH BSR DSPVAL ;OUTPUT IT
MOVE.L (SP)+,D0 ;RESTORE REG
RTS
.PAGE
;-------------------------------------------------------------------------
; Routine to notify user of non-fatal error. Beep speaker and pause
; for 5 seconds.
;-------------------------------------------------------------------------
NOTIFY
.IF ROM16K = 1
BSR.S HIPTCH ;beep at high pitch twice
BSR.S HIPTCH
BSR.S LOPTCH ;beep at low pitch
BSR DELAY5 ;delay 5 seconds
BSR CLRDESK ;clear desktop CHG033
BRA.S DOBOOT ;then go attempt boot
;-------------------------------------------------------------------------
; Subroutine to beep speaker at high pitch
;-------------------------------------------------------------------------
HIPTCH MOVEQ #$20,D0 ; set frequency
BRA.S SETDUR ; and go do it
;-------------------------------------------------------------------------
; Subroutine to beep speaker at low pitch
;-------------------------------------------------------------------------
LOPTCH MOVEQ #$60,D0 ; set frequency
SETDUR MOVE #250,D1 ; 1/8 sec duration
MOVEQ #4,D2 ; low volume
BSR TONE ; and go do it
BSR DELAY_1 ; delay for .1 sec
RTS
.ENDC
.PAGE
;-------------------------------------------------------------------------
; No errors detected - output greeting message
;-------------------------------------------------------------------------
SYSOK CLR.L STATUS ;set status
.IF ROM16K = 1
; BSR CHKSTATPM ;check special save area CHG034
; BCC.S DOBOOT ;skip if valid data saved
; CLR.B STATSAV ;else set status to 0
.ENDC
.IF ROM4K = 0
.IF USERINT = 0
LEA INITMSG,A3 ;set ptr to OK msg
BSR DSPMSGR ; and display
NOTOK BSR.S DSPROMS ;display ROM versions
BRA.S DOBOOT ;and go do boot
.ENDC ;{USERINT}
.ENDC ;{ROM4K}
.IF ROM4K = 0
.IF USERINT = 0
;-------------------------------------------------------------------------
; Subroutine to display ROM version #'s
;-------------------------------------------------------------------------
DSPROMS LEA CROMMSG,A3 ;display CPU ROM version #
BSR DSPMSGR
LEA IORMMSG,A3 ;display IO ROM msg
BSR DSPMSG
MOVE.B DISKROM,D0 ;read ROM #
MOVEQ #2,D1
BSR OUTCHR ;and display it
RTS
.ENDC ;{USERINT}
.ENDC ;{ROM4K}