.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}