-not a Macintosh disk-FbGYa4GYa;0a:a4BH@%L?nNP"N,L 8!"@$|Gn"`I N.@A,H<( F<B<H111.Bx<kNNF`, 8! "NH@"|J(g g`LNu"_ |a||a0@||9݁g|w|a||NH瀀 |(_@"g2<@gBA?N`Fa`||aPLNu  fBR$N"NBH@&|݁ |B$<0HN~NL@dBgg>N&|)`RNuBBBA*2h/ BBB N _"_$_"H&|݁ |B$<0NNd 0<`L$|J HA H  2I<FFI<<FFfHHFFfHHH?B@L"_2N _0H 2<@I6@o Az:<2`6@oJA~:<26" @n2BDBB(`EB@nAJEkz`z2<HAIL0.NL0.N  / p? O@ 0  0  XO _,_2_!.NBBB/ BBBN08 @ gNu@ f"_E!NH\O/ ?`@&x|N _!@"|xEz En"`CE"|xN"Ҹ< A  33"|@E E4n"`C&E"|@.N _LHNFLN*8&E@<<'CJJKK f`  f `><$CS*<FF4>BRIBC Gff&<CBSC`D GnKG45BQf` f `Ns |0< BXHQ!4 _$_"_!XOHH/8/ $ f0<? QN ! N.x $_$ g ! N.x !C !!LLyp!N\OFN  l0P߀ Aǀ`  6lo6@ 0_an*>]> j 56, l602  ۰Poo A` &ll6p@ 0?۷a?^ ꭕ 5o6, l602 8!ED91kE"0369? CoNGNOS BOOT FAILED TRY A NEWER MACHINE AND BOOT PROM _"_NN/A lNNu _.NHL$ orD?|?@?e\SFk!!QSWk:CL<HL|hH>L|4H>L|H>SWjTO>SGk\!Q`TSFk QSWk8L|H|L|H|4L|H|hL|H|LSGkQLx _O NNVH8=| f=|G* G, &N(N n"n$n 0.  S@ZeJ S@BBDBG S@gg.BC CJDg720faL`fa:` 320f8<S@`JDg  fa$` fa`  U@o$SBjt`(N&N><`JGg (Ev#$#$QNukJDg`g 3$f(N`BnLN^ _NUNPACK H>8$O&j.(j4,*8:*,BB6*2SCCn`8CL0@D@04"F K0HEY@2< Vb,g`aJaBVgbHE6SCCo`p`HE4RBCo8B@ j(0 j$L| _pN am znNu _"_$_$0H2< @`Q`BQBNNV;n *N^.NuEVINIT NVH,. ^J]g n0`4B?N. f n0`/.//. /.N6(n)FLN^ _NEAD_BLONV/ (n Jno./.?././ /.Nj nJPg`RSn`(_N^ _NEAD_SEQHNT"|E.|r |BBByBygRBf~NuLHPPNqNqpS_n.0<QLHPPNqNqpS_n|~By&JM*Np|azJGfb|a|,Mpa`JGfH|a<<AaJGf0Avtp BQvr BQH@02N\LhL"4NtB@6Kd a"JDf`02IP g a JDf`Nub SBg pxNuBDNu><Nu4< vB@bp2IPSCfSBfNuppB@(4<dBC(4< CBC(C"H4<BACSBf(CAg><NuJoNV?-,N.H|)?NN^ _TONRAP NV.HgVS@g`J.f& -`мS//<N/<NB+_`-m` . ѭ` -`o<Np`B . \J.f/-\/<N4/<N+_\-m\ -\l<N,N^ _PONGETSPACNV .мS//<N/<N-_ .=@ N^.NuINDSPARNVH.. Bg/N0Hހ m0.@I/./<N 8//<Np @n ?.Bg?<BgNLN^ _ NETMMU NVH+| d+|l+|(+||+|+|t+|(|;TV(|;T|(|.;Tz&| n!SLN^.NuETVARS NVH/Nt;| .䐼/+@ .м/м+@+|`*<(< E"D +@\&|?-|0-VS?NHnHmJNJngp+@JBBg/-BgNz+_ -Э+@XBB<0<H/BgNPN+_P+mPBG` m @I G~V GTVgd Gl|p@ @8`$ Gf|p@BT`| p@BT H< @"@=A?.??<BgNRG Gox mI|p@BT mIP|p@/-P/<N* 8LN^NuOOTINITNVH(nB BgNBgNHH,BgN0HѬ f,/, N"BgNBgNHH,BgN0HѬ f,/, NBgNrBgNjHH,BgN0HѬ f:Jf< N/, NBgN2BgN*HH,BgNb0HѬ g<NLBN,BN+_ n/BN|  _r Ё0p//-`N/-/-`N&m`:=E E0o<N0<H+@l+| -lЭd n2HҀ -Ё"-Ҁ(Bg Э/N0Hѭ -Є+@B</-BgN+_+mh -dЭh+@p -lЭp, n0HІ+@ -Э+@ -Э+@?<f/-/-?<Nb-m/ /./-N n LN^ _ NUILD_SYNVH(nBGBF. gB `P-n n0. PoB."` n0. A-H&n/+/<N  n0>+<+/, NBgN<BgN4HH-@BgNj0H(٬ JVJ_gB."`4JGW WJGV WgJFf n `H n n/B."n/BgN2  _ BNB-_JGf n Q/ n P/Nr` Q@H/ n P/NZ|B. n=h-nA-H n-P/./.p/N JGgR-mBg n/( n r Ё/ n P/ nP/ | ? Q@?N9_Jlg< N, nQ f|"LN^ _NOADSEG NVHBBg/-tBgN+_x -x"-Ҁ+At(|`p}//<Nn -Пx((|p}//<NN -Пx(?<}/-x/-t?<N&|BSLN^.NuLLOC_SCNVHAC 0BgHnNz_m+m-gBBg/-BgNP+_`+m-gBBg/<BgN, м,BgBgBHnBgHnHnBg/.N g<NACD 0BgHnN  g B-n`.BgBgBHnBgHnHnBg/.Nx g<Nf .@+@ -Э+@` B -@+@ -м@+@?</-/-?<N@ <逐.JfB` .ЇP-@JfB` .ЇP-@-g -Ї/ -Ї//./.N`/-/-BBN(|p((|t(LN^.NuOAD_DEB SYSTEM.DEBUG2 SYSTEM.DEBUGNVH nCJp"S@n2&n (nBBgHnN dgZB /, N NBgN BgN HH(BgN0H* f&.B</BgN&B /, N //NlLN^ _ NOAD_UNPNVBgBgBHn</. /.Bg/.N g<NN^ _ NOAD_LLDNVH(n 0-N|>Jg,, .* Ю(H//<N( Д-@`,.(.H//<N-_?//?<N. .P/NdLN^ _NNSTALL_NVH(n=n ~`/, N BgN p_BgN fHH(BgN 0H-@Jg .Ѭ `<N~ .fBN (BN ( GfAB0pB5pB`ACZ 0z`BgN _ .ARE EoHn?<?<HnNAC 0HnHzNg(AB0pp @AB @AB`2HnHzNPgAB0pB5pB`App| 5pgnBg?/.Hn @AHp @AHp</.NX g<NF?. @A/0 @A"0Ҽ/?<NHRGinoLLN^ _ NOADCODEkrni NVBBg/-BgN+_?<e/-/-?<NN^.NuAKESUPSNVH(m . R A T&@-kLN^ _ NINDMAINNVBg/-NF0HѭB</-BgNx+_?<g/-/-?<N\Bg/-|N 0Hѭ|B</-|BgN>+_?<{/-/-|?<N"N^.NuLLOC_OPNV A0C ArC 0AC 0/NLHnHm/NFBgHn0N g< NHnHn/NBgHnrN g<N^/NZBg/.Hn$/N;_N/./.Hm/N-UgNj/.$?-N/N@/N2 n /B/.$0-NH//NR  _ /NBNj+_N^ _PONOADSYS $ SYSTEM.UNPACK SYSTEM.OS SYSTEM.LLDN :NV,_NUvN ,+|v mv PVD@UNHmHmNHm?- -|Э//-NzNZN N]N NuN^NuOADER NVHAv(HA^&HHn?-.0-0H".Ҁ// / NrJng<NLN^.NuEAD_PAGNV0.HBH"-DҀ-A0.HBH@J@=@/.NvAv0.HЈ-@ N^ _TONIND_SENNVBH nCJp"S@n2 n BBgA/A/Nz-m2Av(H&L U.=m6B|`A^-HHAv(BE`:HnN?-.0-0H".ҀH҅///.HNhؼJnNg<NRE Eom6l^Bn So4 X/ U/0S@?A/?<$Hn/. N n gRn G0.D@@20HҌ-A n-P`/ /?A/?<$Hn/. NRFinBo$ n g< G0.D@@20HҌ-A/.HnP?<NN n/B?.vN4  _ LN^ _ ND_SEARCNVH n-h .S/0-:H/N ;@Z-n p+@V;m:\BF` AvIBBlRF Fo=mHnNBgHn?->N>H/p6/NNZBp6/A/NACp S@n0HnN^J.gHHnHnN .Wgz n/B?.N  _ `SFRGm>fBGBNJFfELN^ _PONOOKUP_ENVH.<A"G";n .;m.,?.?-.N;n0BN&Av(HJg<NH;l~:+lD;lB;l>;l@;l<;T8;l26+l.2 2f<N m8lB?,N&_+SH+kL+kPLN^.NuNITMEDINV m8lBg/.HnN2_`/.HnHnNn .gB/.N-_N^.NuPENINPUNVH(.BGBF Go<NR Av:0JEf<N8 EHl@ AvH"Ұ n n Jf<NHH " n ``RGE`LN^ _ NIND_POSNV-mV/.0-:H/N+_VJV]2-ZHV]g<N0-:H/-V/N2 .;@\ -Vg/-VHnHnN/.N"N^.NuILLBUF NV0-\m:f -VR2-:H//NNT0-\AvpRm\N^NuETBYTE NVHBgNHH<BgNH>JGl H м> G=@LN^NuETWORD NVHBgN0H//<ND,BgN0H.Jl޼ Ї-@LN^NuETLONG NVH,. 0-:m\>HǼl>JGo0-\AvA//.H/NH߮Hǜm\0-:HnJV]2-ZHV]g<N -VR/HnHnNn-nA^(H/0-:H/N*l-EJoZHn?-.0-0H".Ҁ/?././ NjJng<N~0-:H/./N(ٮ .Ѯ .ѭV`:Jo -VR2-:H//NNhJfLN^ _PONOVEMULTNVH(n0,k @nH0;N *6BN\BgHlN_`n/,N`dBgN_`XBgN9_`LBN)_`@/,/,N:`2&l.,/ ?-.0-0H", Ҁ/?,/ /NP`<NhLN^.NuRIVER_C//0/2/ AH@B@2/Ё/@" /WXNuNV// /"/N:/A" N^/WXNuNV// /"/N/@" N^/WXNuH>*jD,jD$HBJBf6B@H@g4HB04"B@H@`$&BBxԂрҁmRQJjDjDL|NuNuNuJoNu$_0 _"_J @o4$ Tg,2ABAgSBgS@2@ISA QS@kQN$_0 _"_J`!QN$_02 _`QNHBB oJ0/2/gk gRBSAn` R gSBRAk?B/oL\NuHBB oJ0/2/gk fRBSAn` R fSBRAk?B/oL\NuHr`HBA oJ"oJB@f`fQ AA/oL\NuH"o J oJv`:H"o J oJBC`&H o J"oJv`H o J"oJBCB@BA@m4`4`fQ@n C`cC"/oL\NuH0/ oC"4JBAR`$aJBBB`QQ oC"0/H#//IL._NuH oJB@BA"o JBBBlBA`$HR` fQ`RS@`?A"/oL\NuH o0/2/SA"o JBBA@m`Q/o L NuB`$_02 _ @o0 Ao*BBAm"6@SCBoSA`@"H`RCoN$_0"_ _J/ S@m*BABB@m6B$I”@`!Q`QNuϞJ Rev H 1 of 2~!{t TRANS"|~J  :a$ kTZkJϞe3 "#LUd MH   o0$.%jê$rm248.B.TEXT̞HH$RM248.E.TEXTd}$rm248.K.TEXT$rm248.S.TEXT&00k.OBJ$CMGRASM2.TEXT$sexydate.OBJq$MFSRfn1.TEXT$HWEqu.TEXT>$ MacBTMaint2.TEXT8$ macrmgr.OBJ$!xmaccrsrcore.TEXT$"MacATP.OBJg$#xmacFormat.TEXTk$$SONYRWT.TEXT$-MDEFPROC.TEXT4$/listf68k.OBJm.cd_Priam Diskf7*$system.cd_ProfileŞ7*$system.cd_Serial Cableˑ7+!$system.cd_Sony۰7*$system.debug@07+?$system.debug2@?7+C@@$system.IUDirectory7.Ӟ<.. $system.lldX7+%(($system.os?u7+\ $SYSTEM.PRD>$system.PR_Imagewriter / || DMP'7+hDD$System.PR_Ink Jet Printer'7+88$system.shell'7+($SYSTEM.UNPACKȩ7*$tlasm/diskequ.textxMxO$$$TLAsm/FSEqu.textf4@@H X0h@NN rm248.B.TEXTB.TEXTSn`N^ _PONСϞJ̢wNV n  M RM248.E.TEXTE.TEXTSn`N^ _PONСϞJdw}NV n   rm248.K.TEXTK.TEXTSn`N^ _PONСϞJwNV n   rm248.S.TEXTS.TEXTSn`N^ _PONСϞJwĞ&NV n  o BSR CHKSTATPM ;check special save area CHG034 ; BCC.S DOBOOT ;skip if valid data saved ; CLR.B STATSAV ;else set status to 0 (.ENDC (.IF ROM4K = 0 (.IF USERINT = 0 (LEA INITMSG,A3 ;set ptr to OK msg (BSR DSPMSGR ; and display NOTOK BSR.S DSPROMS ;display ROM versions (BRA.S DOBOOT ;and go do boot (.ENDC ;{USERINT} (.ENDC ;{ROM4K} (.IF ROM4K = 0 (.IF USERINT = 0 ;------------------------------------------------------------------------- ; Subroutine to display ROM version #'s ;------------------------------------------------------------------------- DSPROMS LEA CROMMSG,A3 ;display CPU ROM version # (BSR DSPMSGR (LEA IORMMSG,A3 ;display IO ROM msg (BSR DSPMSG (MOVE.B DISKROM,D0 ;read ROM # (MOVEQ #2,D1 (BSR OUTCHR ;and display it (RTS (.ENDC ;{USERINT} (.ENDC ;{ROM4K} 3.4 "6F^883ND!l^  (.PAGE (.LIST ;------------------------------------------------------------------------- ; All is OK - check for boot device and then do bootstrap ;------------------------------------------------------------------------- DOBOOT BSR CURSORINIT ;init cursor/mouse BOOTCHK (CLR.L D0 ;clear for use (BTST #ALTBOOT,D7 ;check if alternate boot command rcvd (BEQ.S @1 ;skip if no (MOVE.B BOOTDVCE,D0 ;get alternate boot code '.IF BURNIN = 1 (CMP.B #PC,D0 ;power-cycle mode? (BNE.S DVCECHK ;if no, go determine device (BSR SAV2PM ;if yes, save in parameter memory '.ENDC (BRA.S DVCECHK ;and go determine device @1 (.IF USERINT = 1 (BTST #BTMENU,D7 ;boot menu wanted? (BNE BOOTMENU ;skip if yes (.ENDC (BSR CHKPM ;next step is to check parameter memory (.IF AAPL = 1 (BCS NMISET ;skip if not to default boot (.ELSE (BCC.S @2 ;skip if valid ; set default boot (TST.B SYSTYPE ;else check if Lisa 1 CHG030 (BEQ.S @5 ;skip if yes CHG030 (MOVEQ #1,D2 ;else set wait flag CHG030 (BSR CHKPROFILE ;and go check if hard disk attached CHG030 (BEQ.S @5 ;skip if yes to do boot from hard disk CHG030 (MOVEQ #TWIG2,D0 ;else set for boot from floppy CHG030 (BRA.S @3 ; CHG030 @5 MOVEQ #PROFILE,D0 ;else if not valid do default boot from Profile (BRA.S @3 (.ENDC @2 MOVE.B DVCCODE,D0 ;else read device code (LSR.B #4,D0 ;rotate to low nibble (BRA.S DVCECHK (.IF NEWTWIG = 0 (BSR EXPAND ;convert id to keycode (.ENDC @3 (.IF ROM16K = 1 ; Do special check for Applenet and I/O test cards (MOVE #TSTCRD,D1 ;search first for a bootable test card (MOVE #TSTQUAL,D4 (BSR SEARCH ;go do search (BNE.S DVCECHK ;skip if not found (MOVE D2,D3 ;else save its id (MOVE #APPLENET,D1 ;next search for an Applenet card (MOVE #APPLQUAL,D4 (BSR SEARCH (BEQ.S @4 ;skip if found to boot from it (DMT need) (MOVE D3,D2 ;else do boot from I/O test card (DIAG need) (BPL.S DVCECHK ; unless card boot bit not set CHG012 @4 (MULU #3,D2 ;convert to boot id (MOVE D2,D0 ;and set boot id for appropriate slot (.ENDC ; Alternate boot desired - check which DVCECHK MOVE.B D0,BOOTDVCE ;save for later reference (.IF TWIGGY = 1 (TST.B D0 ;boot from upper drive? CHG009 (BNE.S @1 ;no - go to next check (TST.B SYSTYPE ;check system type CHG009 (BEQ.S @11 ;skip if Lisa 1.0 CHG009 @10 BRA PROBOOT ;else do Pepsi boot CHG009 @11 MOVE.B #DRV1,D0 ;else set drive # CHG009 (BRA.S @2 ;and go do boot @1 CMP.B #TWIG2,D0 ;boot from lower drive? CHG009 (BNE.S @3 ;skip if no (MOVE.B #DRV2,D0 ;else set drive # @2 BRA TWGBOOT ;and go boot (.ENDC @3 (.IF PROFLE = 1 (CMP.B #PROFILE,D0 ;boot from Profile? (BEQ.S @10 ;yes - go do it CHG009 (.ENDC (CMP.B #IO1PORT2,D0 ;boot from slot 1, ports 1-2? (BGT.S @4 ;skip if not (MOVE.L #SLOT1L,A1 ;set slot address (BRA.S @9 ;and go do boot @4 CMP.B #IO2PORT2,D0 ;boot from slot 2, ports 1-2? (BGT.S @5 ;skip if not (MOVE.L #SLOT2L,A1 ;set slot address (BRA.S @9 ;and go do boot @5 CMP.B #IO3PORT2,D0 ;boot from slot 3, ports 1-2? (BGT.S @6 ;skip if not (MOVE.L #SLOT3L,A1 ;set slot address @9 BRA IOSBOOT ;and go do boot @6 (.IF BURNIN = 1 (CMP.B #PC,D0 ;power-cycle? (BEQ CHKPASS ;go do cycling (.ENDC (.IF ROM4K = 0 @7 CMP.B #MON,D0 ;abort boot? (BNE.S LSTCHK ;skip if no match (.IF USERINT = 1 (BCLR #NORSTRT,STATFLGS ;allow restart option but (BSET #NOCONT,STATFLGS ; no CONTINUE button for direct to monitor jump (BSR CLRMENU ;clear menu bar and (BSR MAKEPCALRT ; open alert box for monitor or power cycling (.ENDC (.IF BURNIN = 1 ; Check if completing power-cycling operation (.IF DEBUG = 0 (LEA PMERR,A3 ;set vector for parameter mem error (MOVE.L A3,BUSVCTR (.ENDC (BSR CHKPM ;check validity of parameter memory (BCS.S PMEXIT ;skip if not (MOVE.B DVCCODE,D0 ;get boot code (LSR.B #4,D0 ;shift to lower nibble (.IF NEWTWIG = 0 (BSR EXPAND ;convert to keycode (.ENDC (CMPI.B #PC,D0 ;exiting from power-cycling? (BNE.S PMEXIT ;skip if no (CLR.B DVCCODE ;else reset boot and (BCLR #6,MEMCODE ; memory test indicators (LEA LOOPMSG,A3 ;display loop count (BSR DSPMSG (MOVE.L #LCNTHI,A0 ;set ptr to loop count (MOVEP (A0),D0 ;get it (MOVEQ #4,D1 ;set # of digits to display (BSR OUTCHR ;and do display (MOVEQ #PCCOL,D6 ;reset col for proper left margin (BSR DSPCLK ;display final clock value (BSR TWGDSP ;and display Twiggy error count ; Normal exit PMEXIT (.IF DEBUG = 0 (BSR SETBUSVCT ;restore normal bus error vector RM000 (.ENDC ;{debug} (.ENDC ;{BURNIN} (BRA MONITOR ;and go to monitor (.IF BURNIN = 1 ; Bus error handler for parameter memory error PMERR LEA PMMSG,A3 ;setup error message (LEA IOBRD,A2 ;and icon (CLR.L D0 ;no error code (BRA INITMON ;exit to monitor (.ENDC ;{BURNIN} (.ENDC ;{ROM4K} LSTCHK (.IF AAPL = 1 (CMP.B #APPLE,D0 ;Apple boot? (BEQ NMISET ;exit if yes (.ENDC (.IF USERINT = 0 (LEA BADBOOT,A3 ;else display error msg (BSR DSPMSGR (BRA MONITOR ;go to monitor (.ELSE (BSR SQUAWK ;else sound error tone (BRA BOOTMENU ;and go to boot menu (.ENDC (.PAGE ;------------------------------------------------------------------------- ; Subroutine to check parameter memory validity. Calls generalized ; verify checksum routine. ;------------------------------------------------------------------------- CHKPM MOVEM.L D0-D1/A0,-(SP) ;save regs (MOVEA.L #PMSTRT,A0 ;set starting ptr (MOVE #PMWRDS-1,D0 ;and # of words to check (MOVE D0,D1 ;set for shared memory (BSR.S VFYCHKSM ;and go do checksum @1 MOVEM.L (SP)+,D0-D1/A0 ;restore regs (RTS (.IF BURNIN = 1 ;------------------------------------------------------------------------- ; Subroutine to save boot device code to parameter memory. ;------------------------------------------------------------------------- SAV2PM MOVEM.L D0-D1/A0,-(SP) ;save regs (.IF NEWTWIG = 0 (BSR XLATE ;convert keycode to boot id (MOVE.B D2,D0 (.ENDC (LSL.B #4,D0 ;rotate device code to upper nibble (MOVE.B DVCCODE,D1 ;read current setting (ANDI.B #$0F,D1 ;clear device indicator (OR.B D1,D0 ;save other data (MOVE.B D0,DVCCODE ;and write new device code ; also set for full memory test (BSET #6,MEMCODE ;ensure memory test indicator set ; then compute new checksum (MOVEA.L #PMSTRT,A0 ;compute new checksum (MOVEQ #PMWRDS-2,D0 ;leaving out checksum word (BSR.S WRTSUM @2 MOVEM.L (SP)+,D0-D1/A0 ;restore regs (RTS ;---------------------------------------------------------------------- ; Subroutine to write new checksum to parameter memory area ;---------------------------------------------------------------------- WRTSUM MOVE D0,D1 ;set for shared memory (BSR.S VFYCHKSM (NOT D3 ;compute 2's complement (ADDQ #1,D3 (MOVEP D3,(A0) ;write as new checksum (RTS (.ENDC ;------------------------------------------------------------------------- ; Subroutine to verify 16 bit checksum validity for memory contents. ; ; Inputs Required: A0 = starting address for verify ; D0 = # of words-1 to read ; D1 = 0 for regular memory (uses MOVE.W) ; = nonzero for shared memory (uses MOVEP) ; ; Outputs: Carry bit set if computed checksum not 0. ; D2 = expected checksum (last word read) ; D3 = computed checksum ;------------------------------------------------------------------------- VFYCHKSM (CLR.L D2 ;clear regs for use (CLR.L D3 CKLOOP TST D1 ;shared memory? (BEQ.S @1 ;skip if no (MOVEP (A0),D2 ;else read alternate bytes (ADDQ.L #4,A0 ;bump address (BRA.S @2 ;skip to do checksum @1 MOVE (A0)+,D2 ;read words @2 ADD D2,D3 ;add to computed checksum (ROL #1,D3 ;rotate for better effectiveness (DBF D0,CKLOOP ;loop until done (TST D3 ;expected result = 0 (BEQ.S CKXIT (ORI.B #$01,CCR ;else set error indicator CKXIT RTS (.IF NEWTWIG = 0 ;------------------------------------------------------------------------- ; Subroutine to expand boot id read from parameter memory to keycode ;------------------------------------------------------------------------- EXPAND LEA KEYTBL,A2 ;set ptrs to keycode table (LEA TBLEND,A3 (CLR.L D2 ;use for search id @1 CMP.B D2,D0 ;check for match (BEQ.S @2 ;skip if yes (ADDQ #1,D2 ;incr search id (ADDQ.L #1,A2 ;bump table ptr (CMPA.L A2,A3 ;at end? (BNE.S @1 ;loop if not (MOVE.B #APPLE,D0 ;else set for default boot (BRA.S @3 ;and go to exit @2 MOVE.B (A2),D0 ;get keycode @3 RTS (.ENDC (.IF USERINT = 1 ;------------------------------------------------------------------------- ; Subroutine to expand boot id read from parameter memory to keycode ; Returns with keycode in D0. ;------------------------------------------------------------------------- EXPAND MOVEM.L D2/A2-A3,-(SP) ;save regs (LEA KEYTBL,A2 ;set ptrs to keycode table (LEA TBLEND,A3 (CLR.L D2 ;use for search id @1 CMP.B D2,D0 ;check for match (BEQ.S @2 ;skip if yes (ADDQ #1,D2 ;incr search id (ADDQ.L #1,A2 ;bump table ptr (CMPA.L A2,A3 ;at end? (BNE.S @1 ;loop if not (MOVEQ #PROFILE,D0 ;else set for default boot (BRA.S @3 ;and go to exit @2 MOVE.B (A2),D0 ;get keycode @3 MOVEM.L (SP)+,D2/A2-A3 ;restore regs (RTS ;------------------------------------------------------------------------- ; Routine to search I/O slots for specific card ; Expects D1 = card id to search for ; D4 = qualifier for search (mask) ; Returns CC = 0 if card found and ; D2 = slot # ;------------------------------------------------------------------------- SEARCH MOVEM.L D0/D3,-(SP) ;save regs (MOVEQ #0,D2 ;setup as slot counter (MOVEQ #2,D3 ;set # of slots - 1 to check (LEA IO1ID,A0 ;get location of saved slot id's @1 ADDQ #1,D2 ;bump slot # (MOVE (A0)+,D0 ;read slot id (AND D4,D0 ;mask it (CMP D1,D0 ;match? (BEQ.S @2 ;skip if yes (DBF D3,@1 (TST D2 ;set nonzero status if no match @2 MOVEM.L (SP)+,D0/D3 ;restore regs (RTS ;exit (.PAGE ;------------------------------------------------------------------------- ; Routines to display boot icon menu ;------------------------------------------------------------------------- BOOTMENU (ANDI.B #$0F,STATFLGS ;initialize flags (CLR RectCnt ;clear active rectangle counter (MOVEQ #1,D6 ;set min # of boot alternates CHG009 @; i.e., at least have lower drive @; to boot from (TST.B SYSTYPE ;check system type CHG009 (BNE.S @10 ;Skip if Lisa 2 CHG009 (ADDQ #1,D6 ;else incr count for upper floppy drive CHG009 @10 MOVEQ #1,D2 ;set flag to do wait if needed RM011 (BSR CHKPROFILE ;go check for attached Profile (BNE.S @1 ;skip if not there (ADDQ #1,D6 ;else bump boot count @1 CLR.L D4 ;set flag for no status check (BSR RDSLOTS ;go scan the I/O slots (LEA IO1ID,A0 ;check results (MOVE (A0)+,D0 ;read first ID (BPL.S @2 ;skip if not bootable or not there (MOVE.L #SLOT1L,A2 ;set slot address (BSR RDSLT ;go check if any icons (BCS.S @2 ;skip if any error (ANDI #$03,D3 ;else clear don't care bits (max count = 2) (ADD D3,D6 ;and add to icon count @2 MOVE (A0)+,D0 ;check slot 2 (BPL.S @3 ;skip if not bootable (MOVE.L #SLOT2L,A2 ;set slot address (BSR RDSLT ;go check if any icons (BCS.S @3 ;skip if any error (ANDI #$03,D3 ;else clear don't care bits (max count = 2) (ADD D3,D6 ;and add to icon count @3 MOVE (A0)+,D0 ;check final slot (BPL.S @4 (MOVE.L #SLOT3L,A2 ;set slot address (BSR RDSLT ;go check if any icons (BCS.S @4 ;skip if any error (ANDI #$03,D3 ;else clear don't care bits (max count = 2) (ADD D3,D6 ;and add to icon count ; set starting icon display address according to boot count @4 CMP.B #10,D6 ;max of 10 icons in menu (BLE.S @5 ;skip if OK (MOVEQ #10,D6 ;else set max count ; now display blank boot icon menu @5 MOVEQ #BMENUWIDTH,D0 ;set menu parameters (MOVE.L D6,D1 ;get count of entries (MULU #BMENULEN,D1 ;length depends on number of entries (LEA STRTMSG,A3 ;set menu heading (BSR DSPMENUBOX ;and go display the menu (MOVE #MENUSTRT,MenuBase ;setup base menu address (MOVE #MENU1MSG,IconAddr ;and display pt for first entry ; next fill in the menu entries with icons and alternate keycodes ; D0 set with system type ICONCHK (MOVE.B SYSTYPE,D0 ;read system type CHG009/CHG029 (BEQ.S @1 ;skip if Lisa 1.0 CHG009 (CMP.B #3,D0 ;else check if internal disk CHG009/CHG029 (BNE.S @2 ;skip if not - no upper icon CHG009/CHG029 (CLR.L D2 ;else set for no wait CHG009 (BSR CHKPROFILE ; and check if integral disk CHG009 @; installed CHG009 (BNE.S @2 ;skip if not CHG009 (LEA UPPER,A2 ;set icon ptr for integral disk CHG009 (BRA.S @3 ;and go display CHG009 @1 LEA DRIVEN,A2 ;set icon ptr for drive CHG009 (MOVEQ #1,D1 ;set drive id # CHG009 @3 MOVEQ #TWIG1,D2 ;set id code CHG009 (MOVEQ #-1,D3 ;set compressed icon indicator (BSR DSPMNTRY ;display the entry @2 LEA DRIVEN,A2 ;set icon ptr for drive CHG009 (MOVEQ #2,D1 ; and drive id # CHG009 (MOVEQ #TWIG2,D2 ;set id code (MOVEQ #-1,D3 ;set compressed indicator (BSR DSPMNTRY ;display the entry (CLR.L D2 ;set flag for no wait RM011 (CMP.B #3,D0 ;skip check if internal disk CHG009/CHG029 (BEQ.S SCNSLTS ; CHG009/CHG029 (BSR CHKPROFILE ;else check if external disk attached (BNE.S SCNSLTS ;skip if not (LEA PROICON,A2 ;else set icon ptr for Profile (MOVEQ #PROFILE,D2 ;set id code (MOVEQ #-1,D3 ;set compressed indicator (BSR DSPMNTRY ;display the entry ; check for bootable devices in slots (what a pain!) SCNSLTS CLR.L D0 ;clear for use (LEA IO1ID,A0 ;set ptr for slot id (MOVE (A0)+,D0 ;get id (BPL.S CHKS2 ;skip if not bootable or not there (MOVE.L #SLOT1L,A2 ;else set slot address (MOVEQ #1,D1 ;set slot # for generic display if no ROM icon (MOVEQ #IO1PORT1,D2 ;set base boot id for slot (BSR CHKSLOT ;go check slot and display icons CHKS2 MOVE (A0)+,D0 ;read next id (BPL.S CHKS3 ;skip if not bootable or not there (MOVE.L #SLOT2L,A2 ;else set slot address (MOVEQ #2,D1 ;set slot # for generic display (MOVEQ #IO2PORT1,D2 ;set base boot id for slot (BSR CHKSLOT ;go check slot and display icons CHKS3 MOVE (A0)+,D0 ;read slot 3 id (BPL.S WT4BOOT ;skip if not bootable or not there (MOVE.L #SLOT3L,A2 ;else set slot address (MOVEQ #3,D1 ;set slot # for generic display (MOVE #IO3PORT1,D2 ;set base boot id for slot (BSR CHKSLOT ;go check slot 3 and display icons ;--------------------------------------------------------------------------- ; Menu displayed - now wait for operator selection ;--------------------------------------------------------------------------- WT4BOOT (BSR CursorDisplay ;display cursor on screen (BSET #CHKCMD,STATFLGS ;set flag for CMD key check (BSR GETINPUT ;go wait for user input (BCS GETERR ;skip if error (BSR XLATE ;translate and save boot id (BSR CursorHide ;remove cursor from screen (BSR CLRDESK ;clear desktop (BRA BOOTCHK ;and go start boot (.PAGE ;--------------------------------------------------------------------------- ; Routine to check for Profile attached to built-in parallel port. ; Checks for Profile connected (OCD) and tries an initial handshake to ; ensure the device is a Profile. ; ; Inputs: D2 = nonzero if full wait for Profile ready should be done ; Outputs: Zero condition code bit cleared if error ;--------------------------------------------------------------------------- CHKPROFILE (MOVEM.L A0/D0/D2/D4/D6,-(SP) ;save regs RM011 (BSR PROINIT ;init for Profile access (BNE.S @9 ;skip if not attached (BSR WFNBSY3 ;wait for not busy RM000 (TST.B D0 ;check return code (BEQ.S @0 ;skip if OK (TST.B D2 ;do full wait? RM011 (BEQ.S @7 ;skip if not RM011 (CLR.L D0 ;else reset error code for retry (BSR WAITALRT ;output wait alert (BSR WFNBSY2 ;try wait for normal profile boot time CHG019 (MOVEM.L A0/D0,-(SP) ;save regs (BSR CLRDESK ;clear desktop (MOVEM.L (SP)+,A0/D0 ;restore regs (TST.B D0 (BNE.S @8 ;exit if still not ready @0 ANDI.B #$EF,ORB2(A0) ;set command = true (BSR WFBSY ;then get initial Profile response RM016 (BNE.S @1 ;skip if error (CMPI.B #1,PORTA2(A0) ;check for expected '01' response (BEQ.S @1 ;skip if OK (MOVEQ #BADRSP,D0 ;else set error code @1 MOVEQ #0,D3 ;send '0' response to reset Profile (BSR SENDRSP (BSR WFNBSY ;wait until command taken @8 CLR.B DDRA2(A0) ;set port A bits to input (ORI.B #$18,ORB2(A0) ;and set dir=in, cmd=false @7 TST D0 ;set return code @9 MOVEM.L (SP)+,A0/D0/D2/D4/D6 ;restore RM011 (RTS ; and exit ;--------------------------------------------------------------------------- ; Subroutine to invoke display of boot menu entry ; Inputs: ; D2 = boot id ; A2 = ptr to icon ; Outputs: ; Location MenuBase updated with address for next menu "box" ; Side Effects: ; None ;--------------------------------------------------------------------------- DSPMNTRY (MOVEM.L D0/A1,-(SP) ;save boot id and addr ptr (MOVE D2,D0 ;get boot id (BSR EXPAND ;go convert boot id to keycode (MOVE MenuBase,A1 ;get address for display of entry (BSR.S ICONMENU ;go display in menu (MOVEM.L (SP)+,D0/A1 ;restore boot id and addr ptr (RTS ;and exit ;---------------------------------------------------------------------------- ; Subroutine to display icon menu on screen. Creates "active rectangle ; table" as entries are made. ; Inputs: ; D0 = alternate keycode ; D3 = compressed icon indicator ; A1 = address for start of next menu "box" ; A2 = ptr to icon ; Outputs: ; A1 = ptr for display of next menu entry ; Side Effects: ; None ;---------------------------------------------------------------------------- ICONMENU (MOVEM.L D0-D4/A0/A2/A5,-(SP) ; first save icon coordinates in active rectangle table (LEA RectTable,A0 ;get ptr to active rect table (MOVE (A0),D2 ;get current count of rect's (MULU #5,D2 ;five entries per rect (ADD D2,D2 ;double for word index (ADDQ #1,(A0)+ ;incr for new rect (MOVE D0,0(A0,D2.W) ;save keycode id for new rect (BSR KeyToAscii ;convert keycode to Ascii (MOVE D0,D4 ;save for later display ; compute X,Y pixel coordinates from starting address (BSR GETROWCOL ;get pixel row, byte col (MULU #8,D6 ;convert to pixel col (MOVE D6,2(A0,D2.W) ;save upper left X (MOVE D5,4(A0,D2.W) ; and Y coordinates (MOVE #,D0 ;width in pixels of menu entry (ADD D0,D6 ;compute and save (MOVE D6,6(A0,D2.W) ; lower Y coordinate (ADD #,D5 ;compute and save (MOVE D5,8(A0,D2.W) ; lower X coordinate ; now do icon display (SUBA.L A6,A6 ;clear for use (MOVE IconAddr,A6 ;get address for icon display (MOVE.L A6,A1 ;save for later use (ADD.L SCRNBASE,A6 ;convert to screen address (TST.B D3 ;check for compressed icon (BPL.S @1 ;skip if not (BSR DSPICON ;go do display (LEA DRIVEN,A0 ;displaying drive? CHG009 (CMPA.L A0,A2 ; CHG009 (BNE.S @2 ;skip if not CHG009 (MOVE.L A1,A5 ;else set icon display address CHG009 (BSR DSPNUM ; and display with id # CHG009 (BRA.S @2 ;skip to continue CHG009 @1 BSR DSPRGICON ;display an uncompressed icon CHG008 ; now display the alternate keycode @2 ADD #ALTKYADDR,A1 ;set starting display pt (BSR GETROWCOL ;convert to row, col (CLR D0 ;first display the apple (BSR DSPVAL (MOVE D4,D0 ;get Ascii char (BSR DSPVAL ;and display it ; finally compute the next menu entry and icon display address @3 MOVE MenuBase,A1 ;get base address for the entry (ADD #BMenuSpc,A1 ;space to next col (MOVE A1,MenuBase ;and save for next entry (MOVE IconAddr,A1 ;else get this icon's address (ADD #BMenuspc,A1 ;and bump to next spot in column (MOVE A1,IconAddr ;and do update (BRA.S @4 @4 MOVEM.L (SP)+,D0-D4/A0/A2/A5 (RTS ;--------------------------------------------------------------------------- ; Routine to check slots for icons and do display or do generic display. ; Inputs: ; D0 = card id ; D1 = slot # ; D2 = first boot id for slot ; A1 = address for icon display ; A2 = slot address ; Outputs: ; Returns with carry bit set if error. ; Side Effects: ; None ;--------------------------------------------------------------------------- CHKSLOT MOVEM.L D0-D4/A0-A2,-(SP) ;save regs (BTST #ICBIT,D0 ;icon available? (BNE.S CHKICONS ;skip if yes ; no icons available - display slot # and display generic slot card icon (LEA XCARD,A2 ;point to generic icon (MOVEQ #-1,D3 ;set compressed flag (MOVE IconAddr,A1 ;get display address for later use (BSR DSPMNTRY ;go display entry (LEA XCARD,A2 ;set icon ptr (MOVE.L A1,A5 ;get icon address (BSR DSPNUM ;display slot # (BRA.S CHKSXIT ;and exit ; Slot has icon - read ROM and get ptr to desired icon CHKICONS (BSR.S RDSLT ;go read slot (BCS.S CHKSXIT ;exit if error (MOVE.L #ADR128K-4,A1 ;set base address of I/O slot ROM code (MOVE.L D3,D4 ;save icon count (ANDI #$03,D4 ;isolate count (max = 2) (MOVE.L A2,A0 ;get code ptr (MOVE (A0)+,D1 ;get icon offset (MOVE.L A1,A2 ;get base address (ADD D1,A2 ;add offset to set up icon ptr (BSR DSPMNTRY ;display as menu entry (SUBQ #1,D4 ;more than one icon? (BEQ.S CHKSXIT ;skip if not (MOVE (A0)+,D1 ;else get ptr to second icon (ADDQ #1,D2 ;bump boot id ptr for slot (MOVE.L A1,A2 ;restore base address (ADD D1,A2 ;set up icon address (BSR DSPMNTRY ;display as menu entry CHKSXIT MOVEM.L (SP)+,D0-D4/A0-A2 ;restore regs and exit (RTS ;--------------------------------------------------------------------- ; Routine to read I/O slot ROM's and get icon count if any. ; ; Expects D0 = boot id ; A2 = slot address ; ; Returns D3 = icon count ; A2 = address of ptr to first icon if more than one ;--------------------------------------------------------------------- RDSLT MOVEM.L D0/D2,-(SP) ;save boot id's (BTST #ICBIT,D0 ;any icons stored in ROM? (BEQ.S @2 ;skip if none (CLR.L D4 ;set flag for no status check (BSR RDIOSLT ;and go read ROM on slot (BCS.S @1 ;skip if error (CLR.L D3 ;clear for use (MOVE ICONPTR,D3 ;get icon ptr (BSET #0,D3 ;must be odd address (MOVE.L #ADR128K-4,A2 ;set base address (ADD.L D3,A2 ;set actual address (MOVE.B (A2)+,D3 ;read icon count (BRA.S @1 @2 MOVEQ #1,D3 ;set default icon count @1 MOVEM.L (SP)+,D0/D2 ;restore boot id's (RTS (.ENDC ;{USERINT} (.PAGE ;------------------------------------------------------------------------- ; Do default boot from Twiggy specified drive. ; Assumes regs: ; D0 = drive # ; Following assumptions are made for power-up status: ; 1) No interrupt from disk unless diskette inserted or button pushed ;------------------------------------------------------------------------- TWGBOOT LEA DSKVCT,A3 ; first set up bus error vector (MOVE.L A3,BUSVCTR (.IF USERINT = 0 (LEA BOOTMSG,A3 ; output boot msg (BSR DSPMSGR (.ELSE (MOVE.B D0,DRIVE ;save drive id (BSR WAITALRT ;display wait icon (.ENDC (MOVE.L #DISKMEM,A0 ; set ptr to controller memory (MOVE.L #TWGHDR,A1 ; set ptr to load header (MOVE.L #TWGHDR+12,A2 ; and ptr to load data (CLR.L D1 ; set drive/side/sector/track ptr (ANDI.L #$00FF,D0 ; mask off junk (TST D0 ;enable only drive selected (BNE.S @1 (MOVE.B #$08,CMD(A0) ;enable drive #1 (BRA.S @2 @1 MOVE.B #$80,CMD(A0) ;enable drive #2 @2 ROR.L #8,D0 ; get actual drive desired (OR.L D0,D1 ; and save for shared mem format (MOVE.B #ENBLINT,(A0) ;go do enable (BSR CMDCHK ;wait until cmd taken (BCS DSKTIMERR ;skip if timeout error (MOVE.L #VIA1BASE,A3 ;else enable (BCLR #FDIR,DDRB1(A3) ; FDIR ; BTST #FDIR,(A3) ;FDIR present? ; BEQ.S DOREAD ;skip if no to do read CLRINT BSR CLRFDIR ;clear interrupts (BCS DSKTIMERR ;exit if timeout error (.PAGE ;----------------------------------------------------------------------------- ; Read boot data - retry on sector 0 if needed. ;----------------------------------------------------------------------------- DOREAD (CLR D0 ; set speed value (BSR TWGRD ; go read sector 0 RM000 (BCC.S @1 ; skip if OK (CMP.B #TIMOUT,D0 ; timeout error? (BEQ DSKCHK ; exit if yes (BRA.S RDRETRY ; else go do retry @1 MOVE FILEID(A1),D0 ; else get file ID (CMP #BOOTPAT,D0 ; is it a boot file? (BEQ.S RDSCTR1 ; skip if yes ; Do retry by reading track 1 to try to get head properly aligned, then ; retry reading track 0 RDRETRY MOVE.B #1,D1 ; set for track 1 (CLR D0 ; set speed value (BSR TWGRD ; go do read RM000 (BCS.S DSKCHK ; exit if second error (CLR.B D1 ; else retry track 0 (CLR D0 ; set speed value (BSR TWGRD ; go do read RM000 (BCS.S DSKCHK ; exit if error ; Now check again for a valid boot track (MOVE FILEID(A1),D0 ; get file ID (CMP #BOOTPAT,D0 ; is it a boot file? (BEQ.S RDSCTR1 ; skip if yes (MOVEQ #BADTHDR,D0 ; set error code (BRA.S DSKCHK ; and exit RDSCTR1 (.IF NEWTWIG = 0 (ORI #$100,D1 ; set for sector 1 (MOVE.L #TWGHDR+268,A1 ; set new header ptr (MOVE.L #TWGHDR+280,A2 ; and new data ptr (BSR.S TWGREAD ; and read next sector (BCS.S DSKCHK (.ENDC (CLR.L BOOTDATA ;set for no error (LEA DSKERR2,A3 ;set up vectors in case of bad diskette (LEA DSKERR3,A4 (BSR VCTRINIT (MOVE.L #TWGDATA,A2 ;set data ptr (software view) ; Do keyboard/mouse reset before continuing boot process STRTBOOT (MOVEM.L A0/D0,-(SP) ;save regs (BSR RSTKBD ;send reset signal (BSR CLRRST ;then clear it (CLR.B KBDQ ;clear first byte of keyboard queue (MOVEM.L (SP)+,A0/D0 ;restore regs (JMP (A2) ;and away we go ... (.PAGE ;------------------------------------------------------------------------- ; Error occurred - output error message and go to monitor ;------------------------------------------------------------------------- DSKTIMERR (MOVEQ #TIMOUT,D0 ;set timeout error code DSKCHK MOVE.B D0,BOOTDATA ;save the error status (CMPI.B #TIMOUT,D0 ;timeout? (BEQ.S DSKERR ;skip if yes (BSR CLRFDIR ;ensure intrpt cleared (BCS.S DSKOUT ;exit if error (.IF USERINT = 0 (CMPI.B #NODISK,D0 ; no disk in? (BNE.S DSKBAD ; skip if no (LEA DSKMSG,A3 ; get msg ptr (BSR DSPMSGR ; output it (BSR CHKFIN ; go wait for FDIR (BCS.S DSKERR ; and exit if timeout (BSR CLRFDIR ;assume disk in place, clear int (BCS.S DSKERR ;skip if error (BSR CLAMPIT ;issue clamp cmd (BCS.S DSKERR ;exit if error (CLR.B D1 ;reset for track 0 (BRA.S CLRINT ;and go try read again (.ENDC DSKBAD MOVE.B CHKCNT(A0),BOOTDATA+2 ; and data checksum count (.IF NEWTWIG = 1 (MOVE.B CHKCNT2(A0),BOOTDATA+1 ; and address checksum count (MOVE.B RTRYCNT(A0),BOOTDATA+3 ; and retry count (.ENDC DSKOUT BSR EJCTDSK ;then eject the disk DSKDIS BSR DSABLDSK ;disable both drives DSKERR BSR SETBUSVCT ; restore default bus error vector RM000 (.IF USERINT = 0 (LEA BOOTERR,A3 ; and output message (BSR DSPMSGR (.ELSE (BSR CHKDRIVE ;go determine drive (MOVE.B BOOTDATA,D0 ;get error code (CMP.B #NODISK,D0 ;no disk error? (BNE.S @1 ;skip if not @;2 statements deleted CHG009 (LEA INSERTD,A2 ;set icon for insert rqst CHG009 (BSR DSPALRTICON ;display basic icon CHG009 (MOVE #ERRSTRT,A5 ;set display pt for id # CHG009 (BSR DSPNUM ; and display it CHG009 (BRA BFAIL2 ;then go signal user @1 CMP.B #RDWRERR,D0 ;read error? (BEQ.S @2 ;skip if yes (CMP.B #BADTHDR,D0 ;bad file id? (BEQ.S @2 (CMP.B #EBOOT,D0 ;boot error? (BNE.S @3 ;skip if not @2 BSR DSPNUMICON ;display diskette icon with id # (BRA.S TBOOTERR ;and exit @3 LEA IOBRD,A2 ;error must be on I/O board (BSR DSPERRICON ;display icon (.ENDC TBOOTERR (.IF USERINT = 0 (BRA DSPDVC ; and exit to display (.ELSE (BRA BOOTFAIL ;and go signal boot failure (.ENDC ;-------------------------------------------------------------------------- ; Handler for Twiggy boot errors ;-------------------------------------------------------------------------- DSKERR2 BSRS4 SAVEXCP ;go save exception info DSKERR3 BSRS4 BTERR ;regroup (BRA.S DSKOUT ;and display error SAVEXCP (MOVE (SP)+,EXCFC ;save function code (MOVE.L (SP)+,EXCADR ;and address (MOVE (SP)+,EXCIR ;and instruction reg (RTS4 BTERR MOVE (SP)+,EXCSR ;save status reg (MOVE.L (SP)+,EXCPC ;and pc (BSR SAVEREGS ;save regs (MOVEA #STKBASE,SP ;reset stack pointer (BSR SETVCTRS ;reinit vectors (MOVEQ #EBOOT,D0 ;set boot error (MOVE.B D0,BOOTDATA ;and save (RTS4 ;--------------------------------------------------------------------------- ; Subroutine to disable interrupts from both Twiggy drives ; Inputs: ; None ; Outputs: ; Carry bit set if timeout error (in CMDCHK). ; Side Effects: ; A0 trashed (other regs trashed in CMDCHK) ;--------------------------------------------------------------------------- DSABLDSK (MOVE.L #DISKMEM,A0 ;set ptr to shared memory (MOVE.B #$88,CMD(A0) ;disable ints from both drives (MOVE.B #DSABLINT,(A0) (BSR CMDCHK ;wait for command to be taken (RTS ;then return ;-------------------------------------------------------------------------- ; Subroutine to determine drive # in error and get icon ptr ; Inputs: ; Location DRIVE = drive id # (0 or $80) ; Outputs: ; A2 = ptr to diskette icon ; D1 = id # ; Side Effects: ; None ;-------------------------------------------------------------------------- CHKDRIVE (LEA DISKETTE,A2 ;set ptr for diskette icon (MOVE.B DRIVE,D1 ;get drive id (TST.B D1 ; drive #1? (BNE.S @1 ; skip if no (.IF USERINT = 0 (MOVEQ #TWG1,D0 ; else set up ASCII code (.ELSE (MOVEQ #1,D1 ; else set up id code (.ENDC (BRA.S @2 @1 (.IF USERINT = 0 (MOVEQ #TWG2,D0 ; else must be drive #2 (.ELSE (MOVEQ #2,D1 ; else set up id code (.ENDC @2 (RTS ;exit (.IF EXTERNAL = 1 (.LIST (.ENDC (.PAGE ;----------------------------------------------------------------------------- ; Read a Twiggy sector routine. Uses hardware view of the world, with ; 12 bytes for header and 256 bytes (512 for new format) of data per sector. ; Also assumes registers: ; D0 = speed (for new Twiggy code) A0 = disk shared memory address ; D1 = drive/side/sector/track A1 = address to load header(12 bytes) ; D2 = timeout for read A2 = address to load data(256 or 512 bytes) ; D3 = scratch A3 = VIA address for FDIR ; If error, returns with carry bit set and error code in D0. ;------------------------------------------------------------------------------ TWGRD (MOVE.L #FDIRTIME,D2 ; set default timeout value RM000 TWGREAD (.IF TWIGGY = 1 (MOVEM.L D3/A1-A4,-(SP) ; save regs (DISABLE ; disable interrupts (BSR CHKFDIR ;ensure no ints pending (MOVEP.L D1,DRV(A0) ; set disk ptrs (.IF NEWTWIG = 1 (MOVE.B D0,SPEED(A0) ;set speed value (.ENDC (MOVE.B #READS,CMD(A0) ; set for read operation (MOVE.B #EXRW,(A0) ; and go do it (BSR CHKFIN ; wait (BCS.S TWGOUT ; exit if timeout (MOVE.B STAT(A0),D0 ; get disk return code (MOVE.B #$CC,CMD(A0) ;clear RWTS interrupt bits (MOVE.B #CLRSTAT,(A0) (BSR.S CMDCHK ;wait until cmd taken (BCS.S TWGOUT ;exit if error (TST.B D0 ;check status code (BNE.S TWGERR ; and exit if error ; Read successful - transfer header and then data to main memory (.IF NEWTWIG = 0 (MOVE.B #HDRLEN,D0 ; set header length (hardware view) (MOVE.L #HDRSTRT,A4 ; set ptr to Twiggy buffer XFRHDR MOVE.B (A4),(A1)+ ; transfer bytes (ADDQ.L #2,A4 ; bump ptr (SUBQ.B #1,D0 ; and continue until done (BNE.S XFRHDR (MOVE #SECLEN,D0 ; next set sector length (MOVE.L #DSKBFR,A4 ; and set ptr to disk bfr XFRDATA MOVE.B (A4),(A2)+ ; do data transfer (ADDQ.L #2,A4 ; bump disk ptr (SUBQ #1,D0 ; and continue until done (BNE.S XFRDATA (BRA.S TWGOK ; and go to exit (.ELSE (LEA DSKBUFF(A0),A4 ;set address for Twiggy buffer XFRHDR MOVEP.L (A4),D3 ;load header bytes (MOVE.L D3,(A1)+ (MOVEP.L 8(A4),D3 (MOVE.L D3,(A1)+ (MOVEP.L 16(A4),D3 (MOVE.L D3,(A1)+ (LEA DSKDATA(A0),A4 ;set address for data (MOVE.W #31,D0 ;need to load 512 bytes XFRDATA MOVEP.L (A4),D3 ;load data bytes (MOVE.L D3,(A2)+ (MOVEP.L 8(A4),D3 (MOVE.L D3,(A2)+ (MOVEP.L 16(A4),D3 (MOVE.L D3,(A2)+ (MOVEP.L 24(A4),D3 (MOVE.L D3,(A2)+ (ADD.W #32,A4 (DBF D0,XFRDATA ;loop until done (BRA.S TWGOK ;and go to exit (.ENDC ; Error exit - set carry bit as error indicator TWGOUT MOVEQ #TIMOUT,D0 ; set timeout error TWGERR ENABLE ; restore interrupt mask (ORI.B #$01,CCR (BRA.S TWGRXIT ; and exit TWGOK ENABLE ; restore interrupt mask (CLR.L D0 ; set OK return code CHG025 TWGRXIT MOVEM.L (SP)+,D3/A1-A4 ; restore regs (RTS ; and return to caller (.PAGE ;------------------------------------------------------------------------- ; Subroutine to check for disk command taken. Also does check for DSKDIAG ; in case Twiggy controller becomes busy servicing second disk drive before ; command is seen. Loop takes about 12.4 us if DSKDIAG OK, else DSKDIAG ; loop takes about 9.6 us. ; ; Destroys register A0 ;------------------------------------------------------------------------- CMDCHK MOVEM.L D3/A3,-(SP) ;save regs (MOVE.L #CMDTIME,D3 ;set timeout for about 15 secs (MOVE.L #DISKMEM,A0 ;set ptr to shared memory (MOVE.L #VIA2BASE,A3 ;also set up to monitor DSKDIAG (ANDI.B #$BF,DDRB2(A3) @1 TST.B (A0) ;cmd taken when byte 0'ed (BEQ.S @2 @3 BTST #DSKDIAG,IRB2(A3) ;check if controller not ready (BNE.S @4 ;skip if OK (SUBQ.L #1,D3 ;else loop until timeout or ready (BNE.S @3 (BRA.S @5 ;take error exit @4 SUBQ.L #1,D3 (BNE.S @1 ;loop until yes or timeout @5 ORI.B #$01,CCR ;set error @2 MOVEM.L (SP)+,D3/A3 ;restore regs (RTS ;---------------------------------------------------------------------------- ; Subroutine to check for disk interrupt (FDIR asserted) - loop takes 8.8us ; Destroys register D3 and A3 ;---------------------------------------------------------------------------- CHKFIN (.IF NEWTWIG = 0 (MOVE.L #FDIRTIME,D3 ;set fixed timeout of 2 mins (.ENDC (.IF NEWTWIG = 1 (MOVE.L D2,D3 ;set user-supplied timeout (.ENDC (MOVE.L #VIA1BASE,A3 ;set ptr for interface @1 BTST #4,(A3) ;FDIR? (BNE.S @2 ;exit if yes (SUBQ.L #1,D3 (BNE.S @1 ;else loop (ORI.B #$01,CCR ;set error @2 RTS (.PAGE ;------------------------------------------------------------------------- ; Subroutine to eject disk ; Assumes A0 = ptr to disk shared memory ;------------------------------------------------------------------------- EJCTDSK (.IF NEWTWIG = 1 (BSR.S CLRFDIR ;ensure interrupts cleared (BCS.S @1 ;exit if error (MOVE.L #EJCTTIME,D2 ;set eject timeout (.ENDC (MOVE.B #UNCLAMP,CMD(A0) ;set up cmd (MOVE.B #EXRW,(A0) ;go do it (BSR.S CHKFIN ;wait for FDIR (BCS.S @1 ;skip if error (BSR.S CLRFDIR ;clear intrpt and return @1 RTS ;------------------------------------------------------------------------- ; Subroutine to clear interrupt. Waits for FDIR to go low before return. ; Assumes A0 = ptr to disk shared memory. ;------------------------------------------------------------------------- CLRFDIR MOVE.B #$FF,CMD(A0) ;clear FDIR (MOVE.B #CLRSTAT,(A0) (BSR.S CMDCHK ;wait until cmd taken (MOVE.L #VIA1BASE,A3 ;then wait for FDIR to go low (MOVEQ #25,D3 ;set timeout for about 200 us @1 BTST #FDIR,(A3) ;FDIR? (BEQ.S @2 ;skip if none (SUBQ #1,D3 ;else loop until gone or timeout (BNE.S @1 (ORI.B #01,CCR ;set error indicator @2 RTS ;------------------------------------------------------------------------- ; Subroutine to ensure FDIR gone after clear status cmd ;------------------------------------------------------------------------- CHKFDIR MOVE.L #VIA1BASE,A3 ;set ptr for FDIR status (BTST #FDIR,(A3) ;FDIR present? (BEQ.S @1 ;skip if not (BSR.S CLRFDIR ;else do clear @1 RTS ;and exit (.IF USERINT = 0 (.IF NEWTWIG = 1 ;------------------------------------------------------------------------- ; Subroutine to issue clamp cmd ;------------------------------------------------------------------------- CLAMPIT MOVE.B #CLAMP,CMD(A0) ;set cmd (MOVE.B #EXRW,(A0) ;do it (BSR CHKFIN ;wait until done (RTS (.ENDC ;{NEWTWIG} (.ENDC ;{USERINT} (.IF USERINT = 1 ;------------------------------------------------------------------------- ; Subroutine to enable display of wait icon. Main entry point creates ; alert box also, secondary enrty point (DSPWTICON) invokes icon display ; only. ; Inputs: ; None ; Outputs: ; None ; Side Effects: ; A2,A3 trashed ;------------------------------------------------------------------------- WAITALRT DSPWTICON (LEA WAITICON,A2 ;and display wait icon (BSR DSPALRTICON (RTS (.ENDC ;{USERINT} (.ENDC ;{TWIGGY} ;----------------------------------------------------------------------------- ; Routine to reinit vectors before release of control to boot loader. ; Sets all vectors other than reset and interrupts to jump to the ; failing boot device handler. ; ; Inputs: ; A3 = address of boot error handler for bus/address errors ; A4 = address of boot error handler for other exceptions ; Outputs: ; None ; Side Effects: ; A0/D1 trashed ;----------------------------------------------------------------------------- VCTRINIT (MOVEA #BUSVCTR,A0 ;get ptr to vector locations RM000 (MOVE.L A3,(A0)+ ;set up for bus error (MOVE.L A3,(A0)+ ;and address error (MOVEQ #20,D1 ;# of remaining low vectors to init @1 MOVE.L A4,(A0)+ ;setup handler for errors up (SUBQ #1,D1 ; to spurious intrpt vector (BNE.S @1 (MOVEA #TRPVCT0,A0 ;next do all trap vectors RM000 (MOVEQ #32,D1 ;set count @2 MOVE.L A4,(A0)+ ;and do init (SUBQ #1,D1 (BNE.S @2 (RTS (.IF EXTERNAL = 1 (.NOLIST (.ENDC (.PAGE (.IF PROFLE = 1 ;ASSEMBLE ONLY IF PROFILE CODE NEEDED ;----------------------------------------------------------------------------- ; Routine to boot from Profile hard disk attached to parallel port ; Sets up input parameters and then calls READ routine. If no error ; on return (carry not set), a jump to the loaded boot code is done. ;----------------------------------------------------------------------------- PROBOOT (.IF USERINT = 0 (LEA BOOTMSG,A3 ; output boot msg (BSR DSPMSGR (.ELSE (BSR WAITALRT ; display wait icon (.ENDC (MOVE.L #HDRBUFR,A1 ; set up ptr to save header (MOVE.L #HDRBUFR+20,A2 ; ptr for data (CLR.L D1 ; set sector # (MOVE.L #STRTIME,D2 ; set timeout count (3 mins) (MOVEQ #RCNT,D3 ; set retry count (MOVEQ #TCNT,D4 ; set threshold count (BSR PROREAD ; go get data (BCS.S HDSKERR ; exit if error ; Now verify header and if OK, jump to startup program (MOVE FILEID(A1),D0 ; get file id (CMP #BOOTPAT,D0 ; is it a boot block? (BEQ.S PBOOT ; continue if OK (MOVEQ #BADHDR,D0 ; else set error code (BRA.S HDSKERR ; and exit PBOOT LEA HDERR2,A3 ;set up vectors in case of errors (LEA HDERR3,A4 (BSR VCTRINIT (MOVE.L #HDRBUFR+20,A2 ; set ptr for data (BRA STRTBOOT ; and go start execution ; Error detected - output message and abort boot HDSKERR (.IF USERINT = 0 (LEA BOOTERR,A3 ; get msg ptr (BSR DSPMSGR ; display error (MOVEQ #PRO,D0 ; set device code (BRA DSPDVC ; and go display (.ELSE (CMP.B #3,SYSTYPE ;check system type CHG009/CHG029 (BEQ.S @2 ;skip if internal disk CHG009/CHG029 (LEA PROICON,A2 ;else setup Profile icon (BRA.S @3 ;skip to do display CHG009 @2 LEA UPPER,A2 ;set for integral hard disk CHG009 @3 CMP.B #NODSK,D0 ;Profile not attached error? (BNE.S @1 ;skip if not ; If default boot and no Profile attached, go to boot menu (BTST #ALTBOOT,D7 ;is this a default boot? (BNE.S @1 ;skip if not (BSR CLRDESK ;clear desktop (BRA LSTCHK ;and do beep and display the boot menu @1 BSR DSPERRICON ;display with bad mark (.ENDC ;{PROFILE} ; Sound error tones and display error code BOOTFAIL (BSR DSPCODE ;display error code BFAIL2 (BSR HIPTCH ;startup failure causes hi,hi,hi tones (BSR HIPTCH (BSR HIPTCH (BSR CLRMENU ;clear menu bar (ANDI.B #$FC,STATFLGS ;allow CONTINUE option from boot error (BSET #NORSTRT,STATFLGS ; but not restart option (BRA MONITOR ;and go to monitor HDERR2 BSR4 SAVEXCP ;save exception info HDERR3 BSR4 BTERR ;regroup from error (BRA.S HDSKERR ;and go display it (.IF EXTERNAL = 1 (.LIST (.ENDC (.PAGE ;----------------------------------------------------------------------------- ; First initialize and then ensure disk is attached by checking OCD line. ; Assumes ACR and IER registers of VIA set up by caller. For boot, these ; are cleared by power-up reset. ; Register usage: ; D0 = scratch use A0 = VIA address for parallel port interface ; D1 = block to read A1 = address to save header ; D2 = timeout count A2 = address to save data ; D3 = retry count A3 = scratch ; D4 = threshold count A4 = unused ; Returns: ; D0 = error code (0 = OK) ; D1 = error bytes (4) ; D2 - D7 and A1 - A6 are preserved ;----------------------------------------------------------------------------- PROREAD MOVEM.L D2-D7/A1-A6,-(SP) ; save regs (DISABLE ; ensure interrupts off (BSR.S PROINIT ; init for Profile access and check H; if attached (BEQ.S CHKBSY ; go on if OK (MOVEQ #NODSK,D0 ; else set error code and (BRA.S PROERR ; skip if error - no disk attached ; Now check if Profile ready - wait time presently set for about 100 seconds ; to allow enough time for normal Profile startup time of about 80 seconds CHKBSY BTST #BSY,IRB2(A0) ; check if Profile ready (not busy) (BNE.S TRYRD ; skip if yes (SUBQ.L #1,D2 ; else loop until timeout (BNE.S CHKBSY (MOVEQ #DSKBSY,D0 ; set disk busy error code (BRA.S PROERR ; and go to error exit ; Now start read and check status to see if OK TRYRD BSR STRTRD ; go begin read process (BCC.S @1 ; skip if OK CHG016 (BSR WFNBSY ; else check for ready CHG016 (BSR STRTRD ; and do retry CHG016 (BCC.S @1 ; continue if OK CHG016 (BSR DOCRES ; else issue reset signal CHG016 (BSR WFNBSY ; wait until ready CHG016 (BSR STRTRD ; and try one more time CHG016 (BCS.S PROERR ; finally exit if error @1 TST.W STAT3 ; check if reset error CHG016 (BPL.S @2 ; skip if not (BSR STRTRD ; else go try read again (BCS.S PROERR ; and abort if error @2 TST.L STATBFR ; check complete status (BEQ.S RDDATA ; skip if OK (MOVE.L STATBFR,D1 ; else get status (MOVE.L D1,D0 ; save for use (ANDI.L #STATMSK,D0 ; mask don't care bits (BEQ.S RDDATA ; and continue if OK (MOVEQ #STATNZ,D0 ; else set error code (BRA.S PROERR ; and go to error exit ; All OK - go read block and transfer to memory; do as multiple moves for ; max transfer rate. RDDATA MOVEQ #-1,D0 ; set count for header read (BSR.S READIT ; go do it (MOVEQ #-1,D0 ; set count for data read (MOVEA.L A2,A1 ; set new read location (BSR.S READIT (BRA.S PROXIT ; and go to exit ; Error exit - set carry bit as indicator flag PROERR ENABLE ;restore interrupt mask (ORI.B #$01,CCR (BRA.S PROXIT2 ; Normal exit - restore regs and exit PROXIT ENABLE ;restore interrupt mask (CLR.L D0 ;set OK return code CHG025 PROXIT2 MOVEM.L (SP)+,D2-D7/A1-A6 (RTS ;---------------------------------------------------------------------------- ; Subroutine to init parallel port for Profile access. ; Inputs: ; None ; Outputs: ; D0 cleared for error use ; A0 = VIA base address for parallel port ; CCR zero bit set if cable connected ; Side Effects: ; None ;---------------------------------------------------------------------------- PROINIT (CLR.L D0 ; clear for result use (MOVE.L #VIA1BASE,A3 ; get kybd VIA base address CHG036 (ORI.B #$A0,ORB1(A3) ; initialize profile-reset and parity-reset CHG036 (ORI.B #$A0,DDRB1(A3) ; and set lines as outputs CHG036 (MOVE.L #VIA2BASE,A0 ; get paraport VIA base address (ANDI.B #$7B,PCR2(A0) ; set ctrl CA2 pulse mode/positive edge (ORI.B #$6B,PCR2(A0) (MOVE.B #$00,DDRA2(A0) ; set port A bits to input (ORI.B #$18,ORB2(A0) ; then set direction=in, cmd=false, CHG036 (ANDI.B #$FB,ORB2(A0) ; enable=true CHG036 (ANDI.B #$FC,DDRB2(A0) ; set port B bits 0,1=in, (ORI.B #$1C,DDRB2(A0) ; 2,3,4=out (BTST #OCD,IRB2(A0) ; check OCD line (RTS ; and exit ;---------------------------------------------------------------------------- ; Subroutine to read bytes from Profile. Assumes: ; D0 = byte count - 1 ; A0 = VIA address for parallel interface ; A1 = memory load address ;---------------------------------------------------------------------------- READIT MOVE.B IRA2(A0),(A1)+ ; read the bytes (MOVE.B IRA2(A0),(A1)+ (MOVE.B IRA2(A0),(A1)+ (MOVE.B IRA2(A0),(A1)+ (DBF D0,READIT (RTS (.PAGE ;--------------------------------------------------------------------------- ; Subroutine to begin the read process. First calls a routine that ; gets in sync with Profile and sends read command. Then a wait for ; an appropriate response from Profile is executed. ; Assumes regs: ; D0 = scratch use A0 = VIA address ; D1 = block to read A1 = unused ; D2 = used for Profile cmd A2 = unused ; D3 = retry count A3 = scratch use ; D4 = threshold count A4 = unused ; If error, carry bit set and error code in D0. ;--------------------------------------------------------------------------- STRTRD MOVEA #CMDBUFR,A3 ; first set up command RM000 (MOVE.L D1,(A3) ; set read command (0) and block # (MOVE.B D3,RETRY(A3) ; set retry count (MOVE.B D4,THRESH(A3) ; set threshhold for sparing (BSR.S STAT01 ; get 01 byte and send read command (BCS.S STRTXIT ; exit if error ; OK so far - go check if Profile ready to send data (MOVEQ #2,D2 ; get 02 byte RM000 (BSR.S FINDD2 (BCS.S STRTXIT ; exit if timeout error ; Get status bytes GETSTAT MOVEA #STATBFR,A3 ; set buffer ptr RM000 (MOVE.B IRA2(A0),(A3)+ ; read and save the status (MOVE.B IRA2(A0),(A3)+ (MOVE.B IRA2(A0),(A3)+ (MOVE.B IRA2(A0),(A3)+ STRTXIT RTS ; return to caller (.PAGE ;-------------------------------------------------------------------------- ; Subroutine to get in sync with Profile. ; Input regs: ; A0 = VIA address ; A3 = ptr to command buffer ; If error, returns with carry bit set and error code in D0 ;-------------------------------------------------------------------------- STAT01 MOVEM.L D2/D4,-(SP) ; save regs (MOVE.L #1,D2 ; try to find state 01 (BSR.S FINDD2 (BCC.S COPY6 ; skip if OK (CMP.B #TMOUT,D0 ; else check if timeout error (BEQ.S STATERR ; and exit if yes (BSR WFNBSY3 ; ensure Profile ready RM000 (TST.B D0 ; check for timeout error (BNE.S STATERR ; and exit if yes @2 BSR.S FINDD2 ; try to find state 01 again (BCS.S STATXIT ; exit if error again COPY6 ANDI.B #$F7,ORB2(A0) ; set dir=out (MOVE.B #$FF,DDRA2(A0) ; set port A bits to output (MOVE.W #PCMDSZ,D0 ; set command size COPY6LP MOVE.B (A3)+,ORA2(A0) ; send the command bytes (DBF D0,COPY6LP (ORI.B #$08,ORB2(A0) ; reset dir=in (MOVE.B #$00,DDRA2(A0) ; and set port A bits to input (BRA.S STATXIT ; then exit STATERR ORI.B #$01,CCR ; set error indicator STATXIT MOVEM.L (SP)+,D2/D4 ; restore regs (RTS (.PAGE ;------------------------------------------------------------------------------ ; Subroutine to handshake with Profile and wait for command completion. ; Polls busy bit until it goes low (not busy). ; Assumes regs: ; A0 = VIA address ; D2 = Expected response to previously issued command ; If error, carry bit set and error code in D0. ;------------------------------------------------------------------------------ FINDD2 MOVEM.L D1-D4,-(SP) ; save regs (ANDI.B #$EF,ORB2(A0) ; set cmd=true (MOVE.B #$00,DDRA2(A0) ; set port A bits to input (CLR.L D0 ; used for return code (BSR.S WFBSY ; wait for busy (BNE.S FINDERR ; exit if error GETRSP MOVE.B PORTA2(A0),D1 ; get response in D1 w/o handshake (CLR.B D3 ; used for reply to Profile (CMP.B D2,D1 ; did pippin return state requested ? (BEQ.S RSPOK ; skip if yes (MOVEQ #BADRSP,D0 ; else set error code (BRA.S SNDR1 ; and go send reply RSPOK MOVEQ #$55,D3 ; set up OK reply RM000 SNDR1 BSR.S SENDRSP ; send response (TST.B D0 ; check return code (BNE.S FINDERR ; skip if error (BSR.S WFNBSY ; now go wait for not busy FINDERR MOVE.B #$00,DDRA2(A0) ; reset port A bits to input (ORI.B #$18,ORB2(A0) ; and dir = in, cmd=false (TST.B D0 ; check return code (BEQ.S FNDXIT ; skip if OK (ORI.B #$01,CCR ; else set error indicator FNDXIT MOVEM.L (SP)+,D1-D4 ; restore regs(but don't affect CCR bits) (RTS ;------------------------------------------------------------------------------ ; Subroutine to wait for Profile busy signal. Polls busy bit until it ; goes high (busy). ; Assumes regs: ; A0 = VIA address ; D4 = timeout value if WFBSY1 entry point used ; If error, error code in D0. ;------------------------------------------------------------------------------ WFBSY MOVE #RSPTIME,D4 ; set response timeout = 100 msec WFBSY1 BTST #BSY,IRB2(A0) ; wait for busy (BEQ.S @9 ; skip if OK (SUBQ #1,D4 ; else loop until timeout (BNE.S WFBSY1 (MOVEQ #TMOUT,D0 ; set timeout error @9 RTS ;------------------------------------------------------------------------------ ; Subroutine to send response command to Profile. ; Assumes regs: ; A0 = VIA address ;------------------------------------------------------------------------------ SENDRSP ANDI.B #$E7,ORB2(A0) ; set dir=out, cmd=true (MOVE.B #$FF,DDRA2(A0) ; set port A bits to output (MOVE.B D3,PORTA2(A0) ; send reply(00 or 55) w/o handshake (ORI.B #$10,ORB2(A0) ; set cmd=false (RTS ;------------------------------------------------------------------------------ ; Subroutine to wait for Profile not busy signal. Polls busy bit until it ; goes low (not busy). ; Assumes regs: ; A0 = VIA address ; D4 = timeout value if WFNBSY1 entry point used ; If error, D0 has error code. ;------------------------------------------------------------------------------ WFNBSY MOVE.L #RDTIME,D4 ; set timeout for about 16 secs CHG037 (BRA.S WFNBSY1 ; CHG019 WFNBSY2 MOVE.L #STRTIME,D4 ; set initial Profile self-test time CHG019 (BRA.S WFNBSY1 ; CHG019 WFNBSY3 MOVE.L #BSYTIME,D4 ; set timeout for about 10 ms RM000 WFNBSY1 BTST #BSY,IRB2(A0) ; wait for not busy (BNE.S @9 ; exit if OK (SUBQ.L #1,D4 ; else loop until timeout (BNE.S WFNBSY1 (MOVEQ #TMOUT,D0 ; set timeout error @9 RTS ;----------------------------------------------------------------------------- ; Subroutine to send reset to Profile controller to enable handshake retry CHG016 ;----------------------------------------------------------------------------- DOCRES MOVE.L #VIA1BASE,A3 ;use keyboard 6522 CHG026 (ANDI.B #$7F,ORB1(A3) ;set reset signal CHG016/CHG026/CHG036 (BSR DELAY_1 ;delay for controller to get signal CHG016 (ORI.B #$80,ORB1(A3) ;remove reset signal CHG016/CHG026/CHG036 (BSR DELAY_1 ;delay for controller to respond CHG038 (RTS ;and exit (.ENDC ;{PROFLE} (.IF EXTERNAL = 1 (.NOLIST (.ENDC (.PAGE ;------------------------------------------------------------------------- ; Routine to boot from I/O slot. ; Verifies that slot has bootable card installed and then reads in ROM ; data. If status routine exists it is executed, else jump to boot ; routine done if checksum OK. ; ; Inputs: ; D0 = boot device id ($4-$C) ; A0 = scratch use ; A1 = slot address ; Outputs: (relayed to loaded boot program) ; D0 = boot device id ; A1 = slot address ;------------------------------------------------------------------------- IOSBOOT MOVE.B D0,D4 ;save boot device id @; also acts as flag for status check (MOVE.L BUSVCTR,A5 ;save bus error vector (MOVE.L SP,A6 ;save current stack pointer (LEA NOCRD,A3 ;setup new bus error vector (MOVE.L A3,BUSVCTR (MOVEP (A1),D1 ;read card id (.IF USERINT = 0 (LEA BOOTMSG,A3 ;output boot msg (BSR DSPMSGR (.ENDC (TST D1 ;check if card installed (BPL.S INVID ;exit if not bootable (CMP #$FFFF,D1 ;check if special case (BEQ.S INVID (.IF USERINT = 1 (BSR WAITALRT ;display wait icon (.ENDC (MOVE.L A1,A2 ;get slot address (BSR.S RDIOSLT ;go check the board (BCS.S BADBRD ;exit if error STATOK (MOVE.B BOOTDVCE,D0 ;setup boot device id (MOVE.L #BTENTRY,A2 ;and starting program address (BRA STRTBOOT ;and go do boot ... ; Error routines for I/O slot booting. Error code saved and error message output. NOCRD MOVEQ #NOC,D0 ;set error code (MOVE.L A5,BUSVCTR ;restore bus error vector (MOVE.L A6,SP ;and stack ptr (BRA.S SENDMSG ;then go display msg INVID MOVEQ #INV,D0 ;set error code (BRA.S SENDMSG ;go do display BADBRD MOVE.B BOOTDVCE,D4 ;restore boot device id for checking SENDMSG (MOVE.B D0,BOOTDATA ;save error code (.IF USERINT = 0 (LEA BOOTERR,A3 ;set ptr to msg (BSR DSPMSGR ;and display (MOVE.B D4,D0 ;set up boot device id for display (BRA DSPDVC ; and go do it (.ELSE ; determine which slot # being used (LEA XCARD,A2 ;set general I/O slot card ptr (CMP.B #IO1PORT2,D4 ;in slot 1 range? (BGT.S @1 (MOVEQ #1,D1 ;yes - set slot #1 (BRA.S @3 @1 CMP.B #IO2PORT2,D4 ;slot 2 range? (BGT.S @2 (MOVEQ #2,D1 ;set slot 2 id (BRA.S @3 @2 MOVEQ #3,D1 ;else must be slot 3 @3 BSR DSPNUMICON ;display error icon and slot # (BRA BOOTFAIL ;and signal boot failure (.ENDC (.PAGE (.IF NEWTWIG = 1 ;---------------------------------------------------------------------------- ; Routine to read ROM on an I/O slot. ; Inputs: ; A2 = I/O slot base address ; D4 = nonzero if status check also to be done, else 0 for no check ; D1 = card id if status check needed ; Outputs: ; Carry bit set if error, error code saved in D0, error code from ; status check saved in BOOTDATA+1 ; Side Effects: ; D0, A2 trashed ;---------------------------------------------------------------------------- RDIOSLT MOVEM.L D1-D3/A0-A1,-(SP) ;save regs (MOVE.L #ADR128K-4,A0 ;set load pt (also load id/word count) (MOVE.L A2,A1 ;save slot address for later use (CLR.L D0 ;clear for use (MOVEP 4(A2),D0 ;read word count (ADDQ #2,D0 ;incr for id/count fields (CMPI #$0FFF,D0 ;check for max count (BHI.S INVSUM ;exit if error (CLR.L D2 ;clear for use (CLR.L D3 LOADPGM MOVEP (A2),D2 ;read word (MOVE D2,(A0) ;save in memory (MOVE (A0)+,D2 ;reread it from memory (ADD D2,D3 ;add to checksum (ROL #1,D3 ;rotate for better effectiveness (ADDQ.L #4,A2 ;bump address ptr (SUBQ #1,D0 (BNE.S LOADPGM ;loop until done (MOVEP (A2),D2 ;read expected checksum (2 bytes) (ADD D2,D3 ;add to calculated checksum (TST D3 ;check for 0 result (also clears carry bit) (BNE.S INVSUM ;skip if error ; Do status check if desired and available (TST D4 ;do status check? (BEQ.S RDIOXIT ;skip if not (BTST #STBIT,D1 ;status routine available? (BEQ.S RDIOXIT ;skip if not (MOVEM.L D4-D7/A2-A6,-(SP) ;save regs not already saved (JSR STENTRY ;go execute status routine (MOVEM.L (SP)+,D4-D7/A2-A6 ;restore regs (TST D0 ;check status (BEQ.S RDIOXIT ;skip if no error (MOVE.B D0,BOOTDATA+1 ;save card error code (MOVEQ #BADST,D0 ;set general error code (BRA.S SAVERR INVSUM MOVEQ #BADSM,D0 ;set invalid checksum SAVERR MOVE.B D0,BOOTDATA ;save error code (ORI.B #$01,CCR ;set error indicator RDIOXIT MOVEM.L (SP)+,D1-D3/A0-A1 ;restore regs (RTS (.ENDC (.IF BURNIN = 1 (.PAGE ;------------------------------------------------------------------------- ; Special code to enable burnin cycling by the ROM. Does initialization ; on first pass, and then causes cycling for the specified cycle count, ; which defaults to approximately 60 minutes. At ; that point a branch to a system shutdown routine is performed. ;------------------------------------------------------------------------- ; Do first pass initialization CHKPASS CMP.B #$01,INITFLG ;first pass done? (BEQ.S CHKTIM ;skip if yes CHKPAS2 MOVEA.L #INITFLG,A0 ;set ptr for other data areas (MOVEA.L #ENDPM,A1 ;and ending ptr CLRPM CLR.B (A0) ;do clear (ADDQ.L #2,A0 ;bump ptr (CMPA.L A0,A1 ;loop until done (BNE.S CLRPM (MOVEQ #1,D0 (MOVE.B D0,INITFLG ;set init flag (MOVE.B #60,CYCLVAL ;set cycling for 60 minutes (CLR.L CLKDATA ;and init clock data area (CLR CLKDATA+4 ; Set clock to initial value so run can be ended at cycle count. Sends ; value of day=01, all other values=0 (e.g., time = 00:00:00). (MOVEQ #$2C,D0 ;set up clock set cmd (BSR COPSCMD ;and send to COPS (BCS.S @9 ;exit if error RM000 (MOVE.L #SET1,D1 ;set up value for clock (MOVEQ #8,D2 ;set "char" count (BSR TODSET ;and go do it (BCS.S @9 ; RM000 (MOVE.L #SET2,D1 ;set up next value for clock (MOVEQ #8,D2 ;set "char" count (BSR TODSET ;and go do it (BCS.S @9 ; RM000 (MOVEQ #$25,D0 ;finally set up clock enable cmd (BSR COPSCMD ;and send it @9 BCS SETERR1 ;exit if error ; Check to see if cycle count to be changed and if time data needs to be saved CHKTIM (.IF USERINT = 1 (BSR MAKEPCALRT ;setup powercycle alert box (.ENDC (BTST #MSBUTN,STATFLGS ;mouse button detected? (BEQ.S @3 ;skip if no RM000 (MOVE.B CYCLVAL,D0 ;read current setting RM000 (CMP.B #60,D0 ;long cycle set? RM000 (BNE.S @1 (MOVEQ #3,D0 ;set for 3 minute cycle RM000 (BRA.S @2 @1 MOVEQ #60,D0 ;set for 60 minute cycle RM000 @2 MOVE.B D0,CYCLVAL ;save in PM RM000 @3 CMP.B #$01,TIMFLG ;time data saved? RM000 (BEQ.S TWGCHK ;skip if yes (MOVE.L HOUR,D0 ;get minutes (ROL.L #4,D0 (SWAP D0 (MOVE.B D0,MINSAV ;save minutes (CLR.B MINCNT ;and clear minute count (CLR.B CYCLCNT ; and cycle count (MOVE.B #$01,TIMFLG ;and set flag ; Check if time for Twiggy test (do every two minutes) TWGCHK CMP.B #2,MINCNT ;check minute counter (BNE WRTMSG (CLR.B MINCNT ;clear counter (LEA TWGMSG,A3 ;get msg ptr (BSR DSPMSGR ;and display it (MOVEQ #PCCOL,D6 ;reset left margin (LEA DSKVCT,A3 ;set up bus error vector (MOVE.L A3,BUSVCTR (MOVE.L #DISKMEM,A0 ;set ptr to shared memory (MOVE.L #VIA1BASE,A3 (TST.B SYSTYPE ;check system type CHG009 (BEQ.S @1 ;skip if Lisa 1.0 CHG009 (MOVEQ #80,D4 ;else set track count for SONY drive CHG009 (BRA.S @2 ;and go test single drive CHG009 @1 CLR.L D1 ;else set for drive 1, track 0 to start (MOVEQ #45,D4 ;set count (# of tracks) ; Now do the drive test, one drive at a time (BSR CLRFDIR ;first clear interrupts (BCS.S TSTERR ;exit if error (BSR TWGTST ;go do test (BCS.S TSTERR (MOVEQ #45,D4 ;reset track count CHG009 @2 CLR.L D1 ;set for drive 2 CHG009 (MOVE.B #$08,D1 (ROR.L #4,D1 (BSR TWGTST ;and do test again (BCC.S DISINT ;and continue if OK TSTERR LEA TWGFAIL,A3 ;display error msg (BSR DSPMSGR (MOVEQ #PCCOL,D6 ;reset left margin (CMP.B #TIMOUT,D0 ;timeout error? (BEQ CMDERR ;exit testing if yes (ADDQ.B #1,DSKCNTL ;else bump low error count (BCC.S DISINT ;skip if no overflow (ADDQ.B #1,DSKCNTH ;else bump high counter also ; Disable interrupt so disks can be ejected DISINT BSR TWGDSP ;display Twiggy error count (MOVE.B #$88,CMD(A0) ;set ptr for both drives (MOVE.B #DSABLINT,(A0) ;send disable cmd (BSR CMDCHK ;wait until done ; Output initial message WRTMSG LEA BRNMSG,A3 ;get msg ptr (BSR DSPMSG ;and display it (MOVE.B CYCLVAL,D0 ;get cycling value (BSR DSPDEC ;display as decimal (MOVEQ #PCCOL,D6 ;set col for window limits ; Increment loop count and display it on screen CNTINC ADDQ.B #1,LCNTLO ;inc low byte (BCC.S DSPTIM ;skip if no carry (ADDQ.B #1,LCNTHI ;else inc high byte also DSPTIM BSR DSPCLK ;go display time ; Now check time to see if update needed (MOVE.L HOUR,D0 ;get minute value (ROL.L #4,D0 (SWAP D0 (CMP.B MINSAV,D0 ;has value changed? (BEQ.S NOCHG ;skip if not (ADDQ.B #1,MINCNT ;else bump minute count (ADDQ.B #1,CYCLCNT ;and cycle count (MOVE.B D0,MINSAV ;save new minute value ; Delay so screen can be read NOCHG BSR DELAY5 ;delay for 5 secs ; Check to see if run should be ended (MOVE.B CYCLCNT,D0 ;get cycle count (MOVE.B CYCLVAL,D1 ;get desired cycle value (CMP.B D1,D0 ;cycle if same or greater (BGE.S SHUTDOWN ; If not, cause double bus fault to restart diagnostics ; First make parameter memory valid (MOVE.B #PC,D0 ;set power-cycle boot code (BSR SAV2PM ;and go set param mem (BSR PROINIT ;check for attached hard disk CHG019 (BNE.S @1 ;skip if none CHG019 (BSR WFNBSY2 ;else wait until disk ready CHG019 @1 BRA DORESET ;then go cause a system reset ; Do soft power-off for specified cycle period SHUTDOWN (CLR.B TIMFLG ;reset time save indicator (MOVE.L CLKDATA+2,D0 ;and save clock data (MOVE.L #CLKSAVE,A1 (MOVEP.L D0,(A1) ; Disable Twiggy controller to avoid any RAM problems DSCONT (MOVE.L #DISKMEM,A0 ;set ptr to shared memory (MOVE.B #DIE,(A0) ;and send "die" cmd (BSR CMDCHK ;wait until done (BCS.S CMDERR ;exit if error (MOVEQ #$2D,D0 ;enable alarm setting (BSR COPSCMD (BCS.S SETERR2 (CLR.L D1 (MOVE.B CYCLVAL,D1 ;get desired shutdown time (MOVEQ #60,D0 ;multiply by 60 for seconds (MULU D0,D1 (MOVEQ #12,D0 ;rotate to send as alarm value (ROL.L D0,D1 (MOVE.L #ALRMSAV,A1 (MOVEP.L D1,(A1) ;save alarm value (MOVEQ #5,D2 ;5 digits for alarm value (BSR.S TODSET (BCS.S SETERR2 ; Make parameter memory valid (MOVE.B #PC,D0 ;set power-cycle boot code (BSR SAV2PM ;and go set param mem ; And finally send power-off cmd (MOVEQ #$23,D0 ;set up enable/power off cmd (BSR COPSCMD ;send it (BCS.S SETERR2 SELF NOP (BRA.S SELF ;goodbye ... SETERR1 MOVEQ #SERR1,D0 ;set error code (BRA.S DSPERR ;and go display SETERR2 MOVEQ #SERR2,D0 ;set error code DSPERR (.IF USERINT = 0 (LEA IOMSG,A3 ;display error (BSR DSPMSGR (.ELSE (LEA IOBRD,A2 ;set icon ptr (BSR DSPERRICON ;display it (.ENDC (BSR DSPCODE (BRA MONITOR ;and exit to monitor ; Error routine if disk cmd not taken CMDERR BSET #DISK,D7 ;set error bit (BRA TSTCHK ;and exit (.PAGE ;------------------------------------------------------------------------- ; Subroutine to send clock data. Assumes registers: ; D0 = scratch use ; D1 = clock data ; D2 = digit count ;------------------------------------------------------------------------- TODSET ROL.L #4,D1 ;get digit (MOVE.B D1,D0 ;set up for COPS as 1X (ANDI.B #$0F,D0 ; where X = digit for clock (ORI.B #$10,D0 (BSR COPSCMD ;and send it (BCS.S SETXIT ;exit if error (SUBQ #1,D2 ;decr count (BNE.S TODSET ;and loop until done SETXIT RTS (.PAGE ;-------------------------------------------------------------------------- ; Subroutine to do Twiggy testing ; Expects ; D0 = scratch use A0 = shared memory address ; D1 = drive parameters A1 = unused ; D2 = FDIR timeout value A2 = unused ; D3 = unused A3 = VIA address for FDIR access ; D4 = loop count for reads ;-------------------------------------------------------------------------- TWGTST MOVE.B #$88,CMD(A0) ;enable interrupts from both drives (MOVE.B #ENBLINT,(A0) ;do it (BSR CMDCHK ;wait until done (BCS.S TERR ;exit if error (BCLR #FDIR,DDRB1(A3) ;enable FDIR bit (MOVE.L #FDIRTIME,D2 ;set timeout value for FDIR TWGLOOP MOVEP.L D1,DRV(A0) ; set disk ptrs (MOVE.B #READS,CMD(A0) ; set for read operation (MOVE.B #EXRW,(A0) ; and go do it (BSR CHKFIN ; wait (BCS.S TOOLONG ; exit if timeout (MOVE.B STAT(A0),D0 ; get disk return code (BSR CLRFDIR ; clear interrupt indicator (BCS.S TOOLONG (TST.B D0 ;any error? (BNE.S TERR ; and exit if error (ADDQ #1,D1 ;incr track ptr (SUBQ #1,D4 ;decrement count (BNE.S TWGLOOP ;loop until done (RTS TOOLONG MOVEQ #TIMOUT,D0 ;set error code TERR ORI.B #$01,CCR ;set indicator (RTS ;and exit ;------------------------------------------------------------------------ ; Subroutine to display clock reading as D HH MM SS ;------------------------------------------------------------------------ DSPCLK LEA TIMMSG,A3 ;get msg ptr (BSR DSPMSG ;and display it (ADDQ #1,D6 ;add extra space (BSR READCLK ;go read clock (MOVE.L CLKDATA+2,D0 ;get time (minus Ey/dd digits) (MOVE.L #CLKSAVE,A1 ;and save it (MOVEP.L D0,(A1) (ROL.L #4,D0 ;get day value (MOVEQ #1,D1 ;set # of digits to display (BSR OUTCH ;and display it (ADDQ #1,D6 ;bump col ptr (ROL.L #8,D0 ;get hour (MOVEQ #2,D1 ;and display (BSR OUTCH (ADDQ #1,D6 (ROL.L #8,D0 ;display minute (MOVEQ #2,D1 (BSR OUTCH (ADDQ #1,D6 (ROL.L #8,D0 ;display seconds (MOVEQ #2,D1 (BSR OUTCHR (.IF USERINT = 1 (MOVEQ #PCCOL,D6 ;set col for window (.ENDC (RTS (.PAGE ;------------------------------------------------------------------------- ; Subroutine to display Twiggy error count ;------------------------------------------------------------------------- TWGDSP MOVEM.L D0-D1/A3,-(SP) ;save regs (LEA TWGRSLT,A3 ;output msg (BSR DSPMSG (MOVE.L #DSKCNTH,A3 ;set ptr to error count (MOVEP (A3),D0 ;get count (MOVEQ #4,D1 ;# of digits to display (BSR OUTCHR (.IF USERINT = 1 (MOVEQ #PCCOL,D6 ;set col for window (.ENDC (MOVEM.L (SP)+,D0-D1/A3 ;restore and exit (RTS (.ENDC (.PAGE (.IF USERINT = 0 ;------------------------------------------------------------------------- ; Boot failed - see if device code should be displayed ; Assumes D0 = ASCII code to be displayed ;------------------------------------------------------------------------- DSPDVC (LEA DVCMSG,A3 ;set msg ptr (BSR DSPMSG ;and display (BSR DSPVAL ;then display device code (ADDQ #1,D5 ;bump cursor ptrs to next row (MOVEQ #1,D6 (BRA.S MONITOR ;exit to monitor (.ENDC ϞJ Rev H 1 of 2~!{t TRANS"|~J  :a$kTkJϞe3 "#LUd3. "6F^33D!l^(.NOLIST ;===============================================================================; ; ; ; LL II SSSSSSS AAA ; ; LL II SS AA AA ; ; LL II SSSSSSS AAAAAAA ; ; LL II SS AA AA ; ; LLLLLLL II SSSSSSS AA AA ; ; ; ; ; ; BBBBBB OOOOO OOOOO TTTTTTTT RRRRRR OOOOO MMM MMM ; ; BB BB OO OO OO OO TT RR RR OO OO MM M M MM ; ; BBBBBB OO OO OO OO TT RRRRRR OO OO MM M MM ; ; BB BB OO OO OO OO TT RR RR OO OO MM MM ; ; BBBBBB OOOOO OOOOO TT RR RR OOOOO MM MM ; ; ; ; ; ; Copyright 1983, 1984 Apple Computer Inc. ; ; Revision 2H ; ; ; ;===============================================================================; ; ; Filename: RMXXX.Y.TEXT, XXX = ROM VERSION # (e.g., 200 for 2.00) ; Y = E (equates) ; = K (kernel tests) ; = S (secondary tests) ; = B (bootstrap code) ; = M (monitor code) ; = G (graphics, icon and message display) ; ; Function: Initializes LISA system for use and performs preliminary ; diagnostic checks. If all tests pass, the system then ; does a keyboard scan to check for user input. If any key ; is hit other than caps lock or the mouse button, ; a menu is displayed on the screen showing the available ; boot devices. If a valid COMMAND key sequence is detected, ; a boot from an alternate device is attempted (see below). ; If no keyboard input is detected, the system first checks ; parameter memory for a valid boot device and, if none, defaults ; to booting from a Profile attached to the builtin parallel port ; for Lisa 1 systems. ; ; For Lisa 2 systems, a check is first made to verify a disk ; (internal or external) is connected before defaulting to the ; hard disk boot. If no disk is detected, the system defaults ; to booting from the floppy drive. ; ; ; ; Inputs: Checks for keyboard input from the user. Currently, the following ; key sequences are honored if input after the system "clicks" the ; speaker (CMD refers to the Apple key on the keyboard): ; ; CMD/1 - boot from Twiggy drive #1 or integral hard disk ; CMD/2 - boot from Twiggy drive #2 or SONY drive ; CMD/3 - boot from Profile attached to parallel port or integral hard disk ; CMD/4 - boot from I/O slot #1, port 1 ; CMD/5 - boot from I/O slot #1, port 2 ; CMD/6 - boot from I/O slot #2, port 1 ; CMD/7 - boot from I/O slot #2, port 2 ; CMD/8 - boot from I/O slot #3, port 1 ; CMD/9 - boot from I/O slot #3, port 2 ; CMD/ENTER (on key pad) - abort boot, branch to ROM monitor ; CMD/SHIFT/P - abort boot, do power cycling ; ; OUTPUTS: Saves various results and contents of system registers in memory ; for examination by system programs or with the ROM monitor. ; ; $180-183 : Power-up status (x0000000 = ok) ; $184-185 : Memory sizing error results ; $186-1A5 : Results of memory read/write tests ; $1A6-1A9 : Parity error memory address (if error during mem test) ; $1AA-1AB : Memory error address latch ; $1AC-1AF : D7 save on exception errors ; $1B0-1B1 : Results of MMU tests (context/data bits) ; $1B2 : Keyboard ID (00 = no ID received) ; $1B3 : Boot device ID ; $1B4-1B9 : Boot failure data ; $1BA-1BF : Clock setting (Ey,dd,dh,hm,ms,st) ; $1C0-1DF : Data reg save area (D0 - D7) ; $1E0-1FF : Address reg save area (A0 - A7, A7 = USP) ; $240-260 : System serial # ; $260-267 : Scratch area ; $268-26B : Suspected (logical) memory error address for parity error ; $26C-26F : Save of data written to suspected error address ; $270-273 : Actual (logical) error address found during search ; $274-277 : Save of data read during parity error search ; $278-27B : (Physical) error address read from parity error address latch ; $27C : Error row for parity chip failure (0 = first row, 7 = last row) ; $27D : Error column for parity chip failure (9 or 14) ; $27E-280 : Reserved ; $280-293 : Exception data save area ; (FC/EXCADR/IR/SR/PC/EXCTYPE/SSP) ; 44 = NMI or other interrupt ; 45 = bus error ; 46 = address error ; 47 = other exception/interrupt ; 48 = illegal instruction error ; 49 = line 1010 or 1111 trap ; 50 = bus error accessing keyboard VIA ; 51 = bus error accessing parallel port VIA ; 57 = bus error accessing disk controller ; $294-297 : Maximum physical memory address + 1 ; $298-299 : I/O slot 1 card id (0 = no card present) ; $29A-29B : I/O slot 2 card id ; $29C-29D : I/O slot 3 card id ; $29E : Reserved ; $29F : Reserved ; $2A0 : Reserved ; $2A1 : Disk ROM id ; $2A2-2A3 : Reserved ; $2A4-2A7 : Minimum physical address ; $2A8-2AB : Total memory (Max-Min) ; $2AC : SCC test results ; $2AD : Slot # of memory board if memory error ; $2AE : Result of disk controller self-test ; $2AF : System type (0 = Lisa 1, 1 = Lisa 2, 2 = Lisa 2 with external hard disk, ; 3 = Lisa 2 with internal hard disk) ; $2B0-2BF : Keyboard queue (16 bytes) ; $2C0-480 : ROM scratchpad/stack area ; $480-800 : Reserved for ROM local variable usage ; ; Also saves data in special parameter memory area reserved for boot ROM use if error ; encountered. Usage is as follows: ; ; $FCC161 : Error code ; $FCC163-165 : Contents of memory error address latch if parity error ; $FCC167 : Memory board slot # if memory error ; $FCC169-173 : Last value read from clock ; $FCC175-17B : Reserved ; $FCC17D-17F : Checksum ; ; ; Originator: Rich Castro 7/30/81 - Version 0.0 released to manufacturing ; ; Modified by: Rich Castro 7/30 - 11/3/81 - Made the following changes: ; 1) Twiggy bootstrap capability ; 2) Initial COPS test and keyboard scan ; 3) Moved parallel card to slot 2 ; 4) Changed ROM interrupt/exception vectors, ; 5) Created jump table for ROM routines ; ; 11/3/81 - Version 0.7 released to the world ; ; 11/4/81 - 1/15/82 - Made the following changes: ; 1) Added support for new memory cards ; 2) Added warm-start capability and jump ; table for ROM subroutine usage ; 3) Modified MMU reset routine to support ; single step board usage ; 4) Added full memory initialization ; 5) Added 256K memory parity test ; 6) Modified COPS initialization so that ; keyboard commands can be sensed more ; reliably ; 7) Added error code display routines and ; display of CPU and IO ROM versions ; 8) Added preliminary disk controller test ; 9) Updated warm-start check ; 10) Modified disk interface test ; 11) Changed low memory assignments ; 12) Made corrections for no I/O board, disk ; interface error and contrast setting ; 13) Modified memory sizing routine to ; catch memory errors ; 14) Modify MMU test to avoid context 0 ; destruction, add contrast setting for ; new machines, correct disk error and ; CPU ROM messages ; 15) Move stack so old memory test still runs ; ; 1/15/82 - Release version 0.16 ; 1/18/82 - Fix stack problem and release vrsn 0.17 ; 1/19/82 - Change stack for call routine and version ; to 0.18 ; 1/27/82 - Change MMU error routine to do address ; and data line toggling ; 1/28/82 - Add video circuitry test ; 1/30/82 - Add write wrong parity test ; 1/31/82 - Move run time stack to $180 ; 2/6/82 - Add Profile bootstrap with upgrade for ; OS use (add jump table entries also) ; 2/15/82 - Update Twiggy bootstrap and add entry ; for OS use; also add MMU test to ; conditional assembly and add context ; saving to MMUTST2 routine ; 2/17/82 - Add correction to memory test for ; reboot problem and leave parity on ; 2/24/82 - Add code for clock test and special ; burn-in cycling ; 2/25/82 - Add code to simulate soft on switch ; pressed for COPS problem ; 3/1/82 - Removed all changes since ROM 0.18 ; release except for parity enabling, ; no reset feature, memory sizing change ; and Profile booting ; 3/1/82 - Restore default stack ptr loc to $300 ; 3/1/82 - Move default stack to $0400, restore ; everything except MMU testing ; 3/4/82 - Add MMU initialization and modify ; Twiggy, Profile boot routines for new ; load point ; 3/10/82 - Add change for new I/O addresses and ; fix for Twiggy routine ; 3/10/82 - Change contrast value for new I/O's ; 3/15/82 - Add correction for Profile and COPS ; routines and display msg when booting ; 3/17/82 - Restore version # at end of file ; 3/18/82 - Release version 0.22 ; ; 4/5/82 - Make initial 2732 version (1.00); add ; following changes: ; 1) correct MMU error routine bug ; 2) change stack for CALL to $0400 ; 3) add parity disable to WWP routine ; 4) change MMU I/O space code to '9' ; 5) add invalid boot code message ; 4/6/82 - Add speaker click after COPS check ; 4/7/82 - Add jump table entry for speaker ; routine, 1 second delay before "click" ; and alpha lock key check ; ; 4/8/82 - Release version 1.00 ; ; 5/5/82 - Add I/O slot configuration check and ; I/O slot booting. Also add change to ; Profile read routine for PCR setting. ; 5/12/82 - Add burnin power-cycling routine as ; boot option invoked by CMD/P. ; 5/13/82 - Add changes for COPS command timing, ; Twiggy timeout, Twiggy booting, and ; add power-cycling routine. ; 5/14/82 - Add fixes for booting via parameter ; memory and COPS timing experiment. ; 5/17/82 - Add display of loop count and run time, ; and alter parameter memory useage for ; power-cycling option. ; 5/18/82 - Add display of Twiggy errors, change ; COPS routine for precheck code. ; 5/20/82 - Add contrast reset for "warm start", ; add cycle value display, restore COPS ; timeout code. ; ; 5/21/82 - Release version 1.02 ; ; 5/26/82 - Begin addition of ROM monitor; set ; default to Apple if PM = 00. ; 6/1/82 - Make following changes: ; 1) Memory sizing retry count to 64 ; 2) Save results on memory sizing errors ; 3) Update NMI routine to check for parity ; errors. ; 4) Restore default NMI vector after ; memory test. ; 5) Create read clock subroutine and call ; when doing clock display. ; 6) Add boot fix to save device id. ; 6/1/82 - Change to new sizing algorithm and retry ; count back to 32. ; 6/3/82 - Convert to version 1.03 ; 6/3/82 - Made following changes: ; 1)Localize message display to TSTCHK ; 2)Do clear screen only in INITVCT and ; in TSTCHK and second monitor level. ; 3)Change default video page to last. ; 4)Complete first edition of monitor. ; 6/7/82 - Modify monitor level2 user interface. ; 6/10/82 - Made following changes: ; 1)Add boot from Apple as CMD/A. ; 2)Clear screen and display only in ; routine TSTCHK. ; 3)Add ROM checksum error bit. ; 4)Add exception error check to TSTCHK. ; 5)Add speaker click just before ; keyboard scan. ; 6)Reset to first video page for boot ; from Apple. ; 7)Merge in changes from 1.03 file. ; 8)Add parity error check to TSTCHK ; 9)Change power-cycling so that double ; bus fault used to restart diags ; 6/11/82 - Made following changes: ; 1)Increase Twiggy timeout to 2 mins. ; 2)Add 5 sec delay in power-cycle mode ; before shutting down. ; ; 6/14/82 - Release version 1.04 ; ; 6/22/82 - Add loop after COPS test if error ; since keyboard not accessible. Also add ; fix for NMI restore after memory test. ; 6/30/82 - Made following changes: ; 1)Add parameter memory and I/O boot ; checksum routines. ; 2)Remove boot id save to parameter ; memory, except for power-cycle. ; 3)Change to new boot device id's. ; 7/1/82 - 1)Add changes for new Twiggy firmware. ; 2)Add fixes for bugs in 1.04: ; a)Add row setting before error display ; to avoid writing over menu line. ; b)Set device codes for Profile and ; I/O slots to allow display if error. ; c)Enable setting of timeout for Twiggy ; reads. ; d)Save error codes for I/O boot in ; memory. ; e)Add option of clearing memory in ; INITMON routine. ; 7/7/82 - Made following changes: ; 1)Modify checksum routines ; 2)Add keyboard/mouse check/reset code ; 7/13/82 - Add speed parameter for new Twiggy code ; 7/14/82 - Add check for DSKDIAG in disk test, ; change to new Twiggy error codes ; 7/15/82 - Made following changes: ; 1)Add Profile routine updates. ; 2)Restore old boot id codes - new ones ; used only when new Twiggy code ; released. ; 3)Upgrade burnin code for new parameter ; memory usage. ; 4)Attempt to enable keyboard after MMU ; errors. ; 5)Remove I/O boot checksum code until ; conversion to new Twiggy code. ; 6)Add video pattern display code.. ; 7)Remove characters from table and ; make other changes to save bytes. ; 8)Upgrade service mode display option ; to handle count up to $FFFF. ; ; 7/16/82 - Create version 1.05 ; 7/19/82 - Add bug fixes for MMU testing, power- ; cycle memory testing, Profile boot ; and service mode display option. ; ; 7/19/82 - Create version 1.06 ; 7/20/82 - Add fix for MMU testing to properly ; record context in error ; ; 7/20/82 - Release version 1.07 ; ; 7/21/82 - Make keyboard/mouse reset code changes ; and move check to before first "click" ; 7/23/82 - Add extended memory tests ; 7/27/82 - Add screen memory test and VIA tests. ; Change default boot for new Twiggy code ; to upper Twiggy. Add conditionals for ; Apple code. ; 7/29/82 - Add SCC test, optimize code. ; 7/30/82 - Add RAM address uniqueness test. ; 8/4/82 - Added the following: ; 1)Twiggy mods for interleave ; 2)Monitor options CONTINUE and LOOP ; 3)Exception routine for line 1111 and ; line 1010 errors. ; 8/9/82 - Add Twiggy mod for disk clamp, add mods ; for kernel test failures such as screen ; flash on MMU error. ; 8/11/82 - Add memory sizing fix, increase delay ; for COPS and change default boot to ; TWIGGY!! ; 8/12/82 - Begin code changes for new user interface ; and add hooks for icon display. ; 8/14/82 - Add mods for Twiggy changes to monitor ; DSKDIAG line and add initial timeout. ; Continue user interface changes. ; 8/18/82 - Add mouse, cursor code and changes for ; Customer mode to use mouse. ; 8/23/82 - Add controls for 2716 version of ROM. ; Add changes for Service mode to use ; pull down menu, eliminate keyboard ; queuing while awaiting input. ; 8/24/82 - Add dialog box, and window to service ; mode with modified scroll and character ; output routines. ; 8/25/82 - Add icons along with routines to display ; during test and for errors. ; 8/27/82 - Add routines for displaying and using ; boot icon menu. ; 8/30/82 - Add auto boot from Applenet. ; 8/31/82 - Add minor additions to Service mode ; for Set and Loop options. ; ; 8/31/82 - Create and do internal release of ; 2716 (0.24), 2732 (1.15) and 2764 (2.00) ; ROM versions. ; ; 9/8/82 - Add fixes for I/O slot icon display ; and Profile icon display. ; 9/9/82 - Add fix for reboot problem in 2716 ROM. ; Add serial # read routine and test for ; 2732 and 2764 ROM versions. Expand ; stack for serial read routine. ; 9/10/82 - Add fix for device code display for ROM ; versions 0.24 and 1.15. ; ; 9/10/82 - Create and do internal release of new ; ROM versions 0.25, 1.16 and 2.01. ; ; 9/13/82 - Add fixes for memory sizing and I/O ; slot booting. ; ; 9/14/82 - Create and release ROM versions 0.26, ; 1.17 and 2.02. ; ; 9/22/82 - Add fixes and code for: ; 1)Default video latch setting ; 2)Mask for I/O and exception errors ; 3)Message display on external calls ; to ROM monitor ; 4)Contrast setting before screen test ; 5)Disable of NMI key on power-up ; 6)Boot failure after first load ; 7)Error tones for failures ; 8)Loop mode setting of NMI key ; 9/23/82 - Add ; 1)Power cycling ; 2)Full service mode menu ; 3)Loop mode test choice display ; 9/24/82 - Add dump memory option to service mode ; 9/25/82 - Modify display memory option to allow ; count and address data on same line ; 9/29/82 - Add jump table entry for READMMU ; 9/30/82 - Add: ; 1)"No reset" feature ; 2)Verify Disk option for service mode ; 3)Optimize cursor routines and ; remove unused CursorShield routine. ; 4)Invert rectangles when selected from ; keyboard. ; 5)Display boot menu only if down keycode ; detected. ; 10/5/82 - Add: ; 1)Memory error decoding to board level ; 2)New size and position for alert box ; 3)New test icon display ; 4)Diskette # for Twiggy errors ; 10/6/82 - Add: ; 1)Continue keyboard scan after COPS ; errors ; 2)Set extended memory test bit for ; loop on memory test option ; 3)Display I/O slot card # on errors ; 4)Change boot menu to "pull-down" format ; 5)Change to new icons ; 10/7/82 - Add: ; 1)SCC test ; 2)Error if no serial # (allow continue) ; 3)Two passes of memory tests for extended ; mode, one for regular mode ; 10/9/82 - Create version 2.03 ; 10/10/82 - Add bug fixes and I/O slot ROM check in ; config scan. ; ; 10/12/82 - Create and release version 2.04. ; ; 10/13/82 - Make following changes: ; 1)Add keyboard reset code ; 2)Remove SCC test ; 3)Add bug fixes for making alert box ; and displaying bad keyboard ; 10/14/82 - Add display of check marks for test icons ; 10/18/82 - Add fixes for Monitor entry, Profile boot, ; looping on diag tests ; 10/20/82 - Add message translations ; 10/21/82 - 1)Adjust alert box and button dimensions ; 2)Add boot from all ports on I/O slots ; 3)Add fix for CMD key detection in monitor ; 4)Change powercycle window to alert box ; 5)Extend verify timeout to 4 minutes ; 10/22/82 - 1)Add keyboard reset on external entry to ROM ; monitor ; 2)Make Dump Memory routine conditional on ; final LISA ROM ; 10/25/82 - 1)Change wait for disk error to branch to ; monitor - CONTINUE option then continues ; with the same boot device ; 2)Change RETRY phrase to RESTART ; 10/27/82 - Made following changes: ; 1)RESET instruction on startup ; 2)Jump table entries for access to memory ; test and display decimal routines ; 3)Optimize warm start reset check and ; MMU error loop routines ; 4)Change default video page to $2F for ; no memory found. ; 5)Rewrite screen memory test. Change main ; memory test to go from low memory ; to base of screen memory. ; 6)Move inverse video check to after screen ; test, doing rewrite only of screen page. ; 7)Add new boot failure code, with hooks to ; catch booting errors after ROM has ; released control to boot loader for Twiggy ; and Profile booting. ; 10/29/82 - Add display for uncompressed slot card icons. ; Modify TONE routine to init PCR reg. ; 11/1/82 - Change external entry to monitor interface ; so that error code displayed on same line as ; message if no icon displayed ; 11/3/82 - Made following changes: ; 1)Move creation of test icon display till ; after keyboard reset so translation can ; be done if necessary ; 2)Do cursor, mouse init only once so ; cursor posn not reset ; 3)Optimize mouse, cursor routines ; 4)Correct COPSCMD routine ; 5)Upgrade check for Profile routine and ; optimize Profile read code ; 11/8/82 - Conditionally add check for keyboard connected ; routine. ; 11/9/82 - Create version 2.07 ; 11/11/82 - Modify ROM checksum algorithm ; 11/12/82 - Add diskette eject on power-off ; 11/13/82 - 1)Remove Dump Memory/Verify Disk from Service ; mode menu ; 2)Add speaker beep and specific read/write ; loop for memory sizing and lo mem errors ; 11/15/82 - 1)Add keyboard/mouse disconnect check ; 2)Remove memory "clear" from sizing test - now ; done after memory testing ; 11/16/82 - 1)Change power-cycle invoking to CMD/SHIFT/P ; key sequence. ; 2)Change customer monitor mode invoking to ; CMD/ENTER (on key pad) key sequence. ; 3)Add wait for profile loop in boot menu ; display routine ; 4)Add timeout to general wait for clock ; input routine ; 5)Increase delay for poweroff wait loop ; 6)Optimize character display routine ; 11/18/82 - 1)Add save of error code to special parameter ; memory area for use during burnin. ; 2)Add context check for MMU testing ; 3)Create version 2.08 for internal release ; 11/19/82 - 1)Change initial position of cursor to center ; of screen. ; ; 11/19/82 - Release versions 2.08 (internal) and ; 2.09 (for manufacturing) ; ; 12/15/82 - Add: ; 1)Setting of VIA PCR reg for later use ; 2)Reset of keyboard before boot ; 3)Fix for slot 3 card check for boot menu ; 12/16/82 - Add: ; 1)Move Profile cmd buffer to location $304 ; 2)Change default boot device to Profile ; 3)Remove support for third boot port on ; each slot ; 4)Expand id range for test card search ; 5)Don't display Restart button after boot ; error ; 6)New icons ; 12/18/82 - Fix memory test bug ; ; 1/3/83 - Fix bug in reporting parity circuitry ; failure. Change version to 2.10. ; 1/7/83 - Make following changes: ; 1)Change keyboard sequences for I/O slot ; booting ; 2)Extend timeout for inital Profile check ; 1/11/83 - Change SCC test to use max baud rate for ; loopback test ; 1/12/83 - Add running of expansion card status routines ; when configuration check is done ; 1/18/83 - Add fixes for: ; 1)Continuing after memory error ; 2)Checking for no reset function ; 3)Memory sizing - search entire possible 2 meg ; 4)Read of I/O slot ROM for icon data - ; ensure odd address for icon count ; 5)Default boot setting when loop on memory ; test selected ; 1/21/83 - Add save of disk controller self-test status ; ; 1/28/83 - Create and release ROM version 2.11 ; ; 3/15/83 - Extend Profile timeout for case where drive ; may be parking head. (bug RM016) ; 4/20/83 - Add fixes for: ; 1)Memory sizing (bug RM015). ; 2)Garbage sent out serial port (RM014). ; 3)Removed 6504 (bug RM013). ; 4)Never ready Profile (bug RM011). ; Also do some code optimization in icon ; routines to make room for fixes. (RM000) ; 4/22/83 - Do code optimization for setting bus error ; vector (labeled as RM000). ; Add changes for following requests: ; 1)Display ROM id's on bootup (CHG001) ; 2)Loop on address 1Meg-2 if sizing error (CHG002) ; 3)Turn off contrast before doing poweroff (CHG003) ; 4)Change copyright notice. (CHG005) ; Also modify alert msg display routine (CHG005). ; 4/26/83 - Add loop on CPU diags if no memory or I/O ; board installed. Also toggle LED. (CHG004) ; 4/27/83 - Do only basic memory test on warm-start. (CHG006) ; Add fix for NMI bug (RM010). ; 5/9/83 - Made following changes: ; 1)Change ROM id display to rev # (D) (CHG001) ; 2)Change ROM test failure to loop at fixed address ; $00FE00C8 (end of jump table) (CHG007) ; 3)Make correction for screen not cleared when ; continuing from I/O slot error to boot menu. ; (CHG008) ; 5/10/83 - Add change to enable display of uncompressed icons ; upon external entry to ROM Monitor (CHG008). ; ; 5/12/83 - Create and release rev D of boot ROM. ; ; 8/8/83 - Add changes for Pepsi system: (CHG009) ; 1) New icons. ; 2) Display of icons with id #'s. ; 8/9/83 - Add save of disk ROM id in low memory. (CHG010) ; Add fixes for: ; 1) SCC init for Applebus. (CHG011) ; 2) Test card boot search. (CHG012) ; 8/10/83 - Delete inverse video check. (CHG013) ; Add fix to beep routine. (CHG014) ; 8/16/83 - Delete memory address and ping pong routines, ; add routines to decode parity error to ; chip. (CHG015) ; 9/1/83 - Add retry for hard disk booting. (CHG016) ; Add jump table entry for write to ; parameter memory routine. (CHG017) ; 9/2/83 - Add new font, modify display routines. (CHG018) ; Add wait for hard disk ready when ; power-cycling. (CHG019) ; 9/6/83 - Add setting of video latch whenever boot ; error causes jump to ROM low memory default ; vectors. (CHG020) ; Add fix for memory test/initialization ; bug. (CHG021) ; 9/7/83 - Add read of disk controller ROM self-test ; results. (CHG022) ; Add skip of disk eject on power-off if any ; disk controller errors occurred. (CHG023) ; ; 9/8/83 - Release for testing (rev 3B) with Pepsi systems. ; ; 10/10/83 - 1)Make Pepsi icon changes. (CHG024) ; 2)Add fix for proper setting of carry bit ; on floppy or hard disk boots. (CHG025) ; 3)Add fix for video reset on boot from not ready ; Profile. (CHG026) ; 10/12/83 - Add change to reset SCC for Applebus before ; doing memory test. (CHG027) ; 10/20/83 - Add fix for service mode bus error problem. (CHG028) ; ; ; 10/20/83 - Release as rev E for Lisa and Pepsi systems. ; ; 12/15/83 - 1)Add new code to determine system type. (CHG029) ; 2)Change default boot device for Lisa 2 ; system if no hard disk connected. (CHG030) ; 3)Extend timeout for hard disk ready. (CHG031) ; 4)Add bug fix for wrong icon display on Lisa 2. ; (CHG032) ; 5)Add bug fix for menu display when mouse or ; keyboard not connected. (CHG033) ; 6)Remove save of error code in parameter memory. ; (CHG034) ; 12/16/83 - Release as rev 'X' for testing ; ; 12/21/83 - Release as official rev 'F' for all systems ; ; 1/25/84 - 1)Add code to properly initialize Profile-reset ; and parity-reset lines for Profile booting (CHG036) ; ; 2/7/84 - 1)Extend hard disk default read timeout to 16 ; seconds for Widget systems. (CHG037) ; 2)Add delay after hard disk reset for Widget ; systems. (CHG038) ; 2/8/84 - Release as rev G for testing ; ; 2/24/84 - Release as official rev H ; ;----------------------------------------------------------------------------------------------------- (.PAGE ;----------------------------------------------------------------------------------------------------- ; Macro definitions ;----------------------------------------------------------------------------------------------------- (.MACRO BSR6 (LEA @1,A6 (BRA %1 @1 (.ENDM (.MACRO BSRS6 (LEA @1,A6 (BRA.S %1 @1 (.ENDM (.MACRO RTS6 (JMP (A6) (.ENDM (.MACRO BSR4 (LEA @1,A4 (BRA %1 @1 (.ENDM (.MACRO BSRS4 (LEA @1,A4 (BRA.S %1 @1 (.ENDM (.MACRO RTS4 (JMP (A4) (.ENDM (.MACRO BSR2 (LEA @1,A2 (BRA %1 @1 (.ENDM (.MACRO BSRS2 (LEA @1,A2 (BRA.S %1 @1 (.ENDM (.MACRO RTS2 (JMP (A2) (.ENDM (.MACRO DISABLE (MOVE SR,-(SP) (ORI #$0700,SR (.ENDM (.MACRO ENABLE (MOVE (SP)+,SR (.ENDM (.PAGE ;-------------------------------------------------------------------------- ; Conditionals for assembly ;-------------------------------------------------------------------------- DIAGS .EQU 1 ;controls assembly of selected diags NEWLISA .EQU 1 ;controls extra code for new LISA's BURNIN .EQU 1 ;controls code for burnin cycling NORESET .EQU 1 ;controls code for reset feature EXTERNAL .EQU 0 ;controls listing of externally H; callable routines only (w/ EQU's) ROM16K .EQU 1 ;controls code to be added when 16K H; ROM's available NEWTWIG .EQU 1 ;controls code for new Twiggy firmware H; interface FINLISA .EQU 0 ;controls code for final LISA's FINKBD .EQU 1 ;controls check for final keyboard AAPL .EQU 0 ;controls Apple monitor code USERINT .EQU 1 ;controls code for new user interface DEBUG .EQU 0 ;controls global equate allocation ROM4K .EQU 0 ;controls code for 2716 version ROM8K .EQU 0 ;controls code for 2732 version BMENU .EQU 1 ;controls format of boot menu H; 1 = pull down menu FULLSCC .EQU 1 ;controls code for SCC tests INVERTCK .EQU 0 ;controls code for inverse video check CHG013 (.IF EXTERNAL = 1 (.LIST ;----------------------------------------------------------------------------- ; This is a listing of LISA boot ROM routines which are externally callable ; by other programs. Calls are made via a jump table resident at a fixed ; location in the ROM (see listing). Also listed are equates used by these ; routines. If you have any questions/comments/suggestions, please call Rich ; Castro, x2504. ;----------------------------------------------------------------------------- (.ENDC (.PAGE ;-------------------------------------------------------------------------- ; GENERAL EQUATES ;-------------------------------------------------------------------------- ROMBASE .EQU $00FE0000 ;BASE ADDRESS FOR ROM ROMSLCT .EQU $00FE ;MSB'S OF ROM ADDRESS IOSPACE .EQU $00FC0000 ;START OF IO SPACE VIDLTCH .EQU $00FCE800 ;VIDEO ADDRESS LATCH DEFVID .EQU $2F ;default setting for video latch H; (end of 512K board in slot 1) DEFVID2 .EQU $AF ;default video latch setting and LED on (.IF DEBUG = 0 SCRNBASE .EQU $110 ;ptr to base address for video page (.ELSE SCRNBASE .EQU $160 ;ptr to base address for video page (.ENDC (.IF USERINT = 0 RBYTES .EQU 900 ;BYTES FOR EACH DISPLAY ROW (.ELSE RBYTES .EQU 90 ;BYTES FOR EACH DISPLAY ROW (.ENDC TOPOFFSET .EQU 270 ;offset for first row from top of screen RLONGS .EQU 225 ;longs for each row R0 .EQU 0 ;ROW 0 OFFSET R1 .EQU R0+90 ;ROW 1 OFFSET, ETC. R2 .EQU R1+90 R3 .EQU R2+90 R4 .EQU R3+90 R5 .EQU R4+90 R6 .EQU R5+90 R7 .EQU R6+90 BUSVCTR .EQU $0008 ;BUS EXCEPTION VECTOR ADRVCTR .EQU $000C ;ADDRESS EXCEPTION VECTOR ILLVCTR .EQU $0010 ;ILLEGAL INSTRUCTION VECTOR L10VCTR .EQU $0028 ;line 1010 trap L11VCTR .EQU $002C ;line 1111 trap NMIVCT .EQU $007C ;NMI VECTOR LOCATION TRPVCT0 .EQU $0080 ; TRAP 0 VECTOR LOCATION MAXADR .EQU $00200000 ; MAX RAM ADDRESS + 1 (2 meg) ONEMEG .EQU $00100000 ; 1 meg in hex HALFMEG .EQU $00080000 ; 1/2 meg QTRMEG .EQU $00040000 ; 256K ROW2ADR .EQU $00020000 ; 128K - START OF 2ND MEMORY ROW STKBASE .EQU $0480 ; DEFAULT BASE FOR STACK CALLBASE .EQU $0480 ; STACK BASE FOR USE BY CALL ROUTINE SETUP .EQU $00FCE012 ; ADDRESS TO TURN SETUP BIT OFF SETUPON .EQU $00FCE010 ; ADDRESS TO TURN SETUP ON PATRN .EQU $AA55A55A ; PATTERN FOR MEMORY TESTING PATRN2 .EQU $A55A ; PATTERN FOR MMU TEST PARON .EQU $00FCE01E ;PARITY ENABLE PAROFF .EQU $00FCE01C ;PARITY DISABLE MEALTCH .EQU $00FCF000 ;MEMORY ERROR ADDRESS LATCH STATREG .EQU $00FCF801 ;ERROR STATUS REGISTER SFER .EQU 0 ; SOFT ERROR BIT PBIT .EQU 1 ; HARD ERROR (PARITY) BIT VRBIT .EQU 2 ; VR BIT LOCATION VIDBIT .EQU 4 ; VID BIT CSBIT .EQU 5 ; CSYNC BIT INVIDBIT .EQU 6 ; INVERSE VIDEO BIT RETRYCNT .EQU 32 ;RETRY COUNT FOR MEMORY SIZING VTIRDIS .EQU $00FCE018 ;VERTICAL RETRACE DISABLE VTIRENB .EQU $00FCE01A ;VERTICAL RETRACE ENABLE HEX512K .EQU $80000 ;512K in hex HEX128K .EQU $20000 ;128K in hex HEX96K .EQU $18000 ;96K in hex HEX32K .EQU $8000 ;32K in hex HEX8K .EQU $2000 ;8K in hex HEX2K .EQU $0800 ;2K in hex LOMEM .EQU HEX2K ;amount of memory initially tested DG2ON .EQU $00FCE006 ;WRITE WRONG PARITY ENABLE DG2OFF .EQU $00FCE004 ;WRITE WRONG PARITY DISABLE ONESEC .EQU $3D090 ;1 second delay constant TWOSEC .EQU ONESEC*2 ;2 second delay FIVESEC .EQU ONESEC*5 ;5 second delay QTRSEC .EQU ONESEC/4 ;0.25 second delay TNTHSEC .EQU ONESEC/10 ;0.1 second delay KBDDLY .EQU /10 ;1.7 second delay HALFSEC .EQU ONESEC/2 ;0.5 second delay ; Equates for memory parity error routine MSRCHSZ .EQU 64 ;main memory error range CHG015 VSRCHSZ .EQU 32768 ;video memory error range CHG015 VMSK .EQU $FFFF8000 ;mask for video errors CHG015 ADRMSK .EQU $03 ;mask for error byte address CHG015 PHYTOLOG .EQU $80000 ;physical to logical address offset CHG015 (.IF EXTERNAL = 1 (.NOLIST (.ENDC ; Equates for VIA registers (offsets from $XXD181 or $XXD101) VIA1BASE .EQU $00FCDD81 ;BASE ADDRESS FOR COPS 6522 ORB1 .EQU $0 ;PORT B OUTPUT REG ORA1 .EQU $2 ;PORT A OUTPUT REG DDRB1 .EQU $4 ;PORT B DATA DIRECTION REG DDRA1 .EQU $6 ;PORT A DATA DIRECTION REG T1LL1 .EQU $C ;LOW ORDER T1 LATCH T1LH1 .EQU $E ;HIGH ORDER T1 LATCH T2CL1 .EQU $10 ;LOW ORDER T2 COUNTER T2CH1 .EQU $12 ;HIGH ORDER T2 COUNTER SHR1 .EQU $14 ;SHIFT REG ACR1 .EQU $16 ;AUXILIARY CONTROL REG PCR1 .EQU $18 ;PERIPHERAL CONTROL REG IFR1 .EQU $1A ;INTERRUPT FLAG REG IER1 .EQU $1C ;INTRPT ENABLE REG PORTA1 .EQU $1E ;PORT A WITH NO HANDSHAKE FDIR .EQU 4 ;PORT B, BIT 4 HAS FDIR STATE VIA2BASE .EQU $00FCD901 ;BASE ADDRESS FOR OTHER 6522 ORB2 .EQU $0 ;PORT B OUTPUT REG IRB2 .EQU $0 ;PORT B INPUT REG ORA2 .EQU $8 ;PORT A OUTPUT REG IRA2 .EQU $8 ;PORT A INPUT REG DDRB2 .EQU $10 ;PORT B DATA DIRECTION REG DDRA2 .EQU $18 ;PORT A DATA DIRECTION REG T1LL2 .EQU $30 ;LOW ORDER T1 LATCH T1LH2 .EQU $38 ;HIGH ORDER T1 LATCH T2CL2 .EQU $40 ;LOW ORDER T2 COUNTER T2CH2 .EQU $48 ;HIGH ORDER T2 COUNTER PCR2 .EQU $60 ;PERIPHERAL CONTROL REG PORTA2 .EQU $78 ;PORT A WITH NO HANDSHAKE DSKDIAG .EQU 6 ;port B, bit 6 is disk alive indicator CSTRB .EQU $00FCD01C ;STROBE FOR CONTRAST LATCH ; Equates for PIA registers (offsets from $XXA001) (SLOT 2) PIABASE .EQU $00FCA001 ;BASE ADDRESS FOR PIA CARD IN SLOT 2 INDATA .EQU $0 OUTDATA .EQU $2 INCSR .EQU $4 OUTCSR .EQU $6 ; Equates for SCC SCCBCTL .EQU $FCD241 ;SCC channel B control ACTL .EQU 2 ;offset to SCC channel A control SCCDATA .EQU 4 ;offset to SCC data regs RXBF .EQU 0 ;receive buffer full bit TXBE .EQU 2 ;transmit buffer empty bit (.PAGE (.IF USERINT = 0 ; The following equates are used as error indicators CPUSEL .EQU 0 ;CPU selection logic error MMU .EQU 1 ;MMU ERROR VID .EQU 2 ;CPU VIDEO LOGIC ERROR PAR .EQU 3 ;CPU PARITY LOGIC ERROR CPUINTR .EQU 4 ;UNEXPECTED INTERRUPT OCCURRED BUSEXCP .EQU 5 ;BUS ERROR ADREXCP .EQU 6 ;ADDRESS ERROR MISEXCP .EQU 7 ;MISC EXCEPTION ILLEXCP .EQU 8 ;ILLEGAL INSTRUCTION ERROR TRPEXCP .EQU 9 ;line 1111 or 1010 trap VIA1 .EQU 10 ;COPS VIA ERROR VIA2 .EQU 11 ;PARALLEL PORT VIA ERROR IOCOPS .EQU 12 ;IO BOARD COPS ERROR KBDCOPS .EQU 13 ;KEYBOARD COPS ERROR CLK .EQU 14 ;CLOCK ERROR RS232A .EQU 15 ;RS232 PORT A ERROR RS232B .EQU 16 ;RS232 PORT B ERROR DISK .EQU 17 ;DISK ERROR IOEXCP .EQU 18 ;UNEXPECTED IO EXCEPTION OCCURRED IOCOPS2 .EQU 19 ;COPS reset code error MEM .EQU 20 ;MEMORY ERROR MPAR .EQU 21 ;memory parity error IOKBD .EQU 23 ;I/O or keyboard failure KBDOUT .EQU 24 ;KEYBOARD DISCONNECTED MOUSOUT .EQU 25 ;MOUSE DISCONNECTED IO1ERR .EQU 26 ;I/O slot 1 failure IO2ERR .EQU 27 ;I/O slot 2 failure IO3ERR .EQU 28 ;I/O slot 3 failure ALTBOOT .EQU 29 ;alternate boot key request WRMSTRT .EQU 30 ;warm-start indicator LOOP .EQU 31 ;loop on test ERRMSK .EQU $00FFFFFF ;MASK FOR ERROR CHECKING CPUMSK .EQU $0000000F ;MASK FOR CPU ERROR CHECKING EXMSK .EQU $000003F0 ;mask for exception error checking MEMMSK .EQU $00700000 ;mask for memory error checking IOMSK .EQU $008FDC00 ;MASK FOR I/O ERROR CHECKING OTHRMSK .EQU $03000000 ;mask for keyboard/mouse check CONTMSK .EQU $00CE3FFC ;mask for CONTINUE option (.ELSE MMU .EQU 0 ;MMU ERROR CPUSEL .EQU 1 ;CPU selection logic error VID .EQU 2 ;CPU VIDEO LOGIC ERROR PAR .EQU 3 ;CPU PARITY LOGIC ERROR CPUINTR .EQU 4 ;UNEXPECTED INTERRUPT OCCURRED BUSEXCP .EQU 5 ;BUS ERROR ADREXCP .EQU 6 ;ADDRESS ERROR MISEXCP .EQU 7 ;MISC EXCEPTION ILLEXCP .EQU 8 ;ILLEGAL INSTRUCTION ERROR TRPEXCP .EQU 9 ;line 1111 or 1010 trap VIA1 .EQU 10 ;COPS VIA ERROR VIA2 .EQU 11 ;PARALLEL PORT VIA ERROR IOCOPS .EQU 12 ;IO BOARD COPS ERROR KBDCOPS .EQU 13 ;KEYBOARD COPS ERROR CLK .EQU 14 ;CLOCK ERROR RS232A .EQU 15 ;RS232 PORT A ERROR RS232B .EQU 16 ;RS232 PORT B ERROR DISK .EQU 17 ;DISK ERROR IOEXCP .EQU 18 ;UNEXPECTED IO EXCEPTION OCCURRED IOCOPS2 .EQU 19 ;COPS reset code error IOKBD .EQU 20 ;I/O or keyboard failure MEM .EQU 21 ;MEMORY ERROR MPAR .EQU 22 ;memory parity error KBDOUT .EQU 23 ;KEYBOARD DISCONNECTED MOUSOUT .EQU 24 ;MOUSE DISCONNECTED IO1ERR .EQU 25 ;I/O slot 1 failure IO2ERR .EQU 26 ;I/O slot 2 failure IO3ERR .EQU 27 ;I/O slot 3 failure ALTBOOT .EQU 28 ;alternate boot key request BTMENU .EQU 29 ;boot menu request WRMSTRT .EQU 30 ;warm-start indicator LOOP .EQU 31 ;loop on test ERRMSK .EQU $0E7FFFFF ;MASK FOR ERROR CHECKING CPUMSK .EQU $0000000F ;MASK FOR CPU ERROR CHECKING EXMSK .EQU $000003F0 ;mask for exception error checking IOMSK .EQU $001FDC00 ;MASK FOR I/O ERROR CHECKING MEMMSK .EQU $00600000 ;mask for memory error checking OTHRMSK .EQU $01800000 ;mask for keyboard/mouse check IOSMSK .EQU $0E000000 ;mask for I/O slot error checking CONTMSK .EQU $001E3FFA ;mask for CONTINUE option - allow continue H; for MMU,VIDEO,CLK,RS232,MEM,MPAR,KBDOUT, H; MOUSOUT,and IO slot errors SCANMSK .EQU $00183000 ;mask for results of initial keyboard scan ALTBMSK .EQU $70000000 ;mask for D7 when CONTINUE option invoked BOOTMSK .EQU $008FFFFF ;mask for errors that continue to boot attempt CPIOMSK .EQU $001FFFFF ;mask for checking for CPU and IO errors (.ENDC ; Equates for error codes displayed to user (.IF NEWTWIG = 0 ECPUSEL .EQU 0 ;CPU selection logic error EMMU .EQU 1 ;MMU ERROR EVID .EQU 2 ;CPU VIDEO LOGIC ERROR ECPAR .EQU 3 ;CPU PARITY LOGIC ERROR ECPUINTR .EQU 4 ;UNEXPECTED INTERRUPT OCCURRED EBUSEXCP .EQU 5 ;BUS ERROR EADREXCP .EQU 6 ;ADDRESS ERROR EMISEXCP .EQU 7 ;MISC EXCEPTION EILLEXCP .EQU 8 ;ILLEGAL INSTRUCTION ERROR ETRPEXCP .EQU 9 ;line 1111 or 1010 trap EVIA1 .EQU $10 ;COPS VIA ERROR EVIA2 .EQU $11 ;PARALLEL PORT VIA ERROR EIOCOP .EQU $12 ;IO BOARD COPS ERROR EKBDCOP .EQU $13 ;KEYBOARD COPS ERROR ECLK .EQU $14 ;CLOCK ERROR ERS232A .EQU $15 ;RS232 PORT A ERROR ERS232B .EQU $16 ;RS232 PORT B ERROR EDISK .EQU $17 ;DISK ERROR EIOEXCP .EQU $18 ;UNEXPECTED IO EXCEPTION OCCURRED EIOCOP2 .EQU $19 ;IO board COPS code error EMEM .EQU $20 ;R/W MEMORY ERROR EPAR .EQU $21 ;PARITY ERROR EIOKBD .EQU $23 ;I/O or keyboard error ; Special COPS error codes for burnin cycling SERR1 .EQU $32 ;error setting initial time SERR2 .EQU $33 ;error setting alarm (.ELSE EMMU .EQU 40 ;MMU ERROR ECPUSEL .EQU 41 ;CPU selection logic error EVID .EQU 42 ;CPU VIDEO LOGIC ERROR ECPAR .EQU 43 ;CPU PARITY LOGIC ERROR ECPUINTR .EQU 44 ;UNEXPECTED INTERRUPT OCCURRED EBUSEXCP .EQU 45 ;BUS ERROR EADREXCP .EQU 46 ;ADDRESS ERROR EMISEXCP .EQU 47 ;MISC EXCEPTION EILLEXCP .EQU 48 ;ILLEGAL INSTRUCTION ERROR ETRPEXCP .EQU 49 ;line 1111 or 1010 trap EVIA1 .EQU 50 ;COPS VIA ERROR EVIA2 .EQU 51 ;PARALLEL PORT VIA ERROR EIOCOP .EQU 52 ;IO BOARD COPS ERROR EKBDCOP .EQU 53 ;KEYBOARD COPS ERROR ECLK .EQU 54 ;CLOCK ERROR ERS232A .EQU 55 ;RS232 PORT A ERROR ERS232B .EQU 56 ;RS232 PORT B ERROR EDISK .EQU 57 ;DISK ERROR EIOEXCP .EQU 58 ;UNEXPECTED IO EXCEPTION OCCURRED EIOCOP2 .EQU 59 ;IO board COPS code error EIOKBD .EQU 60 ;I/O or keyboard error EMEM .EQU 70 ;R/W MEMORY ERROR EPAR .EQU 71 ;PARITY ERROR EBOOT .EQU 75 ;general boot failure error code ; Special COPS error codes for burnin cycling SERR1 .EQU 61 ;error setting initial time SERR2 .EQU 62 ;error setting alarm (.ENDC ; Secondary status flag (STATFLGS) equates NORSTRT .EQU 0 ;governs display of restart button NOCONT .EQU 1 ;error disallows Monitor CONTINUE option MSBUTN .EQU 2 ;mouse button detected CMDFLG .EQU 3 ;cmd button up/down MOUSE .EQU 4 ;mouse button up/down CHKCMD .EQU 5 ;if =1 user input from keyboard must H; be prefaced by CMD key BTN .EQU 6 ;flag for button use MENU .EQU 7 ;flag for menu use ; MMU equates MMUSADRL .EQU $00008000 ;STARTING MMU LIMIT ADDRESS MMUSADRB .EQU $00008008 ;STARTING MMU BASE ADDRESS MMUEADRL .EQU $00FE8000 ;ENDING MMU LIMIT ADDRESS MMUEADRB .EQU $00FE8008 ;ENDING MMU BASE ADDRESS ADR128K .EQU $00020000 ;128K IN HEX - INCR FOR MMU REGS PTRS PAG128K .EQU $00000100 ;128K PAGE INCREMENT FOR ORG REGS MEMLMT .EQU $0700 ;LIMIT VALUE FOR MEMORY SEGMENTS NMEMLMT .EQU $08FF ;INVERSE OF VALUE (HIGH NIBBLE IGNORED) (.IF ROM4K = 0 IOLMT .EQU $0900 ;LIMIT VALUE FOR I/O SEGMENT NIOLMT .EQU $06FF ;INVERSE IOLMT2 .EQU $0901 ;limit value for no reset feature RSTLMT .EQU $0FFE ;inverse mask for no reset feature (.ELSE IOLMT .EQU $0800 ;LIMIT VALUE FOR I/O SEGMENT NIOLMT .EQU $07FF ;INVERSE (.ENDC SPLMT .EQU $0F00 ;LIMIT VALUE FOR SPECIAL I/O SPACE NSPLMT .EQU $00FF ;INVERSE INVPAG .EQU $0C00 ;INVALID PAGE LIMIT MMU0B .EQU $00008008 ;ADRESS OF ORG REG 0 (FOR LOW MEMORY) MMU0L .EQU $00008000 ;ADDRESS OF LIMIT REG 0 MMU126B .EQU $00FC8008 ;ADDRESS OF ORG REG 126 (FOR I/O SPACE) MMU126L .EQU $00FC8000 ;ADDRESS OF LIMIT REG 126 MMU127B .EQU $00FE8008 ;ADDRESS OF BASE REG 127 (FOR ROM SPACE) MMU127L .EQU $00FE8000 ;ADDRESS OF LIMIT REG 127 SEG1ON .EQU $00FCE00A ;CONTEXT SELECTION BIT 1 ENABLE SEG1OFF .EQU $00FCE008 ;CONTEXT SELECTION BIT 1 DISABLE SEG2ON .EQU $00FCE00E ;CONTEXT SELECTION BIT 2 ENABLE SEG2OFF .EQU $00FCE00C ;CONTEXT SELECTION BIT 2 DISABLE ; Equates for serial number read routine Dlycnst .equ 9 ;constant for delay loop TKiller .equ 172 ;time killer constant BytesPerRead .equ 7 ;bytes per read WordsPerRead .equ BytesPerRead*2 ;during reading one byte fits into one word HalfSize .equ WordsPerRead*8 ;half the size of ScrachSize ScrachSize .equ HalfSize*2 ;size of the scrach array H;I/O segment 126 Snum .equ $0fe8000 ;location of SN1 & SN2 H;special I/O segment 127 dLcnt .equ -4 ;displacement for local variable LOOP COUNTER dSavArry .equ dLcnt-4 ;disp. for Save Array pointer dScrach .equ dSavArry-ScrachSize H;disp. for pointer to local array SCRACH dStack .equ dScrach ;disp. for the Link ; Equates for COPS and keyboard scan MOUSDWN .EQU $86 ;MOUSE BUTTON PRESSED CMDKEY .EQU $FF ;LEFT COMMAND KEY ALPHKEY .EQU $FD ;ALPHA LOCK KEY "DOWN" (.IF NEWTWIG = 0 AKEY .EQU $F0 ;'A' key - for boot from Apple ][ MKEY .EQU $D8 ;'M' key - for abort to monitor FKEY .EQU $E9 ;'F' key - for Twiggy #1 boot GKEY .EQU $EA ;'G' key - for Twiggy #2 boot HKEY .EQU $EB ;'H' key - for Hard disk boot PKEY .EQU $C4 ;'P' key - for Power-cycling KEY1 .EQU $F4 ;'1' key - for I/O slot #1 KEY2 .EQU $F1 ;'2' key - for I/O slot #2 KEY3 .EQU $F2 ;'3' key - for I/O slot #3 (.ELSE KEY1 .EQU $F4 ;'1' key - for Twiggy #1 boot KEY2 .EQU $F1 ;'2' key - for Twiggy #2 boot KEY3 .EQU $F2 ;'3' key - for Profile boot AKEY .EQU $F0 ;'A' key - for I/O slot #3, port 1 BKEY .EQU $EE ;'B' key - for I/O slot #3, port 2 CKEY .EQU $ED ;'C' key - for I/O slot #3, port 3 ;DKEY .EQU $FB ;'D' key - for I/O slot #1, port 4 ;EKEY .EQU $E0 ;'E' key - for I/O slot #2, port 4 ;FKEY .EQU $E9 ;'F' key - for I/O slot #3, port 4 ENTRKEY .EQU $AF ;Right ENTER key - for Monitor invoking SHFTKEY .EQU $FE ;Shift key - used for power-cycling PKEY .EQU $C4 ;'P' key - for Power-cycling (.ENDC RSTCODE .EQU $80 ;reset code KUNPLG .EQU $FD ;keyboard unplugged ICERR .EQU $FE ;I/O board COPS RAM error KCERR .EQU $FF ;keyboard COPS RAM error MSUNPLG .EQU $07 ;mouse unplugged MSPLG .EQU $87 ;mouse plugged in (.IF EXTERNAL = 1 (.LIST (.PAGE (.ENDC ; Equates for Boot device id's (.IF NEWTWIG = 0 TWIG1 .EQU FKEY ;TWIGGY DRIVE #1 TWIG2 .EQU GKEY ;TWIGGY DRIVE #2 PROFILE .EQU HKEY ;PROFILE HARD DISK IO1PORT1 .EQU KEY1 ;I/O SLOT 1, port 1 IO2PORT1 .EQU KEY2 ;I/O SLOT 2, port 1 IO3PORT1 .EQU KEY3 ;I/O SLOT 3, port 1 PC .EQU PKEY ;power-cycle id MON .EQU MKEY ;abort boot, go to monitor id APPLE .EQU AKEY ;abort boot, go to Apple id (.ELSE TWIG1 .EQU $0 ;TWIGGY DRIVE #1 TWIG2 .EQU $1 ;TWIGGY DRIVE #2 PROFILE .EQU $2 ;PROFILE HARD DISK IO1PORT1 .EQU $3 ;I/O SLOT 1, port 1 IO1PORT2 .EQU $4 ;I/O SLOT 1, port 2 IO2PORT1 .EQU $6 ;I/O SLOT 2, port 1 IO2PORT2 .EQU $7 ;I/O SLOT 2, port 2 IO3PORT1 .EQU $9 ;I/O SLOT 3, port 1 IO3PORT2 .EQU $A ;I/O SLOT 3, port 2 PC .EQU $F ;power cycle mode MON .EQU $10 ;abort boot, go to monitor id (.ENDC (.IF USERINT = 0 PC .EQU $C ;power-cycle id APPLE .EQU $E ;abort boot, go to Apple id (.ENDC ; Equates for device code display (ASCII codes) (.IF NEWTWIG = 0 IOS1 .EQU $31 ;I/O slot 1 IOS2 .EQU $32 ;I/O slot 2 IOS3 .EQU $33 ;I/O slot 3 TWG1 .EQU $46 ;Twiggy drive #1 TWG2 .EQU $47 ;Twiggy drive #2 PRO .EQU $48 ;Profile (.ELSE TWG1 .EQU $31 ;Twiggy drive #1 TWG2 .EQU $32 ;Twiggy drive #2 PRO .EQU $33 ;Profile IOS1 .EQU $34 ;I/O slot 1 IOS2 .EQU $37 ;I/O slot 2 IOS3 .EQU $41 ;I/O slot 3 (.ENDC ;---------------------------------------------------------------------------------- ; Equates for Disk controller shared memory/Twiggy boot ;---------------------------------------------------------------------------------- TWIGGY .EQU 1 ;controls Twiggy code assembly (1 = YES) DISKMEM .EQU $00FCC001 ;base address of shared memory CMD .EQU 2 ;offset for command byte DRV .EQU CMD+2 ;offset for drive # SIDE .EQU DRV+2 ;side # SCTR .EQU SIDE+2 ;sector # TRAK .EQU SCTR+2 ;track # (.IF NEWTWIG = 0 STAT .EQU TRAK+2 ;ERROR STATUS CHKCNT .EQU STAT+2 ;CHECKSUM ERROR COUNT HDR .EQU CHKCNT+2 ;HEADER BYTES ROMV .EQU $30 ;ROM VERSION # INTSTAT .EQU $74 ;INTERRUPT STATUS DSKSTAT .EQU $7A ;DISK STATUS DISKROM .EQU $00FCC031 ;absolute address for disk ROM # HDRSTRT .EQU $FCC4BB ;ADDRESS OF HEADER BUFFER DSKBFR .EQU $FCC601 ;DISK BUFFER ADDRESS SEEK .EQU 0 ;FOLLOWING ARE COMMAND BYTES READS .EQU 1 ;READ SECTOR CLAMP .EQU 3 ;CLAMP DISKETTE STATS .EQU 4 ;STATUS REQUEST CMD UNCLAMP .EQU 5 ;UNCLAMP DISKETTE FORMAT .EQU 6 ;format disk VERIFY .EQU 7 ;verify disk (.ENDC (.IF NEWTWIG = 1 SPEED .EQU TRAK+2 ;motor speed control CNFRM .EQU SPEED+2 ;confirm for format cmd STAT .EQU CNFRM+2 ;error status INTLV .EQU STAT+2 ;interleave factor CHG022 TYPE .EQU INTLV+2 ;drive type id CHG009 STST .EQU TYPE+2 ;self-test result CHG022 ROMV .EQU $30 ;ROM version # RTRYCNT .EQU $58 ;retry count INTSTAT .EQU $5E ;interrupt status CHKCNT .EQU $BA ;data checksum error count CHKCNT2 .EQU $C4 ;address checksum error count DSKBUFF .EQU $3E8 ;start of disk buffer DSKDATA .EQU DSKBUFF+24 ;first 12 bytes are header DISKROM .EQU $FCC031 ;absoulte address for disk ROM id SLOTMR .EQU 5 ;id bit for slow timers CHG029 FASTMR .EQU 6 ;id bit for fast timers CHG029 READS .EQU 0 ;read sector w/checksum WRT .EQU 1 UNCLAMP .EQU 2 ;unclamp diskette FMT .EQU 3 VFY .EQU 4 ;verify disk CLAMP .EQU 9 ;clamp disk OK .EQU $FF ;confirmation for format SEEK .EQU $83 ;seek cmd (.ENDC EXRW .EQU $81 ;execute cmd CLRSTAT .EQU $85 ;clear status cmd ENBLINT .EQU $86 ;enable intrpt DSABLINT .EQU $87 ;disable intrpt SLEEP .EQU $88 ;loop in RAM cmd DIE .EQU $89 ;loop in ROM cmd DRV1 .EQU 0 ;drive #1 ID DRV2 .EQU $80 ;drive #2 ID TRK1 .EQU 1 ;track 1 TOPSIDE .EQU 0 ;top side of disk BOTSIDE .EQU 1 ;bottom side of disk (.IF NEWTWIG = 0 HDRLEN .EQU 12 ;LENGTH OF HEADER ON TWIGGY SECLEN .EQU 256 ;LENGTH OF 1 SECTOR TWGHDR .EQU $1FFE8 ;ADDRESS TO LOAD BOOT HEADER TWGDATA .EQU $20000 ;ADDRESS TO LOAD BOOT DATA (.ENDC (.IF NEWTWIG = 1 HDRLEN .EQU 12 ;length of Twiggy header SECLEN .EQU 512 ;length of one sector TWGHDR .EQU $1FFF4 ;address to load boot header TWGDATA .EQU $20000 ;address to load boot data LASTBLK .EQU 1702 ;last block # DSKSIZE .EQU 1702 ;total amount of blocks (.ENDC ; Equates for parameter memory used by boot ROM STATSTRT .EQU $FCC161 ;start of special parameter memory area for boot ROM STATSAV .EQU STATSTRT ;save of error code STATSUM .EQU $FCC17D ;checksum word for special area STATWRDS .EQU 8 ;length in words (16 bytes) PMSTRT .EQU $FCC181 ;start of system paramter memory DVCCODE .EQU $FCC189 ;boot device code MEMCODE .EQU $FCC18D ;mouse/memory test indicator byte MOUSEON .EQU 7 ;bit for mouse attached (1=yes) EXMEM .EQU 6 ;bit for extended memory test (1=yes) PMCHKSM .EQU $FCC1FD ;checksum word PMWRDS .EQU 32 ;length in words (64 bytes) ; Equates for disk errors (.IF NEWTWIG = 0 TIMOUT .EQU $10 ;TIMEOUT ERROR WRPERR .EQU $20 ;WRITE PROTECT ERROR DRVERR .EQU $40 ;DRIVE ERROR (NO DISK IN PLACE) FMTERR .EQU $60 ;FORMAT ERROR RDWRERR .EQU $80 ;READ/WRITE ERROR CMDTIME .EQU $100000 ;TIMEOUT FOR TAKING COMMAND (7 secs) FDIRTIME .EQU $C00000 ;TIMEOUT FOR SETTING FDIR (2 mins) (.ENDC (.IF NEWTWIG = 1 ;new firmware, new error codes DRVERR .EQU 07 ;no disk in drive NODISK .EQU DRVERR ;another name for it WRPERR .EQU 20 ;write protect error CLMPERR .EQU 22 ;clamp error RDWRERR .EQU 23 ;read error UCLMPERR .EQU 25 ;unclamp error BADTHDR .EQU 38 ;bad header (not a boot file id) TIMOUT .EQU 39 ;timeout error CMDTIME .EQU $120000 ;timeout for taking command (15 secs) FDIRTIME .EQU $C00000 ;timeout for setting FDIR (2 mins) VFYTIME .EQU ;timeout for verify disk operation (4 mins) EJCTTIME .EQU $180000 ;timeout for ejecting disk (15 secs) DSKTMOUT .EQU $1C8000 ;timeout for initial speed check (15 secs) INSRTTIM .EQU FDIRTIME ;timeout for disk to be inserted (2 mins) FMTTIME .EQU VFYTIME ;timeout for format operation (.ENDC ; Equates for disk interrupt status DSK1IN .EQU 0 ;drive #1 disk in place BUTN1 .EQU 1 ;drive #1 button pushed RWF1 .EQU 2 ;read/write/format done on drive #1 DSK2IN .EQU 4 ;drive #2 disk in place BUTN2 .EQU 5 ;drive #2 button pushed RWF2 .EQU 6 ;read/write/format done on drive #2 ; Equates for disk status command response DSKIN .EQU 2 ;disk inserted BUTN .EQU 3 ;button pressed DRVTYPE .EQU $FCC015 ;drive type id (0 = Twiggy, CHG009 H; 1 = single SONY, 2 = double SONY) CHG009 (.PAGE ;---------------------------------------------------------------------------- ; Equates for use with Profile boot ;---------------------------------------------------------------------------- PROFLE .EQU 1 ;controls assembly of Profile code OCD .EQU 0 ;OPEN CABLE DETECT INPUT BSY .EQU 1 ;BUSY LINE INPUT CMDBUFR .EQU $304 ;BUFFER FOR COMMAND BYTES STATBFR .EQU $1B4 ;STATUS BYTE BUFFER (uses BOOTDATA area) STAT1 .EQU $1B4 ;STATUS BYTE 1 STAT2 .EQU $1B5 ;STATUS BYTE 2 STAT3 .EQU $1B6 ;STATUS BYTE 3 STAT4 .EQU $1B6 ;STATUS BYTE 4 STATMSK .EQU $C140C000 ;MASK FOR DON'T CARE STATUS BITS CHG016 PCMDSZ .EQU 5 ;BYTES FOR READ CMD - 1 PCMD .EQU 0 ; COMMAND CODE BLKH .EQU 1 ; HIGH BLOCK ADDRESS BLKM .EQU 2 ; MID BLOCK ADDRESS BLKL .EQU 3 ; LOW BLOCK ADDRESS RETRY .EQU 4 ; RETRY COUNT THRESH .EQU 5 ; THRESHOLD COUNT HDRBUFR .EQU $1FFEC ;BUFFER FOR HEADER FILEID .EQU 4 ; OFFSET TO FILEID BOOTPAT .EQU $AAAA ;FILEID FOR BOOT PATTERN DATABFR .EQU $20000 ;BUFFER FOR DATA HDRSIZE .EQU 20 ;HEADER LENGTH BLKSIZE .EQU 512 ;BLOCK SIZE STRTIME .EQU $1200000 ;STARTUP TIMEOUT after power-up = about 3 minutes RSTRTIME .EQU $900000 ;STARTUP TIMEOUT after reset = ABOUT 100 SECS RDTIME .EQU $180000 ;READ TIMEOUT = ABOUT 16 SECS CHG037 BSYTIME .EQU $0500 ;Wait for busy high = about 10 ms RSPTIME .EQU $FFFF ;RESPONSE TIMEOUT = ABOUT 500 ms RCNT .EQU 10 ;BOOT RETRY COUNT TCNT .EQU 3 ;THRESHOLD COUNT FOR 30% SPARING ; Equates for Profile boot error conditions (.IF NEWTWIG = 0 TMOUT .EQU $10 ;TIMEOUT ERROR NODSK .EQU $11 ;NO DISK ATTACHED DSKBSY .EQU $12 ;DISK NOT READY BADRSP .EQU $14 ;UNEXPECTED RESPONSE STATNZ .EQU $15 ;NONZERO STATUS BYTE BADHDR .EQU $16 ;INCORRECT HEADER (.ELSE NODSK .EQU 80 ;DISK NOT ATTACHED DSKBSY .EQU 81 ;DISK NOT READY BADRSP .EQU 82 ;UNEXPECTED RESPONSE STATNZ .EQU 83 ;NONZERO STATUS BYTE BADHDR .EQU 84 ;INCORRECT HEADER TMOUT .EQU 85 ;TIMEOUT ERROR (.ENDC (.PAGE ;---------------------------------------------------------------------------- ; Equates for I/O slot booting ;---------------------------------------------------------------------------- SLOT1L .EQU $FC0001 ;I/O slot 1 SL address SLOT2L .EQU $FC4001 ;I/O slot 2 SL address SLOT3L .EQU $FC8001 ;I/O slot 3 SL address STBIT .EQU 14 ;status bit in id ICBIT .EQU 13 ;icon bit in id TSTBIT .EQU 12 ;test card bit in id STENTRY .EQU $20000 ;entry point for status routine BTENTRY .EQU $20002 ;boot routine entry point ICONPTR .EQU $20004 ;pointer to icons, if any APPLENET .EQU $8001 ;id for Applenet card APPLQUAL .EQU $9FFF ;qualifier for Applenet search TSTCRD .EQU $1000 ;id for test card TSTQUAL .EQU $1800 ;qualifier for test card search ; Error codes for I/O slot booting (.IF NEWTWIG = 0 NOC .EQU $30 ;no card installed INV .EQU $31 ;not bootable card BADSM .EQU $32 ;invalid checksum BADST .EQU $33 ;bad status returned (.ELSE NOC .EQU 90 ;no card installed INV .EQU 91 ;not bootable card BADSM .EQU 92 ;invalid checksum BADST .EQU 93 ;bad status returned (.ENDC (.PAGE (.IF BURNIN = 1 ;---------------------------------------------------------------------------- ; Special equates for burnin cylcing code ;---------------------------------------------------------------------------- INITFLG .EQU $FCC191 ;first pass flag (01 = no) HOURSAV .EQU $FCC193 ;save of last hour value from clock LCNTHI .EQU $FCC195 ;loop count LCNTLO .EQU $FCC197 TIMFLG .EQU $FCC199 ;flag to indicate hour save needed MINSAV .EQU $FCC19B ;save of minute value for Twiggy test DSKCNTH .EQU $FCC19D ;disk read error count - high byte DSKCNTL .EQU $FCC19F ;disk read error count - low byte CLKSAVE .EQU $FCC1A1 ;saved clock value ALRMSAV .EQU $FCC1B1 ;saved alarm value last set CYCLCNT .EQU $FCC1C1 ;count of minutes for power cycling CYCLVAL .EQU $FCC1C3 ;# of mins between power cycles MINCNT .EQU $FCC1C5 ;count of minutes for debug mode ENDPM .EQU $FCC1FF ;end of parameter memory SET1 .EQU $0 ;initial alarm/year/dd setting SET2 .EQU $10000000 ;d/hh/mm/ss/t setting HOUR .EQU $1BC ;location of latest hour value read MINUTE .EQU $1BD ;location of latest minute value read ONEHOUR .EQU $00E0F000 ;one hour setting for alarm ONEMIN .EQU $0003C000 ;one minute setting for alarm TENSECS .EQU $00009000 ;ten seconds DLYTIME .EQU $100000 ;delay for screen display (.ENDC (.PAGE ;---------------------------------------------------------------------------- ; Equates for Monitor code and screen handling ;---------------------------------------------------------------------------- ; Ascii code equates QUESTN .EQU $3F ; ? RET .EQU $0D ; CR BS .EQU $08 ; backspace ; Keyboard code equates KEY4 .EQU $F3 ;'4' KEY5 .EQU $E4 ;'5' KEY6 .EQU $E1 ;'6' KEY7 .EQU $E2 ;'7' KEY8 .EQU $E3 ;'8' KEY9 .EQU $D0 ;'9' SKEY .EQU $F6 ;'S' CmdDwn .EQU CMDKEY ;Command key down CmdUp .EQU $7F ;Command key up MousUp .EQU $06 ;Mouse button up ; Low memory usage KBDBFR .EQU $2C0 ;keyboard buffer start KBDEND .EQU $300 ; and end (64 chars max) (.IF USERINT = 0 CRTROW .EQU $300 ;display row ptr CRTCOL .EQU $301 ;display col ptr (.ELSE CRTROW .EQU $300 ;display row ptr CRTCOL .EQU $302 ;display col ptr (.ENDC MAXTEST .EQU 12 ;max test # for LOOP option (.IF USERINT = 0 FIRSTROW .EQU 3 ;first row for display of msgs FIRSTCOL .EQU 1 ;first column LASTROW .EQU 32 ;last row for display LASTCOL .EQU 88 ;last column (.ELSE ; Equates for new user interface code ROWBYTES .EQU 90 ;width of screen in bytes MaxX .EQU 720 ;width in pixels MaxY .EQU 364 ;length in pixels MENULINE .EQU 1440 ;bottom line loc for menu DESKLINE .EQU 1530 ;top line loc for desktop DESKLMT .EQU 32760 ;bottom line loc for desktop DESKPATRN .EQU $AAAA5555 ;pattern for "grey" desktop WROW .EQU 20 ;window row WCOL .EQU 2 ;starting window col WINDWIDTH .EQU 86 ;width of window in bytes WINDHIGH .EQU 320 ;heigth of window in pixel lines WMIDROW .EQU +WROW ;middle row in window WMIDCOL .EQU +WCOL ;middle col in window W14COL .EQU +WCOL ;col 1/4 across window W34COL .EQU *3+WCOL ;col 3/4 across window WINDSTRT .EQU +WCOL ;start of window ALBOXROW .EQU 49 ;starting row for alert box ALBOXCOL .EQU 6 ;starting col for alert box ALRTWIDTH .EQU 78 ;width of alert box ALRTHIGH .EQU 164 ;heigth of alert box ALRTSTRT .EQU +ALBOXCOL ;upper left corner of alert box MIDALROW .EQU ALBOXROW+ ;middle row of alert box MIDALCOL .EQU ALBOXCOL+ ;middle col of alert box BTNWIDTH .EQU 10 ;width of button BTNHIGH .EQU 28 ;heigth of button BTNSPC .EQU 48*ROWBYTES ;space between upper left corner of buttons BTNMSPC .EQU <10*ROWBYTES>+BTNWIDTH+4 ;position of button label relative to button BTNROW .EQU ALBOXROW+20 ;starting display row for buttons BTNCOL .EQU 52 ;starting display col for buttons BTN1STRT .EQU +BTNCOL ;location of first button BTN2STRT .EQU BTN1STRT+BTNSPC ;location of second button BTN3STRT .EQU BTN2STRT+BTNSPC ;location of third button BTN1MSG .EQU BTN1STRT+BTNMSPC ;location of button descriptions BTN2MSG .EQU BTN2STRT+BTNMSPC BTN3MSG .EQU BTN3STRT+BTNMSPC MENUSTRT .EQU MENULINE+2 ;start of pull down menu MENULEN .EQU 11 ;length of menu per entry MENUSPC .EQU 990 ;vertical space between menu entries MENUWIDTH .EQU 18 ;width of pull down menu MENULOC .EQU 273 ;start pt for menu heading MENU1MSG .EQU MENUSTRT+182 ;location of first menu entry MBARLEN .EQU 16 ;heigth of menu bar MITEMS .EQU 7 ;number of menu items MENUEND .EQU MENUSTRT+ ;bottom of menu (.IF BMENU = 1 BMENUWIDTH .EQU MENUWIDTH ;width of pull down menu BMENULEN .EQU 34 ;length of each boot menu entry BMENUSPC .EQU ;vertical space between boot menu entries (.ENDC DBOXWIDTH .EQU 84-MENUWIDTH ;width of dialog box DBOXHIGH .EQU 20 ;heigth of dialog box DBOXTOP .EQU 4*ROWBYTES ;dialog box spacing down from menu line DBOXLEFT .EQU MENUWIDTH+2 ;dialog box spacing left from menu DBOXSTRT .EQU MENUSTRT+DBOXLEFT+DBOXTOP ;start of dialog box DBOXROW .EQU +4 ;pixel row for dialog msg DBOXCOL .EQU MENUWIDTH+6 ;byte col for dialog msg SVCTOP .EQU *ROWBYTES ;service window spacing down S; from top of dialog box SVCLEFT .EQU MENUWIDTH+2 ;service window spacing left from menu SVCSTRT .EQU DBOXSTRT+SVCTOP ;left corner for service window SVCWIDTH .EQU 84-MENUWIDTH ;width of service window SVCHIGH .EQU 320 ;length of service window FIRSTROW .EQU +20 ;first row for display of msgs FIRSTCOL .EQU MENUWIDTH+6 ;first column ROWSLEFT .EQU SVCHIGH-20 ;pixel rows to bottom of service window CHARROWS .EQU -3 ;rows used for character display LASTROW .EQU +FIRSTROW ;last pixel row for display LASTCOL .EQU FIRSTCOL+SVCWIDTH-2 ;last column ROWLINES .EQU 10 ;pixel row lines per character ROWLEN .EQU |1+1 ;bytes per pixel row (must be even!) NROWS .EQU /ROWLINES ;number of character rows CHRHIGH .EQU 8 ;character heigth in pixel lines CHRWIDTH .EQU 1 ;width of char in bytes CHRSPC .EQU CHRHIGH+2 ;vert pixel lines between chars ICONWIDTH .EQU 6 ;width in bytes of icons ICONHIGH .EQU 32 ;heigth of icons in pixel rows TSTROW .EQU ALBOXROW ;starting row for test alert box TSTCOL .EQU 10 ;starting col for test alert box TSTWSTRT .EQU +TSTCOL ;test alert box start TSTWWIDTH .EQU 70 ;width for test alert box TSTWHIGH .EQU 84 ;heigth for test alert box TSTMROW .EQU TSTROW+15 ;row for test message display TSTMCOL .EQU TSTCOL+4 ;col for test message display MIDTSTROW .EQU TSTROW+ ;middle row of test box CHKROW .EQU MIDTSTROW- ;row for check mark display TSTIROW .EQU CHKROW+10 ;row for test icon display TSTICOL .EQU TSTCOL+10 ;col for test icon display TSTISPC .EQU ICONWIDTH+8 ;space between test icons CPUSTRT .EQU +TSTICOL ;upper left corner for CPU icon MEMSTRT .EQU CPUSTRT+TSTISPC ;upper left corner for MEM icon IOSTRT .EQU MEMSTRT+TSTISPC ;upper left corner for I/O icon XCRDSTRT .EQU IOSTRT+TSTISPC ;upper left corner for slot icon ERRROW .EQU MIDALROW- ;row for error icon display ERRCOL .EQU ALBOXCOL+10 ;col for error icon display ERRSTRT .EQU +ERRCOL ;start address for error icon display ALRTROW .EQU ERRROW ;row for alert icon display ALRTCOL .EQU ERRCOL ;col for alert icon display CODEROW .EQU ERRROW+36 ;row for error code display CODECOL .EQU ERRCOL+2 ;col for error code display MSGROW .EQU ALRTROW+11 ;row for alert/error message display MSGCOL .EQU ALRTCOL+8 ;col for alert/error message display MEMROW .EQU 16 ;offset row for memory board id # display MEMCOL .EQU 4 ;offset col for memory board id # display DISKROW .EQU 18 ;offset row for diskette id # display DISKCOL .EQU 4 ;offset col for diskette id # display CHG024 SLOTROW .EQU 22 ;offset row for slot card id # display SLOTCOL .EQU 3 ;offset col for slot card id # display DRVROW .EQU 6 ;offset row for drive id # display CHG009 DRVCOL .EQU 3 ;offset col for drive id # display CHG009 INSRTROW .EQU 5 ;offset row for insert rqst id # display CHG009/CHG024 INSRTCOL .EQU 4 ;offset col for insert rqst id # display CHG009 DEFROW .EQU WMIDROW- ;row for default boot icon display DEFCOL .EQU W34COL- ;col for default boot icon display DEFSTRT .EQU +DEFCOL ;start address for default boot icon ALTCOL .EQU W14COL- ;col for alternate boot icon display COL1STRT .EQU <78*ROWBYTES>+6 ;start for first column of boot icons COL2STRT .EQU COL1STRT+12 ;start for second col of boot icons COL2MID .EQU +ALTCOL ;middle of second col COL3STRT .EQU COL2STRT+12 ;start for third col of boot icons ICONCSPC .EQU <64*ROWBYTES> ;space between left corner of icons in col ICONMSPC .EQU <12*ROWBYTES>+6+2 ;start addr offset for boot icon alternate keycode ICONRSPC .EQU 12 ;space in between cols in same row ALTKYADDR .EQU ICONMSPC+5 ;address offset for display of alternate keycode in menu bar PCWIDTH .EQU 86 ;width of window for power cycling msgs PCHIGH .EQU 192 ;height of window PCSTRT .EQU WINDSTRT ;upper left corner of window PCROW .EQU ALBOXROW+40 ;first row for power cycle msgs PCCOL .EQU ALBOXCOL+6 ;first col for power cycle msgs ROMIDROW .EQU 3 ;cursor row ptr for ROM id display CHG001 ROMIDCOL .EQU 80 ;cursor col ptr for ROM id display CHG001 (.IF DEBUG = 0 GLOBALS .EQU STKBASE ;start of global area for mouse/cursor (.ELSE GLOBALS .EQU $900 ;place here in debug mode (.ENDC ClockBytes .EQU Globals ;clock data save area MousX .EQU ClockBytes+6 ;mouse X-coordinate (word) MousY .EQU MousX+2 ;mouse Y-coordinate (word) MousDx .EQU MousY+2 ;mouse delta-x (byte) MousDy .EQU MousDx+1 ;mouse delta-y (byte) MousScaling .EQU MousDy+1 ;0=disabled, else=enabled (byte) MousThresh .EQU MousScale|1+1 ;mouse movement threshold (word) CrsrHotx .EQU MousThresh+2 ;hotspot X-coordinate (word) CrsrHoty .EQU CrsrHotX+2 ;hotspot Y-coordinate (word) CrsrHeight .EQU CrsrHotY+2 ;cursor height, 0-32 (word) CrsrX .EQU CrsrHeight+2 ;cursor X-coordinate (word) CrsrY .EQU CrsrX+2 ;cursor Y-coordinate (word) CrsrTracking .EQU CrsrY+2 ;0=disabled, else=enabled (byte) CrsrBusy .EQU CrsrTracking+1 ;0=not busy, else=busy (byte) CrsrVisible .EQU CrsrBusy+1 ;0=not visible, else=visible (byte) CrsrHidden .EQU CrsrVisible|1+1 ;<=0 implies hiddden (word) CrsrObscured .EQU CrsrHidden+2 ;0=not obscured, else=obscured (byte) SavedData .EQU CrsrObscured+2 ;data from under cursor (128 bytes) SavedX .EQU SavedData+128 ;saved data X-coordinate (word) SavedY .EQU SavedX+2 ;saved data Y-coordinate (word) SavedRows .EQU SavedY+2 ;rows of saved data (word) SavedAddr .EQU SavedRows+2 ;saved data screen address (long) LwrRight .EQU SavedAddr+4 ;saved lower right corner address (word) MsgLen .EQU LwrRight+2 ;length of dialog box msg (word) (.IF BMENU = 0 IconBase .EQU Msglen+2 ;base address for first alternate boot icon (word) IconAddr .EQU IconBase+2 ;address for last boot icon displayed (word) (.ELSE MenuBase .EQU Msglen+2 ;address of last boot menu "box" (word) IconAddr .EQU MenuBase+2 ;address for last boot icon displayed (word) (.ENDC IconCnt .EQU IconAddr+2 ;count of boot icons displayed (byte) DRIVE .EQU IconCnt+1 ;drive id for dump/verify options (byte) BLKNUM .EQU DRIVE+1 ;block # for dump option (word) CONTXT .EQU BLKNUM+2 ;context for dump of MMU contents (byte) RectCnt .EQU CONTXT+2 ;count for active rect table (word) RectTable .EQU RectCnt ;active rectangle table (same start) (.ENDC (.PAGE ;---------------------------------------------------------------------------- ; The following memory locations are reserved for ROM use to save test data ;---------------------------------------------------------------------------- STATUS .EQU $0180 ;POWER-UP STATUS (0=OK) SIZRSLT .EQU STATUS+4 ;memory sizing test results MEMRSLT .EQU SIZRSLT+2 ;MEMORY TEST RESULTS BOOTMEM .EQU MEMRSLT+2 ;result for boot area of memory (128K) PEADDR .EQU MEMRSLT+32 ;PARITY ERROR ADDRESS ADRLTCH .EQU PEADDR+4 ;CONTENTS OF MEMORY ADDRESS LATCH D7SAV .EQU ADRLTCH+2 ;save for D7 when exception occurs MMURSLT .EQU $01B0 ;MMU TEST RESULTS KEYID .EQU $01B2 ;Keyboard ID BOOTDVCE .EQU $01B3 ;BOOT DEVICE CODE BOOTDATA .EQU $01B4 ;BOOT FAILURE DATA CLKDATA .EQU $01BA ;CLOCK SETTING READ DATARGS .EQU $01C0 ;DATA REG SAVE AREA ADRREGS .EQU $01E0 ;ADDRESS REG SAVE AREA A6SAV .EQU $01F8 ;SAVE AREA FOR REG A6 USPSAV .EQU $01FC ;SAVE AREA FOR USER STACK PTR SERNUM .EQU $0240 ;saved serial number (28 bytes) KBDQPTR .EQU $0260 ;ptr for keyboard queue XPCTADDR .EQU $0268 ;memory test address for parity error CHG015 XPCTDATA .EQU $026C ;memory test expected data CHG015 ACTADDR .EQU $0270 ;parity error address, phase 2 CHG015 ACTDATA .EQU $0274 ;actual data read on parity error, phase 2 CHG015 PEADR2 .EQU $0278 ;address read from error latch CHG015 PCHPROW .EQU $027C ;parity chip row CHG015 PCHIP .EQU $027D ;parity chip id CHG015 EXCFC .EQU $0280 ; bus function code EXCADR .EQU $0282 ; address of error EXCIR .EQU $0286 ; instruction reg EXCSR .EQU $0288 ; status reg EXCPC .EQU $028A ; PC at time of exception EXCTYPE .EQU $028E ; exception type SUPSTK .EQU $0290 ;SUPERVISOR STACK PTR MAXMEM .EQU $0294 ;MAX MEMORY ADDRESS + 1 IO1ID .EQU $0298 ;I/O SLOT 1 ID IO2ID .EQU $029A ;I/O SLOT 2 ID IO3ID .EQU $029C ;I/O SLOT 3 ID IO1STAT .EQU $029E ;I/O SLOT 1 STATUS IO2STAT .EQU $029F ;I/O SLOT 2 STATUS IO3STAT .EQU $02A0 ;I/O SLOT 3 STATUS IOROM .EQU $02A1 ;I/O ROM VERSION # STATFLGS .EQU $02A2 ;additional status indicators MINMEM .EQU $02A4 ;MINIMUM PHYSICAL ADDRESS TOTLMEM .EQU $02A8 ;total amount of memory SCCRSLT .EQU $02AC ;SCC test results MEMSLOT .EQU $02AD ;Slot # for memory board if memory error DSKRSLT .EQU $02AE ;Disk controller self-test status byte (0=no error) SYSTYPE .EQU $02AF ;System type (0 = Lisa 1; 1, 2, 3 = Lisa 2) CHG029 KBDQ .EQU $02B0 ;KEYBOARD QUEUE QEND .EQU $02C0 ;END OF Q (.INCLUDE RM248.K.TEXT (.INCLUDE RM248.S.TEXT (.INCLUDE RM248.B.TEXT (.INCLUDE RM248.M.TEXT (.INCLUDE RM248.G.TEXT 3. "6F^3D!l^NZZ(.IF EXTERNAL = 1 (.NOLIST (.ENDC (.PAGE (.ABSOLUTE ;makes listing look nicer (.PROC LISAROM,0 (.ORG 0 ; ORG'ED AT 0 BUT RUNS AT $00FE0000 ; Reset vectors here to pick up SP and PC values BASE (.WORD $0000 ;initial SP (.WORD STKBASE (.WORD ROMSLCT ;initial PC (assumes use of MMU reg 127) (.WORD BEGIN ; Set up next locations for exception vectors BUSVCT .WORD ROMSLCT ; BUS ERROR VECTOR (.WORD EXCPERR ADRVCT .WORD ROMSLCT ; ADDRESS ERROR (.WORD EXCPERR ILLVCT .WORD ROMSLCT ; ILLEGAL INSTRUCTION (.WORD EXCPERR DIV0VCT .WORD ROMSLCT ; DIVIDE BY ZERO ERROR (.WORD EXCPERR CHKVCT .WORD ROMSLCT ; CHK INSTRUCTION (.WORD EXCPERR TRAPVCT .WORD ROMSLCT ; TRAPV INSTRUCTION (.WORD EXCPERR PRIVCT .WORD ROMSLCT ; PRIVILEGE VIOLATION (.WORD EXCPERR TRCVCT .WORD ROMSLCT ; TRACE OPERATION (.WORD EXCPERR L10VCT .WORD ROMSLCT ; OPCODE 1010 DETECTED (.WORD EXCPERR L11VCT .WORD ROMSLCT ; OPCODE 1111 DETECTED (.WORD EXCPERR ;------------------------------------------------------------------ ; Exception and interrupt vector handler for ROM - resets SP and ; tries a restart ;------------------------------------------------------------------ EXCPERR MOVEA #STKBASE,SP ;reset stack ptr (CLR.L D7 ;clear error indicator CHG004 (BRA ROMTST ;and restart diags CHG004 (.PAGE ;-------------------------------------------------------------------- ; Subroutine for saving registers and stack pointers ;-------------------------------------------------------------------- SAVEREGS (MOVE.L SP,SUPSTK ;save sup stack ptr SAVEREG2 (MOVE.L A6,A6SAV ;save other regs (that aren't reset) (MOVE.L USP,A6 (MOVE.L A6,USPSAV (MOVE #A6SAV,A6 ;set ptr for saving regs (MOVEM.L D0-D7/A0-A5,-(A6) (RTS ; use spare bytes for message SVCMSG .ASCII 'SERVICE MODE' ; RM000 (.BYTE 0 ; RM000 (.ORG $60 ; The next set of vectors cover spurious and autovector interrupts SPURVCT .WORD ROMSLCT ; SPURIOUS INTERRUPT (.WORD EXCPERR LVL1VCT .WORD ROMSLCT ; INTERNAL I/O INTERRUPTS (DISK,VERT TRACE,ETC.) (.WORD EXCPERR LVL2VCT .WORD ROMSLCT ; KEYBOARD INTERRUPT (.WORD EXCPERR LVL3VCT .WORD ROMSLCT ; I/O SLOT 2 INTERRUPT (.WORD EXCPERR LVL4VCT .WORD ROMSLCT ; I/O SLOT 1 (.WORD EXCPERR LVL5VCT .WORD ROMSLCT ; I/O SLOT 0 (.WORD EXCPERR LVL6VCT .WORD ROMSLCT ; RS-232 (.WORD EXCPERR LVL7VCT .WORD ROMSLCT ; NMI (.WORD NMIEXCP ; RM010 (.IF EXTERNAL = 1 (.LIST (.ENDC (.PAGE (.ORG $80 ;------------------------------------------------------------------------- ; Jump Table for calling by external routines ;------------------------------------------------------------------------- JMPTBL (JMP DORESET ;go to restart point RM000 (JMP INITMON ;jump to ROM Monitor (.IF USERINT = 0 (JMP DSPMSG ;display a message (.ELSE (JMP CONVRTD5 ;convert row ptr and display message (.ENDC (JMP WRTMMU ;write to set of MMU registers (JMP PROREAD ;Profile read a block routine (JMP TWGREAD ;Twiggy read a sector routine (.IF DIAGS = 1 (JMP RAMTEST ;basic memory test (NOP ; CHG015 (RTS ; CHG015 (NOP ; CHG015 (RTS ; CHG015 (.ELSE (NOP (RTS (NOP (RTS (NOP (RTS (.ENDC (JMP READMMU ;read MMU registers (JMP COPSCMD ;Send COPS command (.IF DIAGS = 1 (JMP READCLK ;Read clock setting (.ELSE (NOP (RTS (.ENDC (JMP DSPDEC ;display hex error code in decimal (JMP CONSET2 ;for setting contrast (JMP TONE ;to beep speaker (JMP VFYCHKSM ;verify checksum (.IF ROM4K = 0 (JMP WRTSUM ;rewrite parameter memory CHG017 (JMP RDSERN ;go read system serial # (.ENDC ;******************** Loop point for ROM test failure ******************************** SPIN BRA.S SPIN ;hang system CHG007 ;************************************************************************************* (.IF EXTERNAL = 1 (.NOLIST (.ENDC ;---------------------------------------------------------------------------- ; NMI Exception Handler RM010 ;---------------------------------------------------------------------------- NMIEXCP CLR.B SETUP ;enable memory access RM010 (BTST #1,STATREG ;parity error? RM010 (BNE.S @1 ;skip if not to ignore RM010 (MOVE MEALTCH,ADRLTCH ;save address if yes RM010 (TST.B PAROFF ;and toggle to clear error bit RM010 (TST.B PARON ; RM010 @1 TST.B SETUPON ;return to SETUP state RM010 (RTE ; RM010 (.PAGE ;---------------------------------------------------------------------------- ; First do "warm-start" no reset check - scan I/O MMU regs to see if set up ;---------------------------------------------------------------------------- BEGIN (.IF NORESET = 1 (MOVE MMU126L,D0 ;check reg 126 for special I/O space (ANDI #$0FFF,D0 ;ignore don't care bits (CMPI #IOLMT2,D0 ;for no reset, 126L = $x901 (x = random value) (BNE.S BEGIN2 ;skip if not set up (ANDI #$0FFF,MMU126B ;else also check 126B = $x000 (BNE.S BEGIN2 ; Check OK - set MMU for ROM access and change SETUP before vectoring (MOVE #MEMLMT,MMU0L ;set low memory for r/w (to save regs,etc.) (MOVE #IOLMT2,MMU126L ;set for I/O space access (reset value) (MOVE #SPLMT,MMU127L ;set access for ROM space (MOVE #0,MMU127B (CLR.B SETUP ;enable memory access (MOVE.L SP,SUPSTK ;save supervisor stack ptr (MOVEA #STKBASE,SP ;move stack pointer for ROM use (BSR.S SAVEREG2 ;save other registers ; Restore ROM Monitor environment (BSR4 CONSET ;go set default contrast (SUBA.L A2,A2 ;set for no icons (CLR.L D0 ; error codes (SUBA.L A3,A3 ; or messages (BRA INIT1 ;exit directly to monitor (avoid resaving regs) (.ENDC ;------------------------------------------------------------------------- ; Do second warm-start check to see if contrast should be reset ;------------------------------------------------------------------------- BEGIN2 CLR.L D7 ;clear for error use (MOVE MMU127L,D0 ;check reg 127 for ROM space (ANDI #$0FFF,D0 ;ignore don't care bits (CMPI #SPLMT,D0 ;expect 127L = $xF00 (x = random value) (BNE.S ROMTST ;skip if not (ANDI #$0FFF,MMU127B ;else check if 127B = $x000 (BNE.S ROMTST ; Check OK - set MMU for I/O and ROM access and go set contrast (BSET #WRMSTRT,D7 ;set warm start indicator (MOVEQ #0,D0 ;clear for use (MOVE #IOLMT,MMU126L ;set access for I/O space (MOVE D0,MMU126B (MOVE #SPLMT,MMU127L ;set access for ROM space BEGIN3 RESET ;ensure clean I/O state for "warm-start" (.IF NEWLISA = 1 (BSR4 CONOFF ;and go disable contrast (.ELSE (BSR4 CONSET ;go set default contrast (.ENDC (.PAGE ;------------------------------------------------------------------------- ; Start diagnostics - do ROM checksum test first; expected result = 0 ;------------------------------------------------------------------------- ROMTST (.IF DIAGS = 1 (CLR.L D0 ;clear for checksum use (LEA BASE,A0 ;init ROM address ptrs (LEA LAST,A1 DOSUM ADD (A0)+,D0 ;read location and add to sum (ROL #1,D0 ;rotate to catch multiple bit errors (CMPA.L A0,A1 ;loop until done (BNE.S DOSUM (ADD (A0)+,D0 ;add checksum word (BNE SPIN ;loop if error CHG007 (TST.L D7 ;in loop mode? (BMI.S ROMTST ;restart test if yes (.ENDC (.PAGE ;---------------------------------------------------------------------------- ; Next do read/write and address test of MMU supervisor regs ; Register Usage (by this routine and/or its subroutines): ; A0 = MMU reg pointer D0 = test pattern ; A1 = last MMU limit reg addr D1 = contents read from MMU reg ; A2 = MMU address increment D2 = OR mask of results ; A3 = last MMU base reg addr D3 = pattern expected at last error ; A4 = used for return address D4 = final value for MMU reg ; A5 = MMU address of last error D5 = unused ; A6 = used for return address D6 = unused ; A7 = stack pointer D7 = error indicator (0 = R/W error) ;---------------------------------------------------------------------------- MMUTST (.IF DIAGS = 1 (BSR4 MMUINIT ;initialize test variables (BSR6 MMURW ;and go do read/write test (BNE.S MMUERR ;abort if error (BSRS4 MMUINIT ;reinitialize (BSR6 MMUACHK ;and do address test (BNE.S @2 ;skip if error (BRA SETMMU ;else go do initial MMU setup @2 NOT D7 ;set address error indicator (.PAGE ;---------------------------------------------------------------------------- ; The following code is used to toggle every address and data line ; going to the MMU if an error in the MMU context 0 tests is found. ; Reset signals indicate read/write or addressing error. ;---------------------------------------------------------------------------- MMUERR TST D7 ;check error type (BEQ.S @2 (RESET ;two reset signals for address error @2 RESET ;only one for R/W error ; Toggle every data and address bit MMULP MOVE.L #$00028000,A0 ;set MMU limit reg start address (MOVEQ #1,D1 ;and starting data pattern (MOVEQ #7,D2 ;and loop count (BSRS4 TSTLOOP ;go toggle for limit regs (MOVE.L #$00028008,A0 ;set MMU base reg start address (MOVEQ #5,D2 ;and loop count (BSRS4 TSTLOOP ;go test base regs (BRA.S MMUERR ;and loop indefinitely ; Subroutine to do reg testing TSTLOOP MOVE.L A0,D0 ;save starting address REGTST MOVE D1,(A0) ;do write (MOVE (A0),D3 ;then read (LSL #1,D1 ;update pattern (SWAP D0 ;get address (LSL #1,D0 ;update and restore (SWAP D0 (MOVE.L D0,A0 (SUBQ #1,D2 ;loop until done (BNE.S REGTST (RTS4 ;exit (.PAGE ;---------------------------------------------------------------------------- ; Subroutine to do initial setup for MMU testing ;---------------------------------------------------------------------------- MMUINIT MOVE #PATRN2,D0 ;set test pattern (MOVEQ #0,D1 ;clear for result/error use (MOVEQ #0,D2 ; use MOVEQ for speed (MOVE.L #ADR128K,A2 ;set up increment value (ORI #$0710,SR ;set extend bit and disable interrupts (RTS4 (.PAGE ;---------------------------------------------------------------------------- ; Subroutine to do MMU Read/Write Test for all registers in one context. ; Zero bit set in CCR if no errors. ;---------------------------------------------------------------------------- MMURW MOVE.L #MMUSADRL,A0 ;SET MMU LIMIT START ADDR (MOVE.L #MMUEADRL,A1 ;SET MMU LIMIT END ADDR (MOVE.L #MMUEADRB,A3 ;SET MMU BASE END ADDR RWCHK1 BSR4 CHKRW ;GO DO READ/WRITE CHECK (NOT D0 ;INVERT FOR NEXT PASS (BSRS4 CHKRW ;GO DO AGAIN RWCHK2 NOT D0 ;INVERT BACK TO ORIGINAL PATTERN (BSRS4 CHKRW ;ONE MORE TIME RWCHK3 ROXL #1,D0 ;SET UP NEW PATTERN (CMPA.L A0,A1 ;CHECK IF DONE (BEQ.S CHKBASE ;IF YES GO CHECK FOR BASE REG TESTING (ADDA.L A2,A0 ;ELSE BUMP MMU ADDR (BRA.S RWCHK1 CHKBASE CMPA.L A0,A3 ;DONE WITH BASE? (BEQ.S @2 ;EXIT IF YES (MOVE.L #MMUSADRB,A0 ;ELSE SET STARTING BASE ADDRESS (MOVEA.L A3,A1 ; AND ENDING ADDRESS (BRA.S RWCHK1 ;GO CHECK BASE REGS @2 TST D2 ;check for errors (RTS6 ;and exit test (.PAGE ;---------------------------------------------------------------------------- ; Subroutine to do MMU address check ; Leaves limit registers with invalid page value, base regs with 0 ;---------------------------------------------------------------------------- MMUACHK MOVE.L #MMUSADRL,A0 ;SET MMU LIMIT START ADDR (MOVE.L #MMUEADRL,A1 ;SET MMU LIMIT END ADDR (MOVE.L #MMUEADRB,A3 ;SET MMU BASE END ADDR (MOVE #INVPAG,D4 ;SET FINAL VALUE FOR LIMIT REGS ACHK1 MOVE (A0),D1 ;READ REG (EOR D0,D1 ;CHECK IF EXPECTED (ANDI #$0FFF,D1 ;MASK DON'T CARES (BNE.S MADRERR ;EXIT IF ERROR MMUSET MOVE D4,(A0) ;SET FINAL REG VALUE (ROXL #1,D0 ;SET UP NEW PATTERN (CMPA.L A0,A1 ;CHECK IF DONE (BEQ.S ACHK2 ;IF YES GO CHECK FOR BASE REG TESTING (ADDA.L A2,A0 ;ELSE BUMP MMU ADDR (BRA.S ACHK1 ACHK2 CMPA.L A0,A3 ;DONE WITH BASE? (BEQ.S @2 ;EXIT IF YES (MOVE.L #MMUSADRB,A0 ;ELSE SET STARTING BASE ADDRESS (MOVEA.L A3,A1 ; AND ENDING ADDRESS (MOVEQ #0,D4 ;SET FINAL VALUE FOR BASE REGS (BRA.S ACHK1 ;GO CHECK BASE REGS @2 TST D2 ;check for errors (RTS6 ;and exit test ; Handle MMU address error MADRERR OR D1,D2 ;save error bits (BRA.S MMUSET ; and continue test (.ELSE (CLR.L D2 ;for error patterns (BRA.S SETMMU (.ENDC (.PAGE ;---------------------------------------------------------------------------- ; Subroutine to do MMU actual read/write ;---------------------------------------------------------------------------- CHKRW MOVE D0,(A0) ;do write (MOVE (A0),D1 ;read back (EOR D0,D1 ;compare (ANDI #$0FFF,D1 ;mask don't cares (BNE.S RWERR ;skip if error (RTS4 ;else return ; Error collection RWERR OR D1,D2 ;save error bits (RTS4 ;and return (.PAGE ;-------------------------------------------------------------------------- ; Now do setup of MMU supervisor registers for RAM and I/O space access. ; Also do read check after write and abort if error. ;-------------------------------------------------------------------------- ; Do origin registers first SETMMU MOVE.L #MMUSADRB,A0 ;GET MMU PTR (MOVEQ #0,D0 ;clear for use (MOVEQ #0,D1 (MOVE D2,D4 ;SAVE PREVIOUS RESULTS IF ANY (MOVEQ #0,D2 (MOVEQ #0,D6 (MOVE.L #ADR128K,A2 ;ADDRESS INCREMENT (MOVE.L #PAG128K,A3 ;SET UP BASE ADDRESS INCREMENT (MOVEQ #16,D6 ;LOOP COUNT LOADORG BSRS4 CHKRW ;DO WRITE/READ CHECK (ADD.L A3,D0 ;COMPUTE NEXT MEMORY BASE ADDRESS (ADDA.L A2,A0 ;BUMP MMU ORG PTR (SUBQ #1,D6 (BNE.S LOADORG ;LOOP UNTIL DONE ; Set base for I/O and special I/O space (MOVEA.L #MMU126B,A0 ;PT TO ORG REG 126 (MOVEQ #0,D0 ;set data value (BSRS4 CHKRW (ADDA.L A2,A0 ;BUMP PTR TO REG 127 (BSRS4 CHKRW ; Now do limit registers (MOVEA.L #MMUSADRL,A0 ;GET MMU LIMIT REG PTR (MOVE #MEMLMT,D0 ;LIMIT FOR 128K MEMORY SEGMENTS (MOVEQ #0,D1 ;use as working reg (MOVEQ #16,D6 ;LOOP COUNT LOADLMT BSRS4 CHKRW (ADDA.L A2,A0 ;BUMP MMU PTR (SUBQ #1,D6 (BNE.S LOADLMT ;LOOP UNITL DONE ; Now do MMU limit reg setup for I/O and Special I/O access (MOVEA.L #MMU126L,A0 ;PT TO LMT REG 126 (MOVE #IOLMT,D0 ;SET FOR I/O SPACE, FULL ACCESS (BSRS4 CHKRW (ADDA.L A2,A0 ;BUMP PTR TO REG 127 (MOVE #SPLMT,D0 ;SET FOR SPECIAL I/O, FULL ACCESS (BSRS4 CHKRW (.IF DIAGS = 1 ; Check if errors detected (TST D2 ;CHECK ERROR MASK (BNE MMUERR ;ABORT IF ERROR (MOVE D4,D2 ;ELSE RESTORE PREVIOUS RESULTS (.ENDC (.PAGE ;-------------------------------------------------------------------------- ; Complete testing of MMU by checking other context regs. ; Uses reg D6 for context indicator. ;-------------------------------------------------------------------------- (.IF DIAGS = 1 MMUTST2 MOVEQ #0,D6 ;FOR CONTEXT INDICATOR (BSR4 MMUINIT ;REINITIALIZE FOR TESTING (TST.B SEG1ON ;SET FOR CONTEXT 1 (MOVEQ #1,D6 ;SET CONTEXT INDICATOR (BSR4 CONCHK ;CHECK IF MMU CONTEXT CHANGED (BEQ MMUERR2 ;EXIT IF NO - SEG BIT ERROR (BSR6 MMURW ;ELSE GO DO R/W TEST (BNE MMUERR2 ;exit if error (TST.B SEG2ON ;SET FOR CONTEXT 3 (MOVEQ #3,D6 (BSR4 CONCHK ;CHECK IF MMU CONTEXT CHANGED (BEQ.S MMUERR2 ;EXIT IF NO - SEG BIT ERROR (BSR6 MMURW ;ELSE GO TEST (BNE.S MMUERR2 ;exit if error (TST.B SEG1OFF ;SET FOR CONTEXT 2 (MOVEQ #2,D6 (BSRS4 CONCHK ;CHECK IF MMU CONTEXT CHANGED (BEQ.S MMUERR3 ;EXIT IF NO - SEG BIT ERROR (BSRS6 MMURW ;ELSE GO TEST (BNE.S MMUERR3 ;exit if error (TST.B SEG2OFF ;RESET FOR CONTEXT 0 REGS ; Now do MMU addressing check of remaining context regs (BSR4 MMUINIT ;REINITIALIZE (TST.B SEG1ON ;SET FOR CONTEXT 1 (MOVEQ #1,D6 (BSR6 MMUACHK ;TEST CONTEXT 1 (BNE.S MMUERR2 ;exit if error (TST.B SEG2ON ;TEST CONTEXT 3 (MOVEQ #3,D6 (BSR6 MMUACHK (BNE.S MMUERR2 ;exit if error (TST.B SEG1OFF ;TEST CONTEXT 2 (MOVEQ #2,D6 (BSR6 MMUACHK (BNE.S MMUERR3 ;exit if error (TST.B SEG2OFF ;RESET TO CONTEXT 0 (BRA.S MMULPCHK ;go check for loop mode MMUERR2 TST.B SEG1OFF ;ENSURE RESET FOR CONTEXT 0 MMUERR3 TST.B SEG2OFF (ROR #4,D6 ;get context indicator (OR D6,D2 ;save with error bits (if any) (BSET #MMU,D7 ;set error indicator MMULPCHK (TST.L D7 ;in loop mode? (BMI.S MMUTST ;restart full MMU test if yes (BRA.S START ;else continue to next test (.PAGE ;------------------------------------------------------------------------- ; Subroutine to verify context change made - does comparison to ensure ; destruction of context 0 mapping avoided. Zero bit set if error. ;------------------------------------------------------------------------- CONCHK MOVE MMU126L,D4 ;check limit reg for I/O space (ANDI #$0FFF,D4 ;mask don't care (CMPI #IOLMT,D4 ;still in same context? (BNE.S CONOK ;exit if not (MOVE MMU127L,D4 ;else also check reg for ROM space (ANDI #$0FFF,D4 ;mask don't care (CMPI #SPLMT,D4 ;also set up? (BNE.S CONOK ;exit if not (MOVE MMU0L,D4 ;else do final check on reg for memory access (ANDI #$0FFF,D4 (CMPI #MEMLMT,D4 ;return with match results to caller CONOK RTS4 (.ENDC (.IF ROM4K = 0 (.IF DIAGS = 0 ;------------------------------------------------------------------------- ; Initialize other MMU regs for invalid access ;------------------------------------------------------------------------- (TST.B SEG1ON ;SET FOR CONTEXT 1 (MOVEQ #1,D6 ;SET CONTEXT INDICATOR (BSR6 INITMMU (TST.B SEG2ON ;SET FOR CONTEXT 3 (MOVEQ #3,D6 (BSR6 INITMMU (TST.B SEG1OFF ;SET FOR CONTEXT 2 (MOVEQ #2,D6 (BSR6 INITMMU (TST.B SEG2OFF ;RESET FOR CONTEXT 0 REGS (CLR.L D6 (TST D2 ;CHECK IF ERRORS (BEQ.S START ;exit if ok (ROR.L #8,D6 ;GET CONTEXT INDICATOR (OR.L D6,D2 ;SAVE WITH ERROR BITS (BSET #MMU,D7 ;SET ERROR CODE FOR LATER MESSAGE (BEQ.S START ;AND CONTINUE (.PAGE ;------------------------------------------------------------------------- ; Routine to init MMU regs ;------------------------------------------------------------------------- INITMMU (MOVE.L #MMUSADRL,A0 ;MMU limit start addr (MOVE.L #MMUEADRL,A1 ;MMU limit end addr (MOVE.L #ADR128K,A2 ;increment value (MOVE.L #MMUEADRB,A3 ;MMU base end addr (MOVE #INVPAG,D0 ;set pattern for limit regs RWLOOP BSR4 CHKRW ;go initialize and check (CMPA.L A0,A1 ;done? (BEQ.S CHKBASE ;if yes go check for base reg testing (ADDA.L A2,A0 ;else bump addr (BRA.S RWLOOP CHKBASE CMPA.L A0,A3 ;done with base? (BEQ.S @2 ;exit if yes (MOVE.L #MMUSADRB,A0 ;else set starting base address (MOVEA.L A3,A1 ; and ending address (CLR.L D0 ;set base value (BRA.S RWLOOP ;go do base regs @2 RTS6 ;AND EXIT TEST (.ENDC ;{DIAGS} (.ENDC ;{ROM4K} (.PAGE ;------------------------------------------------------------------------- ; Reset SETUP bit to enable system access and continue with testing ;------------------------------------------------------------------------- START CLR.B SETUP ;TURN OFF SETUP TO ENTER MAP LAND ... ;---------------------------------------------------------------------------- ; Now do memory sizing - assumes 128K minimum memory increment ; Register usage: ; A0 = minimum physical address D0 = scratch use ; A1 = maximum physical address/scratch D1 = incr for search address ; A2 = unused D2 = unused ; A3 = next base memory addr to test D3 = inverted sizing test pattern ; A4 = return address D4 = sizing test pattern ; A5 = unused D5 = retry count ; A6 = saved error mask D6 = error mask ;---------------------------------------------------------------------------- MEMSIZ CLR.L D0 ;setup regs for loop (MOVE.L D0,A0 (MOVE.L D0,A1 (MOVE.L D0,A3 (MOVE.L D0,A6 (MOVEQ #2,D1 ;size at 128K boundaries RM000 (SWAP D1 ; RM000 (MOVE.L #PATRN,D4 ;set test patterns for sizing CHG002 (MOVE D4,D3 ;use only lower word (NOT D3 ;and its inverse CHKLO BSR4 CHKMEM ;first search for low memory address (TST D6 ;memory found? (BEQ.S SAVELO ;yes - go save address (NOT D6 ;else invert to check if all bits in error (TST D6 ;if not, assume memory error (BNE.S @3 ; and go save address @2 ADDA.L D1,A3 ;else bump search address (MOVEA.L A3,A1 ;set as next working address (CMPA.L #MAXADR,A1 ;at max address? (BNE.S CHKLO ;continue search if not ; No memory found - toggle LED and check for I/O board; if no I/O (bus error) CHG004 ; diagnostics are restarted CHG004 (MOVE.B #DEFVID2,VIDLTCH ;set LED on and default video latch setting (PAGE 2F) CHG004 (MOVE #TNTHSEC,D0 ;delay for .1 sec CHG004 @9 SUBQ #1,D0 ; CHG004 (BNE.S @9 ; CHG004 (MOVE.B #DEFVID,VIDLTCH ;reset LED and leave video latch setting CHG004 (MOVE.L #VIA1BASE,A0 ;check for I/O board CHG004 (TST.B (A0) ;bus error will occur if not installed CHG004 ; Go into read/write loop if no memory found but I/O installed (BSR2 LOTONE ;beep speaker for error (BSR4 CONSET ;set contrast (MOVE.L #ONEMEG-2,A0 ;set default memory address (to span both boards) CHG002 @4 MOVE.L D4,(A0) ;go into read/write loop CHG002 (MOVE.L (A0),D3 ; CHG002 (BRA.S @4 ; Low memory address found - save and continue @3 NOT D6 ;reinvert and (MOVE D6,A6 ; save results SAVELO MOVEA.L A3,A0 ;save low address (CMPA.L #ONEMEG,A0 ;check for min low address (BLE.S @1 ;skip if OK (MOVEA.L #ONEMEG,A0 ;else set at min value (one 512K board in slot 1) (.PAGE ;----------------------------------------------------------------------------- ; Now check for high memory address; search to max address of 2 meg ;----------------------------------------------------------------------------- @1 MOVEA.L A3,A2 ;save low address as first high address TSTHI (ADDA.L D1,A3 ;compute next 128K increment (MOVEA.L A3,A1 ;use as new search value (CMPA.L #MAXADR,A1 ;done? (BEQ.S SIZXIT ; Following patch added to detect for wraparound problem of old memory boards (MOVE.L A0,D0 ;check low address RM015 (BNE.S CHKHI ;old memory boards start at address 0 RM015 (CMP (A1),D3 ;are we wrapped back to already tested location? (BEQ.S WRAPXIT ;skip if yes (i.e., old memory board) RM015 ; Else continue with check for high address CHKHI BSRS4 CHKMEM ;go do memory search (TST D6 ;any errors? (BEQ.S SAVEHI ;skip if not to save address (NOT D6 ;else invert to see if all bits in error (TST D6 (BEQ.S TSTHI ;skip if yes to ignore address (MOVE A6,D0 ;else get previous results (NOT D6 ;reinvert and (OR D6,D0 ; add new results (MOVE D0,A6 ;save for later SAVEHI MOVEA.L A3,A2 ;save as new potential high address (CLR (A3) ;clear test pattern RM015 (BRA.S TSTHI ; and continue loop WRAPXIT CLR (A1) ;clear test pattern RM015 SIZXIT ADDA.L D1,A2 ;high address = last valid addr + 128K (MOVEA.L A2,A1 ;save for later use (BRA.S RSTMMU ;continue on (.PAGE ;---------------------------------------------------------------------------- ; Subroutine to do memory check for sizing. If error, tries successive ; memory locations up to retry count (D5). Returns with error mask in D6. ;---------------------------------------------------------------------------- CHKMEM MOVEQ #RETRYCNT,D5 ; set retry count in case of errors (CLR D6 ; clear for error mask @1 MOVE D4,(A1) ; check if true data stores (MOVE D3,2(A1) ; and try complement to next location (CMP (A1),D4 (BEQ.S @2 ; continue if yes (MOVE (A1),D0 ; else get error bits (EOR D4,D0 (OR D0,D6 ; and save them @2 CMP 2(A1),D3 ; check second location (BEQ.S @3 ; exit if data correct (MOVE 2(A1),D0 ; else read again (EOR D3,D0 ; get error bits (OR D0,D6 ; save in error mask @3 MOVE D4,2(A1) ; now try in reverse order (MOVE D3,(A1) (CMP 2(A1),D4 ; check second location (BEQ.S @4 ; skip if OK (MOVE 2(A1),D0 ; else save error bits (EOR D4,D0 (OR D0,D6 @4 CMP (A1),D3 ; and check first (BEQ.S @5 ; continue if yes (MOVE (A1),D0 ; else get error bits (EOR D3,D0 (OR D0,D6 ; and save them @5 TST D6 ; any errors? (BEQ.S @6 ; skip if no (TST.L (A1)+ ; else bump search address to next pair (SUBQ #1,D5 ; decr retry count (BNE.S @1 ; continue until count exhausted @6 RTS4 ; return with results in D6 (.PAGE ;------------------------------------------------------------------------- ; Subroutine to set parms for lo tone from speaker ;------------------------------------------------------------------------- LOTONE MOVEQ #$60,D0 ;set frequency (MOVE #250,D1 ;and duration (MOVEQ #4,D2 ;and volume (medium) (BSR4 TONE2 ;go do tone (RTS2 (.PAGE ;--------------------------------------------------------------------------- ; Now reset MMU regs according to low and high physical address ; Remainder of MMU regs in context 0 are set to invalid page ; ; Register Usage: ; A0 - low physical address D0 - scratch/value stored in base reg ; A1 - high physical address D1 - value stored in limit reg ; A2 - MMU base reg ptr D2 - unused ; A3 - MMU limit reg ptr D3 - holds base reg page incr value ; A4 - used for return address D4 - used for count of regs to set ; A5 - MMU address increment D5 - low physical page ; A6 - not used D6 - high physical page ;--------------------------------------------------------------------------- ; First translate memory addresses to 512 byte page values for MMU use RSTMMU (MOVE.L A0,D5 ;GET MEMORY ADDRESS VALUES (MOVE.L A1,D6 (MOVEQ #9,D0 ;SET SHIFT COUNT (LSR.L D0,D5 ;TRANSLATE TO PAGE VALUES (LSR.L D0,D6 ; Now initialize for MMU write operations (MOVEA.L #MMUSADRB,A2 ;SET MMU BASE REG PTR (MOVEA.L #MMUSADRL,A3 ;SET LIMIT REG PTR (MOVE.L #ADR128K,A5 ;SET INCREMENT VALUE FOR MMU ADDRESSES (MOVE.L #PAG128K,D3 ;SET INCR VALUE FOR BASE REG CONTENTS (MOVEQ #126,D4 ;SET REG COUNT - NO RESETTING OF REGS 126,127 (MOVE D5,D0 ;SET BASE VALUE (MOVE #MEMLMT,D1 ;SET LIMIT VALUE ; Remap MMU regs for existing memory REMAP BSRS4 WRTMMU ;REWRITE SET OF MMU REGS (SUBQ #1,D4 ;DECR REG COUNT (ADD.L D3,D0 ;BUMP PAGE ADDRESS (CMP.L D0,D6 ;CHECK IF AT UPPER LIMIT (BNE.S REMAP ;LOOP IF NO ; Now map remainder of regs for invalid access (CLR D0 ;SET NEW BASE REG VALUE (MOVE #INVPAG,D1 ; AND LIMIT REG VALUE MAPINV BSRS4 WRTMMU ;GO DO REWRITE (SUBQ.L #1,D4 ;DECR COUNT (BNE.S MAPINV ;LOOP UNTIL DONE ; Finally reset video page to last page of memory (LSR.L #6,D6 ;compute address for video page (SUBQ #1,D6 ;decr to last page (MOVE.B D6,VIDLTCH ;and set video latch (BRA.S MEMTST1 ;SKIP TO NEXT TEST (.IF EXTERNAL = 1 (.LIST (.PAGE (.ENDC ;------------------------------------------------------------------------- ; Subroutine to set MMU regs (context 0) - can also be called by external ; routines that provide the following register inputs: ; ; A2 = base reg address D0 = value for base reg ; A3 = limit reg address D1 = value for limit reg ; A5 = reg address increment ;------------------------------------------------------------------------- WRTMMU TST.B SETUPON ;TURN SETUP ON TO ENABLE MMU ACCESS (MOVE D0,(A2) ;SET BASE REG (MOVE D1,(A3) ;SET LIMIT REG (ADDA.L A5,A2 ;BUMP MMU PTRS (ADDA.L A5,A3 (CLR.B SETUP ;BACK TO MAP LAND (RTS4 ;AND BACK TO CALLER (.IF ROM16K = 1 ;------------------------------------------------------------------------- ; Subroutine to read MMU regs - for call by external routines. ; Inputs: ; D2 = context to read (0-3) ; A2 = base reg address ; A3 = limit reg address ; A4 = return address ; A5 = reg address increment ; Outputs: ; D0 = value of base reg ; D1 = value of limit reg ; A2,A3 incremented by value in A5 ; Side Effects: ; D3 trashed ;------------------------------------------------------------------------- READMMU MOVE #$0FFF,D3 ;set mask for result (TST.B SETUPON ;turn setup on to enable MMU access (TST D2 ;check context (BEQ.S @9 ;skip if context 0 (CMP.B #1,D2 ;context 1? (BEQ.S @2 (CMP.B #2,D2 ;context 2? (BEQ.S @1 (TST.B SEG2ON ;must be context 3 (BRA.S @2 ;set both seg bits @1 TST.B SEG2ON ;set for context 2 (BRA.S @9 @2 TST.B SEG1ON ;set for context 1 and 3 ; read the regs @9 MOVE (A2),D0 ;read base reg (AND D3,D0 ;clear junk (MOVE (A3),D1 ;read limit reg (AND D3,D1 ;clear junk (ADDA.L A5,A2 ;incr ptrs (ADDA.L A5,A3 (TST.B SEG1OFF ;restore to context 0 (TST.B SEG2OFF (CLR.B SETUP ;back to map land (RTS4 ;and back to caller (.ENDC (.IF EXTERNAL = 1 (.NOLIST (.ENDC (.PAGE ;-------------------------------------------------------------------------- ; Begin memory testing by checking first 800 hex locations (2K). ; If error here, abort other testing and go into loop since can't relay ; meaningful results. ;-------------------------------------------------------------------------- MEMTST1 MOVEA.L A0,A2 ;save memory lo, hi addresses (MOVEA.L A1,A3 (.IF DIAGS = 1 (SUBA.L A0,A0 ;set test addresses (MOVEA #LOMEM,A1 ;upper address RM000 (BSR4 RAMTEST ;go do memory test (BEQ.S INITMEM ;skip if OK ; Error in low memory - reset video latch, beep speaker and go into R/W loop (MOVE.L A2,D0 ;get low physical address (LSR.L #8,D0 ;convert to page value (LSR.L #7,D0 (MOVE.B D0,VIDLTCH ;set video latch to bad area (BSR4 CONSET ;ensure contrast on (BSR2 LOTONE ;beep speaker twice for low memory error (MOVE #TNTHSEC,D0 ;delay for about 1/10 sec RM000 TONEDLY SUBQ #1,D0 (BNE.S TONEDLY (BSR2 LOTONE ;do second beep (SUBA.L A0,A0 ;loop at first address (MOVE #PATRN2,D0 ;set pattern for use @2 MOVE D0,(A0) (MOVE (A0),D1 (BRA.S @2 ;loop with random display on screen (.ELSE (MOVEQ #0,D3 ;set results reg (MOVEQ #-1,D0 ;set for memory "clear" pattern CLRMEM MOVE.L D0,(A0)+ ;do "clear" (CMPA.L A0,A1 ;done? (BNE.S CLRMEM ;loop until yes (.ENDC ;{DIAGS} ; Now attempt to initialize status areas and save results INITMEM MOVEA #STATUS,A0 ;get ptr to start of status area RM000 (MOVEQ #127,D0 ;set count @2 CLR.L (A0)+ ;clear it (DBF D0,@2 ;until done (MOVE D3,MEMRSLT ;save test results (MOVE A6,SIZRSLT ;save sizing results (MOVE.L A2,MINMEM ;save min memory address (MOVE.L A3,MAXMEM ;save max memory address (SUBA.L A2,A3 ;compute total memory (MOVE.L A3,TOTLMEM ;and save also (MOVE.L #HEX32K,A0 ;compute base address for screen (SUBA.L A0,A3 (MOVE.L A3,SCRNBASE ;and save (MOVE D2,MMURSLT ;and save MMU results also (MOVE.L #KBDQ,KBDQPTR ;init COPS buffer pointer for later use (.PAGE ;------------------------------------------------------------------------ ; Initialize exception and trap vectors to catch unexpected errors ;------------------------------------------------------------------------ INITVCT BSR.S SETVCTRS ;init vectors (BRA SCCSET ;continue testing CHG027 ; Subroutine to set up default vectors SETVCTRS (LEA MISC,A0 (SUBA.L A1,A1 (MOVEQ #64,D0 @1 MOVE.L A0,(A1)+ ; fill with unknown ones (SUBQ #1,D0 (BGT @1 (BSR.S SETBUSVCT ; then, with special ones RM000 (LEA AERR,A0 (MOVE.L A0,ADRVCTR (LEA IERR,A0 (MOVE.L A0,ILLVCTR (LEA NMI,A0 (MOVE.L A0,NMIVCT (LEA TRPERR,A0 ; same routine for line 1010 and 1111 (MOVE.L A0,L10VCTR (MOVE.L A0,L11VCTR (.IF USERINT = 0 (MOVEQ #FIRSTROW,D5 ;set default row and (MOVEQ #FIRSTCOL,D6 ; column cursor ptrs (.ENDC (RTS ;----------------------------------------------------------- ; Subroutine to setup bus error vector RM000 ;----------------------------------------------------------- SETBUSVCT (LEA BERR,A3 ;setup default vector RM000 (MOVE.L A3,BUSVCTR ; RM000 (RTS ; RM000 ;----------------------------------------------------------- ; Exception Handler routines ;----------------------------------------------------------- MISC MOVE.L D7,D7SAV ;save incoming value (MOVEQ #0,D7 (BSET #MISEXCP,D7 ;set error indicator (BRA.S EXCP1 IERR MOVE.L D7,D7SAV ;save incoming value (MOVEQ #0,D7 (BSET #ILLEXCP,D7 ;set error indicator (BRA.S EXCP1 NMI MOVE.L D7,D7SAV ;save incoming value (MOVEQ #0,D7 (BSR TSTSTAT ;check status reg for parity error CHG015 (BNE.S NOTPE ;skip if not (BSET #MPAR,D7 ;set error indicator (BSR GETPADDR ;get and save error address CHG015 (TST.B PAROFF ;toggle to clear error bit (BTST #5,D1 ;video error? CHG015 (BEQ.S @1 ;skip if not CHG015 (ANDI.L #VMSK,D1 ;mask if yes CHG015 @1 MOVE.L D1,PEADDR ;save converted error address CHG015 (BRA.S EXCP1 ;go to exit NOTPE BSET #CPUINTR,D7 ;else set NMI code (BRA.S EXCP1 ; and exit TRPERR MOVE.L D7,D7SAV ;save incoming value (MOVEQ #0,D7 (BSET #TRPEXCP,D7 ;set error indicator (BRA.S EXCP1 BERR MOVE.L D7,D7SAV ;save incoming value (MOVEQ #0,D7 (BSET #BUSEXCP,D7 ;set error indicator (BRA.S EXCP0 AERR MOVE.L D7,D7SAV ;save incoming value (MOVEQ #0,D7 (BSET #ADREXCP,D7 ;set error indicator EXCP0 ; GROUP 0 EXCEPTIONS HERE (MOVE (SP)+,EXCFC ; SAVE THE EXTRA DATA (MOVE.L (SP)+,EXCADR (MOVE (SP)+,EXCIR EXCP1 ; GROUP 1 EXCEPTIONS HERE (MOVE (SP)+,EXCSR ; SAVE COMMON INFO (MOVE.L (SP)+,EXCPC (MOVE D0,EXCTYPE ; save error type (BRA TSTCHK ; and go display error (.PAGE ;------------------------------------------------------------------------- ; Initialize SCC chip for Applebus use. CHG027 ; Bus error vector setup in case of problems. ;------------------------------------------------------------------------- SCCSET (LEA NOIO,A3 ;set bus error vector in case no IO board CHG027 (MOVE.L A3,BUSVCTR ; CHG027 (BSR RSTSCC ;go do setup CHG027 ;------------------------------------------------------------------------- ; Now test VIA for parallel port and contrast latch. ; A read/write test on the timer 1 latches is done, then contrast ; is set if OK. ;------------------------------------------------------------------------- VIA2TST (.IF DIAGS = 1 VIA2CHK (.IF ROM16K = 1 (LEA VIA2VCT,A3 ;OK - set up special bus vector (MOVE.L A3,BUSVCTR (MOVE.L #,A0 ;set base address of timer low latch (MOVEQ #8,D0 ;set offset to high latch (BSRS6 VIATST ;and go do test (BEQ.S @2 ;if OK, continue (BSET #VIA2,D7 ;else set error bit (TST.L D7 ;check if in loop mode (BMI.S VIA2CHK ;restart if yes (BRA.S @3 ;else skip contrast setting (.ENDC @2 TST.L D7 ;in loop mode? (BMI.S VIA2CHK ;restart if yes (BSRS4 CONOFF ;go turn off contrast (.ENDC ;{DIAGS} @3 BRA.S SCRNTST ;else skip to next test (.IF DIAGS = 1 ;------------------------------------------------------------------------ ; Bus error handler for VIA #2 use ;------------------------------------------------------------------------ VIA2VCT MOVEQ #EVIA2,D0 ;SET ERROR CODE (BSET #VIA2,D7 ;set indicator (BRA IOVCT ;AND GO HANDLE I/O EXCEPTION (.ENDC ;{DIAGS} (.IF ROM16K = 1 (.PAGE ;------------------------------------------------------------------------- ; Subroutine to do VIA testing ; A0 = address of first timer latch ; D0 = offset to other latch ;------------------------------------------------------------------------- VIATST MOVE.L A0,A1 ;set up address for second latch (ADDA.L D0,A1 (MOVEQ #0,D0 ;for error use (CLR.B D2 ;clear old data value (MOVE.B #0,(A0) ;and the timer latches (MOVE.B #0,(A1) (MOVE #$FF,D3 ;set up start value (BSRS4 VIARW ;go do read/write test (RTS6 ;and return ; Subroutine to do read/write test - loops thru all 256 values VIARW CMP.B (A0),D2 ;check for old values first (BNE.S VIAFAIL (CMP.B (A1),D2 (BNE.S VIAFAIL (MOVE.B D3,(A0) ;set new value in low timer latch (CMP.B (A1),D2 ;ensure high latch not affected (BNE.S VIAFAIL (CMP.B (A0),D3 ;verify new low latch setting (BNE.S VIAFAIL (MOVE.B D3,(A1) ;set new value in high timer latch (CMP.B (A0),D3 ;ensure low latch not affected (BNE.S VIAFAIL (CMP.B (A1),D3 ;verify new high latch setting (BNE.S VIAFAIL (MOVE.B D3,D2 ;the new value becomes the old (DBF D3,VIARW ;loop thru all 256 values (BRA.S VIARWEND VIAFAIL ADDQ #1,D0 ;set for error VIARWEND TST D0 ;set zero bit indicator (RTS4 (.ENDC (.PAGE ;-------------------------------------------------------------------------- ; Subroutine to set contrast latch - sets for default, off or value in D0 ;-------------------------------------------------------------------------- CONSET MOVE.B #$80,D0 ;set mid range value default (BRA.S CONSET2 CONOFF MOVEQ #-1,D0 ;set for contrast off CONSET2 ;for external entry (MOVE.L #VIA2BASE,A0 ;GET 6522 BASE ADDR (MOVE.B #$84,DDRB2(A0) ;ENSURE NO STRAY DATA TO CONTRAST (MOVE.B #4,ORB2(A0) ; LATCH BY DISABLING DRIVERS (MOVE.B #$FF,DDRA2(A0) ;NOW SET PORT A AS OUTPUTS (MOVE.B D0,ORA2(A0) ;set contrast value (BSET #7,ORB2(A0) ;AND STROBE IT (RTS4 ;RETURN TO CALLER (.PAGE ;------------------------------------------------------------------------- ; Test memory to be used for screen. The screen can then be ; used for test icon display. Default choice is last 32K of memory. ; If this is invalid, do backwards scan through memory until a valid ; area is found. ; Assumes: location SCRNBASE = base address of default screen (set by ; sizing routine) ;------------------------------------------------------------------------- SCRNTST (.IF DIAGS = 1 (MOVE.L SCRNBASE,A0 ;get base address of screen (MOVE.L TOTLMEM,A1 ;set end address (BSR4 RAMTEST ;and go do test (BEQ.S INVTST ;continue if no error (BSET #MEM,D7 ;else set memory read/write error ; save error results and then start search for good video page (BSR TSTINIT ;initialize for further testing (BSR.S SCRNSAV ;save results (MOVE.L SCRNBASE,A1 ;set new search end address (MOVE.L A1,A0 (MOVE.L #HEX32K,A2 ;screen size is 32K (SUBA.L A2,A0 ;set new start addr (end-32K) @1 MOVEM.L A0-A2,-(SP) ;save search addresses (BSR4 RAMTEST ;go test (MOVEM.L (SP)+,A0-A2 ;restore addresses (no effect on CCR) (BEQ.S SCRNOK ;skip if OK (non-zero CCR if error) (MOVE.L A0,D4 ;else go save results (BSR.S SCRNSAV (MOVE.L A0,A1 ;set next end (SUBA.L A2,A0 ; and start addresses (MOVE.L A0,D0 ;continue thru all of memory if necessary (BGT.S @1 SCRNERR BRA.S INVTST ;continue testing, leave screen at default SCRNOK MOVE.L A0,SCRNBASE ;save new screen base (BSR.S SETVLTCH ;and go set video latch (BRA.S INVTST ;and exit to next test ;------------------------------------------------------------------------- ; Subroutine to save error results from screen test routine ; Inputs: ; A3 = ptr to base of save result area ; D4 = base address of test area ; Outputs: ; None ; Side Effects: ; D1/D3-D4 trashed ;------------------------------------------------------------------------- SCRNSAV MOVEQ #17,D1 ;divide base address by 128K (LSR.L D1,D4 (ADD D4,D4 ;double for word index to save area (MOVE.L D3,D1 ;combine error results (SWAP D3 (OR D1,D3 (OR D3,0(A3,D4) ;save and exit (RTS ;------------------------------------------------------------------------- ; Subroutine to set the video latch ; Inputs: ; Location SCRNBASE = logical base address for screen ; Outputs: ; None ; Side Effects: ; D0-D1 trashed ;------------------------------------------------------------------------- SETVLTCH (MOVE.L SCRNBASE,D2 ;get logical screen base address (MOVE.L TOTLMEM,D1 ;get physical amount of memory (SUB.L D2,D1 ;compute screen base offset (MOVE.L MAXMEM,D0 ;get max physical address (SUB.L D1,D0 ;compute physical screen base address (LSR.L #8,D0 ;convert to page value (LSR.L #7,D0 (MOVE.B D0,VIDLTCH ;set latch (RTS ;and exit (.PAGE ;------------------------------------------------------------------------- ; Now check state of INVID bit to see if inverse video is installed. ; If yes, rewrite last 4 words of screen page to avoid retrace line. ;------------------------------------------------------------------------- INVTST (.IF INVERTCK = 1 ; CHG013 (MOVEA.L #STATREG,A5 ;set ptr to status register (BTST #INVIDBIT,(A5) ;check if inverse video installed (BNE.S VIA1TST ;go on to next test if not ; Inverse video requires zeroing of last bit in video page (32K) (MOVE.L SCRNBASE,A0 ;get base address of screen (ADD.L #HEX32K,A0 ;set ptr to end of screen (CLR.L -(A0) ;rewrite last 4 words (CLR.L -(A0) (.ENDC ;{INVERTCK} CHG013 (.ENDC ;{DIAGS} ;------------------------------------------------------------------------- ; Continue testing by now doing COPS VIA test ;------------------------------------------------------------------------- VIA1TST (.IF USERINT = 1 ; Draw desktop on screen for test icon display (BSR DRAWDESK ;draw the desk (BSR.S DSPCPURM ;and CPU ROM id CHG001 (.ENDC (BSR4 CONSET ;set default contrast (.IF ROM16K = 1 VIA1CHK LEA VIA1VCT,A3 ;first set up bus error vector (MOVE.L A3,BUSVCTR (MOVE.L #,A0 ;set base address of timer low latch (MOVEQ #2,D0 ;set offset to high latch (BSR6 VIATST ;go test (BEQ.S @2 ;skip if OK (BSET #VIA1,D7 ;else set error bit (TST.L D7 ;loop? (BMI.S VIA1CHK ;yes - test again (BRA TSTCHK ;else abort further testing @2 TST.L D7 ;check for loop mode (BMI.S VIA1CHK (BRA.S COPSENBL ;else go test COPS ;------------------------------------------------------------------------ ; Subroutine to display CPU ROM id ;------------------------------------------------------------------------ DSPCPURM (MOVE.B REV,D0 ;read ROM rev CHG001 (MOVEQ #ROMIDROW,D5 ;setup cursor ptrs CHG001 (MOVEQ #ROMIDCOL,D6 ; CHG001 (BSR DSPVAL ;do display CHG001 (RTS ; CHG001 (.ENDC (.PAGE ;------------------------------------------------------------------------- ; Try turning COPS on so that keyboard commands can be received ;------------------------------------------------------------------------- COPSENBL (LEA COPSVCT,A3 ;set up bus error vector first (MOVE.L A3,BUSVCTR (BSR.S CPSINIT ;enable COPS (BCS.S COPSBAD ;skip if error (TST.L D7 ;looping desired? (BMI.S COPSENBL ;go repeat test (MOVE.L D7,D0 ;get error indicator (ANDI.L #CPIOMSK,D0 ;mask off don't care bits (BEQ RSTSCAN ;continue if OK to do reset scan (BRA TSTCHK ;else go report error COPSBAD BSET #IOCOPS,D7 ;else set COPS error (TST.L D7 ;looping desired? (BMI.S COPSENBL ;go repeat test (BRA TSTCHK ;else abort further testing ;----------------------------------------------------------------------------- ; Bus error handler for COPS testing with entry point for other I/O tests ;----------------------------------------------------------------------------- COPSVCT MOVEQ #EIOCOP,D0 ;SET ERROR CODE IOVCT BSET #IOEXCP,D7 ;SET I/O EXCEPTION ERROR (BRA EXCP0 ;AND GO HANDLE EXCEPTION ;----------------------------------------------------------------------------- ; Subroutine to initiialize COPS interface for use ;----------------------------------------------------------------------------- CPSINIT MOVEA.L #VIA1BASE,A0 ;GET VIA BASE ADDRESS (MOVE.B #$01,ACR1(A0) ;SET PORT A LATCH ENABLE (OR.B #$09,PCR1(A0) ;SET HANDSHAKE ENABLE (MOVE.B #$7F,IER1(A0) ;CLEAR ALL INTRPT ENABLES (MOVE.B #$7F,IFR1(A0) ;AND CLEAR FLAGS ; Now turn COPS on, disabling mouse and NMI key TURNON CLR D0 ;SET FOR PORT ON CMD (BSR.S COPSCMD ;SEND TO COPS (BCS.S @1 ;EXIT IF TIMEOUT ERROR (MOVEQ #$70,D0 ;DISABLE MOUSE (BSR.S COPSCMD (BCS.S @1 (.IF DEBUG = 0 (MOVEQ #$50,D0 ;disable NMI key (BSR.S COPSCMD (BCS.S @1 (MOVEQ #$60,D0 (BSR.S COPSCMD (.ENDC @1 RTS ;AND EXIT (.PAGE ;----------------------------------------------------------------------------- ; Subroutine to send cmd to COPS ; Assumes registers: ; D0 = cmd value ; If COPS does not respond, timeout error indicated by setting carry bit. ;----------------------------------------------------------------------------- COPSCMD (MOVEM.L D0-D4/A0-A2,-(SP) ;save regs (DISABLE ;disable all interrupts (MOVEA.L #VIA1BASE,A0 ;set COPS VIA interface ptr (MOVEA.L A0,A1 ;save for use as port B output reg address (MOVEA.L A0,A2 (ADDA #DDRA1,A2 ;compute address for port A data direction reg (MOVEQ #$40,D2 ;set up constants for later use (MOVEQ #-1,D3 (MOVEQ #6,D4 (MOVE.B D0,PORTA1(A0) ;set cmd in data reg (no handshake) ;--------------------------------------------------------------------------- ; First find a ready state (CRDY low) ; Each of the following loops take about 32 machine cycles = 6.4 us plus ; a variable amount of time for sync with 6522 (max = 2us) ;--------------------------------------------------------------------------- (MOVE #$061A,D1 ;set timeout for about 10 ms @3 SUBQ #1,D1 (BEQ.S @1 ;exit if timeout (BTST D4,(A1) ;else wait for "ready" (bit 6 = CRDY) (BNE.S @3 ; Now find the next ready state to insure enough time available for data (MULU #1,D0 ;kill some time (about 15.2 us) to get @; out of previous CRDY (MOVE #$061A,D1 ;reinit timeout count @4 SUBQ #1,D1 (BEQ.S @1 ;exit if timeout (BTST D4,(A1) ;wait for another "ready" (BNE.S @4 (MOVE.B D3,(A2) ; ok, jam out the data ; Now wait for CRDY high and then hold data for COPS to read (MOVE #$061A,D1 ;set timeout for about 10 ms @5 SUBQ #1,D1 (BEQ.S @1 ;exit if timeout (BTST D4,(A1) ;wait for "not-ready" (BEQ.S @5 (MOVEQ #$A,D0 ; force about a 40 ms @6 SUBQ #1,D0 ; delay for COPS hold time (BGT.S @6 (CLR.B (A2) ; reset direction reg now (MOVE.B #$82,IER1(A0) ; and, enable CA1 (BRA.S @2 ; go to normal exit ; Timeout occurred - set error indicator @1 ENABLE ;reenable (ORI.B #$01,CCR ;set carry bit (BRA.S @9 ;skip to exit @2 ENABLE ;restore interrupt levels @9 MOVEM.L (SP)+,D0-D4/A0-A2 ;restore regs (RTS ;and return to caller (.PAGE ;------------------------------------------------------------------------- ; Scan COPS for proper reset codes. Delay added for normal COPS power-up ; time of about 1.7 seconds. ; ; Send reset signal and then scan keyboard/mouse interface. First "clears" ; COPS of any pending codes, and then issues reset. Works via ; a "state machine" that checks codes received and sets flags as follows: ; ; D1 = 0 - reset signal in place ; = 1 - reset signal removed ; ; D3 = 0 - no keyboard codes received => keyboard disconnected ; = 1 - keyboard disconnect code ($80/$FD) received ; => ignore, may be old keyboard ; = 2 - keyboard disconnect/connect codes ($80/$FD/$80/id) received ; => keyboard connected ; ; D4 = 0 - no mouse codes received => mouse connected ; = 1 - only mouse connect code ($87) received => ignore, may be old sys ; = 2 - mouse connect/disconnect ($87/$07) codes received ; => mouse disconnected ;-------------------------------------------------------------------------- RSTSCAN (MOVE.L KBDQPTR,A1 ;setup buffer ptrs (MOVEA #QEND,A2 @1 BSR.S GETJMP ;clear COPS queue, saving data (BCC.S @1 (BSR RSTKBD ;do reset of keyboard/mouse interfaces (.IF ROM4K = 0 (CLR.L D1 ;init some flags (CLR.L D3 (CLR.L D4 (BSR.S GETJMP ;check for data (BCS.S RSTXIT ;exit if none (may be old keyboard) ; State 0 - waiting for reset flag or mouse connect code RST0 CMPI.B #RSTCODE,D0 ;reset flag? (BEQ.S RST1 ;skip if yes to state 1 (CMPI.B #MSPLG,D0 ;mouse connect code? (BEQ.S RST2 ;skip if yes to state 2 (CMPI.B #MSUNPLG,D0 ;mouse disconnect code only? (BNE.S GET0 (MOVEQ #2,D4 ;set flag for disconnect state GET0 BSR.S GETJMP ;go get next code (BCS.S RSTXIT ;exit if no more codes (BRA.S RST0 ;else continue scan loop ; State 2 - waiting for mouse unplugged code RST2 MOVEQ #1,D4 ;set flag for mouse connect received (BSR.S GETJMP ;go get next byte (BCS.S RSTXIT ;exit if none or queue full (CMPI.B #MSUNPLG,D0 ;mouse disconnect code? (BNE.S RST0 ;no - return to state 0 (MOVEQ #2,D4 ;yes - set flag (BRA.S GET0 ;and return to state 0 ; State 1 - waiting for reset code RST1 BSR.S GETJMP ;go get next byte (BCS.S RSTXIT ;exit if no more (CMPI.B #KUNPLG,D0 ;keyboard unplugged code? (BNE.S @1 ;skip if not (MOVEQ #1,D3 ;else set flag (BRA.S GET0 ;and return to state 0 @1 CMPI.B #$DF,D0 ;id code? (BHI.S @2 ;skip if not (MOVE.B D0,KEYID ;else save for later use (MOVEQ #2,D3 ;update flag (BRA.S GET0 ;and return to state 0 @2 CMPI.B #KCERR,D0 ;Keyboard COPS error? (BNE.S @3 ;skip if not (BSET #KBDCOPS,D7 ;else set error indicator @3 CMPI.B #ICERR,D0 ;I/O COPS error code? (BNE.S @4 ;skip if not (BSET #IOCOPS,D7 ;else set error indicator @4 BRA.S GET0 ;continue scan from state 0 ; Insert to save code space GETJMP BSR.S GETDATA ;go get COPS data (RTS ;and return to caller ; Reset exit - analyze results RSTXIT TST.B D1 ;reset signal lifted? (BNE.S @1 ;skip if yes (BSR CLRRST ;else remove reset signal (MOVEQ #1,D1 ;set "removed flag" (BSR.S GETDATA ;any data? (BCC.S RST0 ;go decode if yes @1 (.IF FINKBD = 1 (TST.B D3 ;any keyboard data detected? (BNE.S MSCHK ;skip if yes - assume keybd connected (BSET #KBDOUT,D7 ;if none, keyboard is disconnected MSCHK (TST.B D4 ;any mouse data? (BEQ.S SCANXIT ;skip if none - mouse connected @1 SUBQ #1,D4 ;flag = 1? (BEQ.S SCANXIT ;ignore if yes (BSET #MOUSOUT,D7 ;else mouse disconnected (BRA.S SCANXIT ;and go to exit (.ELSE (BRA.S SCANXIT (.ENDC ;{FINKBD} ; Error exits - set appropriate indicator SCANERR BSET #IOKBD,D7 ;I/O or keyboard failure (BRA.S SCANXIT IOCERR BSET #IOCOPS,D7 ;I/O COPS error (.ELSE @1 BSR.S GETDATA ;clear COPS queue (BCC.S @1 (BSR.S CLRRST ;clear reset signal @2 BSR.S GETDATA ;any data? (BCC.S @2 ;clear the queue (.ENDC ;{ROM4K} SCANXIT MOVE.L A1,KBDQPTR ;save queue ptr for later use (.IF ROM4K = 0 (MOVE.L D7,D0 ;check error codes (ANDI.L #SCANMSK,D0 ; for scan errors (TST.L D0 ;any found? (BNE TSTCHK ;skip if yes (.ENDC (BRA.S BEEP ;else continue testing (.PAGE ;------------------------------------------------------------------------- ; Subroutine to get COPS data ; Assumes registers: ; D0 - scratch use A0 - VIA address ; D1 - unused A1 - Ptr to data save area ; D2 - scratch use A2 - Ptr to end of data area ; Puts data in save area and also leaves in register D0. ; Carry bit set if timeout error or keyboard queue full. ;------------------------------------------------------------------------- GETDATA CMPA.L A1,A2 ;check if at end of queue (BEQ.S @2 ;exit if yes (MOVE.L #$1FF,D2 ;else set timeout for about 5 ms (MOVEA.L #VIA1BASE,A0 ;set COPS VIA interface ptr @1 MOVE.B IFR1(A0),D0 ;check if data avail (BTST #1,D0 (BNE.S GETIT ;skip if yes (SUBQ #1,D2 (BNE.S @1 ;else continue @2 ORI.B #$01,CCR ;set timeout error (RTS GETIT MOVE.B ORA1(A0),D0 ;read data (MOVE.B D0,(A1)+ ;save it (RTS ;and exit with results (.PAGE ;------------------------------------------------------------------------- ; Subroutine to do reset of keyboard and mouse interfaces ; Inputs: ; None ; Outputs: ; None ; Side Effects: ; D0/A0 trashed ;------------------------------------------------------------------------- RSTKBD MOVEA.L #VIA1BASE,A0 ;set VIA ptr (BCLR #0,ORB1(A0) ;set reset signal (ORI.B #$01,DDRB1(A0) ;send it (MOVE.L #3000,D0 ;do delay for 12 ms (BSR.S DELAY (RTS ;------------------------------------------------------------------------- ; Subroutine to remove reset signal for keyboard and mouse interfaces ; Inputs: ; A0 = ptr to parallel port VIA (set in RSTKBD routine) ; Outputs: ; None ; Side Effects: ; D0 trashed ;------------------------------------------------------------------------- CLRRST BSET #0,ORB1(A0) ;remove reset signal (BSR.S KBDDELAY ;delay for keyboard reset time (RTS ;---------------------------------------------------------------------------- ; Subroutine to delay for count in D0 (each count = 4 us). Additional ; entry points set up for fixed delays. ;---------------------------------------------------------------------------- (.IF ROM4K = 0 DELAY_1 MOVE.L #TNTHSEC,D0 ;.1 second delay (BRA.S DELAY DELAY5 MOVE.L #FIVESEC,D0 ;5 second delay (BRA.S DELAY KBDDELAY (MOVE.L #KBDDLY,D0 ;delay for COPS debounce loop (.ENDC DELAY SUBQ.L #1,D0 ;loop until count = 0 (BNE.S DELAY (RTS (.PAGE ;------------------------------------------------------------------------- ; Sound starting "tone" ;------------------------------------------------------------------------- BEEP (BSR.S CLICK ;go click speaker (BRA VIDTST ;then go do video test ;------------------------------------------------------------------------- ; Subroutine to set parms for speaker "click" ;------------------------------------------------------------------------- CLICK MOVE.B #$A0,D0 ;set frequency (MOVEQ #0,D1 ;and duration (MOVEQ #8,D2 ;and volume (medium) RM000 @;then fall thru to tone routine RM000 ;------------------------------------------------------------------------- ; Routine to beep the speaker ; Assumes regs set up as ; D0 = desired frequency ($00 - $AA) ; D1 = duration (0 = .5 msec) ; D2 = volume (0,2,4,...,E) ;------------------------------------------------------------------------- TONE MOVEM.L A0/A4/D3,-(SP) ;save regs (BSRS4 TONE2 ;go do tone (MOVEM.L (SP)+,A0/A4/D3 ;restore and exit (RTS ; separate entry point for call without memory usage TONE2 MOVEA.L #VIA1BASE,A0 ;set VIA ptr (ORI.B #$0E,DDRB1(A0) ;set volume bits for output (ANDI.B #$F1,ORB1(A0) ;clear and then (OR.B D2,ORB1(A0) ; set volume bits (ANDI.B #$E3,ACR1(A0) ;clear shift mode bits (ORI.B #$10,ACR1(A0) ;set shift reg for continuous rotate ; check system type (TST.B DISKROM ;test for Lisa 1 board CHG014 (BPL.S @3 ;no changes if yes CHG014 (BTST #SLOTMR,DISKROM ;else check if slow timers CHG029 (BNE.S @3 ;skip if yes CHG029 (MOVE.B D0,D3 ;else adjust input parm CHG014 (LSR.B #2,D3 ; by factor of .25 CHG014 (ADD.B D3,D0 ; CHG014 @3 MOVE.B D0,T2CL1(A0) ;set frequency (MOVE.B #$0F,SHR1(A0) ;set for square wave and trigger ; Do time delay - enter with count in D1 (about .5 msec per count) @1 MOVE.W #$00D0,D3 ;set delay constant @2 DBF D3,@2 (DBF D1,@1 SILENCE ANDI.B #$E3,ACR1(A0) ;disable tone (RTS4 ;and return (.IF DIAGS = 1 ;------------------------------------------------------------------------- ; Routine to handle I/O board selection errors. Does check for access ; of other I/O board devices to try to pinpoint error. ;------------------------------------------------------------------------- NOIO BSET #RS232B,D7 ;set SCC port B access error CHG027 (MOVE #STKBASE,SP ;restore stack pointer ; try access of other I/O board devices (LEA NOIO2,A3 ;set up new bus error vector (MOVE.L A3,BUSVCTR (MOVE.L #VIA2BASE,A0 ;set base address CHG027 (TST.B (A0) ;try access (BRA VIA2TST ;return to testing if OK CHG027 NOIO2 BSET #VIA2,D7 ;set VIA #2 error also CHG027 (LEA NOIO3,A3 ;try final access to VIA #1 CHG027 (MOVE.L A3,BUSVCTR (MOVE.L #VIA1BASE,A0 ;set base address CHG027 (TST.B (A0) (BRA.S SCRNTST ;exit if OK CHG027 NOIO3 BSET #CPUSEL,D7 ;most likely CPU board error (BRA TSTCHK ;go report errors CHG027 (.ENDC 3. "6F^A A 3ND!l^JXX(.PAGE ;---------------------------------------------------------------------------- ; VIDEO CIRCUITRY TEST ; The following test checks the vertical retrace signal of the ; video circuitry to verify it is toggling. ; Register usage: ; D0 = timeout count A0 = unused ; D1 = unused A1 = unused ; D2 = bit pointer A2 = unused ; D3 = unused A3 = address to disable VTIR ; D4 = unused A4 = address to enable VTIR ; D5 = unused A5 = address of bus status register ;---------------------------------------------------------------------------- VIDTST (.IF ROM4K = 0 (.IF USERINT = 1 (BSR MAKETEST ;display test icons (MOVEA #CPUSTRT,A1 ;hilite CPU board icon (BSR INVICON (.ENDC VIDCHK (MOVEA.L #VTIRDIS,A3 ;ADDRESS FOR DISABLING VTIR (MOVEA.L #VTIRENB,A4 ;ADDRESS FOR VTIR ENABLE (MOVEA.L #STATREG,A5 ;STATUS REGISTER LOCATION FOR BYTE OPS (MOVE #$0DF4,D0 ;SET TIMEOUT COUNT FOR ABOUT 20 MS (MOVEQ #VRBIT,D2 ;VR BIT LOCATION (TST (A3) ;RESET THEN (TST (A4) ; ENABLE VTIR @1 BTST D2,(A5) ;WAIT FOR LOW (BEQ.S @2 ;EXIT IF YES (DBF D0,@1 ;ELSE LOOP (ABOUT 5.6 MS PER LOOP) (BRA.S VIDERR ;AND SET ERROR IF TIMEOUT @2 TST (A3) ;RESET VTIR (TST (A4) ;THEN RENABLE (BTST D2,(A5) ;SHOULD BE HIGH BY NOW (BEQ.S VIDERR ;GO TO ERROR EXIT IF NOT (TST (A3) ;DISABLE VTIR (BRA.S VIDXIT ;and go to exit ; Error exit VIDERR BSET #VID,D7 ;SET ERROR INDICATOR (TST.L D7 ;in loop mode? (BMI.S VIDCHK ;restart test if yes (BRA TSTCHK ;else go to error msg routine ; Normal exit VIDXIT ;---------------------------------------------------------------------------- ; Now, try reading of system serial number ;---------------------------------------------------------------------------- (MOVEA #SERNUM,A0 ;ptr for save of serial # (BSR.S RDSERN ;go do read (BCC.S VIDERR ;exit if error (TST VTIRDIS ;else disable vertical retrace (TST.L D7 ;check for loop mode (BMI.S VIDCHK ;if not, fall thru to next test (BRA PARTST ;and go on to next test (.PAGE ;-------------------------------------------------------------------------- ; ; Routine to read system serial # from video prom. ; Written by Ken Schmal and Ron Hochsprung. ; ; Register Usage: ; ; temporary and iterative D0 ; temporary and iterative D1 ; temporary and iterative D2 ; temporary and iterative D3 ; boolean FOUND to be returned D4 ; pointer to save area for serial # A0 ; SN1 & SN2 pointer A1 ; STATUS REGISTER pointer A2 ; SCRACH array pointer A3 ; SCRACH END pointer A4 ; Tag const A5 ; static link and stack frame ; base pointer register A6 ; ; Returns with carry bit set if all OK. ; All registers except D7 and A0 trashed. ; ;-------------------------------------------------------------------------- RDSERN (MOVEM.L D7/A0,-(SP) ;save regs ; turn off all interrupts (move SR, -(sp) ;save the present status register (ori.w #$0700, SR ;set interrupt to level 7 ;-------------------------------------------------------------------------- ; now set up registers for the algorithm ;-------------------------------------------------------------------------- (move.l #Snum, a1 ;location in MMU of SN1 & SN2 (move.l #Statreg,a2 ;Status Register pointer (link a6, #dStack ;make room for SCRACH (lea dScrach(a6), a3 ;get pointer for SCRACH (lea Tag,a4 (move.l a0,dSavArry(a6) ;-------------------------------------------------------------------------- ; first we get the block out of the vertical half ;-------------------------------------------------------------------------- ; ; sync up to the vertical retrace bit ; GetBits1: (moveq #2, d1 ;vertical retrace is bit #2 (move.l #BytesPerRead,dLcnt(a6) ;read this many bytes (clr VTIRDIS ;clear vertical retrace bit (clr VTIRENB ;set vertical retrace interrupt @1: btst d1, (a2) ;wait until it's true (bne.s @1 ; ;------ read the first block ------ ; @3: movem (a1), d0-d7 (movem d0-d7, (a3) (addq.l #8, a3 (addq.l #8, a3 (nop (moveq #dlycnst-1, d0 (subq.l #1, dLcnt(a6) @4: dble d0, @4 (bgt.s @3 ;-------------------------------------------------------------------------- ; then we get the block out of the horizontal half ;-------------------------------------------------------------------------- ; ; kill time until we're near the last vertical retrace line ; GetBits2: (move.l #BytesPerRead, dLcnt(a6);get the last few bytes (move.w #TKiller-1, d0 ;time killer constant @1: dbra d0, @1 ;loop ; ;------ read the second or last block ------ ; @2: movem (a1), d0-d7 (movem d0-d7, (a3) (addq.l #8, a3 (addq.l #8, a3 (nop (moveq #dlycnst-1, d0 (subq.l #1, dLcnt(a6) @3: dble d0, @3 (bgt.s @2 ;-------------------------------------------------------------------------- ; now we have to find sync bytes and extract the bit stream ;-------------------------------------------------------------------------- (clr VTIRDIS ;turn off vertical retrace (moveq #1, d4 ;initialize FOUND to true GetBytes: (lea dScrach(a6), a3 ;pointer to 1/2 Scrach Array pointer (move.l a3, a4 (adda #HalfSize, a4 ;pointer to end of 1/2 Scrach Array RM000 ; ; find the first sync byte ; (bsr FindSync (tst.w d4 (beq.s Exit ;exit if no sync byte found ; ; now pull out the first block from the bit stream ; (bsr GetNibbles ; ; here we look for the second sync byte. ; (lea dScrach(a6), a3 (adda #HalfSize, a3 ;pointer to 2/2 Scrach Array pointer RM000 (move.l a3,a4 (adda #HalfSize,a4 ;pointer to end of 2/2 Scrach Array RM000 ; (bsr FindSync (tst.w d4 (beq.s Exit ;again, exit if no sync byte found ; ; now pull out second block from the bit stream ; (bsr GetNibbles ;---------------------------------------------------------------------- ; Check the checksum of the read data ;---------------------------------------------------------------------- CheckSum: (move.l dSavArry(a6),a0 (clr.w d0 (move.b 24(a0),d0 (move.w #100,d2 (mulu d2,d0 (move.b 25(a0),d1 (move.w #10,d2 (mulu d2,d1 (add.w d1,d0 (move.b 26(a0),d1 (add.w d1,d0 (clr.w d1 (clr.w d2 (clr.w d3 @2: move.b 0(a0,d1),d3 (add.w d3,d2 (addq.w #1,d1 (cmpi.w #24,d1 (bne.s @2 (move.b 27(a0), d3 (add.w d3,d2 (subi.w #4 * $F, d2 (cmp.w d0,d2 (beq.s @3 (clr.w d4 @3: ;--------------------------------------------------------------------------- ; job well done, lets go home ;--------------------------------------------------------------------------- Exit: (unlk a6 (move (sp)+, SR ;restore status reg (MOVEM.L (SP)+,D7/A0 ;and regs (clr VTIRENB ;re-enable interrupts (LSR #1,D4 ;shift to set/reset error indicator @1 RTS ; and exit (.PAGE ;--------------------------------------------------------------------------- ; subroutine to find a sync byte ;--------------------------------------------------------------------------- FindSync: (clr.l d0 (moveq #2, d1 ;two passes to find the sync byte @1: move.w (a3)+, d2 ; (lsl.w #1, d2 ; (roxl.b #1, d0 ;get SN1 (cmpa.l a3, a4 ;assure the buffer's circular (bne.s @2 ; (adda.l #-HalfSize, a3 ;if it's at the end then (subq #1, d1 ; check if it's the second try (beq.s @3 ; and exit if so @2: cmpi.b #$0ff, d0 ;test here if it's a sync byte (bne.s @1 ;no: loop again (lsl.w #4, d0 ;yes: adjust the byte (lsr.b #4, d0 ; (move.w d0, (a0)+ ;save it (rts ;and return @3: clr.w d4 ;uh, oh. No sync byte. (rts ;clear FOUND and return ;-------------------------------------------------------------------------- ; subroutine to pull out a 14 nibble block from the bit stream ;-------------------------------------------------------------------------- GetNibbles: (moveq #BytesPerRead-1, d2 ; @1: moveq #8, d1 ;8 bits/byte (clr.l d0 ; @2: lsl (a3)+ ;get SN1 in the next scrach word (roxl.b #1, d0 ;shift it into the save buffer (cmpa.l a3, a4 ;assure a circular bufer (bne.s @3 ; (adda.l #-HalfSize, a3 ; @3 subq #1, d1 ;decrement bit/byte counter (bne.s @2 ;loop again if still in byte (lsl.w #4, d0 ;separate the nibbles (lsr.b #4, d0 ; (move d0, (a0)+ ;save these nibbles (subq #1, d2 ;decrement byte/SN counter (bne.s @1 ;loop again if still more to go (rts Tag .word $4b41,$5300 (.PAGE ;---------------------------------------------------------------------------- ; PARITY CIRCUITRY TEST ; The purpose of this test is to verify the operation of the parity checking ; logic by forcing a parity error and ensuring it is caught. ; Register usage: ; D0 = pattern written A0 = logical address used for test ; D1 = read results A1 = corresponding physical address ; D2 = NMI indicator A2 = save for NMI vector ; D3 = save of memory contents A3 = scratch ; D4 = save of error addr latch A4 = unused ; D5 = unused A5 = address of bus status register ; D6 = unused A6 = unused ;---------------------------------------------------------------------------- PARTST (.ENDC (.IF ROM16K = 1 (MOVE.L NMIVCT,A2 ;SAVE STANDARD NMI VECTOR (LEA WWPERR,A3 ;THEN SET UP NEW PARITY ERROR (NMI) VECTOR (MOVE.L A3,NMIVCT (MOVEA.L #STATREG,A5 ;setup status reg ptr for byte ops (TST.B PAROFF ;disable parity initially (CLR.L D2 ;clear regs for result use (CLR.L D4 (MOVE #$01FF,D0 ;SET UP PATTERN FOR WRITE (MOVEA #$300,A0 ;SET UP ADDRESS FOR USE (in already verified mem) RM000 (MOVE (A0),D3 ;SAVE ITS CONTENTS (MOVEA.L A0,A1 ;COMPUTE CORRESPONDING (ADDA.L MINMEM,A1 ; PHYSICAL ADDRESS (TST.B DG2ON ;ENABLE WRITE WRONG PARITY FUNCTION (MOVE D0,(A0) ;DO WRITE TO CREATE BAD PARITY (TST.B DG2OFF ;DISABLE WWP (TST.B PARON ;ENABLE PARITY ERROR DETECTION (TST D2 ;SHOULDN'T HAVE INTERRUPT YET (BNE.S PARERR ;EXIT IF ERROR (MOVE (A0),D1 ;DO READ - PARITY ERROR SHOULD OCCUR (NOP ;GIVE A LITTLE EXTRA TIME (TST D2 ;NMI RECEIVED? (BEQ.S PARERR ;ERROR IF NO ; Check that parity error and failing address correctly caught (BTST #PBIT,(A5) ;PARITY ERROR BIT SET? (BNE.S PARERR ;EXIT IF NOT (MOVE MEALTCH,D4 ;GET ERROR ADDRESS (TST.B PAROFF ;disable parity to clear error bit (LSL.L #5,D4 ;NORMALIZE THE ADDRESS (CMPA.L D4,A1 ;SAME ADDRESS AS WRITTEN TO? (BNE.S PARERR ;EXIT IF ERROR (MOVE.L A2,NMIVCT ;ELSE RESTORE NMI VECTOR (CLR D0 (NOT D0 (MOVE D0,(A0) ;"clear" bad parity (TST.B PARON ;reenable parity (BRA.S PARXIT ;and skip to exit ; Error exit PARERR BSET #PAR,D7 ;SET INDICATOR (TST.L D7 ;in loop mode? (BMI.S PARTST ;restart if yes (TST.B PAROFF ;else ensure parity disabled (MOVE.L A2,NMIVCT ;RESTORE NMI VECTOR (BRA TSTCHK ;AND ABORT FURTHER TESTING ; Normal exit PARXIT TST.L D7 ;check for loop mode (BMI.S PARTST ;restart test if yes (BSR CHKCPU ;place check over CPU (all tests OK) (BRA.S MEMTST2 ;else go do memory test ; NMI routine for parity error checking WWPERR MOVEQ #1,D2 ;SET INDICATOR (RTE ;AND RETURN ;------------------------------------------------------------------------ ; Bus error handler for VIA #1 use ;------------------------------------------------------------------------ VIA1VCT MOVEQ #EVIA1,D0 ;SET ERROR CODE (BSET #VIA1,D7 ;set indicator (BRA IOVCT ;AND GO HANDLE I/O EXCEPTION (.ENDC ;(ROM16K) (.PAGE ;------------------------------------------------------------------------- ; Now do full memory test with and without parity enabled. If parameter ; memory bit set for extended memory testing, memory tests executed in ; twice. If warm-start, execute only one pass with parity enabled. ; Uses registers: ; A0 = starting address to test D0 = used to consolidate test results ; A1 = ending address to test D1 = scratch ; A2 = unused D2 = address increment ; A3 = save address for results D3 = test results for each 128K ; A4 = return address D4 = max test address ; A5 = unused D5 = pass count ;------------------------------------------------------------------------- MEMTST2 (.IF ROM4K = 0 (.IF USERINT = 1 (MOVEA #MEMSTRT,A1 ;hilite memory board test icon (BSR INVICON (.ENDC (BSR SETBUSVCT ;restore normal bus error vector RM000 MEMLOOP (LEA PRTYINT1,A1 ;setup up vector for parity intrpt CHG015 (MOVE.L A1,NMIVCT ; CHG015 (.IF ROM16K = 1 ; First check if this is a warm-start CHG006 (BTST #WRMSTRT,D7 ;warm-start? CHG006 (BEQ.S @0 ;skip if not CHG015 (MOVEQ #1,D5 ;else set count for one pass CHG015 (BRA.S @3 ;skip to do it CHG015 ; Next check parameter memory to see if extended testing desired @0 BSR CHKPM ;go check parameter memory (BCS.S @1 ;skip if not valid to do only one pass (BTST #6,MEMCODE ;else check extended memory test indicator (BEQ.S @1 ;exit if not set (MOVEQ #2,D5 ;run two passes for extended mode CHG015 (BRA.S @2 ;go do it CHG015 @1 MOVEQ #1,D5 ;run one pass for normal mode CHG015 ; Run the memory tests @2 TST.B PAROFF ;first run with parity off CHG015 (BSR.S RUNTESTS ;run test pass CHG015 (BNE.S TSTDONE ;skip if error CHG015 @3 TST.B PARON ;then run pass with parity on CHG015 (BSR.S RUNTESTS ;run test pass CHG015 (BNE.S TSTDONE ;exit if error CHG015 (SUBQ #1,D5 ;decr pass count CHG015 (BNE.S @2 ;continue testing until done CHG015 TSTDONE TST.L D7 ;in loop mode? (BMI.S MEMLOOP ;restart if yes (BTST #MEM,D7 ;memory error? (BNE TSTCHK ;abort if yes (BSR CHKMBRD ;else signal memory OK (LEA NMI,A3 ;restore NMI vector CHG015 (MOVE.L A3,NMIVCT ; CHG015 (BRA IOTST ;go on to next test ;----------------------------------------------------------------------- ; Subroutine to run the memory tests - saves results as test proceeds ; Zero condition code bit set if no errors. ;----------------------------------------------------------------------- RUNTESTS ; Do the basic test BASICTST (BSR.S TSTINIT ;init for new test CALL3 (BSR4 RAMTEST (BEQ.S @1 ;skip if no errors (BSET #MEM,D7 ;else set error indicator @1 BSR.S SAVRSLT ;save results (BNE.S CALL3 ;loop until done CHG021 (BTST #MEM,D7 ;set condition code CHG015 (RTS ;and exit (.ELSE (TST.B PARON ;enable parity... ; Do the basic test BASICTST (BSR.S TSTINIT ;init for new test CALL3 (BSR4 RAMTEST (BEQ.S @1 ;skip if no errors (BSET #MEM,D7 ;else set error indicator @1 BSR.S SAVRSLT ;save results (BCC.S CALL3 ;and loop until done TSTDONE LEA NMI,A3 ;restore normal NMI vector (MOVE.L A3,NMIVCT (TST.L D7 ;in loop mode? (BMI.S MEMLOOP ;restart if yes (BTST #MEM,D7 ;memory error? (BNE TSTCHK ;abort if yes (BRA IOTST ;else go on to next test (.ENDC ;{ROM16K} (.PAGE ;---------------------------------------------------------------------- ; Subroutine to do initialization for memory tests ;---------------------------------------------------------------------- TSTINIT (MOVEQ #2,D2 ;test in 128K increments RM000 (SWAP D2 ; (sets D2 = $20000) RM000 (MOVE.L SCRNBASE,D4 ;get max test address (base of screen) (MOVEA #LOMEM,A0 ;set initial start (MOVE.L D2,A1 ; and ending address (MOVEA #MEMRSLT,A3 ;set address of result area RM000 (RTS ;---------------------------------------------------------------------- ; Subroutine to save results and update ptrs. ;---------------------------------------------------------------------- SAVRSLT MOVE D3,D0 ;get low results (SWAP D3 ;get high results (OR D0,D3 ;combine (OR D3,(A3)+ ; and save (CMP.L A1,D4 ;at max test address? (BEQ.S @1 ;exit if yes (MOVEA.L A1,A0 ;else set new addresses (ADDA.L D2,A1 ; to check next row of memory (CMP.L A1,D4 ;in last segment? (BGE.S @1 (MOVE.L D4,A1 ;set at base of video page @1 RTS (.PAGE ;----------------------------------------------------------------------------- ; BASIC MEMORY TEST - writes pattern and its complement in memory location, ; then verifies by reading. Also does second scan as ; addressing check. Uses long word operations for speed. ; Inputs: ; A0 - Starting address to test ; A1 - Ending address ; A4 - Return address ; Outputs: ; CCR zero bit set if no error ; D3 = OR mask of errors ; Uses registers: ; A0 = current test address D0 = current test pattern ; A1 = ending test address D1 = scratch ; A2 = unused D2 = unused ; A3 = unused D3 = OR mask of errors ; A4 = return address D4 = unused ; A5 = saved start address D5 = unused ; A6 = used for return address D6 = unused ;----------------------------------------------------------------------------- RAMTEST MOVE.L A0,A5 ;save start address (MOVE.L #PATRN,D0 ;get pattern (NOT.L D0 ;use complement first (MOVEQ #0,D3 ;clear for result use (ORI #$0010,SR ;set extend bit for use with pattern rotate RAMRW MOVE.L D0,(A0) ;do write (CMP.L (A0),D0 ;verify (BEQ.S RAMCHK2 ;skip if OK (BSRS6 RDERR ;else save error bits RAMCHK2 NOT.L D0 ;now use inverse (MOVE.L D0,(A0) ;write to check for stuck bits (CMP.L (A0)+,D0 ;verify and bump address (BEQ.S RAMNXT ;skip if OK (SUBQ.L #4,A0 ;else get error address (BSRS6 RDERR ;go save error bits (ADDQ.L #4,A0 ;and restore next test address RAMNXT ROXL.L #1,D0 ;create new pattern (NOT.L D0 ;invert for test (CMPA.L A0,A1 ;done? (BNE.S RAMRW ;loop if not ; Now do address check - writes memory as all F's during scan ADRTST MOVE.L #PATRN,D0 ;reinitialize (MOVE.L A5,A0 ;get start address (MOVEQ #0,D1 (NOT.L D1 ;final pattern for write (ORI #$0010,SR ;set extend ADRCHK CMP.L (A0),D0 ;check contents (BEQ.S ADRCLR ;skip if OK (BSRS6 RDERR ;else save errors ADRCLR MOVE.L D1,(A0)+ ;'clear' and go to next location (ROXL.L #1,D0 ;create next pattern (CMPA.L A0,A1 ;done? (BNE.S ADRCHK ;loop if not ; Check results (TST.L D3 ;set condition codes (RTS4 ; Failure routine - save results and continue testing RDERR MOVE.L (A0),D1 ;do read again 'EOR.L D0,D1 ;isolate bad bits 'OR.L D1,D3 ;save result 'RTS6 ;and return (.PAGE ;------------------------------------------------------------------------------ ; Phase 1 Parity error handler for memory tests. Objective for handler is to ; isolate parity error to chip level. ; Assumes: ; D0 = expected data pattern ; A0 = error address or address + 4 ; Uses registers: ; D1 = parity error address ; D2 = search size for byte in error ; D3 = low memory address ; A1 = search address ;------------------------------------------------------------------------------ PRTYINT1 (BSR.S TSTSTAT ;check if parity error CHG015 (BNE NMI ;skip if not CHG015 (BSET #MPAR,D7 ;set error indicator CHG015 (MOVE.L D0,XPCTDATA ;save data and address CHG015 (MOVE.L A0,XPCTADDR ; CHG015 (MOVE.L MINMEM,D3 ;get low memory address CHG015 (BSR GETPADDR ;read and convert parity address CHG015 (BTST #5,D1 ;main mem error? CHG015 (BNE.S @1 ;skip if not CHG015 (MOVEQ #MSRCHSZ-1,D2 ;setup up search size for main mem CHG015 (BRA.S @2 ;skip to do it CHG015 @1 MOVE #VSRCHSZ-1,D2 ;setup for video memory search CHG015 (ANDI.L #VMSK,D1 ;mask off undefined info CHG015 @2 MOVE.L D1,PEADDR ;save error address CHG015 ; Reset NMI vector and start search for exact address CHG015 (LEA PRTYINT2,A1 ;setup new vector CHG015 (MOVE.L A1,NMIVCT ; CHG015 (SUB.L D3,D1 ;convert to logical address CHG015 (MOVE.L D1,A1 ;setup for use CHG015 (TST.B PAROFF ;clear parity bit CHG015 (TST.B PARON ; CHG015 (CLR.L D4 ;clear for use CHG015 @3 MOVE.B (A1)+,D4 ;search for parity error by byte CHG015 (DBRA D2,@3 ;loop until found CHG015 ; Error did not repeat CHG015 (BRA.S PRIXIT ;go save error info and exit CHG015 ;----------------------------------------------------------------------------- ; Subroutine to check for parity error ;----------------------------------------------------------------------------- TSTSTAT BTST #1,STATREG ;check for parity error CHG015 (RTS ;return with condition code set CHG015 ;----------------------------------------------------------------------------- ; Parity error handler, phase 2. ; Assumes: ; A1 = error address + 1 ; D0 = expected data (long) ; D4 = error data (byte) ; Uses registers: ; D1 = error address ; D2 = scratch ;----------------------------------------------------------------------------- PRTYINT2 (BSR.S TSTSTAT ;parity error? CHG015 (BNE NMI ;skip if not to handle NMI CHG015 (BSR GETPADDR ;get error address CHG015 (MOVE.L D1,PEADR2 ;save it CHG015 (SUBA.L #1,A1 ;get actual address CHG015 (MOVE.L A1,ACTADDR ;save address and data CHG015 (MOVE.L D4,ACTDATA ; CHG015 (BTST #5,D1 ;video error? CHG015 (BNE.S PRIXIT ;skip if yes CHG015 (MOVE.L A1,D1 ;get error address CHG015 (ANDI.L #ADRMSK,D1 ;setup up rotate count CHG015 (MOVE.L D1,D2 ;save it CHG015 (BEQ.S @2 ;skip if pre-rotate not needed CHG015 @1 LSL.L #8,D0 ;shift expected data to high byte CHG015 (SUBQ #1,D1 ; CHG015 (BNE.S @1 ; CHG015 @2 ROL.L #8,D0 ;shift to low byte CHG015 (ANDI.L #$FF,D0 ;strip unneeded info CHG015 (EOR.B D4,D0 ;isolate bad bits CHG015 (BEQ.S PCERR ;skip if no data error CHG015 (BTST #0,D2 ;check if high or low byte error CHG015 (BNE.S @3 ;skip if low byte CHG015 (LSL #8,D0 ;else shift to high byte CHG015 @3 MOVEA #MEMRSLT,A3 ;set ptr to save area CHG015 (MOVE.L A1,D4 ;set error address CHG015 (MOVE.L D0,D3 ;and error bits CHG015 (BSR SCRNSAV ;then go save data CHG015 PRIXIT TST.B PAROFF ;disable parity CHG015 (BRA EXCP1 ;and go to exit CHG015 ; no data error - must be parity chip failure; decode to chip id CHG015 PCERR MOVE.L A1,D1 ;get error address CHG015 (BTST #0,D1 ;check if odd or even CHG015 (BEQ.S @1 ;skip if even CHG015 (MOVE.B #$14,PCHIP ;bad parity chip in low word CHG015 (BRA.S @2 ; CHG015 @1 MOVE.B #9,PCHIP ;bad chip in high word CHG015 @2 MOVEQ #17,D2 ;calculate row address CHG015 (LSR.L D2,D1 ; for parity error CHG015 (MOVE.B D1,PCHPROW ;save row info CHG015 (BRA.S PRIXIT ;and exit CHG015 ;----------------------------------------------------------------------------- ; Subroutine to get parity error address ; Returns D1 = error address ;----------------------------------------------------------------------------- GETPADDR (CLR.L D1 ;clear for use CHG015 (MOVE MEALTCH,D1 ;read error latch CHG015 (MOVE D1,ADRLTCH ;save it CHG015 (LSL.L #5,D1 ;convert to physical address CHG015 (RTS ; CHG015 (.PAGE ;----------------------------------------------------------------------------- ; Continue with I/O board testing ;----------------------------------------------------------------------------- IOTST (.ELSE ;{ROM4K} (MOVE.L #FIVESEC,D0 ;delay to allow keyboard input (BSR.S DELAY (.ENDC ;{ROM4K} (.IF USERINT = 1 (MOVEA #IOSTRT,A1 ;hilite I/O board test icon (BSR INVICON (.ENDC (.IF FULLSCC = 1 ;-------------------------------------------------------------------------------; ; SCC Test (Checks RS232 port controller) ; ; The SCC interrupt vector is written and read with all 8 bit patterns ; to check SCC addressing. An internal loopback test is then done on ; channel B. RM014 ; ; The chip is always left in an initial state as follows: ; both channels are reset ; master interrupt enable is reset ; DTR, RTS outputs set high on channel B CHG011 ; ; Runs with interrupts off, uses stack. Uses registers: ; ; A0 = SCC address D0 = error indicator ; A2 = scratch D1 = scratch ; D2 = scratch ; D3 = scratch ; ; Errors saved in D0 and stored in low memory as follows: ; ; 0000 0001 -> SCC vector read/write error (accessed via channel A) RM014 ; 0000 0010 -> channel B transmit buffer empty timeout RM014 ; 0000 0100 -> channel B receive buffer full timeout RM014 ; 0000 1000 -> channel B data compare error RM014 ; ;-------------------------------------------------------------------------------; SCCTEST LEA SCCVCT,A3 ;set up bus error vector (MOVE.L A3,BUSVCTR (BSR RSTSCC ;reset and set up A0 for SCC (ADDQ.L #ACTL,A0 ;adjust SCC address for channel A (MOVEQ #0,D1 ;SCC interrupt vector starts out 0 (MOVEQ #0,D0 ;no errors VECTLOOP (MOVE.B #2,(A0) ;test scc write register 2 (interrupt vector) @; via channel A RM014 (MOVE (SP),(SP) ;delay (MOVE.B (A0),D2 ;read unmodified vector (CMP.B D1,D2 ;ok? (BEQ.S @1 ;branch if so (MOVEQ #1,D0 ;otherwise set error code (BRA.S SCCEXIT ;and exit @1 MOVE (SP),(SP) (MOVE.B #2,(A0) ;write next vector value (ADDQ.L #1,D1 ;increment and delay (MOVE.B D1,(A0) ;write it (BNE.S VECTLOOP ;go through 256 values (BRA.S SETSCC ;now go do loopback init ;----------------------------------------------------------------------- ; Now init channel B for max baud rate and internal loopback. ; External transmit is inhibited by setting DTR low. ;----------------------------------------------------------------------- ; Initialization data for SCC: max baud RS-232 async communication b96data: (.byte 9,$00 ;disable all interupts RM014 (.byte 4,$4D ;x16 clk, 2 stop bits, odd parity (.byte 11,$50 ;baud rate gen clk to receiver, transmitter (.byte 12,$00 ;set baud rate to max (.byte 13,$00 (.byte 14,$13 ;enable baud rate gen, BR=PCLK, loopback (.byte 3,$C1 ;8 bits/char recv, enable receiver (.byte 5,$EA ;DTR low, 8 bits/char xmit, enable xmit, CRC RM014 b96lth .equ *-b96data SETSCC LEA B96DATA,A2 ;setup channel B RM014 (MOVE.W #B96LTH,D1 (SUBQ.L #ACTL,A0 ;set address for channel B (BSR.S WRITESCC ; RM000 ; do the loopback test @; RM014 LPTEST MOVEQ #0,D1 ;go thru 256 bytes (MOVEQ #-1,D3 ;set up timeout count SCCLOOP (BTST #TXBE,(A0) ;wait for transmit buffer empty (BNE.S SCCOUT (DBRA D3,SCCLOOP (ADDQ #2,D0 (BRA.S SCCLXIT ;report timeout error SCCOUT MOVE (SP),(SP) (MOVE.B D1,SCCDATA(A0) SCCLOOP2 (BTST #RXBF,(A0) ;wait for data byte to come in (BNE.S SCCIN (DBRA D3,SCCLOOP2 (ADDQ #4,D0 (BRA.S SCCLXIT SCCIN MOVE (SP),(SP) (MOVE.B SCCDATA(A0),D2 (CMP.B D1,D2 (BNE.S SCCLERR (MOVEQ #-1,D3 ;update timeout count (ADDQ.B #1,D1 ;increment data (BNE.S SCCLOOP ;just do it 256 times SCCLXIT BRA.S SCCEXIT SCCLERR ADDQ #8,D0 ; exit, saving errors SCCEXIT MOVE.B D0,SCCRSLT ;save results (BEQ.S @3 ;continue if OK (BTST #0,D0 ;check for chan A error RM014 (BEQ.S @1 (BSET #RS232A,D7 @1 LSR #1,D0 ;check for chan B error RM014 (TST.B D0 (BEQ.S @2 (BSET #RS232B,D7 @2 BSR.S RSTSCC ;leave SCC at initial condition (TST.L D7 ;looping required? (BMI.S SCCTEST ;restart test if yes (BRA TSTCHK ;else go report error @3 BSR.S RSTSCC ;leave SCC at initial condition (TST.L D7 ;in loop mode? (BMI.S SCCTEST ;restart test if yes (BRA.S DSKTST ;else continue to next test RM014 (.PAGE ;------------------------------------------------------------------------ ; WRITESCC: used to initialize a series of SCC registers. ; ; A0 = SCC address for channel to be initialized ; A2 = pointer to an initialization data block as above ; A4 = return address ; D1 = initialization data block size in bytes ; ; A2, D1, D2 are modified. ; ;------------------------------------------------------------------------ WRITESCC (MOVE.B (A0),D2 ;read to make sure SCC is sync'ed up (BRA.S @2 ;delay for timing, too @1 MOVE.B (A2)+,(A0) @2 DBRA D1,@1 (RTS ;------------------------------------------------------------------------ ; Subroutine to initialize SCC. Does reset and zeroes interrupt vector. ;------------------------------------------------------------------------ INITBDATA (.BYTE 2,$00 ;zero interrupt vector (.BYTE 9,$C0 ;reset both channels INITBLTH .EQU 4 ; CHG011 INITB2 .BYTE 5,$82 ;set DTR, RTS high for Applebus CHG011 INITB2L .EQU 2 ; CHG011 RSTSCC (MOVE.L #SCCBCTL,A0 ;point to SCC base address (chan B) (LEA INITBDATA,A2 ;point to channel B init data (MOVEQ #INITBLTH,D1 ; and set up the length CHG011 (BSR.S WRITESCC ;then init channel B (MOVEQ #12,D0 ;delay for SCC reset (BSR DELAY (LEA INITB2,A2 ;setup DTR, RTS outputs CHG011 (MOVEQ #INITB2L,D1 ; CHG011 (BSR.S WRITESCC ; CHG011 (RTS ;and return ;----------------------------------------------------------------------------- ; Bus error routine for SCC testing ;----------------------------------------------------------------------------- SCCVCT CMPA.L #SCCBCTL,A0 ;accessing channel B? (BNE.S @1 ;skip if no (MOVEQ #ERS232B,D0 ;set error code for chan B (BRA.S @2 @1 MOVEQ #ERS232A,D0 ;set error code for chan A @2 TST.L D7 ;check if in loop mode (BPL.S @3 ;skip if not (MOVEA #STKBASE,SP ;else restore stack ptr RM000 (BRA SCCTEST ;and restart test @3 BRA IOVCT ;and go handle I/O card bus error (.ENDC (.PAGE ;---------------------------------------------------------------------------- ; Test of disk interface - ensure R/W capability to shared RAM, then ; try disable interrupts command. This test will also verify ; the results of the disk controller's own self-test (ROM and RAM test). ;---------------------------------------------------------------------------- DSKTST (.IF DIAGS = 1 (LEA DSKVCT,A3 ;set up vector in case of bus timeout (MOVE.L A3,BUSVCTR (MOVE.L #DISKMEM,A0 ;set ptr for shared memory ; Display ROM id CHG001 (MOVEQ #ROMIDROW,D5 ;set cursor ptrs CHG001 (MOVE #ROMIDCOL+1,D6 ; CHG001 (MOVEQ #'/',D0 ;preceed with / char CHG001 (BSR DSPVAL ;display it CHG001 (MOVE.B ROMV(A0),D0 ;read id CHG001 (MOVE.B D0,IOROM ;save in low memory CHG010 (MOVEQ #2,D1 ; CHG001 (BSR OUTCH ; CHG001 ; Read system type CHG009 (BSR.S SETTYPE ;determine system type CHG029 ; Check disk alive indicator (CLR.L D2 ;clear for use CHG022 (MOVE.L #VIA2BASE,A1 ;set ptr to parallel port 6522 (ANDI.B #$BF,DDRB2(A1) ;ensure bit 6 is input (MOVE.L #DSKTMOUT,D0 ;set up timeout count for 15 secs @2 BTST #DSKDIAG,IRB2(A1) ;check indicator (BNE.S @3 ;skip if set (SUBQ.L #1,D0 ;else loop until timeout (about 8 us per loop) (BNE.S @2 (MOVEQ #EDISK,D2 ;error if not set CHG022 ; Try read operation and check results of self-test @3 (.IF DIAGS = 1 (MOVE.B STST(A0),DSKRSLT ;get results of disk self-test CHG022 (BNE.S INTERR ;exit if error CHG022 @4 TST.B D2 ;previous error? CHG022 (BNE.S INTERR ;exit if yes CHG022 ; Then try simple write operation to shared RAM (MOVEQ #$55,D0 ;set up pattern RM000 (MOVE.B D0,CMD(A0) ;try write (CMP.B CMD(A0),D0 ;verify (BNE.S INTERR ;exit if error ; Finally try a command to disable interrupts (BSR DSABLDSK ;go issue disable cmd (BCC.S DSKXIT ;skip if OK (.ELSE (BRA.S COPSCHK ;continue (.ENDC INTERR BSET #DISK,D7 ;else set disk error (TST.L D7 ;restart if in loop mode (BMI.S DSKTST (BRA TSTCHK ;and abort further testing DSKXIT TST.L D7 ;restart if in loop mode (BMI.S DSKTST (.ENDC (BRA.S COPSCHK ;else go to next test ;----------------------------------------------------------------------------- ; Bus error routine for disk testing ;----------------------------------------------------------------------------- DSKVCT MOVEQ #EDISK,D0 ;SET ERROR CODE (.IF ROM4K = 0 (TST.L D7 ;check if in loop mode (BPL.S @3 ;skip if not (.ENDC (MOVEA #STKBASE,SP ;else restore stack ptr RM000 (BRA DSKTST ;and restart test @3 BRA IOVCT ;GO HANDLE I/O CARD BUS ERROR ;------------------------------------------------------------------------- ; Subroutine for determining system type ; Returns type value in D0 and sets SYSTYPE location in memory ; D0 = 0 - Lisa 1 ; 1 - Lisa 2/external disk with slow timers ; 2 - Lisa 2/external disk with fast timers ; 3 - Lisa 2/internal disk (Pepsi) with fast timers ;------------------------------------------------------------------------- SETTYPE CLR.L D0 ;clear for type usage CHG029 (MOVE.B DISKROM,D1 ;read disk id CHG029 (TST.B D1 ;check for Lisa 1 CHG029 (BPL.S @9 ;skip if yes CHG029 (BTST #SLOTMR,D1 ;Lisa 2 with slow timers? CHG029 (BEQ.S @1 ;skip if not CHG029 (MOVEQ #1,D0 ;else set type CHG029 (BRA.S @9 ; CHG029 @1 BTST #FASTMR,D1 ;Lisa 2 with fast timers? CHG029 (BEQ.S @2 ;skip if not CHG029 (MOVEQ #2,D0 ;else set type CHG029 (BRA.S @9 ; CHG029 @2 MOVEQ #3,D0 ;else must be Pepsi with fast timers CHG029 @9 MOVE.B D0,SYSTYPE ;save system type CHG029 (RTS ; CHG029 ).PAGE ;------------------------------------------------------------------------- ; Scan the keyboard for user commands. Click speaker first to alert user. ;------------------------------------------------------------------------- COPSCHK LEA COPSVCT,A3 ;set up bus error vector (MOVE.L A3,BUSVCTR (BSR CLICK ;notify user that keyboard about to be scanned (BSR DELAY_1 ;delay for 1/10 sec (MOVEA.L #VIA1BASE,A0 ;set up VIA address (MOVE.B #$C9,PCR1(A0) ;set intrpt control for later use @; also causes second "click" (BSR.S SCANCPS ;go check for keyboard input (BRA CLKTST ;and continue on ;-------------------------------------------------------------------------- ; Subroutine to do scan of keyboard COPS ;-------------------------------------------------------------------------- SCANCPS (MOVE.L KBDQPTR,A1 ;set up queue ptrs (MOVEA #QEND,A2 ; Scan for keyboard data KEYSCAN BSR GETDATA ;go check for keyboard input (BCS.S @9 ;exit if no data or queue full (CMPI.B #CMDKEY,D0 ;is it the command key? (BNE.S @1 ;skip if no (BSR GETDATA ;yes - get next char to see if boot cmd (BCS.S @9 ;exit if queue full or no more data (CMPI.B #SHFTKEY,D0 ;check for shift key (BNE.S @2 ;skip if no - go save as boot code (BSR GETDATA ;else keep checking for command sequence (BCS.S @9 ;skip if Q full or no data (CMPI.B #PKEY,D0 ;'P' key for power-cycling (BNE.S @1 ;skip if not (MOVE.B #PC,BOOTDVCE ;set for power-cycle mode (BSET #ALTBOOT,D7 ;set alternate boot (BRA.S KEYSCAN ;and continue scan @1 (.IF USERINT = 1 ; do test for downstroke or mouse button (used for burnin cycling) (TST.B D0 ;check keycode (BPL.S @4 ;skip if not downstroke (CMPI.B #ALPHKEY,D0 ;ignore alpha lock key (BEQ.S KEYSCAN (.ENDC (.IF BURNIN = 1 (CMP.B #MOUSDWN,D0 ;mouse button? (BNE.S @3 ;skip if not (BSET #MSBUTN,STATFLGS ;else set flag for later use (BRA.S KEYSCAN ;and continue scan (.ENDC @3 (.IF USERINT = 1 (BSET #BTMENU,D7 ;set indicator for boot menu (.ENDC (BRA.S KEYSCAN ;and continue scan ; Save code as possible boot id and set indicator @2 BSR.S XLATE ;translate to boot id code and save (BRA.S KEYSCAN ;and continue keyboard scan ; Check if release of mouse or COMMAND key (in case continuing after error) @4 CMP.B #MOUSUP,D0 ;mouse release? (BNE.S @5 (BCLR #MOUSE,STATFLGS ;clear marker if yes (BRA.S KEYSCAN ;and continue scan @5 CMP.B #CMDUP,D0 ;Left CMD key release? (BNE.S @6 (BCLR #CMDFLG,STATFLGS ;clear marker if yes @6 BRA.S KEYSCAN ;continue scan @9 MOVE.L A1,KBDQPTR ;save buffer ptr (RTS ;and return to caller ;--------------------------------------------------------------------- ; Subroutine to translate keycodes to boot device codes. Returns ; with boot code in D2 if match found, else D2 = $F for no match. ; Also saves boot id in memory, and sets alternate boot indicator. ; Destroys A3 and D2. ;--------------------------------------------------------------------- XLATE LEA KEYTBL,A3 ;get ptr to keycode table (CLR.L D2 ;clear for counter @1 CMP.B (A3)+,D0 ;do search until match (BEQ.S @2 ;skip if match (ADDQ #1,D2 ;else bump cntr (TST.B (A3) ;at end? (BNE.S @1 ;if not continue scan (MOVEQ #$7F,D2 ;else set for invalid code @2 (MOVE.B D2,BOOTDVCE ;save as boot device code (BSET #ALTBOOT,D7 ;set indicator (RTS ;and exit KEYTBL .BYTE KEY1,KEY2,KEY3 ;1,2,3 (.BYTE KEY4,KEY5,01 ;4,5,reserved (01 is invalid keycode) (.BYTE KEY6,KEY7,01 ;6,7,reserved (.BYTE KEY8,KEY9,01 ;8,9,reserved (.BYTE 01,01,01 ;reserved (.BYTE 01 ;reserved for power-cycle mode (.BYTE ENTRKEY ;Enter on numeric key pad J; (for Monitor access) TBLEND .BYTE 0 ;ensure on word boundary (.PAGE ;------------------------------------------------------------------------------ ; Try initial clock read and save data for later use ;------------------------------------------------------------------------------ CLKTST (.IF NEWLISA = 1 (.IF DIAGS = 1 (BSR.S READCLK ;go read clock (TST.L D7 ;restart if in loop mode (BMI.S CLKTST (BTST #CLK,D7 ;any errors? (BNE TSTCHK ;abort if yes (BSR CHKIOBRD ;else mark I/O board OK (BRA.S CONFIG ;and exit to next test ; Subroutine to read clock - destroys regs A0-A2, D0-D1 READCLK DISABLE ;disable all interrupts (MOVEQ #$02,D0 ;set up read clock cmd (BSR COPSCMD ;and send to COPS (BCS.S CLKERR ;exit if error (MOVEA #DATARGS,A2 ;set ptr to end of save area RM000 RDCLK0 MOVEA #CLKDATA-1,A1 ;set ptr to start of save area RM000 (BSR.S GETDATA ;go get clock reset code (BCS.S CLKERR ;exit if timeout error (CMP.B #$80,D0 ;is it the reset code? (BNE.S RDCLK0 ;skip if no to continue wait (BSR.S GETDATA ;go check if clock data (BCS.S CLKERR (ANDI.B #$F0,D0 ;mask to check if clock flag (CMP.B #$E0,D0 ;clock data? (BNE.S RDCLK0 ;continue wait if no (MOVEQ #5,D1 ;set expected byte count RDCLK1 BSR GETDATA ;go read clock data (BCS.S CLKERR ;exit if error (SUBQ #1,D1 ;else loop until all data received (BNE.S RDCLK1 (ENABLE ;restore interrupt mask (RTS ; Error exit - set indicator and return CLKERR BSET #CLK,D7 (ENABLE ;restore interrupt mask (ORI.B #$01,CCR ;leave carry bit set (RTS (.ENDC (.ENDC (.PAGE ;------------------------------------------------------------------------- ; Scan I/O slots to determine what cards, if any, are installed and save ; id's of installed cards. ;------------------------------------------------------------------------- CONFIG (.IF USERINT = 1 (MOVEA #XCRDSTRT,A1 ;hilite I/O slot test icon (BSR INVICON (.ENDC CONFIG2 MOVEQ #1,D4 ;set flag for status check (BSR.S RDSLOTS ; and go scan the slots (.IF DIAGS = 1 (TST.L D7 ;restart if in loop mode (BMI.S CONFIG2 (.ENDC (BSR CHKXCRD ;mark I/O slots OK (BRA TSTCHK ;exit to check overall results ;------------------------------------------------------------------------- ; Subroutine to scan I/O expansion slots ; Inputs: ; D4 = non-zero if status check to be done, else 0 for no check ; Outputs: ; Saves card id's in locations $298-$29C ; Error bits set in D7 if slot card errors encountered ; Error code saved in location BOOTDATA+1 ; Side Effects: ; A5,A6 trashed ;------------------------------------------------------------------------- RDSLOTS MOVEM.L D1/A1-A3,-(SP) ;save regs (MOVE.L SP,A6 ;save stack ptr (CLR.L D1 ;for result use (MOVEA #IO1ID,A1 ;get ptr to id save area RM000 (MOVE.L #SLOT1L,A2 ;get slot 1 address (MOVE.L BUSVCTR,A5 ;save current bus vector value (LEA NOCRD1,A3 ;init bus error vector (MOVE.L A3,BUSVCTR ; in case no card installed (MOVEP (A2),D1 ;read id for slot 1 (BSR.S CHKID ;go check id (BCC.S SLOT2 ;skip if OK (BSET #IO1ERR,D7 ;else set error indicator (BRA.S SLOT2 ;and continue NOCRD1 CLR (A1)+ ;set id for no card SLOT2 MOVE.L #SLOT2L,A2 ;do same for slot 2 (LEA NOCRD2,A3 (MOVE.L A3,BUSVCTR (MOVEP (A2),D1 ;read and check id (BSR.S CHKID (BCC.S SLOT3 ;skip if OK (BSET #IO2ERR,D7 ;else set error indicator (BRA.S SLOT3 ;and continue NOCRD2 CLR (A1)+ ;set id for no card SLOT3 MOVE.L #SLOT3L,A2 ;and finally for slot 3 (LEA NOCRD3,A3 (MOVE.L A3,BUSVCTR (MOVEP (A2),D1 ;read and check id (BSR.S CHKID (BCC.S CFGEXIT ;skip if OK (BSET #IO3ERR,D7 ;else set error indicator (BRA.S CFGEXIT ;go to exit NOCRD3 CLR (A1)+ ;set id for no card ; Restore default bus error vector and SP and continue CFGEXIT ORI #$0700,SR ;ensure interrupts off (MOVE.L A5,BUSVCTR ;restore from previous saves (MOVE.L A6,SP (MOVEM.L (SP)+,D1/A1-A3 ;and restore regs (RTS ;then exit ;------------------------------------------------------------------------- ; Subroutine to do I/O slot card id check. ; Requires D1 = card id ;------------------------------------------------------------------------- CHKID (CMP #$FFFF,D1 ;check for prototype card (BEQ.S @9 ;skip if not - treat as no card (MOVE D1,(A1)+ ;else save id (BMI.S @7 ;if bootable go do check (BTST #STBIT,D1 ; or do if status routine exists (BEQ.S @8 ;skip if not @7 BSR RDIOSLT ;else go check for good board @8 RTS @9 CLR (A1)+ ;set id for no card (RTS (.PAGE ;------------------------------------------------------------------------- ; Check test results by checking error indicators in reg D7. ; Output greeting message if system contains memory and all is OK. ; Else output appropriate error messages. ;------------------------------------------------------------------------- TSTCHK BSR SAVEREGS ;save regs first (LEA TST2,A3 ;setup bus error vector for type check CHG032 (MOVE.L A3,BUSVCTR ; CHG032 (BSR SETTYPE ;go set system type CHG032 TST2 BSR SETBUSVCT ;restore default bus error vector RM000 (MOVEA #STKBASE,SP ; and default stack (BSR SETVLTCH ;and set video latch CHG020 (.IF USERINT = 0 (BSR CLRSCRN ;clear screen for display (MOVEQ #FIRSTROW,D5 ;set row for display (MOVEQ #FIRSTCOL,D6 ;set col for display (.ELSE (BSR CLRDESK ;clear desktop (.ENDC (MOVE.L D7,D0 ;GET ERROR INDICATORS (ANDI.L #ERRMSK,D0 ;MASK OFF NON-FATAL ERRORS (TST.L D0 ;OK? (BEQ OTHER ;SKIP IF YES (.IF ROM4K = 0 ;--------------------------------------------------------------------------- ; Errors detected - scan D7 for CPU error indicators ;--------------------------------------------------------------------------- (MOVE.L D7,D0 ;get error indicators (ANDI.L #CPUMSK,D0 ;mask off no-CPU errors (TST.L D0 ;any? (BEQ.S EXCHK ;skip if none to check for exception errors (.IF USERINT = 0 (LEA CPUMSG,A3 ;ELSE GET MSG PTR (BSR DSPMSGR ;AND DISPLAY IT (.ELSE (LEA CPUBRD,A2 ;set ptr for CPU board icon (.ENDC ; Check for specific error (.IF DIAGS = 1 (BTST #CPUSEL,D7 ;check for CPU selection error (BEQ.S @1 ;skip if not (MOVEQ #ECPUSEL,D0 ;else get error code (BSR ERRDISP ;display it (BRA VIA2TST ;and loop on parallel port VIA test ; Sound error tones if not selection error (controls path to speaker) @1 BSR LOPTCH ;CPU error causes lo,lo,hi tones (BSR LOPTCH (BSR HIPTCH ; Continue check for specific error (BTST #MMU,D7 ;CHECK IF MMU ERROR (BEQ.S @2 ;SKIP IF NO (MOVEQ #EMMU,D0 ;ELSE GET ERROR CODE (BRA.S @9 ;and go output it @2 (.IF NEWLISA = 1 (.IF ROM16K = 1 (BTST #VID,D7 ;CHECK IF VIDEO ERROR (BEQ.S @3 ;SKIP IF NO (MOVEQ #EVID,D0 ;ELSE GET ERROR CODE (BRA.S @9 ;and go output it @3 MOVEQ #ECPAR,D0 ;else must be parity ckt error (.ENDC ;{ROM16K} (.ENDC ;{NEWLISA} (.ENDC ;{DIAGS} @9 BRA TSTXIT ;go to exit (.ENDC ;{ROM4K} ;---------------------------------------------------------------------------- ; Scan for exception errors ;---------------------------------------------------------------------------- EXCHK MOVE.L D7,D0 ;mask off non-exception errors (ANDI.L #EXMSK,D0 (TST.L D0 ;OK? (BEQ.S IOCHK ;skip if yes to next check (.IF USERINT = 0 (LEA EXCPMSG,A3 ;output general error msg (BSR DSPMSGR (.ELSE ; Sound error tones (BSR LOPTCH ;general logic failure causes lo,hi tones (BSR HIPTCH (LEA LISA,A2 ;set ptr for general LISA error (.ENDC ; Scan for details on exception errors (BTST #CPUINTR,D7 ;NMI? (BEQ.S @1 (MOVEQ #ECPUINTR,D0 ;set error code (BRA.S @9 ;and go display @1 BTST #BUSEXCP,D7 ;bus error? (BEQ.S @2 (MOVEQ #EBUSEXCP,D0 ;set error code (BRA.S @9 @2 BTST #ADREXCP,D7 ;address error? (BEQ.S @3 (MOVEQ #EADREXCP,D0 ;set error code (BRA.S @9 @3 BTST #MISEXCP,D7 ;miscellaneous error? (BEQ.S @4 (MOVEQ #EMISEXCP,D0 ;set error code (BRA.S @9 @4 BTST #ILLEXCP,D7 ;illegal instruction error? (BEQ.S @5 (MOVEQ #EILLEXCP,D0 ;set error code (BRA.S @9 @5 MOVEQ #ETRPEXCP,D0 ;must be a trap error @9 BRA TSTXIT ;and go to exit ;------------------------------------------------------------------------- ; Check for I/O errors ;------------------------------------------------------------------------- IOCHK MOVE.L D7,D0 ;GET ERRORS (ANDI.L #IOMSK,D0 ;MASK OFF NON-IO ERRORS (TST.L D0 ;OK? (BEQ KBDCHK ;SKIP IF YES TO NEXT CHECK (.IF USERINT = 0 (LEA IOMSG,A3 ;GET I/O ERROR MSG (BSR DSPMSGR ;OUTPUT IT (.ELSE (LEA IOBRD,A2 ;set ptr for I/O board icon (.ENDC (.IF ROM4K = 0 ; Scan for details on I/O errors (.IF ROM16K = 1 (BTST #VIA1,D7 ;check for keyboard VIA errors (BEQ.S @1 ;skip if OK (MOVEQ #EVIA1,D0 ;else set error code (BSR.S ERRDISP ;display the error (BRA VIA1CHK ;and loop on VIA #1 test ; Sound error tones if not VIA #1 error (controls the speaker) @1 BSR LOPTCH ;I/O errors cause lo,hi,lo tones (BSR HIPTCH (BSR LOPTCH ; Continue scan for detailed errors (BTST #VIA2,D7 ;parallel port VIA error? (BEQ.S @2 (MOVEQ #EVIA2,D0 ;set error code (BRA.S @19 (.ENDC @2 BTST #IOCOPS,D7 (BEQ.S @3 (MOVEQ #EIOCOP,D0 ;get error code (BSR.S ERRDISP ;display error (BRA COPSENBL ;and go do loop on COPS test @3 (.IF DIAGS = 1 (BTST #CLK,D7 (BEQ.S @4 (MOVEQ #ECLK,D0 ;ELSE GET ERROR CODE (BRA.S @19 (.ENDC @4 (.IF FULLSCC = 1 (BTST #RS232A,D7 (BEQ.S @6 (MOVEQ #ERS232A,D0 ;ELSE GET ERROR CODE (BRA.S @19 @6 BTST #RS232B,D7 (BEQ.S @7 (MOVEQ #ERS232B,D0 ;ELSE GET ERROR CODE (BRA.S @19 (.ENDC @7 BTST #DISK,D7 (BEQ.S @8 (MOVEQ #EDISK,D0 ;ELSE GET ERROR CODE (BRA.S @19 @8 BTST #IOEXCP,D7 (BEQ.S @9 (MOVEQ #EIOEXCP,D0 ;ELSE GET ERROR CODE (BRA.S @19 @9 BTST #IOCOPS2,D7 ;COPS code error? (BEQ.S @10 (MOVEQ #EIOCOP2,D0 ;get error code (BRA.S @19 @10 BTST #IOKBD,D7 ;I/O or keyboard error? (BEQ.S @19 (MOVEQ #EIOKBD,D0 ;get error code (.ENDC ;{ROM4K} @19 BRA TSTXIT ;-------------------------------------------------------------------------- ; Subroutine to do display for fatal errors ;-------------------------------------------------------------------------- ERRDISP (.IF USERINT = 1 (BSR DSPERRICON ;display error (.ENDC (BSR DSPCODE ;output error code (BSET #LOOP,D7 ;set for looping operation (RTS ;-------------------------------------------------------------------------- ; Check for keyboard error ;-------------------------------------------------------------------------- KBDCHK BTST #KBDCOPS,D7 ;Keyboard error? (BEQ.S MEMCHK ;skip to next check if not (.IF USERINT = 1 ; Sound error tones (BSR HIPTCH ;Keyboard error causes hi,lo,hi tones (BSR LOPTCH (BSR HIPTCH (LEA KEYBDOUT,A2 ;set ptr for keyboard icon (.ENDC (MOVEQ #EKBDCOP,D0 ;set error code (BRA TSTXIT ;and go to exit ;-------------------------------------------------------------------------- ; Check for memory errors ;-------------------------------------------------------------------------- MEMCHK (MOVE.L D7,D0 ;GET ERRORS (ANDI.L #MEMMSK,D0 ;MASK OFF NON-memory ERRORS (TST.L D0 ;any errors? (BEQ IOSCHK ;skip if no - must be I/O slot error (.IF USERINT = 0 (LEA RAMMSG,A3 ;ELSE GET RAM ERROR MSG (BSR DSPMSGR (.ELSE ; Sound memory error tones (BSR LOPTCH ;memory error causes lo,hi,hi tones (BSR HIPTCH (BSR HIPTCH ; determine which memory card in error if more than one (CMPI.L #HEX512K,TOTLMEM ;more than 1 memory card? (BGT.S SCNRSLTS ;skip if yes ; only one card - check memory addresses to determine slot (MOVE.L MINMEM,D0 ;get low physical address CHKMADR CMPI.L #ONEMEG,D0 ;address in slot 1? (BLT.S @2 ;skip if not (MOVEQ #1,D1 ;set board id for slot 1 (BRA.S @3 @2 MOVEQ #2,D1 ;set board id for slot 2 @3 BRA.S MERRCHK ;and go scan for details ; more than one memory card - scan memory test results to determine which card SCNRSLTS (BTST #MPAR,D7 ;parity error? (BEQ.S @1 ;skip if not (MOVE.L PEADDR,D0 ;go get error address CHG015 (BRA.S CHKMADR ;and check it ; Check for R/W error @1 MOVEA #MEMRSLT,A0 ;set ptr to OR masks RM000 (MOVEQ #8,D0 ;and set counter @4 TST (A0)+ ;check the rows (BNE.S @5 ;skip if error detected (SUBQ #1,D0 ;else check all masks (BNE.S @4 ;until done @5 CMP.B #4,D0 ;check where error found (BGT.S @6 ;skip if low memory error (MOVEQ #1,D1 ;high memory on card 1 (BRA.S MERRCHK @6 MOVEQ #2,D1 ;low memory on card 2 (.ENDC ;{USERINT} (.IF ROM4K = 0 ; scan for error details MERRCHK BTST #MEM,D7 ;check for main memory R/W error (BEQ.S @2 ;exit if not (MOVEQ #EMEM,D0 ;else display error code (MOVE.B D1,MEMSLOT ;save slot # for board in error (BRA.S MEMERR @2 MOVEQ #EPAR,D0 ;must be parity error (.ENDC ;{ROM4K} MEMERR (.IF USERINT = 1 (MOVE.L D7,STATUS ;save power-up status (LEA MEMBRD,A2 ;set ptr for memory board icon (BSR DSPNUMICON ;display icon and board slot # (BRA.S TSTXIT2 ;finally exit to monitor (.ELSE (BRA.S TSTXIT (.ENDC ;{USERINT} ;-------------------------------------------------------------------------- ; Must be I/O slot errors ;-------------------------------------------------------------------------- IOSCHK (.IF ROM4K = 0 (.IF USERINT = 0 (LEA IOSMSG,A3 ;ELSE GET RAM ERROR MSG (BSR DSPMSGR (.ELSE ; Sound error tones (BSR HIPTCH ;I/O slot error causes hi,lo,lo tones (BSR LOPTCH (BSR LOPTCH (LEA Xcard,A2 ;set ptr for I/O slot board icon (.ENDC @1 BTST #IO3ERR,D7 ;check for slot 3 error (BEQ.S @2 ;exit if not (MOVEQ #3,D1 ;else set slot # (BRA.S @4 @2 BTST #IO2ERR,D7 ;slot 2 error? (BEQ.S @3 (MOVEQ #2,D1 ;set slot # (BRA.S @4 @3 MOVEQ #1,D1 ;must be slot 1 error @4 MOVE.B BOOTDATA,D0 ;get error code (BSR DSPNUMICON ;display error icon and slot # (BRA.S TSTXIT2 ;and exit to monitor (.ENDC ;{ROM4K} TSTXIT (.IF USERINT = 0 (MOVE.L D7,STATUS ;save status (BSR DSPCODE ;display error code (BRA MONITOR ;exit to monitor (.ELSE (BSR DSPERRICON ;display error icon TSTXIT2 (MOVE.L D7,STATUS ;save status (BSR DSPCODE ;display the error code ; Save error data in special parameter memory area, then exit to monitor ;**************************** ; Delete for LISA 2 CHG034 ;**************************** ; LEA PMVCT,A3 ;setup bus error vector for PM RM013 ; MOVE.L A3,BUSVCTR ; RM013 ; BSR.S CHKSTATPM ;check if error already saved ; BCC.S GOTOMON ;skip if yes ; MOVEA.L #STATSTRT,A0 ;set starting ptr ; MOVE.B D0,(A0) ;save error code ; MOVE ADRLTCH,D0 ;save error address latch contents ; MOVEP D0,2(A0) ; MOVE.B MEMSLOT,6(A0) ;save memory slot # ; MOVE.L CLKDATA,D0 ;save clock data ; MOVEP.L D0,8(A0) ; MOVE CLKDATA+4,D0 ; MOVEP D0,16(A0) ; CLR.L D0 ;clear remaining area ; MOVEP.L D0,20(A0) ; MOVEQ #STATWRDS-2,D0 ;validate save area ; BSR WRTSUM GOTOMON BSR SCANCPS ;clear COPS queue (BSR CPSINIT ;reinit interface (BSR CURSORINIT ;init cursor and mouse (BRA MONITOR ;then jump to monitor ;------------------------------------------------------------------------- ; Parameter memory bus error handler RM013 ;------------------------------------------------------------------------- PMVCT MOVEA #STKBASE,SP ;reset stack RM013 (BSR SETBUSVCT ;restore bus error vector RM013 (BRA.S GOTOMON ;and exit to monitor RM013 ;------------------------------------------------------------------------- ; Subroutine to check special parameter memory validity. ; Verify checksum routine sets carry bit if checksum not valid. ;------------------------------------------------------------------------- ;CHKSTATPM CHG034 ; MOVEM.L D0-D1/A0,-(SP) ;save regs ; MOVEA.L #STATSTRT,A0 ;set starting ptr ; MOVEQ #STATWRDS-1,D0 ;and # of words to check ; MOVE D0,D1 ;set for shared memory ; BSR VFYCHKSM ;and go do checksum ;@1 MOVEM.L (SP)+,D0-D1/A0 ;restore regs ; RTS (.ENDC ;------------------------------------------------------------------------ ; Scan for non-fatal errors ;------------------------------------------------------------------------ OTHER (.IF ROM16K = 1 (MOVE.L D7,D0 ;get errors (ANDI.L #OTHRMSK,D0 ;isolate to non-fatal errors (TST.L D0 ;OK? (BEQ.S @9 ;skip if no errors (BTST #KBDOUT,D7 ;Keyboard disconnected? (BEQ.S @1 ;skip if no (.IF USERINT = 0 (LEA KBDMSG,A3 ;else output message (BSR DSPMSGR (.ELSE (LEA KEYBDOUT,A2 ;display keyboard icon (BRA.S @2 ;with question mark (.ENDC @1 ;must be mouse (.IF USERINT = 0 (LEA MOUSMSG,A3 ;else output message (BSR DSPMSGR (.ELSE (BSR CHKPM ;check parameter memory before notify @; of mouse disconnect (BCS.S @8 ;ignore error if invalid (BTST #MOUSEON,MEMCODE ;check if should be installed (BEQ.S @8 ;skip if not (LEA MOUSEOUT,A2 ;else display mouse icon @2 BSR DSPQICON ;with question mark (.ENDC (BRA NOTIFY ;alert user (.ENDC ;{ROM16K} @8 BCLR #MOUSOUT,D7 ;ignore mouse disconnected error @9 BRA SYSOK ;system must be OK (.PAGE ;------------------------------------------------------------------------- ; Subroutine to output error code ;------------------------------------------------------------------------- DSPCODE MOVEM.L D0-D3,-(SP) ;save regs (.IF USERINT = 0 (LEA ERRMSG,A3 ;get msg ptr (BSR DSPMSG (.ENDC (.IF NEWTWIG = 0 (MOVEQ #2,D1 ;# of digits to display (.ENDC (.IF USERINT = 1 (MOVE #CODEROW,D5 ;set screen ptrs for display (MOVE #CODECOL,D6 (.ENDC (BRA.S GETDIG ;go do display (.IF NEWTWIG = 1 ; Translate up to 4 digit hex error code to decimal ; Second entry point for routine DSPDEC (MOVEM.L D0-D3,-(SP) ;save regs GETDIG ANDI.L #$0FFFF,D0 ;clear other digits (MOVEQ #1,D1 ;display 1 char at a time (TST D0 ;is it 0? (BEQ.S @9 ;exit if yes to display it (CLR.L D2 ;clear working regs (CLR.L D3 ; display all non-zero digits @1 DIVU #$A,D0 ;converting to decimal (SWAP D0 ;get remainder (MOVE.B D0,D2 ;save for display (ROR.L #4,D2 (ADDQ #1,D3 ;set count (CLR D0 ;clear remainder (SWAP D0 ;get new quotient (TST D0 ;quit when =0 (BEQ.S @2 ;skip to do display (BRA.S @1 @2 ROL.L #4,D2 ;get char for output (MOVE.B D2,D0 (SUBQ #1,D3 ;decr digit count (BEQ.S @9 ;skip to display last digit (BSR.S OUTCH ;display a digit (BRA.S @2 ;and loop until done (.ENDC @9 BSR.S OUTCHR ;do output and CR DSPCXIT MOVEM.L (SP)+,D0-D3 ;restore regs (RTS ;and return ;------------------------------------------------------------------------- ; Subroutine to invoke code display routine, then do CR ;------------------------------------------------------------------------- OUTCHR BSR.S OUTCH ;output digits (.IF USERINT = 0 (ADDQ #1,D5 ;bump to next char row (.ELSE (ADD #CHRSPC,D5 ;bump to next char row (.ENDC (MOVEQ #1,D6 ;and do CR (RTS (.PAGE ;------------------------------------------------------------------------- ; Subroutines to enable display of hex codes ; Requires D0 = value to display ; D1 = # of digits to display ;------------------------------------------------------------------------- OUTCH MOVEM.L D0-D2,-(SP) ;save regs (MOVEQ #8,D2 ;set max digits to display @1 CMP.B D1,D2 ;check digits desired (BEQ.S @2 ;and skip if match (ROL.L #4,D0 ;else skip over digit (SUBQ #1,D2 ;update count (BRA.S @1 ;and loop until match @2 ROL.L #4,D0 ;rotate to next digit (BSR.S OUTNIB ;go output one digit (SUBQ #1,D1 ;decr count (BNE.S @2 ;loop until done (MOVEM.L (SP)+,D0-D2 ;restore and exit (RTS ; The following routine does conversion to ASCII to enable display OUTNIB MOVE.L D0,-(SP) ;SAVE REG (ANDI #$000F,D0 ;ISOLATE DIGIT TO DISPLAY (CMPI.B #9,D0 ;CHECK IF NUMERIC (BHI.S ALPHA ;SKIP IF NOT (ORI.B #$30,D0 ;CONVERT TO ASCII (BRA.S DSPCH ;AND GO DISPLAY ALPHA SUBI.B #9,D0 ;CONVERT FOR (ORI.B #$40,D0 ; ASCII DSPCH BSR DSPVAL ;OUTPUT IT (MOVE.L (SP)+,D0 ;RESTORE REG (RTS (.PAGE ;------------------------------------------------------------------------- ; Routine to notify user of non-fatal error. Beep speaker and pause ; for 5 seconds. ;------------------------------------------------------------------------- NOTIFY (.IF ROM16K = 1 (BSR.S HIPTCH ;beep at high pitch twice (BSR.S HIPTCH (BSR.S LOPTCH ;beep at low pitch (BSR DELAY5 ;delay 5 seconds (BSR CLRDESK ;clear desktop CHG033 (BRA.S DOBOOT ;then go attempt boot ;------------------------------------------------------------------------- ; Subroutine to beep speaker at high pitch ;------------------------------------------------------------------------- HIPTCH MOVEQ #$20,D0 ; set frequency (BRA.S SETDUR ; and go do it ;------------------------------------------------------------------------- ; Subroutine to beep speaker at low pitch ;------------------------------------------------------------------------- LOPTCH MOVEQ #$60,D0 ; set frequency SETDUR MOVE #250,D1 ; 1/8 sec duration (MOVEQ #4,D2 ; low volume (BSR TONE ; and go do it (BSR DELAY_1 ; delay for .1 sec (RTS (.ENDC (.PAGE ;------------------------------------------------------------------------- ; No errors detected - output greeting message ;------------------------------------------------------------------------- SYSOK CLR.L STATUS ;set status (.IF ROM16K = 1 ; """""""""" " " " " """"""""""""";O? NOMPNQORPSQTRUSVT WU XV YW ZX [Y\Z][^\_]`^a_b`cadbecfdgehfigjhkiljmk nl!om"pn#qo$rp%sq&tr'us(vt)wu*xv+yw,zx-{y.|z/}{0~|1}2~3456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~O       !" #!$"%#&$'%(&)'*(+),*-+.,/- 0.!1/"20#31$42%53&64'75(86)97*:8+;9,<:-=;.></?=0@>1A?2B@3CA4DB5EC6FD7GE8HF9IG:JH;KINL?OM@PNAQOBRPCSQDTREUSFVTGWUHXVIYWJZXK[YL\ZM][N^\O_]P`^Qa_Rb`ScaTdbUecVfdWgeXhfYigZjh[ki\lj]mk^nl_om`pnaqobrpcsqdtreusfvtgwuhxviywjzxk{yl|zm}{n~|o}p~qrstuvwxyz{|}~ÁāŁƁǁȁɁʁˁ́́΁ρЁсҁӁԁՁցׇ      ! " #  $  %  & ' ()*+,-./012345678 9!:" ;#!<$"=%#>&$?'%@(&A)'B*(C+)D,*E-+F.,G/-H0.I1/J20K31L42M53N64O75P86Q97R:8S;9T<:U=;V><W?=X@>YA?ZB@[CA\DB]EC^FD_GE`HFaIGbJHcKIdLJeMKfNLgOMhPNiQOjRPkSQlTRmUSnVToWUpXVqYWrZXs[Yt\Zu][v^\w_]x`^ya_zb`{ca|db}ec~fdgehfigjhkiljmknlmpqorpsqtrusvtwuxv yw zx {y |z }{~|}~ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~