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