; ; File: USTTestMgr.a ; ; Contains: This file includes the Test Manager routines. ; ; Written by: Dave Holzer, Gary Rensberger ; Unmercifully ; Mutated by: Every new CPU we do ; ; Copyright: © 1983-1990, 1992-1993 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; 12/13/93 PN Roll in KAOs and Horror changes to support Malcom and AJ ; machines. ; 6/14/93 kc Roll in Ludwig. ; 4/14/93 fau Changed the baud rate for the TestManager communication from ; 9600 to 19200. ; 3/7/93 fau While storing results into PRAM, made sure that the whole ; register is cleared, even though only 1 byte is used. WrXByte ; for Cyclone had a problem with this not being so. ; 3/6/93 fau Made sure that when running the memory test (cmd9) all access ; are non-cacheable and serialized. If not, writes to CUDA would ; not occur. ; 01/07/93 HY Fix problem with XX test and all ROM based tests. The offset ; into the TestTable was off by 4 because 4 tests had been removed. ; TJR In MMUOff (*3 STM command) the data cache needed to be ; turned off because without the MMU the I/O area was being ; cached and this caused data to be read from the cache and ; not the physical device. Only the 68030 case was fixed. ; 12/22/92 HY Fix a problem with serial test manager. ; 11/16/92 fau When storing results to PRAM, I made sure that a CudaInit is ; done for CUDA machines, in order to set Cuda so it can respond ; to Rd/WrXByte. This is because the CudaManager has gone away ; (since we tested all the memory). ; 11/3/92 rab Roll in Horror changes. Comments follow: ; 8/3/92 AL Fixed the TestManager cmd4 access to critical tests. ; 7/27/92 BG Fix SetupBases to not use A3 to save A6. ; 7/20/92 AL Fixed the TestManager cmd8 access to non-critical tests, fixed ; some comments. ; 7/1/92 AL Fixed the Serial Test Manager *N and *T commands, and the ; TestManager cmd4 and cmd6 functions, which were affected by ; moving this file to USTStartTest1.a (see comments at
. ; 6/17/92 AL Added identifiers for a bunch of new machines to the table used ; by STM to fill out the *5 command. Updated the descriptions of a ; couple of existing entries in that table. ; 6/9/92 AL Changed StoreResults to preserve the return address in USP ; rather than A0 because the PG&E version of WrXByte trashes A0. ; 6/7/92 AL Fixed a couple of references to table-based data from longs to ; words (because the data is word length). Added DartanianLC to ; the table of machine identifiers used by STM. Removed a couple ; of unnecessary lines of code. Enhanced the NJump table to allow ; access to the SONIC tests for STM. Added some comments to ; existing code. Fixed the TestManager ATrap access mechanism for ; the TJump table because of problems that arose when this file ; was moved to a different link area (see comments under H6). ; 9/25/92 RB Changed a few BSR6 macros to jumps. ; 9/24/92 WS The jump table for the diagnostic test had been changed to use ; long jumps but the offset in the calling rountines still uses ; word offsets. Fixed this - actually borrow fix from horror. ; 8/19/92 CSS Update from Reality: ; <43> 8/18/92 DTY Change the name of BootGlobs to StartGlobals to avoid confusion ; with BootGlobals, which is used by the boot code in Boot[1-3].a. ; 5/16/92 kc Roll in Horror Changes. ;
3/6/92 AL Added support for the new CTE v2.1 kernel. Added a "new" ; TestManager routine at the end that takes care of handling CTE ; stuff for anybody that wants it to. After the conditionalized ; PROC mods made by jmp, it was discovered that the original ; USTStartTest.a had outgrown its allocated space in the ROM. So, ; I had to create a new file, USTSTartTest1.a, and moved this file ; and USTEnvirons.a into it. Added in support to access the new ; DBLite noncritical tests (PG&E Selftest and GSC registers test). ; Moved the PRAM routines RdXByte, WrXByte and ClkWpOff over to ; the file USTPram.a where they will be within BSR6 range of all ; the references to them from USTStartTest.a. There are a few ; references to them from USTStartTest1.a, but they can be ; converted to BigBSR6,a0 accesses. ;
01/27/92 jmp Conditionalized the PROC parts of this file for use in lining up ; the UST part of HORROR with that of TERROR/Zydeco. ;

11/25/91 CCH Use standard VIA equates. ;

11/6/91 SWC Universalized the RAM-less Power Manager routines. Modified the ; PRAM routines to call hardware-specific code thru a new table ; entry in the ProductInfo table. The hardware-dependent code is ; now in ClockPRAMPrimitives.a Removed SendToClk, ReadFrClk since ; they're no longer used. ;

10/23/91 jmp Updating from the Zydeco-TERROR project. ; <6> 4/22/91 BG Rolled in Scott Smyers changes: Fixed Atrap invoked RAM tests ; for Orwell machines. Also improved error reporting for ROM based ; RAM tests. ; <5> 4/13/91 BG Rolled in Scott Smyer's changes: Removed the diagROMEntry code ; and moved it to USTEnvirons.a. Added the 53C96 register test to ; the NJUMP table, along with some stubs for tests which are in ; the Apollo ROMs, but not Terror (these are placeholders to keep ; the test numbers consistent between all machines). Added the ; "get name" selector to the _TestManager Atrap. ; <4> 1/14/91 CCH Rolled in Scott Smyer's changes. ; <3> 12/14/90 HJR Added hook for CTE to serial test manager. ; <2> 9/17/90 CCH Modified data cache disable code to be 68040-friendly. ; ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ ; Pre-Terror ROM comments begin here. ; ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ ; <12> 6/14/90 CV Fixed cmd8 to use a1 and a0 so they're set up for the run time ; checks in RBV test and Egret test. ; <11> 5/31/90 BA Rolling in changes from Reality. Original comments below. ; {25} 5/30/90 SS Enhanced the version command so that it also returns the ROM ; version number, release number and machine number. ; {24} 5/30/90 SS Changed the restart command ('*I') so that it jumps to the ; restart vector, instead of just jumping to the start tests. The ; old way was causing problems on Egret based machines. ; {23} 5/21/90 SS Added a version command (*V) which returns the current version ; of the serial test manager to the serial port. Ericson/Elsie ; STM will be version 2.0; previous revisions do not support the ; version command and will respond with a ? indicating pre-2.0. ; <10> 5/16/90 JJ Rolling in changes from Reality. ; {22} 5/16/90 SS Changed some register usage at cmd4, 5, 6 and 9 initialization ; to be compatible with critical tests that test memory. ; {21} 5/7/90 SS Fixed the cmd9 RAM test so that if it's on an Elsie it uses the ; ElsieTMVectors and does not attempt to turn off the MMU. ; {20} 5/2/90 SS Fixed the *3 command so that it doesn't use RAM and so that it ; checks if it's on an 030 machine before playing with the MMU. ; <9> 4/27/90 CV Rolling in changes from mainproj. Original comments below. ; {19} 4/26/90 SS Don't set up TMvectors in RAM except when you come in through ; TMRestart - otherwise, it may be a memory failure that you're in ; the test manager! Also, restore the stack after running a ; critical test. Any failure of SizeMemory destroys a7! ; {18} 4/23/90 SS Replaced critical test 0 with sizememory again. This is ; required by some service software. Made the moving inversions ; test critical test #7 (was the new #0). Removed the new test ; *Q, which was the new size memory test. ; {17} 4/20/90 SS Changed the PRAM interface routines by removing some extra waits ; and also changed them to use equates from the EgretEqu.a file, ; as per suggestions which came up in the code review of 4/16/90. ; {16} 4/19/90 SS Fixed up some register usage and some inconsistancies in how the ; exception vectors were initialized on noncritical tests and on ; entry to the test manager. Also added support for the Elsie ; test manager vector table for critical tests. ; <8> 4/10/90 JJ Rolling in changes from mainproj. Original comments below. ; {15} 4/6/90 rle update service id boot string to include new machines (CPUs/LWs) ; {14} 4/3/90 SS Following the memory tests in cmd9 I now load the warm start ; constant into RAM where expected so that the non-critical tests ; are not run at startup. Before, any failure in the NC tests ; would obliterate some of the memory test results. Also cleaned ; some things up in cmd9 results reporting area to make things ; less ambiguous (word vs long register operations were being used ; interchangeably). ; {13} 3/27/90 SS Added a timeout for waiting for the first IRQ on the packet type ; byte of the PRAM read and write egret transactions. Also ; conditionalized the calls to TM_WAIT in storeresults, the delay ; is only necessary when talking to an Egret when you don't know ; if you've banged on the VIA recently. ; <7> 3/27/90 CV Fixed bug in RdxByte and WrxByte to prevent system from hanging ; in the middle of a transaction. ; <6> 3/27/90 CV Rolling in changes from mainproj. Original comments below. ; {12} 3/23/90 SS Made some additional adjustments to RDXBYTE and WRXBYTE to look ; for the case where the Egret has a pending operation at the ; start of a PRAM access. Also added new machines to the machine ; code table which the Test Manager uses to display a unique ASCII ; character for each mac. ; {11} 3/20/90 SS Cleaned up the Egret communication transactions in RDXBYTE and ; WRXBYTE. ; {10} 3/19/90 SS In RDXBYTE and WRXBYTE, I removed the delay that I used to have ; between sampling XcvrSession and sending the packet type. The ; packet type needs to go out in <25΅S! ; <5> 3/12/90 CV Rolling in changes from mainproj. Original comments below. ; {9} 3/9/90 SS Fixed up the way I get VIA1 address from the product info ; record. Also fixed a register conflict in StoreResults. ; <4> 3/2/90 CV Replacing existing file with file from mainproj. ; <8> 2/27/90 SS Changed my PRAM interface support routine names to be specific ; to the test manager (previous names conflicted outside when I ; exported them). Also added the RPU, Egret and sound interrupt ; tests to the serial test manager test table. ; <7> 2/16/90 SS Added a flag to all statements which changed to support Ericson. ; <6> 2/15/90 SS Conditionalized the Egret PRAM interface routines properly. ; Also restored registers following sizemem for the serial test ; manager. ; <5> 2/13/90 MA Conditionalized the Egret based PRAM read/write code with ; onMac32. ; <4> 2/12/90 MA Changed crit. test table so that sizemem is replaced by the ; moving inversions RAM test. SizeMem is now Test Manager command ; *Q. USP now holds ptr to prodInfo table. Used to hold ptr to ; viaBase. Save/Restore A1/A2 between calls to tests. Changed ; RDXByte and WRXByte to work w/ EGRET. ; <2> 1/3/90 SES Changes made for Mark Appleman. Added FMCCacheTest to NJump ; table. Removed OSSCntrTest from NJump table. ; <2.9> 11/22/89 rle needed for ZoneV: move exception table into ROM for memory tests ; run ; <2.8> 11/21/89 MSH Power turn on turned on too much. Changed 2 haspowermgr to ; onhcmac, better feature based conditional descriptions. ; <2.7> 11/13/89 rle fixed one small bug when checking number of banks in cmd9 ; <2.6> 11/13/89 SES Added diagnostics for FMC shift register, OSS registers, counter ; and interrupt. ; <2.5> 11/11/89 rle needed for ZoneV: fixed bugs inadvertantly introduced when ; rewriting STTestMgr--various fixes to serial test manager to ; keep interface the same as on previous CPUs, fixed trap test ; cmd9 to properly test memory, calling SizeMemory when the chunk ; table is blown away ; <2.4> 11/9/89 GMR Disabled cache before calling SizeMem in cmd9, so size memory ; properly sizes. Eliminated problem of memory test wiping out ; chunk table in cmd9 when doing more then 1 pass. ; <2.3> 11/1/89 GMR NEEDED FOR ZONE5: Setup a2 with VIA1 base before calling ; StoreResults, used by the TestManager trap. It previously used ; the VIA lowmem, which could be blown away during a RAM test. ; <2.2> 10/16/89 rle changed Aurora16 bootstring identifier to "A" so that it doesn't ; conflict with other identifiers previously assigned ; <2.1> 10/9/89 GMR Fixed conditional around cmd9 to fix Emacs build. ; <2.0> 10/7/89 GMR NEEDED FOR ZONE5: Cleaned up test manager trap interface, to ; make it universal, and not call GetHardwareInfo. Changed SizeMem ; glue routine to set d7.b = $FF if d6 contains error bitmask, ; otherwise, d7.b = 0 if d6 pts to memory chunk table. ; <1.9> 8/22/89 GMR Removed runtime machine check on entering Test Manager. ; <1.8> 7/15/89 GMR Setup exception table in RAM at start of test manager, so ; non-critical tests won't need to. Save universal registers ; around non-critical test calls (*N). ; <1.7> 6/26/89 GMR Added stub sizemem routine which returns pointer to chunk table ; in d6. Made U_TMRestart decide which test manager to call ; (Fremont's or universal) ; <1.6> 6/16/89 GGD Fixed echoing bug in the 'L' command. ; <1.5> 6/14/89 GMR Changed the timed system message to output proper code for ; system we're running on. ; <1.4> 6/13/89 GMR Added Gary D's fast Mod3Test and a shorter RomTest, in new file ; USTCritTests.a ; <1.3> 6/13/89 GGD Modified to work with latest version of Beep.a, leave cache on, ; pass VIA1 base to Beep calls in A5. ; <1.2> 6/11/89 GMR Fixed lea VBase to make universal in StoreResults. ; <1.1> 6/11/89 GMR Removed INCLUDES, now in header file which includes all others. ; <1.0> 6/11/89 GMR Added new universal StartTest files for first time to EASE. ; Based on Fremonts file 'TestMgr.a' version <2.0>. ;------------------------------------------------------------------------------ TMProc PROC ; EXPORT SetVectorTable ; <2.1> EXPORT SetupBases EXPORT TestManager EXPORT TMEntry1 EXPORT TMRestart EXPORT StartTimer EXPORT GetChar EXPORT CvtAscii EXPORT OutChar EXPORT TJump ; IMPORT USTPmgrTurnOn IMPORT USTPmgrSendCommand ;

IMPORT USTPMGRSendByte ;

IMPORT USTPMGRRecvByte ;

EXPORT TM_SendByte ;<8> EXPORT TM_GetByte ;<8> EXPORT TM_Wait ;<8> IMPORT StartTest1 IMPORT JGetHardwareInfo IMPORT StartTestFlags IMPORT SizeMemory IMPORT Mod3Test IMPORT RevMod3Test IMPORT RomTest IMPORT DataBusTest IMPORT AddrLineTest IMPORT ExtRAMTest IMPORT MovInvTest ;<7> IMPORT SizeV8VRAM ;<35> IMPORT NoTest IMPORT SCCRegTest IMPORT SCCLoopTest IMPORT SCCTimerTest IMPORT VIATest IMPORT TestSCSI IMPORT TestASC IMPORT PramTest IMPORT TestRBV IMPORT TestSWIM IMPORT Float_Test IMPORT TestPGC IMPORT FMCRegTest ;<2.6> IMPORT FMCCacheTest ;<2> IMPORT OSSRegTest ;<2.6> IMPORT OSSIntTest ;<2.6> IMPORT RPUTest ;<8> IMPORT USTTests IMPORT TMVectors ; IMPORT ElsieTMVectors ; <16> IMPORT SetSCCIOPBypass ; IMPORT ErrorBeep4 ; IMPORT EgretTest ;<8> IMPORT TestSndInts ;<8> IMPORT TestCLUT ;<27> IMPORT TestVRAM ;<28> IMPORT TestC96 ; IMPORT TestGSCRegs IMPORT PGESelfTest IMPORT TestCSCRegs IMPORT UTECmd ;<36> IMPORT BaseOfRom IMPORT CLKWPOFF,WRXBYTE,USTSUBTESTS,USTCPUList CASE ON IMPORT GI_InitInterface IMPORT GI_GetVersion IMPORT GI_AllocPermMem IMPORT GI_AllocTempMem IMPORT GI_FreeTempMem IMPORT GI_GetCommentary IMPORT GI_GetDefaultExecutionOptions IMPORT GI_ExecuteDTM IMPORT SONIC_Test ;SONIC Ethernet chip test IMPORT SONIC_BitMarch ;SONIC Ethernet register bitmarch subtest IMPORT SONIC_CAMDMA ;SONIC Ethernet on chip DMA subtest IMPORT SONIC_Loopback ;SONIC Ethernet loopback subtest CASE OFF nuBusTTxlat EQU $00FFC040 ; require serialized writes fau ioNuBusTTxlat EQU $00FFC040 ; for all I/O space fau ;))) [C660/22Jan87>[C703/30Jan87> DAH EJECT ;--------------------------------------------------------------------------- ; This is the Trap entry to the Test Manager. It is entered by a trap ; call _TestManager. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; On entry, D0 = the requested TestManager routine code, as follows: ; ; Any TestManager call that has a code less than $xxx10000 is ; considered to be an "old" style TestManager call. Anything with ; a code of $xxx10000 or greater is a "new" style call. A "new" style ; call will utilize CTE v2.1 (or greater) to execute DTMs. The user ; is free to mix and match, since there are no overlapping functions ; between the "old" and "new" TestManager functions. Here are the ; "new" TestManager codes and their corresponding functions: ; ; CTE routines accessible by the "new" TestManager: ; $xxx10000 GI_InitInterface ; $xxx10001 GI_GetVersion ; $xxx10002 GI_AllocPermMem ; $xxx10003 GI_AllocTempMem ; $xxx10004 GI_FreeTempMem ; $xxx10005 GI_GetCommentary ; $xxx10006 GI_GetDefaultExecutionOptions ; $xxx10007 GI_ExecuteDTM ; ; Utility routines accessible by the "new" TestManager: ; $xxx20000 Initialize the CTE interface for use with the TestManager ; $xxx20001 Get the info for a ROM-based test and subtest ; ; On entry to this routine, the first thing to do is check for ; "old" vs. "new". If it's new, then jump down to the new TM entry ; point. Otherwise, stay here and do the old stuff. ; ; ; These are the "old" TM codes (still supported, of course): ; ; $xxxx0000 for normal canned test request ; $xxxx0001 for RTS immediately, interrupts ON ; $xxxx0002 for RTS immediately, interrupts OFF ; $xxxx0003 for setup and jump to Test Manager ; $xxxx0004 for registers already prepped for test ; $xxxx0005 for like #0 but test number is a bit mask ; $xxxx0006 for like #4 but test number is a bit mask ; $xxxx0007 for PMgr systems only like #5 [v1.2> ; $xxxx0008 index is to non-critical tests (not a bit mask) ; $xxxx0009 for canned memory testing of discontiguous memory ; ; A0 = Pointer to Canned Test Request Block (CTRB) ; ; CTRB = Record ; Ops: integer; {test options} ; NumPass: integer; {test number/passes to run} ; RAMLow: Ptr; {RAM low address} ; RAMHigh: Ptr; {RAM high address} ; result: longint; {test result} ; mask: integer; {mask of tests to run} ; End; ; ; Options word = ; Bit 12 = stop on first failure and exit ; Bit 13 = loop on any failure forever ; Bit 14 = store test results clock parameter RAM ; Bit 15 = boot when done testing ; ; Test bit #15 (test 7) is used to force the test count through one more loop ; of all tests. Kinda hokey but there seems to be a register shortage in this ; here machine. ; ; If the boot when done testing bit is not set, then return is via an RTS ; after restoring all registers. ; ; If the boot when done testing bit is set, then no direct return is done, ; but the system is rebooted. ; ; For commands #4 and #6, registers are assumed to be correctly set up ; on entry for the test(s) to run. The required registers may depend on the ; test(s) to be executed, but generally the following is true: ; ; a0 = pointer to low memory address for RAM test ; a1 = pointer to high memory address for RAM test ; d7 = options set up according to the bits defined in this file ; and test/pass count in d7.w ; d6 = 0, prepped for error codes ; ; For commands #5 and #6, the test number is assumed to be a bit mask of ; the tests to run consecutively. This option is for queuing up RAM tests. ; The command #5 is like command #0 and #6 is like #4 in the method ; used to set up the registers. ; ;--------------------------------------------------------------------------- CTEAtrap equ $10000 ; a value in d0 greater than or equal to this ; indicates that this is a "new" style TM call TestManager cmp.l #CTEAtrap,d0 ; all function calls LOWER than this bge.l NewTMCall ; call the old test manager, if appropriate movem.l d1-d5/a0-a6,-(sp) ; save regs (except d6,d7) move.w sr,-(sp) ; save current SR or.w #HiIntMask,sr ; disable all ints but NMI for all cpu's movec VBR,a2 ; get old VBR move.l a2,-(sp) ; save it suba.l #VTEntries*4,sp ; put VBR below stack move.l d0,d3 ; save d0 movea.l a0,a3 ; save a0 movea.l a1,a4 ; save a1 movea.l sp,a1 ; put VBR at current stack BSR6 SetVectorTable ; Setup our exception table in RAM (a2=VBR) move.l d3,d0 ; restore d0 movea.l a3,a0 ; restore a0 movea.l a4,a1 ; restore a1 lea TestMgrCmds,a2 ; point to the command dispatch table cmp.w (a2)+,d0 ; range check the command number bhs.s TestMgrExit ; if out of range, just return add.w d0,d0 ; command*2 to index into table adda.w 0(a2,d0.w),a2 ; point to the routine jmp (a2) ; execute the command ;_________________________________________________________________________________ TestMgrExit ; done with trap, exit back to caller adda.l #VTEntries*4,sp ; dump vector table movea.l (sp)+,a2 ; get saved VBR movec a2,VBR ; restore it move.w (sp)+,sr ; restore SR movem.l (sp)+,d1-d5/a0-a6 ; restore registers we trashed rts ;_________________________________________________________________________________ TestMgrCmds dc.w (@End-@Start)/2 ; number of table entries @Start dc.w cmd0 -@Start ; Command #0, normal canned test request dc.w cmd1 -@Start ; Command #1, RTS immediately, ints ON dc.w cmd2 -@Start ; Command #2, RTS immediately, ints OFF dc.w TMEntry0-@Start ; Command #3, setup and jump to Test Manager dc.w cmd4 -@Start ; Command #4, registers already prepped for test dc.w cmd5 -@Start ; Command #5, like #0 but test number is a bit mask dc.w cmd6 -@Start ; Command #6, like #4 but test number is a bit mask IF hasPowerMgr THEN ;if on portable dc.w cmd7 -@Start ; Command #7, for PMgr systems only like #5 ELSE dc.w TestMgrExit-@Start ; Command #7, unused on this system ENDIF dc.w cmd8-@Start ; Command #8, index is to non-critical tests (not a bit mask) dc.w cmd9-@Start ; Command #9, complete RAM test, reboot on exit dc.w TestName-@Start ;Command #10, return a test name dc.w NubMgrDispatch-@Start ; Command #11, dispatch to the nub manager <32> @End ;_________________________________________________________________________________ cmd2 ori.w #HiIntMask,(VTEntries+1)*4(sp) ; disable interrupts in saved SR cmd1 bra.s TestMgrExit ; restore state and return ;_________________________________________________________________________________ ; Process command #0, execute a canned test request cmd0 clr.l d6 ;clear error register move.l Ops(a0),d7 ;load test options/test/passes move.l RAMHigh(a0),a1 ;point to RAM high if RAM test move.l RAMLow(a0),a0 ;point to RAM low if RAM test ;_________________________________________________________________________________ ; Now d7 has the options bits, the test number, and the passes to run ; Entry to this point either from above or a command #4 cmd4 move.w d7,d1 ;get test number lsr.w #8,d1 ;isolate test number ; cmp.w MaxTest,d1 ;is legal test request? and.l #$0000ffff,d1 ;mask off everything except test number cmp.l MaxTest,d1 ;is legal test request? bge.s TestMgrExit ;not legal, exit to caller movea.l UnivInfoPtr,a2 ;Get the Universal info pointer <22> move.l a2,USP ;Put it in the User Stack Pointer <22> ; add.w d1,d1 ;adjust for table access ; lea TJump,a5 ;point to test jump table ; adda.w 0(a5,d1.w),a5 ;point to test lsl.l #2,d1 ;adjust for longword table access lea TJump,a5 ;point to test jump table move.l (a5,d1.l),d1 ;fetch test offset from table lea (a5,d1.l),a5 ;point to test @loop lea @1,a6 ; setup return address rb jmp (a5) ;execute requested test rb @1 ; rb tst.l d6 ;any errors this test? beq.s @noErr ;no, continue btst #loop,d7 ;Error, wants to loop? bne.s TestLoop ;yes btst #stop,d7 ;want stop on error? bne.s StopTest ;yes @noErr subq.b #1,d7 ;decrement passes to run bne.s @loop ;not done testing StopTest btst #pram,d7 ;wants to store results in clock? beq.s @noStore ;no move.l USP,a1 ;Get UnivInfoPtr <7> movea.l ProductInfo.DecoderInfoPtr(a1),a2 ; <7> adda.l a1,a2 ;Add base to get target address <9> movea.l DecoderInfo.VIA1Addr(a2),a2 ;Get VIA1 base <7> BSR6 StoreResults @noStore btst #boot,d7 ;wants to boot when done? beq.s TestMgrExit ;no, just RTS as normal BigJmp BaseOfRom+ROMHeader.ReStart,a0 ; address of restart routine [v1.3> <1.4> TestLoop lea TestLoop,a6 jmp (a5) ;execute test forever... ;_________________________________________________________________________________ ; Process command #5, test number is a bit mask cmd5 clr.l d6 ;clear error register move.l Ops(a0),d7 ;load test options/testmask/passes move.l RAMHigh(a0),a1 ;point to RAM high if RAM test move.l RAMLow(a0),a0 ;point to RAM low if RAM test ;_________________________________________________________________________________ ; Now d7 has the options bits, the test number bit mask, and the passes ; to run. Entry to this point either from above or a command #6 cmd6 moveq.l #0+8-1,d1 ; d1 is bit number (test number + 8) in the ; test bit field of d7. It is the test number ; + 8 because the test bit field is in the ; second byte of d7 (bits 8 - 15), so we need ; to add 8 to the bit number. movea.l UnivInfoPtr,a2 ; get the universal info pointer <22> move.l a2,USP ; save it for PRAM routines <22> @next addq.l #1,d1 ; next test number cmpi.w #15,d1 ; see if all tests run bgt.s @cntPass ; exit if so btst.l d1,d7 ; do we want to run this test beq.s @next ; if not, try next one ; add.w d1,d1 ;adjust for table access (test num + 8)*2 ; lea TJump,a5 ;point to test jump table ; adda.w -16(a5,d1.w),a5 ;point to test ; add.w d1,d1 ; adjust for table indexing (test num + 8)*4 ; lea @return-32(d1.w),a6 ; setup return address ; jmp (a5) ;execute requested test lsl.l #2,d1 ; adjust for long word table access (test num + 8)*4 lea TJump,a5 ; point to test jump table adda.l -32(a5,d1.l),a5 ; point to test (remember to subtract out the " + 8 * 4" ; included in the lsl.l above) lea @return-32(d1.l),a6 ; setup return address jmp (a5) ; execute requested test @return moveq.l #0+8,d1 ; return from test number 0, bit 8 bra.s @checkErrors ; check for errors moveq.l #1+8,d1 ; return from test number 1, bit 9 bra.s @checkErrors ; check for errors moveq.l #2+8,d1 ; return from test number 2, bit 10 bra.s @checkErrors ; check for errors moveq.l #3+8,d1 ; return from test number 3, bit 11 bra.s @checkErrors ; check for errors moveq.l #4+8,d1 ; return from test number 4, bit 12 bra.s @checkErrors ; check for errors moveq.l #5+8,d1 ; return from test number 5, bit 13 bra.s @checkErrors ; check for errors moveq.l #6+8,d1 ; return from test number 6, bit 14 bra.s @checkErrors ; check for errors moveq.l #7+8,d1 ; return from test number 7, bit 15 * bra.s @checkErrors ; check for errors @checkErrors tst.l d6 ;any errors on last test? beq.s @next ;no, go to next test ; Error encountered, check for loop and stop on error options btst #loop,d7 ;wants loop on error? bne.s TestLoop ;yes btst #stop,d7 ;want stop on error? bne.s StopTest ;yes ; One pass through all tests requested done, any errors processed @cntPass subq.b #1,d7 ;decrement passes to run bne.s cmd6 ;not done testing bclr #15,d7 ;see if doubling the pass count bne.s cmd6 ;force another pass through bra.w StopTest ;done testing ; ))) [C129/16Sep86> DAH ;))) russ ;--------------------------------------------------------------------------- ; ; Test Manager Command 8: This is the method used to access the non-critical ; tests through the NJump test table. Since there are more than 8 (and are ; likely to be more than 16) tests available here, they are only available one ; at a time--a bit mask is not used. The upper word of d7 is still reserved for ; various flag bits, such as stop on error or loop on error. (These are the only ; two flags supported within this command.) The upper byte of the lower word ; of d7 is a numerical index into the NJump test table, while the lower byte ; is the number of passes. Note that this structure allows for 128 tests which ; can run for up to 256 passes one at a time. ; <7> ; On entry: <7> ; a0 = pointer to the CTRB. <7> ; ;--------------------------------------------------------------------------- cmd8 clr.l d6 ;clear error register move.l Ops(a0),d7 ;load test options/testmask/passes <7> @loop move.l d7,d1 ;move working copy of testmask lsr.w #8,d1 ;shift mask into byte position sub.w #$84,d1 ;subtract out non-crit offset ; cmp.w MaxNTst,d1 ;is valid test number? and.l #$0000ffff,d1 ;mask off all but the test number cmp.l MaxNTst,d1 ;is valid test number? bge.s @exit ;invalid, exit to caller ; add.w d1,d1 ;adjust for table index ; lea NJump,a5 ;point to test jump table ; adda.w 0(a5,d1.w),a5 ;point to test asl.l #2,d1 ;adjust for table index lea NJump,a5 ;point to test jump table move.l (a5,d1.l),d1 ;fetch test offset from table lea (a5,d1.l),a5 ;point to test @test movea.l UnivInfoPtr,a1 ;get lowmem UnivInfoPtr. <26><7> movea.l a1,a0 ;get univinfoptr into a0 also <26> adda.l ProductInfo.DecoderInfoPtr(a0),a0 ; ptr to base addresses <26> move.l AddrMapFlags,d0 ;base addr valid bit mask <7> move.w ProductInfo.ProductKind(a1),d2 ; get the BoxFlag value <26><5.8><7> lea @1,a6 ; setup return address rb jmp (a5) ;execute requested test rb @1 ; rb tst.l d6 ;any errors last test? beq.s @cntPass ;no, count a pass.... btst #loop,d7 ;error, wants to loop ? bne.s @test ;yes, test again btst #stop,d7 ;want stop on error? bne.s @exit ;yes @cntPass subq.b #1,d7 ;decrement passes to run bne.s @loop ;not done testing @exit bra.w TestMgrExit ; restore state and return ;--------------------------------------------------------------------------- ; ; Test Manager Command 9: This is the method used to test memory on systems ; with discontiguous memory. Currently, this means MDU-based machines (Aurora ; and Four Square) and early versions of F-19. The process is as follows: ; SizeMem is called to establish the location of the first bank of memory. ; That bank is then tested with mod3, revmod3, and extram tests. SizeMem is ; called again to establish the presence of any additional banks of ram, and if ; they exist, they are tested the same way. Low bank results (register d6) are ; stored in bytes 252-255 of parameter ram, while high bank results are placed ; in bytes 244-247. The system is rebooted upon exit. ; ;--------------------------------------------------------------------------- CAWA equ 13 ;CACR WA bit for 030 CPUs <20> cmd9 clr.l d6 ;clear error register <2.1> move.l Ops(a0),d7 ;load test options/passes ; <34> BigLea ElsieTMVectors,a3 ;First see if we are on an Elsie <21> BigLea StartTest1,a4 ;Get the address of the start vector <21> cmpa.l 4(a3),a4 ;Does this agree with where we are? <21> beq.s @onElsie ;Continue if so <21> BigLea TMVectors,a3 ;Otherwise, load the default TM vectors <21> @onElsie ; <21> movec a3,VBR ;VBR points to our exception table <21> movec cacr,d0 ;First lets make sure we're not on an 020 box <21> move.l d0,d1 ;Save the contents of the cacr register <21> ; ₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯ bset.l #15,d0 ; set the 040 CACR[DE] bit to see if on an 040> movec d0,CACR ; see if the 040 CACR[DE] bit sticks movec CACR,d0 ; btst.l #15,d0 ; are we on an 040? bne.s @onAn040 ; IF we're not on an 040 THEN bset.l #CAWA,d0 ; Set the Write allocate bit (020s don't have this) movec d0,cacr ; move it into the CACR <21> movec cacr,d0 ; read it back <21> movec d1,cacr ; restore the cacr <21> btst.l #CAWA,d0 ; See if we were able to set the WA bit <21> beq.s @not030 ; IF we're on a 68030 THEN lea -4(sp),sp ; make room on the stack <21> pmove.l TC,(sp) ; read logical address mode of MMU <21 move.l (sp),d0 ; Put the value in a data register <21> bclr.l #31,d0 ; Turn off MMU enable bit <21> move.l d0,(sp) ; move it back to memory <21> pmove.l (sp),TC ; Load it into the MMU register <21> lea 4(sp),sp ; pop off the space @not030 ; ELSE movec cacr,d0 ; get cache value bclr #8,d0 ; disable the data cache movec d0,cacr ; do it bra.s @begin ; and move on @onAn040 ; ELSE ; Revamped this routine a little. Made sure that the transparent translation registers fau ; make all i/o space non-cacheable and serialized. fau MACHINE MC68040 ; required for the below instructions cpusha bc ; make sure caches are invalidated fau sub.l d0,d0 ; clear d0 fau movec d0,CACR ; disable both instruction and data caches fau movec d0,TC ; make sure that the MMU is disabled fau move.l #nuBusTTxlat,D0 ; get value to translate upper nuBus space fau movec d0,DTT0 ; use serialized writes on this space fau movec d0,ITT0 ; use serialized writes on this space fau move.l #ioNuBusTTxlat,D0 ; get value to translate i/o and nuBus space fau movec d0,DTT1 ; use serialized writes on this space fau movec d0,ITT1 ; use serialized writes on this space MACHINE MC68030 ; return to previous MACHINE directive ; ENDIF @begin ; BigBSR6 SizeMemory,a0 ;Size memory and set up the stack <16> movea.l (sp),sp ;keep ptr to chunk table in sp movea.l sp,a4 ;and keep the working copy in a4 clr.l d6 ;clear out error register @testm movea.l (a4)+,a0 ;bottom of memory to be tested movea.l a0,a1 ;set up top of memory adda.l (a4)+,a1 ;top of memory to be tested next first bank BigBSR6 Mod3Test,a2 ;go launch Mod3Test tst.l d6 ;any errors on last test? bne @error ;yes, go process errors BigBSR6 RevMod3Test,a2 ;go launch RevMod3Test tst.l d6 ;any errors on last test? bne @error ;yes, go process errors BigBSR6 ExtRAMTest,a2 ;go launch ExtRAMTest tst.l d6 ;any errors on last test? bne @error ;yes, go process errors BigBSR6 SizeMemory,a0 ;Size memory and set up the stack <16> movea.l (sp),sp ;keep ptr to chunk table in sp clr.l d6 ;clear out error register cmpi.l #-1,(a4) ;does another bank exist? bne @testm ;yep, go do it!!! bra @pass ;one pass completed!!! ;--------------------------------------------------------------------------- ; Error encountered, check for loop and stop on error options ;--------------------------------------------------------------------------- @error btst #loop,d7 ;wants loop on error? beq.s @stp ;no @loop lea @loop,a6 ; jmp (a5) ;execute test forever... @stp btst #stop,d7 ;want stop on error? bne.w @done ;yes ; One pass through all tests done, any errors processed @pass subq.b #1,d7 ;decrement passes to run bne.w @begin ;not done testing bclr #15,d7 ;see if doubling the pass count bne.w @begin ;force another pass through ; We either exhausted the passes to run counter or stopping on an error @done btst #pram,d7 ;wants to store results in clock? beq.s @boot ;no moveq.l #0,d2 ;Assume nothing about this machine <34> BigBSR6 JGetHardwareInfo,a0 ; <35> movea.l DecoderInfo.VIA1Addr(a0),a2 ;Get VIA1 base <34><2.3><3.1><7> suba.l sp,a4 ;get the offset into the chunk table move.l a4,d2 ;we need to work in this value lsl.w #5,d2 ;effectively shift right by 3 and left by 8 (bank # in high byte) swap d7 ;get high word of d7 move.w d2,d7 ;replace it with the bank number swap d7 ;and put it back in the high word BSR6 StoreResults ; @boot move.l #WmStConst,StartGlobals.sgWarmStart(sp) ; CSS make this a warm start to preserve PRAM <14> BigJmp BaseOfRom+ROMHeader.ReStart,a0 ;jump to restart routine <2.2> ;--------------------------------------------------------------------------- ; This routine stores the test results in the clock parameter RAM. This ; RAM has a total of 256 bytes, of which the last 16 bytes belong to ; Test Engineering. The current usage is as follows: ; ; bytes 240-243 = results from register D7 ; bytes 244-247 = results from register D6 ; bytes 248-249 = $4448 = results from MacPP, $5448 = results from NuMac ; bytes 250-251 = check sum word validating what is in 240-247 ; bytes 252-255 = used by RAM based tests. ; ; Entry via BSR6 ; ; Registers used: d0,d1,d2,d3,d4,a0,a1,a2,a4,a6 ;--------------------------------------------------------------------------- IMPORT CudaInit StoreResults move.l a6,USP ;save return address <9> ; CudaInit implies a SyncAck cycle which synchronizes Cuda to the system and disables ; all asynchronous messages sources (Auto Poll, RTC, Power Messages, Unknown). No further ; individual disabling of asynchronous message sources is required. (R. Montagne 5/25/92) ; ; d0 should contain the Flags indicated which base addresses are valid, from HardwareInfo move.l d0,d3 ; save a copy of d0 move.l #EgretFWMask,d0 ; mask for Egret Firmware and.l d1,d0 ; isolate the field sub.l #Egret8,d0 ; see if we have Egret FW beq.w @CudaDone ; do Egret 8 or Caboose FW INIT, LC/si sub.l #Egret8,d0 ; see if we have Caboose FW beq.s @CudaDone ; do Caboose FW Init (same as Egret8) sub.l #Egret8,d0 ; see if we have Cuda FW bne.s @CudaDone ; if not, just exit BigBSR6 CudaInit ;Setup Cuda Sysnc Ack with System @CudaDone BigBSR6 ClkWpOff,a4 ;turn write protect off clock chip clr.l d4 ;clear for checksum move.l #240,d3 ;start at byte 240 @loop1 clr.l d1 ;Make sure that the registers we pass to the WrXByte fau clr.l d2 ;are clear on the upper bytes. It needs them like so fau rol.l #8,d7 ;align msb to send first move.b d7,d2 ;get data byte to send move.b d3,d1 ;get address byte to send BSR6 TM_WAIT ;Delay a min of 300΅s before writing <13> BSR6 TM_WAIT ;to PRAM <13> BigBSR6 WrXByte,a4 addq.w #1,d3 ;bump to next byte cmp.w #244,d3 ;done with d7? blt.s @loop1 ;no @loop2 rol.l #8,d6 ;align msb to send first move.b d6,d2 ;get data byte to send move.b d3,d1 ;get address byte to send BigBSR6 WrXByte,a4 addq.w #1,d3 ;bump to next byte cmp.w #248,d3 ;done with d6? blt.s @loop2 ;no move.l #$54480000,d5 ;setup special bytes move.w d4,d5 ;include checksum move.l d5,d4 ; <7> @loop3 rol.l #8,d4 ;align msb to send first <7> move.b d4,d2 ;get data byte to send <7> move.b d3,d1 ;get address byte to send BigBSR6 WrXByte,a4 addq.w #1,d3 ;bump to next byte cmp.w #12,d3 ;done with d3? <7> blt.s @loop3 ;no move.l USP,a0 ;restore return address jmp (a0) ;return to caller <9> ;--------------------------------------------------------------------------- ; ; This is _TestManager selector number 10. It's function is to return a ; ROM test name given the test number (i.e., the test number reported ; in the diagnostic PRAM area). ; ; Aaron Ludtke 11/5/91 ; Note that for the Horror ROM, the name strings were changed to pStrings from ; cStrings. I did this because it makes it more convenient to get the name info ; from the Serial Test Manager if you know the address of a string (pString) and ; can determine the length of the info to download across the serial port. ; ;--------------------------------------------------------------------------- TestName ; WITH USTSubtest, USTTest ; move.w Ops(a0),d1 ;get the subtest number ext.l d1 ;make it a long BigLea USTSubtests,a1 ;get the address of the subtests table move.w #sizeofUSTSubtest,d2 ;get the size of the subtest list tst.w NumPass(a0) ;is this a test number, or subtest number? beq.s @Subtest ;branch if this is a subtest BigLea USTTests,a1 ;else, load the test table move.w #sizeofUSTTest,d2 ;and the size of the test list @Subtest move.l a1,d6 ;start with the address of the table @SearchLoop cmp.l TTest_ID(a1),d1 ;is this our subtest? beq.s @Foundit ;branch if so adda.w d2,a1 ;else, go to the next entry cmp.l #-1,TTest_ID(a1) ;are we at the end? bne.s @SearchLoop ;continue if not moveq.l #0,d6 ;return with a zero pointer bra.s @exit ;and exit @Foundit add.l TNamePtr(a1),d6 ;dereference the name pointer ENDWITH @exit bra TestMgrExit ;return to caller ;=========================================================================== ; TestTable is a set of pointers to the canned test routines living in ; the System ROM. This table is accessed by the Test Manager when it ; receives a "T" command, followed by a test number, which is an index ; into this table. ; ; Note that only 7 'critical' tests are available from the TJump ; TestTable. (Ex: *T000400010000 will run ROMTest for one pass) ; ; NOTE: Because this file (USTTestMgr.a) was moved over to a the overpatch ; USTStartTest1.a file, the dc.w references to functions in USTCritTests.a ; and USTNonCritTests.a are too short. The references need to be changed ; to dc.l, but I'm not sure what effect it will have on the code. So, I ; need to go through and thoroughly test everything. AARON AARON ; ;--------------------------------------------------------------------------- ; ₯₯₯TJump dc.w SizeMem-TJump ;Test #0 = SizeMemory <18> ; ₯₯₯ dc.w DataBusTest-TJump ;Test #1 = DataBusTest ; ₯₯₯ dc.w Mod3Test-TJump ;Test #2 = Mod3Test <1.4> ; ₯₯₯ dc.w AddrLineTest-TJump ;Test #3 = AddrLineTest ; ₯₯₯ dc.w RomTest-TJump ;Test #4 = ROMTest <1.4> ; ₯₯₯ dc.w RevMod3Test-TJump ;Test #5 = RevMod3Test <1.4> ; ₯₯₯ dc.w ExtRAMTest-TJump ;Test #6 = ExtRAMTest ; ₯₯₯ dc.w MovInvTest-TJump ;Test #7 = MovInvTest <18> ; ₯₯₯ dc.w SizeV8VRAMShell-TJump ;Test #8 = Size the Video RAM <35> ; ₯₯₯ dc.w NoTest-TJump ;Test #9 = NoTest ; ₯₯₯MaxTest dc.w (*-TJump)>>1 ;Max test number <18> TJump dc.l SizeMem-TJump ;Test #0 = SizeMemory <18> dc.l DataBusTest-TJump ;Test #1 = DataBusTest dc.l Mod3Test-TJump ;Test #2 = Mod3Test <1.4> dc.l AddrLineTest-TJump ;Test #3 = AddrLineTest dc.l RomTest-TJump ;Test #4 = ROMTest <1.4> dc.l RevMod3Test-TJump ;Test #5 = RevMod3Test <1.4> dc.l ExtRAMTest-TJump ;Test #6 = ExtRAMTest dc.l MovInvTest-TJump ;Test #7 = MovInvTest <18> dc.l SizeV8VRAMShell-TJump ;Test #8 = Size the Video RAM <35> dc.l NoTest-TJump ;Test #9 = NoTest ;MaxTest dc.l (*-TJump)>>1 ;Max test number <18> MaxTest dc.l (*-TJump)>>2 ;Max test number <18> ;--------------------------------------------------------------------------- ; TestTable is a set of pointers to the canned test routines living in ; the System ROM. This table is accessed by the Test Manager when it ; receives a "N" command, followed by a test number, which is an index ; into this table. ; ; Note that up to 128 (0-$7f) 'non-critical' tests are available from the NJump ; TestTable. (Ex: *N008600020000 will run SCCTimerTest for two passes) ;--------------------------------------------------------------------------- NJump dc.l SCCRegTest-NJump ;test #84 = SCCRegTest dc.l SCCLoopTest-NJump ;test #85 = SCCLoopTest dc.l SCCTimerTest-NJump ;test #86 = SCCTimerTest dc.l VIATest-NJump ;test #87 = VIATest dc.l TestSCSI-NJump ;test #88 = SCSITest dc.l TestASC-NJump ;test #89 = SndTest dc.l PramTest-NJump ;test #8A = PramTest dc.l TestRBV-NJump ;test #8B = TestRBV dc.l TestSWIM-NJump ;test #8C = TestSWIM dc.l Float_Test-NJump ;test #8D = Float_Test dc.l TestPGC-NJump ;test #8E = TestPGC dc.l FMCRegTest-NJump ;test #8F = FMCRegTest <2.6> dc.l FMCCacheTest-NJump ;test #90 = FMCCacheTest <2> dc.l OSSRegTest-NJump ;test #91 = OSSRegTest <2.6> dc.l OSSIntTest-NJump ;test #92 = OSSIntTest <2.6> dc.l RPUTest-NJump ;test #93 = RPUTest <8> dc.l EgretTest-NJump ;test #94 = EgretTest <8> dc.l TestSndInts-NJump ;test #95 = TestSndInts <8> dc.l TestCLUT-NJump ;test #96 = TestCLUT <27> dc.l TestVRAM-NJump ;test #97 = TestVRAM <28> dc.l TestPWM-NJump ;test #98 = in Apollo ROM only dc.l TimeSoundInts-NJump ;test #99 = in Apollo ROM only dc.l TestC96-NJump ;test #9A = TestC96 CASE ON ; this is for the SONIC test names - they're C functions dc.l SONIC_BitMarch-NJUMP ;test #9B = SONIC_BitMarch dc.l SONIC_CAMDMA-NJUMP ;test #9C = SONIC_CAMDMA dc.l SONIC_Loopback-NJUMP ;test #9D = SONIC_Loopback CASE OFF dc.l TestGSCRegs-NJump ;test #9E = TestGSCRegs dc.l PGESelfTest-NJump ;test #9F = PGESelfTest dc.l TestCSCRegs-NJump ;test #A0 = TestCSCRegs MaxNTst dc.l (*-NJump)>>2 ;maximum number of tests available TestPWM ; TimeSoundInts ; moveq.l #-1,d6 ;These tests are not in this ROM, indicate test does not apply RTS6 ;and return EJECT ;================================================================================== ;Universal Test Manager ;--------------------------------------------------------------------------- ; NuMac ROM resident Test Manager for service and board burn in and any ; power up test failure. The Test Manager entry points are used ; as follows: ; ; TMEntry0 = Entry from _TestManager trap command or NMI. ; TMRestart = entry point from CritErr. ; TMEntry1 = entry point for board burn in. ; ;--------------------------------------------------------------------------- ; General Register Usage: ;--------------------------------------------------------------------------- ; d0 ----SCRATCH---- ; d1 ----SCRATCH---- ; d2 ----SCRATCH---- ; d3 SCC write base offset ; d4.hw set by *B command ; d4.lw timer counter ; d5.hw command byte (for echo) ; d5.lw ----SCRATCH---- ; d6 minor error ; d7 major error/flags ; ; a0 set by *0 command ; a1 set by *1 command ; a2 VIA1 base address ; a3 SCC read base ; a4 set by *L command (load address), saves return address for PRAM rtns ; a5 Saves return address (for BSR5/RTS5), used by cmd parser ; a6 Saves return address (for BSR6/RTS6) ; a7 sp, reserved! ; ;----------------------------------------------------------------------------- TMRestart ; <19> WITH DecoderInfo,hwCfgInfo ; <19> lea -VTEntries*4(sp),sp ;For ³010 CPUs, VBR goes above the stack <19><16> movea.l sp,a1 ; <19><16><1.8> BSR6 SetVectorTable ;Set up our exception table in RAM <16> TMEntry0 ; <19> clr.l d6 ;start with clean plate <19> clr.l d7 ; <19> TMEntry1 ; <19><1.9> moveq.l #0,d2 BigBSR6 JGetHardwareInfo,a0 ; <35> move.l VIA1Addr(a0),a2 ;get VIA1 base address btst.l #(hwCbPwrMgr+16),d2 ;do we have a pmgr? beq.s @noPmgr ;branch if not move.l a0,d0 ; do I need to save a0? BigBSR6 USTPmgrTurnOn,a0 ;turn on a bunch of things move.l d0,a0 ; restore a0 @noPmgr @checkForASC btst #test,d7 ;are we in board burn in? bne.s @SkipSound ;yes, then skip the noise moveq.l #0,d2 ;know something about machine already BigBSR6 JGetHardwareInfo,a0 ; <35> btst.l #ASCExists,d0 ;do we have a sound chip? beq.s @SkipSound move.l ASCAddr(a0),A3 ;get sound chip addr [2.6>[2.7> movea.l VIA1Addr(a0),a5 ;setup VIA1 address for Beep <1.3> BigBSR6 ErrorBeep4,a0 ;the fourth choice of several squawks... @SkipSound clr.l d5 ;clear command register BSR6 SetupBases ;Get VIA1,SCC base addresses in a2,a3,d3 BSR6 InitSCC getCmd BSR6 GetChar ;look at SCC/KBD for any input tst.w d0 ;test char, neg word means no input bmi Continue ;if negative then didn't get a char @gotChar and.b #$7f,d0 ;mask character cmpi.b #'*',d0 ;is it a star? bne.s @checkCmd ;no, see if command char <36> bset #star,d7 ;yes, flag that we've seen it bra Continue @checkCmd ;we got some other character <36> btst #star,d7 ;have we already seen a star first? <36> bne.s @gotStar ;yes, it must be a normal STM cmd <36> cmpi.b #UTEChar,d0 ;Else, is this the UTE command char? <36> bne Invalid ;just echo it if not <36> bsr UTECmd ;else, go do it (we don't know if we're inited) <36> move.l d0,-(sp) ;save the return status BSR6 SetupBases ;After doing a CTE thing, we need to reinit BSR6 InitSCC ;reinit scc if needed move.l (sp)+,d0 ;restore the return status tst.l d0 ;is everything OK? bne CTEReturn ;echo what you have if not move.b #UTEChar,d0 ;else, echo the UTE character to say we're done bra CTEReturn ;Jump to invalid to send prompt @gotStar ; <36> bclr #star,d7 ;yes, we have a command byte... moveq #0,d1 ;clear command offset reg moveq #0,d2 ;clear byte counter lea CmdTable,a5 ;point to our command table @loop move.w (a5)+,d2 ;get count/command byte beq Invalid ;exit if end of table cmp.b d2,d0 ;is this our command? beq.s @found ;yes, process it adda.l #2,a5 ;no, skip over routine offset bra.s @loop ;and try next @found move.l a5,d5 ;save table entry pointer lsr.w #8,d2 ;get byte cnt in lower byte BSR6 GetNBytes ;Get up to 4 bytes in D1 move.l d5,a5 ;restore table entry pointer move.b -1(a5),d5 ;re-fetch command byte swap d5 ;keep in high byte of d5 move.w (a5),d0 ;get routine offset @jump jmp (a5,d0.w) ;and jump to our routine EJECT ;----------------------------------------------------------------------------------- ; Command Table Entries are long words of the form: ; Routine Offset (Word) ; Chars to get (Byte) ; Cmd Character (Byte) ;----------------------------------------------------------------------------------- ALIGN 2 CmdTable DC.B 0,'S' DC.W Service-* DC.B 4,'L' DC.W LoadAddr-* DC.B 2,'B' DC.W ByteCnt-* DC.B 0,'D' DC.W GetData-* DC.B 0,'C' DC.W CheckSum-* DC.B 4,'G' DC.W Execute-* DC.B 4,'0' DC.W LoadA0-* DC.B 4,'1' DC.W LoadA1-* DC.B 4,'2' DC.W SetCache-* DC.B 0,'3' DC.W MMUOff-* DC.B 0,'4' DC.W ClearResult-* DC.B 0,'5' DC.W StartBootMsg-* DC.B 0,'6' DC.W CPUReset-* DC.B 0,'7' DC.W PreventSleep-* DC.B 0,'A' DC.W ASCIIMode-* DC.B 0,'H' DC.W HEXMode-* DC.B 0,'R' DC.W SendResults-* DC.B 0,'M' DC.W MemDump-* DC.B 0,'E' DC.W EchoOn-* DC.B 0,'I' DC.W InitTestManager-* DC.B 2,'P' DC.W PwrMgrCmd-* DC.B 4,'T' DC.W DoCritTest-* DC.B 4,'N' DC.W DoNonCritTest-* DC.B 0,'V' ;Version command <23> DC.W EchoVersion-* ; <23> DC.B 0,'Z' ;Exit to the nub manager <32> DC.W NubSTMDispatch-* ;Dispatch directly to the NUB <32> DC.L 0 EJECT EchoCmd move.b #'*',d0 ;echo an asterisk BSR6 OutChar ; swap d5 ;get upper word move.b d5,d0 ;get copy of received character swap d5 ;restore d5 CTEReturn BSR6 OutChar ;echo received char bset #crlf,d7 ;send crlf moveq #0,d2 ;no command BSR6 PutNBytes ;send the crlf bclr #crlf,d7 ;no more crlf bra.s Continue ;skip invalid char processing Invalid BSR6 OutChar ;echo received char Continue btst #MsgQ,d7 ;any message queued to go out? beq @NoUnQ ; Message queued up for output, see if timer active btst #timer,d7 ;see if timer bit set beq.s @NoTimer ;no, continue with message ; The timer is active so see if its expired yet btst #5,VIFR(a2) ;see if counted out beq @NoUnQ ;no, continue on move.b #$20,VIER(a2) ;disable timer 2 interrupts move.b #$FF,vT2C(a2) ;low byte move.b #$FF,vT2CH(a2) ;high byte subq.w #1,d4 ;count a timer expiration event bpl @NoUnQ ;still counting... move.w #sec,d4 ;expired, re-init d4.w @NoTimer lea a1Msg,a1 ; BSR6 SendString ; d6.l/d7.w have the result codes to embed in the text stream bclr.l #crlf,d7 ;no bset.l #aski,d7 ;send as ascii characters move.l d6,d0 ;send d6.l result code register moveq.l #4,d2 ;send 4 bytes BSR6 PutNBytes ;send um move.w d7,d0 ;send d7.w result code register moveq.l #2,d2 ;send 2 bytes BSR6 PutNBytes ;send um bclr.l #aski,d7 ;revert to hex mode ; follow it up with the trailor msg that identifies the system move.b #'*',d0 BSR6 OutChar ;output * BSR6 SetupBases ;reinit the bases (also gets box flag in d2) lea b1Msg,a1 ;point to our table <1.5> lsr.w #8,d2 ;get boxflag <1.5> ext.w d2 ;sign extend for neg offset if needed <1.5> move.b (a1,d2.w),d0 ;get digit for this machine <1.5> BSR6 OutChar ;send send it <1.5> lea trailer,a1 ;point to *crlf BSR6 SendString ;send it btst #timer,d7 ;if timer is active then bne.s @NoUnQ ; don't un-queue message bclr #MsgQ,d7 ;not active so un-queue message @NoUnQ bra getCmd ;keep looping.... EJECT ;================================================================================ ; Test Manager Commands ;================================================================================ ;------------------------------------------------------------------------------- ; *S Service mode request, turn off timer and queue flags. ; ; Inputs: none ; Outputs: none ; Destorys: none ;------------------------------------------------------------------------------- Service bclr #MsgQ,d7 ;clear any queued message bclr #timer,d7 ;clear any timer active bit lea EchoCmd,a6 ;load return address jmp PutNBytes ;send result register ;------------------------------------------------------------------------------- ; *L Load Address. Setup our load address register (a4) ; ; Inputs: d1 - address received from serial port ; ; Outputs: a4 - load address ;------------------------------------------------------------------------------- LoadAddr move.l d1,a4 ;a4 now has load address swap d4 ; clr.w d4 ;initialize byte count to default swap d4 ; btst #echo,d7 ;wants an echo today? beq EchoCmd ;no bclr #crlf,d7 ;no move.l d1,d0 ;copy of load address moveq #4,d2 ;send 4 bytes lea EchoCmd,a6 ;load return address jmp PutNBytes ;send load address ;------------------------------------------------------------------------------- ; *B Set byte count ; ; Inputs: d1.w - [from serial port] ; ; Outputs: d4.hw - byte count received ; ; Destroys: d0,d2 ;------------------------------------------------------------------------------- ByteCnt swap d4 move.w d1,d4 ;save byte count in d4.hw swap d4 btst #echo,d7 ;wants an echo today? beq EchoCmd ;no bclr #crlf,d7 ;no move.w d1,d0 ;copy of byte count moveq #2,d2 ;send 2 bytes lea EchoCmd,a6 ;load return address jmp PutNBytes ;send byte count ;------------------------------------------------------------------------------- ; *D Data. Get data coming... generate checksum in d6, ; store data off a4 for d4.hw bytes ; ; Inputs: a4 - start address to checksum ; d4.hw - number of bytes to checksum ; ; Outputs: d6.l - checksum ; ; Destroys: d0,d1,d2,d4.hw,a4,a5 ;------------------------------------------------------------------------------- GetData clr.l d6 ;clear for checksum calculation swap d4 sub.w #1,d4 ;adjust for dbra blt.s @exit ;exit if no bytes to get @fetch moveq #1,d2 ;get a byte BSR6 GetNBytes ;check for input move.b d1,(a4)+ ;stuff into appropriate place clr.l d0 move.b d1,d0 ;character to sum add.l d0,d6 ;add to sum dbra d4,@fetch ;until done.... @exit swap d4 bra EchoCmd ;then send response ;------------------------------------------------------------------------------- ; *C Checksum. Calculate the checksum off a4 for d4.hw ; bytes, then send checksum to serial port ; ; Inputs: a4 - start address to checksum ; d4.hw - number of bytes to checksum ; ; Outputs: d6.l - checksum ; ; Destroys: d0,d1,d2,d4.hw,a4,a5 ;------------------------------------------------------------------------------- CheckSum clr.l d6 ;clear for checksum calculation [v1.1> swap d4 sub.w #1,d4 ;adjust for dbra [v1.1> blt.s @noMore ;ok to continue [v1.1> @sum move.b (a4)+,d1 ;get a byte [v1.1> clr.l d0 move.b d1,d0 ;character to sum [v1.1> add.l d0,d6 ;add to sum [v1.1> dbra d4,@sum @noMore swap d4 bclr #crlf,d7 ;no [v1.1> move.l d6,d0 ;copy of result register d6.l [v1.1> moveq #4,d2 ;send 4 bytes [v1.1> lea EchoCmd,a6 ;load return address [v1.1> jmp PutNBytes ;send result register [v1.1> ;------------------------------------------------------------------------------- ; *G Go execute ; ; Inputs: d1 - Starting address ; ; Outputs: d5 - 00470000 ; ; Destroys: d0,d2,a2,???? ;------------------------------------------------------------------------------- Execute move.l d1,a2 ;get jump address lea @1,a6 ; setup return address rb jmp (a2) ;jump to downloaded code rb @1 ; rb BSR6 SetupBases ;restore VIA1,SCC registers move.l #$00470000,d5 bra EchoCmd ;back to command parser ;------------------------------------------------------------------------------- ; *0 Set register A0. Load next 4 bytes into register a0 ; ; Inputs: d1 - 4 bytes to load in a0 ; ; Outputs: a0 - set to d1 ; ; Destroys: d0,d1,d2,a5 ;------------------------------------------------------------------------------- LoadA0 move.l d1,a0 ;copy to a0 btst #echo,d7 ;wants an echo today? beq EchoCmd ;no bclr #crlf,d7 ;no move.l d1,d0 ;copy of received data moveq #4,d2 ;send 4 bytes lea EchoCmd,a6 ;load return address jmp PutNBytes ;send received data ;------------------------------------------------------------------------------- ; *1 Set register A1. Load next 4 bytes into register a1 ; ; Inputs: d1 - 4 bytes to load in a1 ; ; Outputs: a1 - set to d1 ; ; Destroys: d0,d1,d2,d3,a5 ;------------------------------------------------------------------------------- LoadA1 move.l d1,a1 ;copy to a1 btst #echo,d7 ;wants an echo today? beq EchoCmd ;no bclr #crlf,d7 ;no move.l d1,d0 ;copy of received data moveq #4,d2 ;send 4 bytes lea EchoCmd,a6 ;load return address jmp PutNBytes ;send received data ;------------------------------------------------------------------------------- ; *2 Set cache control register ; ; Inputs: d1 - 4 bytes to load in CACR ; ; Outputs: CACR set to 4 byte input ; ; Destroys: d0 ;------------------------------------------------------------------------------- SetCache movec d1,CACR ;if heading to test manager bra EchoCmd ;and echo ;------------------------------------------------------------------------------- ; *3 Turn off MMU translation ; and disable the data cache so I/O area will not be cached. ; ; Note: The data cache is only turned off in the 68030 case ; the 68040 case may need this done also. ; ; Inputs: none ; ; Outputs: MMU turned off ; ; Destroys: d0, d1, a0 ;------------------------------------------------------------------------------- MMUDis dc.l 0 ;Disable MMU translation <20> MMUOff ; Even tho the -IF- says "³ 030", this means that we might have an 020 <30> ; because the Mac32 build will work for 020s as well, and is assembled with <30> ; CPU = 030. So we need to check whether or not we're an 020/030/040 <30> movec cacr,d0 ;Test to see what kind of CPU we're on <20><30> move.l d0,d1 ;Save the contents of the cacr register <20> bset.l #31,d0 ; set CACR[DE] to test if on an 040 <30> movec d0,CACR ; write it out <30> movec CACR,d0 ; ... and see if it stuck <30> btst.l #31,d0 ; are we on an 040? <30> bne.s @onAn040 ; YES ... go disable 040 MMU <30> ; NO ... make sure we're not on an 020 <30> bset.l #CAWA,d0 ;Set the Write allocate bit (020s don't have this) <20> movec d0,cacr ;move it into the CACR <20> movec cacr,d0 ;read it back <20> btst.l #CAWA,d0 ;Are we an 030? (were we able to set WA?) <20> beq.s @exit ;NO ... exit. CACR has not changed. <20> lea MMUDis,a0 ;YES ... point to TC value that disables the MMU<20> move.l #$00003819,d1 ;get ready to clear data and Inst. caches & disable data cache. movec d1,cacr ;do the cache stuff before turning off the MMU pmove (a0),tc ;turn off 030 MMU <20> bra.s @exit ; ... then exit <30> @onAn040 ; This is done this way to preserve the current setting for the pagesize bit <30> ; Otherwise, it could be done with: <30> ; sub.l d0,d0 ; set all TC bits to zero <30> ; movec d0,TC ; disable MMU, pagesize set to 4K <30> MACHINE MC68040 ; required for below instructions <3> movec TC,d0 ; retrieve TC <3> bclr #15,d0 ; TC[E] bit is bit 15 on 040s. <3> movec d0,TC ; disable MMU <3> MACHINE MC68030 ; return to previous MACHINE directive <3> @restoreCACR ; <30> movec d1,cacr ;restore the cacr <20> @exit bra EchoCmd ;command not implemented ;------------------------------------------------------------------------------- ; *4 Clear result registers ; ; Inputs: none ; ; Outputs: d6 - cleared ; d7.w - cleared ; ; Destroys: none ;------------------------------------------------------------------------------- ClearResult clr.w d7 ;clear error registers clr.l d6 ; bra EchoCmd ;and echo ;------------------------------------------------------------------------------- ; *5 Queue up boot msg for host ; ; The boot message for board burn in or service log on is built from ; a header, result codes, and a trailor that identifies the system. ; ; The normal non-failure type message looks like this: ; ; *APPLE*876543210000*1* ; ; The 87654321 part is the minor error code. These are decoded as ; follows: $87654321 = good, no failure ; $xxxxxxxx = 32 bits failed bits mask for RAM, Bus tests ; $yyyyyyyz = z is 4 bit mask of chip that failed ROM checksum ; ; The 0000 part is the major code as the ; equates in this file indicate by ErrXXXX codes. ; ; [v1.3> ((( ; ; Note that in cpus after laguna (Hcmac) the 0000 part will consist of two parts: ; The msb of the word will contain the exception error code indicated by the exception ; error code equates in this file, if an unexpected exception occurred while running a test. ; If no exception occurred, then this byte will be clear. ; The lsb of the word will still contain the major error code indicated by the lsb of ; the ErrXXXX equate. ; ; ))) [v1.3> ; ; ; The *1* part identifies the system as a Mac II (or family member) ; The *2* part identifies the system as a Mac SE ; The *3* part identifies the system as a Mac+ ; The *4* part identifies the system as a vader (laser ntx) [v1.3> ; The *5* part identifies the system as a Luke (laser nt) [v1.3> ; The *6* part identifies the system as a Portable (HcMac) [v1.3> ; The *7* part identifies the system as a Mac IIci (HafMac) ; The *8* part identifies the system as a Mac IIfx (MvMac) ; The *9* part identifies the system as a Woodstock ; The *A* part identifies the system as a Atlantic ; The *B* part identifies the system as a XO <15> ; The *C* part identifies the system as a Ericson <15> ; The *D* part identifies the system as a Elsie <15> ; The *E* part identifies the system as a Eclipse <15> ; The *F* part identifies the system as a Kirin <15> ; The *G* part identifies the system as a Kirin Dry <15> ; ;--------------------------------------------------------------------------- ; ; Inputs: none ; ; Outputs: d4.lw - set to delay count ; d7 - flags set ; ; Destroys: none ;------------------------------------------------------------------------------- StartBootMsg bset #timer,d7 ;timer is active bset #MsgQ,d7 ;boot msg is queued move.w #sec,d4 ;set extended timer count bsr6 StartTimer ;and start the timer lea EchoCmd,a6 ;command end processor jmp SetupBases ;restore VIA1,SCC registers ;------------------------------------------------------------------------------- ; *6 CPU Reset ; ; Inputs: none ; Outputs: none ; Destroys: none ;------------------------------------------------------------------------------- CPUReset Reset ;issue reset instruction bra EchoCmd ;and echo ;------------------------------------------------------------------------------- ; *7 Prevent lack of charger from causing sleep; note ; that doing this probably requires a charger to be ; hooked up temporarily in order to issue this ; command. ; ; Inputs: none ; Outputs: d7 - nosleep flag set ; Destroys: none ;------------------------------------------------------------------------------- PreventSleep bset #nosleep,d7 ;set sleep bit to prevent us from napping bra EchoCmd ;and echo ;------------------------------------------------------------------------------- ; *A set ASCII mode ; ; Inputs: none ; Outputs: d7 - flag set ; Destroys: none ;------------------------------------------------------------------------------- ASCIIMode bset #aski,d7 ;set ascii mode bit bra EchoCmd ;------------------------------------------------------------------------------- ; *H set HEX mode ; ; Inputs: none ; Outputs: d7 - flag cleared ; Destroys: none ;------------------------------------------------------------------------------- HEXMode bclr #aski,d7 ;clear ascii mode bit bra EchoCmd ;------------------------------------------------------------------------------- ; *R send test results (4 bytes) to serial port ; ; Inputs: none ; Outputs: none ; Destroys: d0,d1,d2,a5 ;------------------------------------------------------------------------------- SendResults bclr #crlf,d7 ;no move.l d6,d0 ;copy of result register d6.l moveq #4,d2 ;send 4 bytes BSR6 PutNBytes ;send result register bclr #crlf,d7 ;no move.w d7,d0 ;copy of result register d7.w moveq #2,d2 ;send 2 bytes lea EchoCmd,a6 ;load return address jmp PutNBytes ;send result register ;------------------------------------------------------------------------------- ; *M Memory dump. Dump memory from (a4) for (d3.w) bytes ; ; Inputs: a4 - starting address of dump ; d4.hw - number of bytes to dump ; ; Outputs: a4 - points past last byte dumped ; ; Destroys: d0,d1,d2,d4,a5 ;------------------------------------------------------------------------------- MemDump swap d4 ;get byte cnt subq.w #1,d4 ;and for dbra bge.s @dump ;is it ok to continue? clr.w d4 ;always dump at least one byte @dump bset #crlf,d7 ;append @loop move.l (a4)+,d0 ;get 4 bytes to send moveq #4,d2 ;send 4 bytes BSR6 PutNBytes ;send um dbra d4,@loop @done swap d4 bra EchoCmd ;done ;------------------------------------------------------------------------------- ; *E set echo mode ; ; Inputs: none ; Outputs: d7 - flag set ; Destroys: none ;------------------------------------------------------------------------------- EchoOn bset #echo,d7 ;echo received parameters bra EchoCmd ;------------------------------------------------------------------------------- ; *I Initilize (restart) the Test Manager ;------------------------------------------------------------------------------- InitTestManager BigJmp BaseOfRom+ROMHeader.ReStart,a0 ;jump to restart vector <24> ;------------------------------------------------------------------------------- ; *P Power Manager command (command.b,cnt.b) ; ; Inputs: d1 - command/byte cnt ; a2 - VIA1 base ; ; Outputs: d7 - flag set ; ; Destroys: d0,d1,d2,d3,a1,a4,a5 ;------------------------------------------------------------------------------- PwrMgrCmd lea ErrorMsg,a1 lea EchoCmd,a6 ; [v1.1> jmp SendString ;we can't process it [v1.1> EJECT ;------------------------------------------------------------------------------- ; *T Test (test#,passes,options) ; ; Inputs: d1 - test#,passes ; ; Outputs: d5 - $00540000 ; ; Destroys: a0-a6,d0-d4 ;------------------------------------------------------------------------------- DoCritTest BigLea ElsieTMVectors,a5 ;First see if we are on an Elsie <16> BigLea StartTest1,a4 ;Get the address of the start vector <16> cmpa.l 4(a5),a4 ;Does this agree with where we are? <16> beq.s @onElsie ;Continue if so <16> BigLea TMVectors,a5 ;Otherwise, load the default TM vectors <16> @onElsie ; <16> movec a5,VBR ;VBR points to our exception table <16> move.l d1,a4 ;save test#/passes btst #echo,d7 ;Echo wanted? beq.s @getOpt ;no move.l d1,d0 moveq #4,d2 BSR6 PutNBytes ;---echo test#/passes @getOpt moveq #2,d2 BSR6 GetNBytes ;now get the options word moveq.l #-1,d0 ;Create a mask for the option field in d7 <16> move.l #stop,d2 ;Get lsb of options field <16> lsl.l d2,d0 ;create our mask <16> not.l d0 ;Invert it <16> and.l d0,d7 ;and clear the options field <16> move.w d1,d0 ;save a copy in case echo needed lsl.l d2,d1 ;align error option bits or.l d1,d7 ;and plop them into flags register btst #echo,d7 ;echo wanted? beq.s @loop ;no moveq #2,d2 BSR6 PutNBytes ;---echo options word ; Next get the test number back and case it out to run the test requested. @Loop clr.l d6 ;clear results register d6.l move.l a4,d1 swap d1 ;get test number requested move.b #nak,d0 ;preset invalid number received ; cmp.w MaxTest,d1 ;is valid test number? and.l #$0000ffff,d1 ;clear out options word for now cmp.l MaxTest,d1 ;is valid test number? bge Invalid ;invalid, echo ? as nak ; asl.w #1,d1 ;adjust for table access asl.l #2,d1 ;adjust for table access lea TJump,a5 ;point to test jump table ; Due to the relocation of this file to USTStartTest1.a, I had to make the references ; in the TJump table longs instead of words. Therefore I had to modify some access code: ; WARNING: This is probably going to break STM because d1 is holding two values (in ; high word and low word). CHECK THIS OUT AARON AARON ;₯₯₯ move.w (a5,d1.w),d1 ;fetch test offset from table ;₯₯₯ lea (a5,d1.w),a5 ;... move.l (a5,d1.l),d1 ;fetch test offset from table lea (a5,d1.l),a5 ;... lea @1,a6 ; setup return address rb jmp (a5) ;go execute test rb @1 ; rb movea.l #aStack,a7 ;Reset stack pointer, in case it was destroyed <19> move.l a0,d4 ;save regs in case looping move.l a1,d5 BSR6 SetupBases ;Get VIA1,SCC base addresses in a2,a3,d3 move.l d4,a0 ;restore regs move.l d5,a1 tst.l d6 ;any errors this test? beq.s @Continue ;no ; Error on test, check for loop and stop on error options lea ErrorMsg,a1 BSR6 SendString ;send error message to serial port btst #loop,d7 ;wants to loop on error? beq.s @NoLoop ;no @ErrLoop lea @ErrLoop,a6 ;yes, loop on test jmp (a5) ;until the cows come home.... @NoLoop btst #stop,d7 ;wants to stop on error? bne.s @Echo ;yes @Continue move.l a4,d1 subq.w #1,d1 ;count a pass beq.s @echo ;done, clean up and exit movea.l d1,a4 ;save pass cnt BSR6 GetChar tst.w d0 bmi.s @Loop ;continue testing @Echo move.l #$00540000,d5 ;fake a "T" to echo bra EchoCmd EJECT ;------------------------------------------------------------------------------- ; *N Non-critical Test (test#,passes,options) ; ; Inputs: d1 - test#,passes ; ; Outputs: d5 - $004E0000 ; ; Destroys: a0-a6,d0-d4 ; ; Note: Several non-critical tests require that the VBR be setup in RAM, so they ; can patch the interrupt vectors. ;------------------------------------------------------------------------------- DoNonCritTest movea.l d1,a4 ;save test#/passes in a4 BigBSR6 SizeMemory,a0 ;Size memory and set up the stack <16> movea.l (sp),a1 ;Put the vectors at the base of bank A <16> movea.l (a1),a1 ; <16> BSR6 SetVectorTable ;Set up our exception table in RAM <16> BSR6 SetupBases ;Get VIA1,SCC base addresses in a2,a3,d3<16> btst #echo,d7 ;Echo wanted? beq.s @getOpt ;no move.l a4,d0 ;Restore the test#/passes for echo <16> moveq #4,d2 BSR6 PutNBytes ;---echo test#/passes @getOpt moveq #2,d2 BSR6 GetNBytes ;now get the options word moveq.l #-1,d0 ;Create a mask for the option field in d7 <16> move.l #stop,d2 ;Get lsb of options field <16> lsl.l d2,d0 ;create our mask <16> not.l d0 ;Invert it <16> and.l d0,d7 ;and clear the options field <16> move.w d1,d0 ;save a copy in case echo needed lsl.l d2,d1 ;align error option bits or.l d1,d7 ;and plop them into flags register btst #echo,d7 ;echo wanted? beq.s @valid ;no moveq #2,d2 BSR6 PutNBytes ;---echo options word ; Next get the test number back and case it out to run the test requested. @valid move.l a4,d1 swap d1 ;get test number requested sub.w #$84,d1 ;subtract out non-crit offset ; cmp.w MaxNTst,d1 ;is valid test number? and.l #$0000ffff,d1 ; mask off test number cmp.l MaxNTst,d1 ;is valid test number? blt @table ;yes, continue move.b #nak,d0 ;preset invalid number received bra Invalid ;invalid, echo ? as nak ;@table asl.w #1,d1 ;adjust for table access @table asl.l #2,d1 ;adjust for table access lea NJump,a5 ;point to test jump table ; Due to the relocation of this file to USTStartTest1.a, I had to make the references ; in the NJump table longs instead of words. Therefore I had to modify some access code: ; WARNING: This is probably going to break STM because d1 is holding two values (in ; high word and low word). CHECK THIS OUT AARON AARON ;₯₯₯ move.w 0(a5,d1.w),d1 ;fetch test offset from table ;₯₯₯ lea 0(a5,d1.w),a5 ;... move.l 0(a5,d1.l),d1 ;fetch test offset from table lea 0(a5,d1.l),a5 ;... move.w a4,-(sp) ;keep loopcount on stack <1.8> move.l a5,-(sp) ;save on stack <1.8> moveq.l #0,d2 ;d2 prep'd for universal call <1.8> BigBSR6 JGetHardwareInfo,a0 ; <35> move.l (sp)+,a5 ;save on stack <16><1.8> movem.l d0-d2/a0-a2/a5,-(sp) ;save universal registers <16><1.8><7> @Loop clr.l d6 ;clear results register d6.l movem.l (sp),d0-d2/a0-a2/a5 ;setup universal regs <16><7> lea @1,a6 ; setup return address rb jmp (a5) ;go execute test rb @1 ; rb BSR6 SetupBases ;Get VIA1,SCC base addresses in a2,a3,d3 BSR6 InitSCC ;reinit scc if needed tst.l d6 ;any errors this test? beq.s @Continue ;no ; Error on test, check for loop and stop on error options lea ErrorMsg,a1 ;point to *Error* string BSR6 SendString ;we can't process it [v1.1> btst #loop,d7 ;wants to loop on error? beq.s @NoLoop ;no @ErrLoop lea @ErrLoop,a6 ;yes, loop on test movem.l (sp),d0-d2/a0-a2/a5 ;restore regs <16><1.8><7> jmp (a5) ;until the cows come home.... @NoLoop btst #stop,d7 ;wants to stop on error? bne.s @Echo ;yes @Continue subq.w #1,28(sp) ;count a pass <7> beq.s @echo ;done, clean up and exit BSR6 GetChar ; tst.w d0 ; bmi @Loop ;continue testing @Echo lea 30(sp),sp ;dump saved registers off stack <16><1.8><7> move.l #$004E0000,d5 ;fake a "N" to echo bra EchoCmd ;------------------------------------------------------------------------------- <23> ; *V Echo version number <23> ; <23> ; Inputs: none <23> ; <23> ; Outputs: Echos the current serial test manager version number <23> ; <23> ; Destroys: a0-a3,a5,d0,d2,d3 <23> ; <23> ;------------------------------------------------------------------------------- <23> EchoVersion ; <23> BSR6 SetupBases ;Restore our state, in case we're lost <23> BSR6 InitSCC ;reinit scc if needed <23> lea Version,a1 ;Get a pointer to the version string <23> BSR6 SendString ;print error msg <23> move.l d7,d4 ;Preserve d7 <25> bset.l #aski,d7 ;Set to ASCII mode <25> bclr.l #crlf,d7 ;clear the CRLF option <25> BigLea BaseOfRom+ROMHeader.ROMVersion,a0 ;Get address of ROM ver # <25> move.b (a0),d0 ;Get the version # <25> moveq.l #1,d2 ;get # bytes to write <25> BSR6 PutNBytes ;write out this information <25> move.b #' ',d0 ;put out a space seperator BSR6 OutChar ; Biglea BaseOfRom+ROMHeader.ROMRelease,a0 ;Get address of release # <25> move.w (a0),d0 ;put release # in place <25> moveq.l #2,d2 ;# bytes to write <25> bset.l #crlf,d7 ;set the CRLF option <25> BSR6 PutNBytes ;Write out this information <25> move.l d4,d7 ;restore d7 <25> bra EchoCmd ;Echo command and finish <23> ;------------------------------------------------------------------------------- <32> ; *Z Dispatch to the nub manager <32> ; <32> ; Inputs: none <32> ; <32> ; This entry point simply jumps to the nub manager. This is a one way street, <32> ; i.e., once you go to the nub manager, you can't come back! <32> ; <32> ;------------------------------------------------------------------------------- <32> ; This is a jump to self for now - nub entry point to be added later <32> NubTMEntry NubSTMDispatch BigJmp NubTMEntry,a0 ;Jump to the nub <32> ; This is a jump to self for now - nub entry point to be added later <32> NubMgrTrap NubMgrDispatch BigJmp NubMgrTrap,a0 ;Jump to the nub <32> EJECT ;--------------------------------------------------------------------------- ; Routine sets up the VIA1 and SCC base addresses in registers, for use ; throughout the Test Manager. ; ; Called by BSR6 ; ; Inputs: ; ; Outputs: a2 - VIA1 base address ; a3 - SCC read base address ; d3 - SCC write base offset ; ; Destroys: a0-a3,a5,d0-d3 ;--------------------------------------------------------------------------- SetupBases WITH DecoderInfo move.l a6,d3 ;save return address moveq.l #0,d2 BigBSR6 JGetHardwareInfo,a0 move.l d3,a6 ;restore return address move.l VIA1Addr(a0),a2 ;get VIA1 base address btst.l #SCCIOPExists,d0 ;do we have an iop scc? beq.s @noIOP move.l SCCIOPAddr(a0),a3 ;get iop scc base address moveq.l #0,d3 ;write base offset is 0 bra.s @exit @noIOP move.l SCCRdAddr(a0),a3 ;get scc read base move.l SCCWrAddr(a0),d3 ;get scc write base sub.l a3,d3 ;calculate write reg offset ENDWITH @exit RTS6 ;--------------------------------------------------------------------------- ; Routine to initialize the SCC chip for I/O at 9600 baud async. ; Set the SCC inited bit status register D7 when done. This routine uses ; the table that follows. ; ; Called by BSR6 ; ; Inputs: d0 - Bases valid flags ; a2 - VIA1 base address ; a3 - SCC base address ; d3 - SCC write base offset ; ; Outputs: d7 - flags set to indicate scc inited ; ; Destroys: d0-d2,a0,a1,a5 ; ;--------------------------------------------------------------------------- InitSCC movea.l a6,a5 ; Save caller's return address @installed ; btst.l #SCCIOPExists,d0 ;do we have an iop scc? beq.s @sync ;no, init it BigBSR6 SetSCCIOPBypass,a0 ;yes, throw SCC IOP into bypass mode @sync tst.b 0(a3,d3.l) ;sync up accept address byte lea PortSetUp,a1 ;point at set up table @loop move.b (a1)+,d0 ;get SCC register to access bmi.s @done ;done with init move.b d0,Actl(a3,d3.l) ;select SCC register move.b (a1)+,Actl(a3,d3.l) ;write data to SCC register bra.s @loop ;until done... @done bset #SCCok,d7 ;set SCC inited status bit move.b aData(a3),d0 ; bset.b #sync,vDirA(a2) ;set the sync bit as an output <38> move.b vBufA(a2),d0 ;get current output register A bclr #sync,d0 ;clear the sync bit move.b d0,vBufA(a2) ;write ORA with overlay off jmp (a5) ;then exit ;----------------------------------------------------------------------------------- ; Serial port A set up table, for 9600 baud async. The calculation for baud ; rate constant is: ; ; BR constant = [Clock Rate/(32*BaudRate)] - 2 ; ; This translates to (NuMacConst/BaudRate) - 2 = 115200/9600 - 2 = about $000A ; ; or (MacConst/BaudRate) - 2 = 114709/9600 - 2 = about $000A ; ; For BaudRate of 19200: = 11709/19200 - 2 = about $0004 ;----------------------------------------------------------------------------------- PortSetUp dc.b $09,$C0 ;reg 9, reset hardware dc.b $0F,$00 ;reg 15, disable interrupts dc.b $04,$4C ;reg 4, X16clk,8 bit,2 stop dc.b $0B,$50 ;reg 11, rClk = tClk = BR gen dc.b $0E,$00 ;reg 14, disable BR gen ; dc.b $0D,$00 ;reg 13, high byte 9600 baud ; dc.b $0C,$0A ;reg 12, low byte 9600 baud dc.b $0C,$04 ;reg 12, low byte 9600 baud dc.b $0D,$00 ;reg 13, high byte 9600 baud dc.b $0E,$01 ;reg 14, enable BR gen dc.b $0A,$00 ;reg 10, NRZ dc.b $03,$C1 ;reg 3, Rx 8 bits, enabled dc.b $05,$EA ;reg 5, Tx 8 bits, DTR/RTS dc.b $01,$00 ;reg 1, Ext Sts interrupts disabled dc.b $FF,$FF ;end of table ;--------------------------------------------------------------------------- ; Routine to send out a character on SCC port A. Note that is routine will ; hang waiting for TXBE status since there is no timeout. ; ; Called by BSR6 ; ; Inputs: d0.b - character to send ; a3 - SCC base address ; d3 - SCC write base offset ; Outputs: none ; ; Destroys: d0 ;--------------------------------------------------------------------------- OutChar move.b #$30,Actl(a3,d3.l) ;reset any errors move.b d0,Adata(a3,d3.l) ;send character @wait move.w #1,d0 ;wait until all sent status move.b d0,Actl(a3,d3.l) ;select RR1 btst #0,Actl(a3) ;All Sent? beq.s @wait RTS6 ;exit EJECT ;--------------------------------------------------------------------------- ; This routine sends the message pointed to by a1 to the serial port. ; The string should be terminated by a null. ; ; Called by BSR6 ; ; Inputs: d3 - SCC write base offset ; a1 - ptr to zero terminated string ; a3 - SCC read base ; a6 - return address ; Outputs: none ; ; Destroys: d0,d1,a0,a1 ;--------------------------------------------------------------------------- SendString movea.l a6,a0 ;save return address [v1.1> @loop move.b (a1)+,d0 ; [v1.1> beq.s @done BSR6 OutChar ; bra.s @loop ; @done jmp (a0) ; [v1.1> ;--------------------------------------------------------------------------- ; note: the following identifiers are reserved for use on LaserWriter <15> ; products and must not be used by CPU products: 4,5,9,F,G <15> ;--------------------------------------------------------------------------- ErrorMsg dc.b '*ERROR*',0 ;error message a1Msg dc.b '*APPLE*',0 ;header message dc.b '0' ;$FD boxflag = unknown trailor message dc.b '3' ;$FE boxflag = MacPlus trailor message dc.b '2' ;$FF boxflag = MacSE trailor message b1Msg dc.b '1' ; 0 boxflag = Mac II trailor message dc.b '1' ; 1 boxflag = Mac IIx trailor message dc.b '1' ; 2 boxflag = Mac IIcx trailor message dc.b '1' ; 3 boxflag = Mac SE30 trailor message dc.b '6' ; 4 boxflag = Esprit trailor message dc.b '7' ; 5 boxflag = Aurora25 trailor message dc.b '8' ; 6 boxflag = 4Sq trailor message dc.b '8' ; 7 boxflag = F19 trailor message dc.b 'A' ; 8 - Aurora 16MHz 3 slot package <2.2> dc.b 'A' ; 9 - Aurora 25MHz SE30 package (reserved for future) <12> dc.b 'A' ;10 - Aurora 16MHz SE30 package (reserved for future) <12> dc.b 'B' ;11 - XO (SE with 1 int floppy, brightness PWM) <12> dc.b 'C' ;12 - Macintosh IIsi (20MHz, 030, optl 68882, MDU, RBV,1 direct slot) <12> dc.b 'D' ;13 - Macintosh LC (16 MHz, 020, 1 direct slot) <12> dc.b 'E' ;14 - Eclipse (040, 5 slots+PDS, VIA1&2, Orwell MCA, 2 IOPs, SCSI DMA) <12> dc.b 'H' ;15 - Tim (16/25 MHz, 030, optional FPU, VIA1&2, JAWS, PMGR dc.b 'I' ;16 - Spike (25MHz 040, 1 PDS, 2 NuBus, Orwell dc.b 'J' ;17 - Apollo dc.b 'K' ;18 - Asahi (Its a Sony!) Portable - PowerBook 100 dc.b 'L' ;19 - 16 Mhz Tim (TimLC - PowerBook 140) dc.b 'M' ;20 - Zydeco (33 MHz Eclipse) - Quadra 950 dc.b 'N' ;21 - Vail (25 MHz, 030, optional FPU, 1 PDS, Sonora) dc.b 'O' ;22 - Carnation (33 MHz, 030, FPU, 1 direct NuBus-capable slot, 3 NuBus slots) dc.b 'P' ;23 - DBLite (Dark Becks, in case you were wondering) dc.b 'Q' ;24 - Wombat (25MHz 040 or 040LC, 3 slots+PDS, VIA1&2, djMEMC, SCSI 53c96, optional enet) dc.b 'R' ;25 - Columbia (25 Mhz, 030, PDS, Atlantis Decoder, Color Classic) dc.b 'S' ;26 - 33MHz DBLite (030, PMGR, expansion connector, no floppy) dc.b 'T' ;27 - Dartanian (33Mhz, 030, FPU, VIA1&2, Niagra, PMGR, 1 direct slot) dc.b 'U' ;28 - DartanianLC dc.b 'V' ;29 - Wombat (33MHz 040, 3 slots+PDS, VIA1&2, djMEMC, SCSI 53c96,enet, Frigidaire plastics) dc.b 'W' ;30 - Wombat (33Mhz 040, 3 slots+PDS, VIA1&2, djMEMC, SCSI53c96, enet, Lego plastics) dc.b 'X' ;31 - Foster Farms (68030 LC) dc.b 'Y' ;32 - 16MHz DBLite (030, PMGR, expansion connector, no floppy) dc.b 'Z' ;33 - 20MHz DBLite (030, PMGR, expansion connector, no floppy) dc.b 'a' ;34 - Vail (16 MHz, 030, optional FPU, 1 PDS, Sonora) dc.b 'b' ;35 - Carnation (25 MHz, 030, FPU, 3 NuBus slots) dc.b 'c' ;36 - Carnation (16 MHz, 030, FPU, 3 NuBus slots) dc.b 'd' ;37 - Cyclone dc.b 'e' ;38 - Brazil (16Mhz, Lego package) dc.b 'f' ;39 - Brazil (32MHz on motherboard, Lego package) dc.b 'g' ;40 - Brazil (16MHz, Fridgidaire minitower package) dc.b 'h' ;41 - Brazil (32MHz on motherboard, Fridgidaire package) dc.b 'i' ;42 - Brazil (any speed, any package for consumer release) dc.b 'j' ;43 - Slice dc.b 'k' ;44 - Monet (33MHz 030/FPU, VIA1&2, Niagara, PMGR, 16 color LCD, 1 direct slot) dc.b 'l' ;45 - Wombat (40MHz 040, 3 slots+PDS, VIA1&2, djMEMC, SCSI 53c96, enet) dc.b 'm' ;46 - WLCD (20 MHz 040LC, PDS only, VIA1&2, djMEMC, SCSI 53c96, optional enet) dc.b 'n' ;47 - WLCD (25 MHz 040LC, PDS only, VIA1&2, djMEMC, SCSI 53c96, optional enet) dc.b 'o' ;48 - PowerBook 145 (25MHz 030, no FPU, otherwise same as 140) trailer dc.b '*',$0D,$0A,00 ;*crlf Version dc.b 'STM Version 2.2, Aaron Ludtke ',$0D,$0A ;STM version number <38> dc.b 'CTE Version 2.1 ',$0D,$0A ;CTE version number <38> dc.b 'ROM Version ' ;ROM version number goes next <38> dc.b 0 ;terminator align EJECT ;--------------------------------------------------------------------------- ; Start VIA 1 timer 2. ; ; Called by BSR6 ; ; Inputs: a2 - VIA1 base address ; a6 - return address ; Outputs: none ; Destroys: d0-d2,a0-a5 ;--------------------------------------------------------------------------- StartTimer move.l a6,a3 ;save away in a3 (only safe place!) moveq.l #0,d2 ;prepare for universal call BigBSR6 JGetHardwareInfo,a0 ; <35> move.l VIA1Addr(a0),a2 ;point to VIA 1 base move.b #$00,VACR(a2) ;set up timer 2 for timed interrupts move.b #$20,VIER(a2) ;disable timer 2 interrupts move.b #$FF,vT2C(a2) ;low byte move.b #$FF,vT2CH(a2) ;high byte jmp (a3) ;--------------------------------------------------------------------------- ; Check VIA 1, timer 2 count and if expired, restart, then decrement ; d4.lw. If d4.lw counted < 0, then d0 is set < 0 for caller to ; indicate timer has expired. ; ; Called by BSR6 ; ; Inputs: d0.w - d4 init value, if timer expires ; d4.lw - interrupt counter ; a2 - VIA1 base address ; a6 - return address ; ; Outputs: d0.w - sign bit set if we timed out ; d4.lw - decremented, set to d0.w if expired ; ; Destroys: d1-d2,a0-a1,a5 ;--------------------------------------------------------------------------- CheckTimer move.l a6,a5 ;save return address bclr #15,d0 ;say timer not expired btst #5,VIFR(a2) ;see if counted out beq.s @exit ;no, continue on move.b #$20,VIER(a2) ;disable timer 2 interrupts move.b #$FF,vT2C(a2) ;low byte move.b #$FF,vT2CH(a2) ;high byte subq.w #1,d4 ;count a timer expiration event bpl.s @exit ;still counting... move.w d0,d4 ;expired, re-init d4.w bset #15,d0 ;flag expired with d0.w < 0 @exit jmp (a5) ;and exit ;--------------------------------------------------------------------------- ; Routine to check SCC for any available input. ; ; Called by BSR6 ; ; Inputs: a3 - SCC read base ; d3 - SCC write base offset ; ; Outputs: d0.w - Character received. Bit 15 set if SCC not ; inited or no character in rcv buffer ; ; Destroys: none ;--------------------------------------------------------------------------- GetChar move.w #$8000,d0 ;say no input btst #SCCok,d7 ;SCC inited? beq.s @exit ;no, exit this place with no input btst #rxbf,Actl(a3) ;any char avail at port A? beq.s @exit ;exit no char avail moveq #1,d0 ;address register 1 for errors move.b d0,Actl(a3,d3.l) ;select reg 1 move.b Actl(a3),d0 ;get error flags byte and.b #$70,d0 ;mask off non-error bits beq.s @CharWaiting ;no errors, skip error reset move.b #$30,Actl(a3,d3.l) ;reset errors @CharWaiting lsl.l #8,d0 ;shift flags to upper byte move.b Adata(a3),d0 ;read data byte @exit RTS6 ;got input char, exit to caller ;--------------------------------------------------------------------------- ; Routine to convert from hex ascii to hex. If the character to convert is ; not in the range $30 - $39 or $41 - $46 then hex $00 is returned for ; the converted value. ; ; Called by BSR6 ; ; Inputs: d0.b - ascii character ['0'-'9','A'-'F'] ; Outputs: d0.b - converted nibble [0-15] ; ; Destroys: none ;--------------------------------------------------------------------------- ; CvtAscii and.w #$007F,d0 ;clear any other debris sub.b #$30,d0 ;remove ascii bits bmi.s @error ;below min bound, exit with $00 code cmp.b #$16,d0 ;is above max bound? bgt.s @error ;yes, exit with $00 code cmp.b #9,d0 ;is a letter code? ble.s @numeric ; sub.b #7,d0 ;remove letter part @numeric RTS6 ;exit @error clr.w d0 ;code $00 RTS6 ;exit ;--------------------------------------------------------------------------- ; Get the next N input bytes into register d1, where N is in d2. ; ; Inputs: d2.w - number of bytes to get [0..4] ; d3 - SCC write base offset ; a3 - SCC read base offset ; ; Outputs: d1 - bytes [1..4] ; ; Destroys: d0,d2,a5 ;--------------------------------------------------------------------------- GetNBytes move.l a6,a5 ;copy return address tst.w d2 ;any bytes to get? beq.s @exit ;no, exit clr.l d1 ;clear dest reg btst #aski,d7 ;doing hex or ascii? beq.s @adjust ;hex asl.w #1,d2 ;ascii, double byte count @adjust subq.w #1,d2 ;adjust for dbra @loop BSR6 GetChar ;check for input tst.w d0 bmi.s @loop ;wait for char btst #aski,d7 ;hex or ascii? beq.s @hex ;hex BSR6 CvtAscii ;converted to hex nibble $0-$F lsl.l #4,d1 ;make room for another nibble or.b d0,d1 ;or in the nibble, bits 8-15 = 0 bra.s @next @hex lsl.l #8,d1 move.b d0,d1 ;move byte xx to result register @next dbra d2,@loop @exit jmp (a5) ;--------------------------------------------------------------------------- ; Routine to convert from hex ascii to hex. If the character to convert is ; not in the range $30 - $39 or $41 - $46 then hex $00 is returned for ; the converted value. ; ; Called by BSR6 ; ; Inputs: d0.b - nibble to convert [0-15] ; Outputs: d0.b - converted ascii char ['0'-'9','A'-'F'] ; ; Destroys: none ;--------------------------------------------------------------------------- ; CvtHex cmp.b #10,d0 ;needs number or letter? blt.s @num add.b #7,d0 ;offset for letters @num add.b #$30,d0 ;make ascii character RTS6 ;exit ;--------------------------------------------------------------------------- ; Routine to output N bytes from register d0, where N is passed in d2. ; If N = 0 then just send cr-lf if flag is true. ; ; Called by BSR6 ; ; Inputs: d0.l - Bytes to send ; d2 - Number of bytes to send [0..4] ; d3 - SCC write base offset ; a3 - SCC read base address ; Outputs: none ; ; Destroys: a5,d0,d1,d2 ;--------------------------------------------------------------------------- PutNBytes move.l a6,a5 ;save return address move.l d0,d1 ;copy bytes to send tst.w d2 ;sending anything today? beq.s @crlf ;maybe just cr-lf moveq #4,d0 ;get a 4 sub.w d2,d0 ;4-n = number of places to shift up mulu #8,d0 ;number of bits to shift left rol.l d0,d1 ;align first byte to shift to msb btst #aski,d7 ;doing hex or ascii? beq.s @hex ;hex asl.w #1,d2 ;ascii, double byte count @hex subq.w #1,d2 ;adjust for dbra @loop btst #aski,d7 ;doing hex or ascii? bne.s @ascii ;ascii rol.l #8,d1 ;hex, get the whole byte ready move.b d1,d0 ;msb bra.s @send ;and skip the ascii conversion @ascii rol.l #4,d1 ;get first nibble move.b d1,d0 ;get first byte and.b #$0F,d0 ;...nibble at it BSR6 CvtHex ;convert nibble to ASCII @send BSR6 OutChar ; dbra d2,@loop ;and repeat until done @crlf btst #crlf,d7 ;wants a appended? beq.s @exit ;no move.b #cr,d0 ;send BSR6 OutChar move.b #lf,d0 ;send BSR6 OutChar @exit jmp (a5) ;and exit ;--------------------------------------------------------------------------- TM_SendByte ; <11><8> movea.l a6,a5 ; Save return address <11> move.b d2,vSR(a2) ; Put data in VIA data reg <11> bset.b #vViaFullBit,vBufB(a2) ; Assert VIA Full <11> @10 btst.b #ifSR,vIFR(a2) ; Wait for IRQ <11> beq.s @10 ; Poll until set <11> tst.b vSR(a2) ; Clear IRQ <11> bclr.b #vViaFullBit,vBufB(a2) ; De-assert VIA Full <11> movea.l a5,a6 ; Have the next routine return to caller <11> jmp TM_Wait ; Give Egret a breather <11><8> ;--------------------------------------------------------------------------- TM_GetByte ; <8> movea.l a6,a5 bclr.b #vViaFullBit,vBufB(a2) ; De-assert VIA Full <11> @10 btst.b #ifSR,vIFR(a2) ; Wait for IRQ beq.s @10 ; Poll until set bset.b #vViaFullBit,vBufB(a2) ; Assert VIA Full move.b vSR(a2),d2 ; Read data from VIA (clears IRQ) BSR6 TM_Wait ; Give Egret a breather <8> and.w #$00FF,d2 ; isolate the byte btst.b #vXcvrSesBit,vBufB(a2) ; Return with state of XCVR Session jmp (a5) ; Return to caller ;--------------------------------------------------------------------------- TM_Wait move.w #delay325uS,d0 ;Delay using a VIA access as a time base <17> @delay tst.b vBufB(a2) ;Touch the VIA (each access is ~127΅S <17> dbra.w d0,@delay ;Delay RTS6 ;--------------------------------------------------------------------------- dispose movea.l a6,a4 ; save the return address btst.b #vXcvrSesBit,vBufB(a2) ; Is XCVR Session asserted? bne.s @20 ; if not, just delay and return BSR6 TM_Wait ; Give Egret a breather <11><8> bset.b #vSysSesbit,vBufB(a2) ; Else set Sys Session <11> @10 BSR6 TM_GetByte ; Read a byte - to throw away <8> beq.s @10 ; xcvr ses still on? (active low) bclr.b #vSysSesbit,vBufB(a2) ; Turn off SYS Session bclr.b #vViaFullBit,vBufB(a2) ; Then de-assert VIA Full <11> @20 movea.l a4,a6 ; Have the next routine return to caller jmp TM_Wait ; dispatch to wait 250΅Secs <8> ;--------------------------------------------------------------------------- ; This routine is a register-based version of the Power Mgr trap. It is ; used when we don't know the state of RAM but still need to access the ; Power mgr for some reason, i.e. store startTest results in parameter RAM. ; d0.w should contain the command byte and the number of data bytes to transfer. ; d1 contain the data to tranfer. Obviously, any command that requires over ; 4 data bytes can not be used. For those commands that require a receive ; buffer, data will be placed back into d0-d1, thus destroying the previous ; contents. In addition, a0.w will contain 0 if successful, error code if ; unsuccessful. This is as much of a direct port of the real Power manager ; as was possible. Data is read out of the xfer/rcv 'buffer' from msb to lsb ; of d1. ; ; Called by BSR6 ; ; Inputs: d0.w - command byte/#bytes ; d1.l - up to 4 bytes to xfer/rcv ; a2 - VIA1 base address ; ; Outputs: a0 - 0 if successful, error code otherwise ; ; Destroys: a4-a5,d0-d2, d5 ; Preserves: a1-a3, d3-d4 ;--------------------------------------------------------------------------- quasiPwrMgr ; [v1.1> move.l a6,a5 ;save return address jmp (a5) ;--------------------------------------------------------------------------- ; This routine calls the OS SizeMemory routine, and returns the pointer ; to the memory location table in register d6, with d7.b clear. If SizeMemory ; returned an error, the bad bit mask is left in d6, with d7.b=$FF. ;--------------------------------------------------------------------------- SizeMem ; <1.7><2.0> move.l a6,usp ;save return address ; ₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯₯ ; WARNING! Check this out carefully...it seems to me that some of the diagnostic ; environments that jump through this SizeMem area rely on ALL of the registers ; to stay intact. If that's true, then I can't make a BigBSR6,a0 call to SizeMemory ; because it will wipe out a0. There is no memory available right now to save ; registers. TRIPLE CHECK THIS!!! AARON AARON ; ; The SizeMemoryPatch uses a0 to do a GetHardwareInfo call, so it's safe to trash ; a0 here. HAL 2/12/92 BigBSR6 SizeMemory,a0 ;make OS call sne d7 ;d7=0 if good, d7=$FF if SizeMem failed bne.s @exit ;errors, leave bit mask in d6... move.l (sp),d6 ;return start of memory location table in d6 @exit move.l usp,a6 ;retrieve return address jmp (a6) ;go back home SizeV8VRAMShell ;----------------------------------------------------------------------------- <35> ; ; This test sizes the Elsie V8 implementation of video RAM ; This is a very dangerous test! If video RAM is resized it will change the way ; address lines are multiplexed to the DRAMs from the V8 chip. This will result in ; system memory being scrambled. ; ; This test is OK to run from the serial test manager ; ; inputs: ; none ; ; output: ; d6.l -1 test does not apply (not on a V8 elsie ; 0 no video RAM installed (should have a latch SIMM ; 256K 256K of video RAM installed ; 512K 512K of video RAM installed ; ;----------------------------------------------------------------------------- <35> movea.l a6,a3 ;save the return address <35> moveq.l #0,d2 ;First set up the universal registers <35> BigBSR6 JGetHardwareInfo,a0 ; <35> moveq.l #0,a2 ;Make sure a2 is zero now <35> BigBSR6 SizeV8VRAM,a4 ;and call the VRAM sizing routine <35> move.l a2,d0 ;see what a2 is <35> bne.s @applies ;if it's not zero, keep going <35> moveq.l #-1,d6 ;otherwise, this test does not apply <35> bra.s @done ;exit here <35> @applies moveq.l #0,d6 ;now zero d6 <35> btst.b #V8vRAMIn,V8Exp(a2) ;is there any VRAM? <35> beq.s @done ;nope, leave d6 set to zero <35> move.l #1<<18,d6 ;else, report 256K of VRAM <35> btst.b #V8512Row,V8Exp(a2) ;do we have 512K? <35> bne.s @done ;exit if not <35> lsl.l #1,d6 ;else, adjust d6 <35> @done jmp (a3) ;return (d6 contains the info) <35> ; ;------------------------------------------------------------------------------- ; Routine: SetVectorTable ; ; Inputs: a1 - where we want the table to be located ; ; Outputs: VBR - Points to RAM based exception table ; ; Destroys: a0-a2,d0-d2 ; ; This routine sets up the exception vector table in RAM for any machine. ; A1 points to where we want the exception table. It makes the vectors point ; to the table in which we're presently running (ROM or RAM). ;------------------------------------------------------------------------------- SetVectorTable IF forRomulator THEN ; check if we are ReAnimatorͺing TestInRAM a0 ; are we running in ram? beq.s @Normal ; Change the VBR if we're not in RAM movec vbr,a0 ;else, get the current vbr move.w #VTEntries-1,d0 ;get the size of the vector table movea.l a1,a2 ;save the new location @CopyVBR move.l (a0)+,(a1)+ ;copy a long dbra.w d0,@CopyVBR ;copy it all movec a2,vbr ; RTS6 ; @Normal ENDIF ; {forRomulator} BigLea BaseOfRom,a0 ;get actual base of rom address move.l a0,d2 subi.l #RomStart,d2 ;subtract out equate BigLea TMVectors,a0 ;point to ROM vector table move.l a1,a2 ;keep copy of start of RAM vector table move.w #VTEntries-1,d0 ;get number of entries @loop move.l (a0)+,d1 ;get entry offset add.l d2,d1 ;make it absolute move.l d1,(a1)+ ;move into vector dbra d0,@loop ; movec a2,VBR ;VBR points to our exception table RTS6 ;return ;------------------------------------------------------------------------------ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; This marks the beginning of the "new" TestManager code. ; ;------------------------------------------------------------------------------ ; ; If we get here we can assume that a0 points to the information that needs ; to be on the stack in order to make the selected call (the info has been setup by ; the "phony" GI_xxx calls in the file "app interface.a"). This entry point copies ; this information to the stack, then makes the call. ; ; In addition, d0 contains the TestManager function code as requested by the user. The ; function codes are divided up into two categories, with the delimiter being the value ; in the high word of d0. If the high word is 0001, then the request is for a CTE ; GI_xxx routine. If it is 0002, then it is a TM utility function. The codes are defined ; as follows: ; ; d0 = $xxx10000 GI_InitInterface ; $xxx10001 GI_GetVersion ; $xxx10002 GI_AllocPermMem ; $xxx10003 GI_AllocTempMem ; $xxx10004 GI_FreeTempMem ; $xxx10005 GI_GetCommentary ; $xxx10006 GI_GetDefaultExecutionOptions ; $xxx10007 GI_ExecuteDTM ; ; $xxx20000 Initialize the CTE interface for use with the TestManager ; $xxx20001 Get the info for a ROM-based test and subtest ; ; As it stands right now, there are entry points in the file "app interface.a" ; that setup the necessary info on the stack (with a0 pointing to it) and jump into ; the _TestManager entry point. There, the function code in d0 is checked, and if it ; is a "new" style TM call, it branches to here. Then, this routine takes care of ; setting up for the particular call and making it. ; ; I'm not sure if the utility routines are going to stay around, or are going to be ; published as required setup stuff for shells using the ATrap and CTE, or what. ; Stay tuned. ; ;------------------------------------------------------------------------------ NewTMCall @savedregs reg d1-d7/a0-a6 ; saved registers (might as well save it all (except result reg, d0)! movem.l @savedregs,-(sp) ; save some registers move sr,-(sp) ; save our status ori.w #hiIntMask,sr ; turn off interrupts link a5,#0 ; must do this after saving the regs because ; we don't know ahead of time how much stuff we're ; going to stick on the stack move.l (a0)+,d1 ; get the number of longs in the call beq.s @noParams ; branch if there are none lea (a0,d1.l*4),a0 ; go to the end of the list subq.l #1,d1 ; adjust for dbra loop @copy move.l -(a0),-(sp) ; copy the items onto the stack dbra.w d1,@copy ; and keep going until done @noParams lea LocalFunctions,a0 ; get the base address of the local function table move.l d0,d1 ; make a copy of the opcode swap d1 ; get the high word of of the opcode cmp.w #1,d1 ; is this a utility function call? (0002 is a utility) bne.s @UtilFunc ; branch if so lea NewTM_Table,a0 ; else, assume we have a CTE function @UtilFunc move.l (a0,d0.w*4),d0 ; get the offset from base to the routine jsr (a0,d0.l) ; make the reference absolute and make the call unlk a5 ; get rid of how ever much stuff we put on the stack move (sp)+,sr ; restore the status register movem.l (sp)+,@savedregs ; and restore saved regs rts ;------------------------------------------------------------------------------ ; ; This table is for the local utility calls used by the "new" TestManager. ; ;------------------------------------------------------------------------------ LocalFunctions ; requested routine function code (d0) ; ----------------- ------------------ dc.l LclInitializeCTEandUST -LocalFunctions ; $xxx2 0000 dc.l LclGetROMBasedDTMInfo -LocalFunctions ; $xxx2 0001 ;------------------------------------------------------------------------------ ; ; This table takes care of the CTE calls supported by the "new" TestManager. ; ;------------------------------------------------------------------------------ NewTM_Table CASE ON ; requested routine function code (d0) ; ----------------- ------------------ dc.l GI_InitInterface -NEWTM_TABLE ; $xxx1 0000 dc.l GI_GetVersion -NEWTM_TABLE ; $xxx1 0001 dc.l GI_AllocPermMem -NEWTM_TABLE ; $xxx1 0002 dc.l GI_AllocTempMem -NEWTM_TABLE ; $xxx1 0003 dc.l GI_FreeTempMem -NEWTM_TABLE ; $xxx1 0004 dc.l GI_GetCommentary -NEWTM_TABLE ; $xxx1 0005 dc.l GI_GetDefaultExecutionOptions -NEWTM_TABLE ; $xxx1 0006 dc.l GI_ExecuteDTM -NEWTM_TABLE ; $xxx1 0007 CASE OFF LclGetROMBasedDTMInfo ;------------------------------------------------------------------------------ ; ; This routine will take a ROM-based test and subtest ID, and a pointer to an info ; structure for each (allocated by the caller), and fill in those info structures ; based on information from the ROM-based tables of tests and subtests. This routine ; is available for shells that wish to use the ATrap to run ROM-based DTMs under ; CTE. The shell need only allocate memory for the various structures needed (this ; can be accomplished by asking the TestManager to make an AllocPermMem call and ; getting the pointer back from the TestManager), and the TestManager will take care ; of making the calls to CTE in the ROM. The advantage is that the TestManager can ; also help the shell access ROM-based DTMs, get the ROM-based info about them in ; the structures, then let the shell override some of that info (such as standard ; test params, etc.). ; ; If a shell is using a ROM-based test or subtest with a non ROM-based test or ; subtest, then it only needs the info for the ROM-based entity it is using. In ; that case, it should pass in 0 for the ID of the entity (test or subtest) that ; it doesn't need me to get the info for, and I will skip it. ; StackFrame RECORD 0, Increment ; Starts at offset 0 into the stack @return ds.l 1 ; Return address @CTEInfoPtr ds.l 1 ; CTE information pointer @SubtestID ds.l 1 ; ID of subtest to return information for @STinfoPtr ds.l 1 ; Pointer to where to put the subtest info @STinfoSize ds.l 1 ; size of subtest info area @TestID ds.l 1 ; ID of the ROM-based Test @TinfoPtr ds.l 1 ; Pointer to where to put the test info @TinfoSize ds.l 1 ; size of test info area ENDR ; ;------------------------------------------------------------------------------ WITH CTETestInfo, CTESubtestInfo, StackFrame move.l @STinfoSize(sp),d0 ;get the size of the reserved area for subtest info cmp.l #sizeofCTESubtestInfo,d0 ;is it big enough? bge.s @STInfoAreaOK ;continue if OK move.l #-5,d0 ;else, signal error bra.w @exit ;and exit immediately @STInfoAreaOK move.l @TinfoSize(sp),d0 ;get the size of the reserved area for test info cmp.l #sizeofCTETestInfo,d0 ;is it big enough? bge.s @TInfoAreaOK ;continue if OK move.l #-6,d0 ;else, signal error bra.w @exit ;and exit immediately ENDWITH @TInfoAreaOK WITH StackFrame, USTSubtest, CTEInfo, USTGlobals, CPUTestList, CTEDTMExecutionOptions movea.l @CTEInfoPtr(sp),a0 ; get the CTEInfo pointer movea.l executionOptions(a0),a0 ; get the execution options ptr ; get the ptr to the userInfo (which ; points to the USTGlobals) movea.l CTEDTMExecutionOptions.userInfo(a0),a0 movea.l GlobCPUTestList(a0),a1 ; and finally, the pointer to the CPU test table ; Given the subtest ID from the user, find it in our machine-specific DTM table, make ; sure it's OK to run in this environment (ATrap), and fill in the subtestInfo ; structure information: move.l @SubtestID(sp),d0 ; get the subtest ID beq.s @TestSearch ; if it's zero, then get the info for the test ; and skip the subtest stuff @CPUTestListLoop cmp.w TLSubTest_ID(a1),d0 ; is this the one? beq.s @foundCPUST adda.l #sizeofCPUTestList,a1 ; go to the next entry cmp.w #-1,TLTest_ID(a1) ; is this the end bne.s @CPUTestListLoop ; keep looking if not move.l #-10,d0 ; else, sigal error - subtest not found bra.s @exit ; and exit @foundCPUST move.w TLrunflags(a1),d1 ; get the run flags and.w RunMode(a0),d1 ; see if it's OK to run this bne.s @STOK ; branch if so move.l #-11,d0 ; else, error out bra.s @exit @STOK ;;; movea.l #USTSubtests,a3 ; get a pointer to the subtest list in ROM BigLea USTSubtests,a3 ; this will only work in ROM move.l a3,d2 ; save this for later movea.l @STinfoPtr(sp),a1 ; get the pointer to the subtest info ; Go through the process of searching the ROM-based Subtest list for the target ; subtest ID, and load its info into the provided info structure: @SubtestListLoop WITH USTSubtest, CTESubtestInfo cmp.l STSubtest_ID(a3),d0 ; is this our subtest? beq.s @foundSTEntry ; jump if so add.l #sizeofUSTSubtest,a3 ; go to next entry bra.s @SubtestListLoop ; and keep looking @foundSTEntry move.l #0,userInfo(a1) ; fill in the user info move.l STSubtest_ID(a3),id(a1) ; fill in the subtest ID move.l STEntryPtr(a3),functionEntry(a1) ; fill in the entry pointer add.l d2,functionEntry(a1) ; and de-reference it move.l STParamSize(a3),paramsSize(a1) ; fill in the param size move.l STResultSize(a3),resultsSize(a1) ; and the result size ENDWITH ; Now, do the same with the Test ID, using the ROM-based Test list: @TestSearch move.l @TestID(sp),d0 ; get the test ID beq.s @finished ; if it's zero, then the user wanted info ; for a subtest and not a test, so ; just skip all of this BigLea USTTests,a3 ; get a pointer to the test information move.l a3,d2 ; and save it here movea.l @TinfoPtr(sp),a1 ; get a pointer to the test information to fill out @TestListLoop WITH USTTest, CTETestInfo cmp.l TTest_ID(a3),d0 ; is this our test? beq.s @foundTEntry ; jump if so add.l #sizeofUSTTest,a3 ; go to next entry bra.s @TestListLoop ; and keep looking @foundTEntry move.l #0,userInfo(a1) ; fill in the user info pointer move.l TTest_ID(a3),id(a1) ; fill in the test ID move.l TEntryPtr(a3),functionEntry(a1) ; fill in the entry pointer add.l d2,functionEntry(a1) ; and de-reference it move.l #0,paramsSize(a1) ; zero out the paramsize move.l #0,resultsSize(a1) ; and the result size ENDWITH ENDWITH @finished moveq.l #0,d0 ;signal success @exit rts LclInitializeCTEandUST ;------------------------------------------------------------------------------ ; ; This is the entry point used to initialize the CTE kernel for use by the "new" ; TestManager ATrap. The ATrap is unique among the five ROM-based diagnostics ; environments (Startup/Restart, Serial Test Manager, ROM BurnIn, In House Tester ; hook, TestManager ATrap) in that it doesn't make the USTInit call (but it does ; use the USTGlobals). Also, it doesn't use a5 to keep track of the USTGlobals because ; the ATrap is running under the MacOS, where the other diagnostics environments ; are running before the OS is created and initialized (they own the Mac at that ; point). So, for a lack of an a5, the ATrap uses a little trick to keep track of ; the USTGlobals without the need to modify the CTE globals to keep a pointer in ; there (this provides for a cleaner separation of church and state, i.e., the ; ATrap and CTE). The ATrap stores the USTGlobals pointer in the userInfo field ; of the executionOptions structure, which is created as part of the CTE initialization. ; As long as the user is relying on the ATrap to handle CTE stuff, then this is ; safe. If the user wishes to modify the exeuctionOptions userInfo pointer, then ; the user is responsible for re-initializing the ATrap's environment or at least ; restoring the userInfo field to point to the USTGlobals. ; ; If an outside shell is going to be using the ATrap with CTE, it will need to ; allocate the necessary memory from the Memory Manager (remember, the ATrap is ; the only ROM-based diagnostics environment that runs while the OS is active). It ; passes a pointer to this memory and its size to this routine, which will treat it ; as the CTE workspace. ; ; CASE ON LclInitializeCTEandUSTStackFrame RECORD 0, Increment ;Starts at offset 0 into the stack @ReturnAddr ds.l 1 ;Caller's return address @CTEGlobs ds.l 1 ;Pointer to the CTE globals @CTESpaceSize ds.l 1 ;size of CTE workspace ENDR ; ;------------------------------------------------------------------------------ WITH LclInitializeCTEandUSTStackFrame, ProductInfo, USTGlobals, CTEInfo, CTEDTMExecutionOptions movea.l @CTEGlobs(sp),a0 ; get the CTE globals pointer move.l @CTESpaceSize(sp),d0 ; and the size of the globals CASE ON GIM_InitInterface (a0), d0 ; initialize the interface CASE OFF movea.l @CTEGlobs(sp),a0 ; get the CTE globals again move.l #sizeofUSTGlobals,d0 ; and the size of the USTGlobals CASE ON GIM_AllocPermMem (a0), d0 ; allocate our USTGlobals from CTE space CASE OFF movea.l @CTEGlobs(sp),a0 ; get the CTE globals again movea.l executionOptions(a0),a0 ; get the executionOptions pointer move.l d0,CTEDTMExecutionOptions.userInfo(a0) ; and put the USTGlobals pointer in the ; userInfo field of the CTE ; executionOptions structure, where the ; ROM-based Test can find it (if the ; ROM-based Test is being used...if not, ; then the user can change the userInfo ; field if needed) movea.l d0,a1 ; and put the USTGloblas pointer here for ; immediate use (this routine only) movea.l @CTEGlobs(sp),a0 ; get the CTE globals again movem.l a0-a1,-(sp) ; save our registers move.l #gestaltProcessorType,d0 ; find out the processor type we're on _Gestalt ; ask gestalt for the info tst.w d0 ; any errors? beq.s @OkProc ; if not, return result moveq #envCPUUnknown,a0 ; oh well, use SysEnvs bad way of saying ; "unknown processor type" @OkProc move.w a0,d0 ; save the processor type from Gestalt ; IS THIS CORRECT? IS a0 THE RETURN VALUE ; FROM GESTALT??? movem.l (sp)+,a0-a1 ; get our registers back move.l d0,processorType(a0) ; save the processor type ; Fill out the rest of the USTGlobals structure for use by the ATrap: movea.l UnivInfoPtr,a2 ; get the pointer to the universal information ; (this is a lowmem global that points to the ; ProductInfo structure) moveq.l #0,d1 ; zero out a register move.b ProductKind(a2),d1 ; get the boxflag ;;; The boxflag is never used in Scott's ATrap stuff, so I'm going to comment it out ;;; for now, and remove it if it turns out to be unnecessary. ;;; ;;; move.l d1,boxFlag(a0) ; store it move.w #RunBits.ATrap,RunMode(a1) ; store our environment flag move.l a0,CTEGlobals(a1) ; store a pointer to the CTE kernel move.l #0,ErrorHandler(a1) ; zero out the error handler pointer move.l a2,PrdctInfPtr(a1) ; get a pointer to the product info pointer movea.l (a2),a3 ; get a pointer to the decoderinfo record adda.l a2,a3 ; dereference it move.l a3,DcdrInfPtr(a1) ; put it in our local area move.l AddrMapFlags,BasesValidFlags(a1) ; and store the bases valid flags ; (AddrMapFlags is a lowmem global ; that contains the bit numbers of ; BasesValid flags) WITH CPUList, CPUTestList ;;; movea.l #USTCPUList,a0 ; a move for now, a load when it gets to ROM BigLea.l USTCPUList,a0 ; start at the beginning of the list of tables move.l a0,d3 ; save this for later @itemloop move.w cpuBoxFlag(a0),d2 ; Get the box flag for this test table cmp.b #boxUnknown,d2 ; Is this the end of the table? beq.s @found ; quit if so - we'll use the default tests cmp.b d2,d1 ; is this the table entry for this machine? beq.s @found ; quit if so addq.l #sizeofCPUList,a0 ; else, go to the next table entry bra.s @itemloop ; and keep looking @found movea.l CPUTestListPtr(a0),a0 ; get a pointer to the test table for this CPU lea.l (a0,d3.l),a0 ; and dereference it move.l a0,GlobCPUTestList(a1) ; and store it in our global area ENDWITH ENDWITH moveq.l #0,d0 ; clear out the return status rts ENDPROC