* SK*DOS BIOS FOR THE PT-68K-4 COMPUTER * USING THE WD1002-WX1 HARD DISK CONTROLLER * (C) 1986 BY PETER A. STARK FOR STAR-K SOFTWARE SYSTEMS CORP * REVISED 2-13-2000 FOR Y2K COMPATIBILITY * REVISED 7-13-90 FOR 37C65 CONTROLLER ON PT68K-4 * REVISED 7-3-90 FOR PT-68K-4 TO PERMIT 16 MHZ OPERATION * REVISED 8-20-88 FOR NRETRY, FOTHER >>A<< * REVISED 8-19-88 TO ADD PRINT-SCREEN * REVISED 4-4-88 TO FIX GETDT * REVISED 12-8-87 TO FIX BOOT DELAY, BOOT ERROR IF NO WX1 EXISTS, * REVISED 10-4-87 FOR I/O CONTROL * REVISED 9-30-87 FOR WX1 CONTROLLER * REVISED 6-30-87 FOR NEW PT-2 HUMBUG * REVISED 6-23-87 TO FIX PT-2 CLOCK ADDRESS * REVISED 6-12-87 FOR PT-68K-2 68000 COMPUTER * REVISED 4-19-87 FOR PT-68K-1A 68008 COMPUTER * REVISED 3-15-87 TO USE BIOS JUMP VECTORS AT 10B0, 10B6 * REVISED 2-23-87 TO ADD GET DATE AND TIME FUNCTION * REVISED 1-16-87 TO MODIFY INPUT STATUS AND ADD OUTPUT STATUS * REVISED 11-09-86 TO CHANGE CLOCK FROM BCD TO BINARY * REVISED 10-24-86 BY ADDING WINCHESTER DRIVERS * REVISED 10-10-86 BY CHANGING ADDRESSES OF STPRAT, DRUSED, * AND VERFLG, CHANGING FUNCTION OF DRUSED, AND CHANGING DRIVE * DRIVE NUMBER TEST TO USE PHYSICAL RATHER THAN LOGICAL DRIVE * EXTERNAL REFERENCES - MOST OF THESE ARE REFERENCED TO 'DOSORG', * WHICH IS THE BEGINNING POINT OF SK*DOS. * FOR EXAMPLE, A TYPICAL SK*DOS BEGINS AT $1000, SO DOSORG IS * SET TO $1000 BELOW. MAKE SURE TO MODIFY DOSORG AS NECESSARY. ****** CAUTION - THE NEXT ADDRESSES MAY CHANGE!!!! **** LVL5IA EQU $2F4A LEVEL 5 VECTOR PUTCD5 EQU $4AB0 PUTCHR INTERNAL ******************************************************* DOSORG EQU $1000 BEGINNING LOCATION OF SK*DOS WINTAB EQU DOSORG+$200 WINCHESTER DATA TABLE VRBLES EQU DOSORG+$400 BEGINNING OF SK*DOS VARIABLE AREA GETDAT EQU DOSORG+$00C VECTOR TO GET THE DATE INTIME EQU DOSORG+$012 VECTOR TO GET THE TIME CDAY EQU VRBLES+751 Current date - day CMONTH EQU VRBLES+750 Current date - month CYEAR EQU VRBLES+752 Current date - year BREAK EQU VRBLES+762 BREAK ADDRESS DICOLD EQU DOSORG+$100 DISK COLD-START INIT DIWARM EQU DOSORG+$106 DISK WARM-START INIT DIREAD EQU DOSORG+$10C DISK READ DIWRIT EQU DOSORG+$112 DISK WRITE DICHEK EQU DOSORG+$118 DISK READY CHECK DIMOFF EQU DOSORG+$11E TURN OFF DISK MOTOR DIREST EQU DOSORG+$124 PRIMARY DISK RESTORE DISEEK EQU DOSORG+$12A PRIMARY DISK SEEK ERRTYP EQU VRBLES+782 ERROR TYPE INDOS EQU VRBLES+794 0=OUTSIDE DOS, ELSE IN DOS INECHO EQU VRBLES+800 INPUT ECHO FLAG DEVOUT EQU VRBLES+3275 OUTPUT DEVICE NUMBER STPRAT EQU DOSORG+$130 STEPRATES FOR THREE DRIVES VERFLG EQU DOSORG+$13A VERIFY FLAG DRUSED EQU DOSORG+$13C DRIVE USED TABLE NRETRY EQU DOSORG+$150 FLOPPY RETRY COUNTER FOTHER EQU DOSORG+$151 =0 IF SK*DOS, ELSE # SECT/SIDE NUMBHD EQU DOSORG+$152 NUMBER OF HARD DRIVES SINITV EQU DOSORG+$180 SERIAL PORT INIT STATVE EQU DOSORG+$186 SERIAL PORT STATUS CHECK STATV1 EQU DOSORG+$1D4 INPUT STATUS CHECK W/O TYPEAHEAD OUTCHV EQU DOSORG+$18C OUTPUT TO PORT OFFINI EQU DOSORG+$018 INITIAL OFFSET VALUE INCHV EQU DOSORG+$192 INPUT FROM KBD WITH ECHO KINPUV EQU DOSORG+$198 INPUT W/O ECHO KINPV1 EQU DOSORG+$1DA INPUT W/O ECHO W/O TYPEAHEAD ICNTRL EQU DOSORG+$1A4 INPUT CONTROL MONITV EQU DOSORG+$1AA RETURN TO MONITOR RESETV EQU DOSORG+$1B0 RESET MONITOR/SYSTEM TIMINI EQU DOSORG+$1B6 TIMER INITIALIZE TIMOFF EQU DOSORG+$1BC TIMER OFF TIMON EQU DOSORG+$1C2 TIMER ON OSTATV EQU DOSORG+$1C8 OUTPUT STATUS VECTOR GETDTV EQU DOSORG+$1CE GET DATE AND TIME VECTOR KILLV1 EQU DOSORG+$1E0 FLUSH TYPEAHEAD BUFFER PSTRNV EQU DOSORG+$B6 PRINT STRING VECTOR ASKDAV EQU DOSORG+$B0 ASK FOR DATE VECTOR * SK*DOS FCB EQUATES FCBPHY EQU 72 Physical drive number FCBDAT EQU 96 Beginning of data buffer (256 bytes) FCBCSE EQU 35 Current sector in buffer FCBCTR EQU 34 Current track in buffer FCBDRV EQU 3 Logical Drive number FCBERR EQU 1 Error code * HUMBUG EQUATES FL0C EQU $00FF0BE9 CONTROLLER TYPE FOR DRIVE F0 FL0D EQU $00FF0BEB F NUMBER AND DRIVE TYPE, PACKED * THE FOLLOWING ORG POINT DEPENDENT ON TOP OF SK*DOS. BEFORE * ASSEMBLING, DO A LOCATE ON SK*DOS.COR TO CHECK THE TOP * ADDRESS, AND THEN MAKE ORG HIGHER THAN THAT * THIS ORG DEPENDS ON THE LAST ADDRESS OF SK*DOS.COR ORG $6300 *************************************** **** --- PART 1 - DISK DRIVERS --- **** *************************************** * CAUTION - THESE DRIVERS MUST PRESERVE ALL REGISTERS!!! **************************************** **** --- PART 1A - DRIVER SELECT -- **** **************************************** * THIS PART SELECTS EITHER THE FLOPPY DRIVERS OR HARD DRIVERS ************************ *** READ ENTRY POINT *** ************************ * THIS IS ESSENTIALLY SREAD OPERATION * ENTER: A4 POINTS TO FCB WHICH NEEDS DATA. * FCBPHY(A4) HAS PHYSICAL DRIVE NUMBER * FCBCTR(A4) HAS TRACK NUMBER * FCBCSE(A4) HAS SECTOR NUMBER * EXIT: ZERO IF NO ERROR; * IF ERROR: NON-ZERO, * FCBERR(A4) AND ERRTYP BOTH HAVE ERROR CODE * ALL REGISTERS RESTORED! PRIMRD MOVEM.L D0-D7/A1-A6,-(A7) MOVE.B FCBPHY(A4),D7 CHECK PHYSICAL DRIVE NUMBER BTST #4,D7 FLOPPY? BNE.S FLOPRD YES BTST #5,D7 WINCHESTER? BNE.L HARDRD YES MOVE.B #15,D6 NEITHER, ERROR 15 BRA.L RWERR4 AND QUIT * ON FLOPPY, DECIDE WHETHER TO USE 1772 OR 37C65 CONTROLLER FLOPRD AND.L #$0F,D7 RETRIEVE F NUMBER LSL.B #2,D7 X4 LEA FL0D,A6 POINT TO FIRST ENTRY ADD.L D7,A6 POINT TO THIS ENTRY MOVE.B -2(A6),D6 CMP.B #$37,D6 IS IT 37C65? BEQ.L RD3765 YES * IF WE GO TO 37C65 ROUTINE, A6 POINTS TO FLXD CMP.B #$17,D6 IS IT 1772? BEQ.L RD1772 YES * IF IT IS NOT SET, THEN DEFAULT TO 1772 AND SET SRAM MOVE.B #$17,-2(A6) SET TO 1772 LSL.B #2,D7 F NUMBER IN LEFT NYBBLE MOVE.B D7,(A6) BRA.S RD1772 ************************* *** WRITE ENTRY POINT *** ************************* * THIS IS ESSENTIALLY SWRITE OPERATION * ENTER: A4 POINTS TO FCB WHICH NEEDS DATA. * FCBPHY(A4) HAS PHYSICAL DRIVE NUMBER (F NUMBER) * FCBCTR(A4) HAS TRACK NUMBER * FCBCSE(A4) HAS SECTOR NUMBER * EXIT: ZERO IF NO ERROR; * IF ERROR: NON-ZERO, * FCBERR(A4) AND ERRTYP BOTH HAVE ERROR CODE * ALL REGISTERS RESTORED! PRIMWR MOVEM.L D0-D7/A1-A6,-(A7) MOVE.B FCBPHY(A4),D7 CHECK PHYSICAL DRIVE NUMBER BTST #4,D7 FLOPPY? BNE.S FLOPWR YES BTST #5,D7 WINCHESTER? BNE.L HARDWR YES MOVE.B #15,D6 NEITHER, ERROR 15 BRA.L RWERR4 AND QUIT FLOPWR AND.L #$0F,D7 RETRIEVE F NUMBER LSL.B #2,D7 X4 LEA FL0D,A6 POINT TO FIRST ENTRY ADD.L D7,A6 POINT TO THIS ENTRY MOVE.B -2(A6),D6 CMP.B #$37,D6 IS IT 37C65? BEQ.L WR3765 YES * IF WE GO TO 37C65 ROUTINE, A6 POINTS TO FLXD CMP.B #$17,D6 IS IT 1772? BEQ.L WR1772 YES * IF IT IS NOT SET, THEN IT'S AN ERROR 15 ON WRITING MOVE.B #15,D6 ERROR 15 BRA.L RWERR4 QUIT **************************************************** **** --- PART 1B - 1772 FLOPPY DISK DRIVERS --- **** **************************************************** * EQUATES DLATCH EQU $FE00C1 * EXPLANATION OF DLATCH OPERATION: * BITS 0 & 1 SELECT DRIVES 0 - 4 * BITS 2-4 UNUSED * BIT 5 SELECTS DENSITY (1 = DD) * BIT 6 SELECTS SIDE (0 = SIDE A) * BIT 7 - NOT USED * * SIDE SELECTION IS HANDLED THROUGH SSO OF 2797 CONTROLLER * * THE 1772 IS SLIGHTLY DIFFERENT FROM 2790-SERIES FDC'S, * PARTICULARLY IN COMMAND REG BIT 3 (WHICH IS USUALLY 1 IN * THE 2790 SERIES, 0 IN THE 1772), AND IN STATUS REGISTER * BIT 7 (WHICH IS 'NOT READY' AND SHOULD BE TESTED IN THE 279X, * BUT WHICH MEANS MOTOR IS ON AND SHOULD NOT BE TESTED IN 1772) COMREG EQU $FE0101 STAREG EQU COMREG TRKREG EQU COMREG+2 SECREG EQU COMREG+4 DATREG EQU COMREG+6 ********************************************* * 1772 READ ROUTINE ********************************************* RD1772 MOVE.B NRETRY,D3 RETRY COUNTER >>A<< JSR DDRIVE SELECT DRIVE AND MOTOR ON BNE.L RWERR4 IF DRIVE NUMBER ERROR PRLOOP JSR DSEEK SEEK TO TRACK BNE.S RDAGIN REPEAT READ IF ERROR JSR DREAD GO TRY TO READ BEQ.L RWEXIT EXIT NORMALLY IF NO ERROR RDAGIN SUB.B #1,D3 DECR RETRY COUNTER BEQ.S RDERR1 GIVE UP AND QUIT IF 0 MOVE.B FCBPHY(A4),D7 CHECK PHYSICAL DRIVE NUMBER AND.L #$0F,D7 RETRIEVE F NUMBER LSL.B #2,D7 X4 LEA FL0D,A6 POINT TO FIRST ENTRY ADD.L D7,A6 POINT TO THIS ENTRY JSR DR1772 RESTORE DISK BRA.S PRLOOP AND TRY AGAIN ********************************************* * 1772 WRITE ROUTINE ********************************************* WR1772 MOVE.B NRETRY,D3 RETRY COUNTER >>A<< JSR DDRIVE SELECT DRIVE AND MOTOR ON BNE.S RWERR4 IF DRIVE NUMBER ERROR PWLOOP JSR DSEEK SEEK TO TRACK BNE.S WRAGIN REPEAT WRITE IF ERROR JSR DWRITE GO TRY TO WRITE BNE.S WRAGIN IF ERROR TST.B VERFLG VERIFY? BEQ.S RWEXIT NO, SO JUST QUIT JSR DVERIF YES, GO VERIFY SECTOR BEQ.S RWEXIT EXIT NORMALLY IF NO ERROR WRAGIN BTST.B #6,D6 WRITE PROTECT? BNE.S WRERR1 YES, IMMED PROCESS ERROR SUB.B #1,D3 DECR RETRY COUNTER BEQ.S WRERR1 GIVE UP AND QUIT IF 0 MOVE.B FCBPHY(A4),D7 CHECK PHYSICAL DRIVE NUMBER AND.L #$0F,D7 RETRIEVE F NUMBER LSL.B #2,D7 X4 LEA FL0D,A6 POINT TO FIRST ENTRY ADD.L D7,A6 POINT TO THIS ENTRY JSR DR1772 RESTORE DISK, IGNORE ERR BRA.S PWLOOP AND TRY AGAIN ******************************************************** * ERROR PROCESSING FOR BOTH FLOPPY READ AND WRITE - 1772 ******************************************************** * TRANSLATE INTO SK*DOS ERROR CODES AND * STORE IN FCB RDERR1 MOVE.B STAREG,D6 GET FDC ERROR AND.B #$7F,D6 GET RID OF 1772 MOTOR ON BIT*** LEA RDETAB,A6 POINT TO READ ERROR CODE TABLE BRA.S RWERR2 WRERR1 MOVE.B STAREG,D6 GET FDC ERROR AND.B #$7F,D6 GET RID OF 1772 MOTOR ON BIT*** LEA WRETAB,A6 POINT TO WRITE ERROR CODE TABLE RWERR2 ASL.B #1,D6 SHIFT ERROR CODE LEFT BCS.S RWERR3 GOT ERROR BIT IN CARRY LEA 1(A6),A6 POINT TO NEXT ERROR CODE BRA.S RWERR2 AND LOOK AT NEXT BIT RWERR3 MOVE.B (A6),D6 GET ERROR CODE RWERR4 MOVE.B D6,FCBERR(A4) PUT INTO FCB MOVE.B D6,ERRTYP RWEXIT MOVEM.L (A7)+,D0-D7/A1-A6 RTS RDETAB DC.B 16 BIT 7 = DISK NOT READY DC.B 9 BIT 6 = UNKNOWN ERROR DC.B 9 BIT 5 = RECORD TYPE DC.B 14 BIT 4 = SEEK ERROR DC.B 9 BIT 3 = CRC ERROR DC.B 9 BIT 2 = LOST DATA DC.B 16 NOT READY DC.B 31 VERIFY ERROR WRETAB DC.B 16 BIT 7 = DISK NOT READY DC.B 11 BIT 6 = WRITE PROTECT DC.B 10 BIT 5 = WRITE ERROR DC.B 14 BIT 4 = SEEK ERROR DC.B 9 BIT 3 = CRC ERROR DC.B 9 BIT 2 = LOST DATA DC.B 16 NOT READY DC.B 31 VERIFY ERROR ********************************************************* * DDRIVE - SELECT DRIVE SPECIFIED BY FCBPHY AND FLxD, AND * TURN MOTOR ON - 1772 ONLY ********************************************************* * * CALLED BY: PRIMWR AND PRIMRD * INPUT: A4 POINTS TO FCB, A6 POINTS TO FLxD ENTRY * OUTPUT: RETURN ZERO IF NO ERROR; * NONZERO AND ERROR 15 IN D6 IF BAD DR NUM * REGISTERS USED: D5, D6, A5, A6 DDRIVE MOVE.B (A6),D5 PICK UP PHYS# & DR TYPE LSR.B #4,D5 KEEP PHYS DR NUM ON CTRLR CLR.L D6 MOVE.B DRIVNO,D6 GET OLD DRIVE NUMBER CMP.B D5,D6 SAME DRIVE NUMBER? BEQ.S SAMEDR YES LEA TRTABL,A6 POINT TO DRIVE DATA TABLE MOVE.B TRKREG,0(A6,D6.L) SAVE LAST TRACK IN TABLE MOVE.B D5,DRIVNO NEW DRIVE NUMBER MOVE.B 0(A6,D5.L),TRKREG GIVE NEW TRACK TO FDC SAMEDR MOVE.B D5,D6 DRIVE NUMBER AND.B #3,D6 DR NUM IS BIT 0-1 JSR SIDENS COMBINE DENSITY AND SIDE CMP.B MLATCH,D6 CHECK IF ALREADY IN DLATCH BEQ.S NOD1 DON'T SEND IF YES MOVE.B D6,DLATCH SELECT DRIVE, DENSITY, SIDE NOD1 MOVE.B D6,MLATCH SAVE NEW LATCH STATUS CLR.L D6 0 MEANS THERE WAS NO ERROR AND.B #$FE,CCR CLEAR CARRY RTS DRIVNG MOVE.B #15,D6 ERROR 15 - DRIVE NUM NG OR.B #$01,CCR SET CARRY RTS RETURN ON ERROR *************************************************************** * RESTORE - SELECT DRIVE SPEC BY FCB AND RESTORE IT TO 0 - 1772 *************************************************************** * * CALLED BY: DIREST ENTRY POINT FROM DOS, AND ALSO * PRIMWR AND PRIMRD (WHICH BYPASS BEGINNING TEST) * INPUT: A4 POINTS TO FCB, * OUTPUT: RETURN ZERO IF NO ERROR; * NONZERO AND ERROR IN D6 IF BAD DR NUM * REGISTERS USED: D5, D6, A6 DREST MOVE.B FCBPHY(A4),D7 CHECK PHYSICAL DRIVE NUMBER BTST #4,D7 FLOPPY? BNE.S FLOPDR YES TEMP MOVE.B #15,D6 NEITHER, ERROR 15 MOVE.B D6,FCBERR(A4) RTS AND QUIT * ON FLOPPY, DECIDE WHETHER TO USE 1772 OR 37C65 CONTROLLER FLOPDR AND.L #$0F,D7 RETRIEVE F NUMBER LSL.B #2,D7 X4 LEA FL0D,A6 POINT TO FIRST ENTRY ADD.L D7,A6 POINT TO THIS ENTRY MOVE.B -2(A6),D6 CMP.B #$37,D6 IS IT 37C65? BEQ.S TEMP TEMPORARY ****++++-=-= * FOR 1772, JUST DROP THROUGH; ELSE * IF WE GO TO 37C65 ROUTINE, A6 POINTS TO FLXD DR1772 CLR.B TRKREG SO DDRIVE STORES 0 IN TABLE BSR.L DDRIVE SELECT DRIVE BNE.S RTS ON ERROR MOVE.B #$00,D6 USE 08 FOR OTHER FDC'S OR.B STPRAT,D6 PLUS STEP RATE BITS MOVE.B D6,COMREG RESTORE, LOAD HEAD, SLOW STEP BSR.S WNBUSY WAIT UNTIL NOT BUSY AND.B #$18,D6 CHECK NR, SK, CRC ERRORS AND.B #$FE,CCR CLEAR CARRY RTS RTS RTS AND RETURN ********************************************* * WAIT - WAIT ROUTINE TO WAIT A WHILE - 1772 ********************************************* * * CALLED BY: WNBUSY, SEEK, READ, WRITE * INPUT: NONE * OUTPUT: NONE * REGISTERS USED: NONE WAIT BSR.S WAIT8 NOP WAIT8 BSR.S WAIT4 MOD 7-3-90 NOP DITTO WAIT4 BSR.S WAIT2 NOP WAIT2 BSR.S WAIT1 NOP WAIT1 BSR.S WAIT0 NOP WAIT0 RTS ******************************************************* * WNBUSY - WAIT FOR FDC CHIP TO BECOME NOT BUSY - 1772 ******************************************************* * * CALLED BY: RESTOR, SEEK, READ, WRITE, VERIFY * INPUT: NONE * OUTPUT: RETURN ZERO WHEN FDC BECOMES NOT BUSY * ELSE D6 CONTAINS ANY FDC ERROR CODE * REGISTERS USED: D6 WNBUSY BSR.S WAIT WAIT FOR COMMAND TO SETTLE MOVE.B STAREG,D6 GET STATUS BTST.B #0,D6 CHECK BUSY FLAG BNE.S WNBUSY WAIT IF STILL BUSY RTS ELSE RETURN WITH B=STATUS ************************************************************** * SIDENS - GET SIDE AND DENSITY FOR CURRENT DRIVE/TRACK - 1772 ************************************************************** * * CALLED BY: DDRIVE AND DSEEK * INPUT: A4 POINTS TO FCB * D6 CONTAINS DRIVE BITS * OUTPUT: SIDE = 0 FOR SIDE A, 1 FOR SIDE B * D6 CONTAINS DRIVE, DENSITY, SIDE BITS FOR DLATCH * REGISTERS USED: D5, D6, A6 SIDENS MOVE.B FCBPHY(A4),D5 CHECK PHYSICAL DRIVE NUMBER AND.L #$0F,D5 RETRIEVE F NUMBER LSL.B #2,D5 X4 LEA FL0D,A6 POINT TO FIRST ENTRY MOVE.B 0(A6,D5),D5 PICK UP F NUMBER AND DR TYPE LSR.B #4,D5 KEEP F NUMBER LEA DSTABL,A6 DRIVE DATA TABLE FOR TR>0 TST.B FCBCTR(A4) CHECK TRACK NUMBER BNE.S NOTTR0 USE THIS TABLE IF T<>0 LEA D0TABL,A6 ELSE SWITCH TO TR 0 TABLE NOTTR0 ADD.L D5,A6 POINT TO DRIVE'S ENTRY IN IT MOVE.L A6,DSPTR SAVE POINTER FOR LATER CLR.L D5 TEMP ASSUME SINGLE DENSITY MOVE.B (A6),D5 GET CURRENT ENTRY AND.B #1,D5 KEEP ONLY DENSITY ASL.B #5,D5 D5=0 ON SD, 20 ON DD MOVE.B D5,DENSTY OR.B D5,D6 AND ADD TO DRIVE BITS TST.B FOTHER MS-DOS DISK? >>A<< BEQ.S NOTMS1 NO >>A<< MOVE.B FOTHER,D5 ELSE SET UP FOR 9/SIDE >>A<< BRA.S NOTMS2 NOTMS1 ASR.B #2,D5 D5=0 ON SD, 8 ON DD ADD.B #10,D5 D5=10 ON SD, 18 ON DD, 9 ON MSDOS NOTMS2 CMP.B FCBCSE(A4),D5 COMPARE WITH DESIRED SECTOR BCS.S SWSIDB USE SIDE B IF >10 (SD) OR 18(DD) CLR.B SIDE SIDE A BRA.S SIDEOK SWSIDB MOVE.B #$40,SIDE SIDE B SIDEOK OR.B SIDE,D6 OR IN SIDE BIT RTS AND THEN RETURN WITH D6 *************************************** * DSEEK - SEEK TO TR-SEC IN FCB - 1772 *************************************** * * CALLED BY: READ, WRITE * INPUT: A4 POINTS TO FCB * OUTPUT: RETURN ZERO IF NO ERROR; * ELSE D6 CONTAINS ANY FDC ERROR CODE * REGISTERS USED: D5 - D7, A6 (ALL DESTROYED) DSEEK MOVE.B FCBCSE(A4),D6 DESIRED SECTOR TST.B FOTHER MS-DOS DISK? >>A<< BEQ.S DSEEK1 NO >>A<< CMP.B FOTHER,D6 YES, CHECK WHICH SIDE >>A<< BLS.S DSEEK1 <=9 IS STILL A >>A<< SUB.B FOTHER,D6 >9 IS B, SO RENUMBER >>A<< DSEEK1 MOVE.B D6,SECREG GIVE SECTOR NUMBER TO FDC >>A<< MOVE.B MLATCH,D6 GET CURRENT MLATCH IMAGE JSR SIDENS COMBINE WITH DENSITY BIT CMP.B MLATCH,D6 CHECK IF SAME AS BEFORE BEQ.S NOD2 YES, LEAVE AS IS MOVE.B D6,DLATCH SELECT DRIVE, DENSITY, SIDE MOVE.B D6,MLATCH SAVE MEMORY NOD2 MOVE.B FCBCTR(A4),D5 CMP.B TRKREG,D5 ALREADY ON DESIRED TRACK? BEQ.S TRKOK YES, WAIT AND EXIT CLR.L D6 MOVE.B (A6),D6 CHECK DISK PARAMETERS AND.B #2,D6 DOUBLE STEPPING? MOVE.B D6,DUBSTE STORE FOR LATER BEQ.S NODUB1 IF NOT DOUBLE STEPPING MOVE.B TRKREG,D6 GET CURRENT TRACK ASL.B #1,D6 FOOLS FDC INTO DOUBLE-STEPPING MOVE.B D6,TRKREG ASL.B #1,D5 NODUB1 MOVE.B D5,DATREG AND GIVE NEW TRACK TO FDC BSR WAIT MOVE.B #$10,D5 SEEK COMMAND OR.B STPRAT,D5 OR STEP RATE MOVE.B D5,COMREG SEEK, COMMAND BSR WNBUSY WAIT FOR COMPLETION TST.B DUBSTE DOUBLE-STEPPING? BEQ.S NODUB2 NO MOVE.B TRKREG,D6 YES, FIX UP FDC TRACK REG LSR.B #1,D6 MOVE.B D6,TRKREG BSR WNBUSY CHECK FDC BITS ONCE MORE NODUB2 AND.B #$18,D6 CHECK NR,SK,CRC ERRORS RTS TRKOK BSR WAIT WAIT FOR COMPLETION MOVE.L #0,D6 IF NO ERROR RTS ************************************* * DREAD - READ SECTOR ROUTINE - 1772 ************************************* * * CALLED BY: PRIMRD * INPUT: A4 POINTS TO FCB * OUTPUT: RETURN ZERO IF NO ERROR; * ELSE D6 CONTAINS ANY DOS ERROR CODE * REGISTERS USED: D5 - D7, A5 - A6 (ALL DESTROYED) * A4 USED AND PRESERVED DREAD MOVE.W SR,D5 SAVE CURRENT SR OR.W #$0700,SR TURN OFF INTERRUPTS MOVE.L A4,D7 SAVE A4 IN D7 LEA FCBDAT(A4),A5 POINT A5 TO FCB DATA AREA LEA STAREG,A6 POINT A6 TO STATUS REG LEA DATREG,A4 POINT A4 TO DATA REG MOVE.B #$80,COMREG READ COMMAND BSR WAIT WAIT FOR FDC TO SETTLE RDLOOP MOVE.B (A6),D6 CHECK STATUS BTST.B #1,D6 DRQ? BNE.S RDBYTE YES BTST.B #0,D6 BUSY? BNE.S RDLOOP YES, SO WAIT BRA.S RDFINR THEN EXIT RDBYTE MOVE.B (A4),(A5)+ GET DATA BYTE BRA.S RDLOOP RDFINR BSR WNBUSY WAIT FOR NOT BUSY BTST.B #4,D6 RNF ERROR? BEQ.S READEX NO, SOMETHING ELSE? MOVE.L DSPTR,A6 YES, POINT TO DRIVE DATA BYTE ADD.B #1,(A6) TRY NEXT SETTING READEX MOVE.W D5,SR RESTORE INTERRUPTS AND.B #$1C,D6 NR, RNF, CRC, OR LOST DATA? MOVE.L D7,A4 RESTORE A4 RTS RTS AND RETURN **************************************** * DWRITE - WRITE SECTOR ROUTINE - 1772 **************************************** * * CALLED BY: PRIMWR * INPUT: A4 POINTS TO FCB * OUTPUT: RETURN ZERO IF NO ERROR; * ELSE D6 CONTAINS ANY DOS ERROR CODE * REGISTERS USED: D5 - D7, A5 - A6 (ALL DESTROYED) * A4 USED AND PRESERVED DWRITE MOVE.W SR,D5 SAVE CURRENT SR OR.W #$0700,SR TURN OFF INTERRUPTS LEA FCBDAT(A4),A5 POINT A5 TO FCB DATA AREA MOVE.L A4,D7 PRESERVE A4 LEA STAREG,A6 POINT A6 TO STATUS REGISTER LEA DATREG,A4 POINT A4 TO DATA REG MOVE.B #$A4,COMREG WRITE COMMAND BSR WAIT WAIT FOR FDC TO SETTLE WRLOOP MOVE.B (A6),D6 CHECK STATUS BTST.B #1,D6 DRQ? BNE.S WRBYTE YES BTST.B #0,D6 BUSY? BNE.S WRLOOP YES, SO WAIT BRA.S SDFINW THEN EXIT WRBYTE MOVE.B (A5)+,(A4) WRITE DATA BYTE BRA.S WRLOOP REPEAT UNTIL DONE SDFINW JSR WNBUSY WAIT FOR NOT BUSY BTST.B #4,D6 RNF ERROR? BEQ.S WRITEX NO, SOMETHING ELSE? MOVE.L DSPTR,A6 YES, POINT TO DRIVE DATA BYTE ADD.B #1,(A6) TRY NEXT SETTING WRITEX MOVE.W D5,SR RESTORE INTERRUPTS AND.B #$5C,D6 NR, WP, RNF, CRC, OR LOST DATA? MOVE.L D7,A4 RESTORE A4 RTS AND RETURN ********************************************* * DVERIF - VERIFY SECTOR JUST WRITTEN - 1772 ********************************************* * * CALLED BY: PRIMWR * INPUT: (ASSUMES DWRITE JUST SET EVERYTHING UP) * OUTPUT: RETURN ZERO IF NO ERROR; * ELSE D6 CONTAINS ANY DOS ERROR CODE * REGISTERS USED: D6 (DESTROYED) DVERIF MOVE.W SR,D5 SAVE CURRENT SR OR.W #$0700,SR TURN OFF INTERRUPTS MOVE.B #$80,COMREG READ COMMAND BSR WNBUSY WAIT FOR NOT BUSY MOVE.W D5,SR RESTORE INTERRUPTS AND.B #$18,D6 NR, RNF, OR CRC (NOT LOST DATA!) RTS AND RETURN ******************************************************* * CHKRDY - CHECK IF DRIVE SPEC BY FCB IS READY - 1772 ******************************************************* * * CALLED BY: FCS20 * INPUT: A4 POINTS TO FCB, FCBDRV(A4) IS DRIVE NUMBER * OUTPUT: RETURN ZERO AND CLC IF NO ERROR; * NONZERO AND ERROR $80 IN D6 IF NOT READY * REGISTERS USED: D6 AND A6 (NEED NOT RESTORE) CHKRDY CLR.L D6 MOVE.B FCBDRV(A4),D6 GET LOGICAL DRIVE NUMBER LEA DRUSED,A6 POINT TO DRIVE USED TABLE BTST.B #4,0(A6,D6.L) CHECK CONTROLLER TYPE BEQ.S CHKNG CLR.L D6 NO ERROR AND.B #$FE,CCR CLEAR CARRY RTS RTS CHKNG MOVE.B #$80,D6 NOT READY BIT OR.B #$01,CCR SET CARRY RTS DRIVNO DC.B 0 CURRENT DRIVE NUMBER DENSTY DC.B 0 0=SD, 02=DD SIDE DC.B 0 SIDEA=0, SIDEB=1 DUBSTE DC.B 0 DOUBLE-STEP FLAG (0=SINGLE) DSPTR DC.L 0 POINTER TO ENTRY IN... * IN THE FOLLOWING, BIT 0 = DENSITY, BIT 1 = DOUBLE-STEPPING D0TABL DC.B 0,0,0,0 TRACK 0 DENSITY TABLE DSTABL DC.B 0,0,0,0 DENSITY/DOUBLE-STEP TABLE TRTABL DC.B $FF,$FF,$FF,$FF TRACK TABLE MLATCH DC.B $FF COPY OF DLATCH ********************************************* *** PART 1C - WD37C65 FLOPPY DISK DRIVERS *** ********************************************* * IF WE COME HERE, THEN A6 POINTS TO FLxD BYTE IN SRAM, A4 -> FCB, * AND 14 REGISTERS ARE ON STACK D0-D7 AND A1-A6 * CONTROLLER EQUATES REGOPER EQU $FA07E5 OPERATIONS REGISTER REGSTAT EQU REGOPER+4 MAIN STATUS REGISTER REGDATA EQU REGOPER+6 DATA REGISTER REGCONT EQU REGOPER+10 CONTROL REGISTER * REGISTER USAGE * A1 POINT TO PADRIV OR PBDRIV * A4 POINT TO FCB * D0 UNIT NUMBER * D3 TEMP IN RESTORE * D4 IRQ FLAG FOR SENDIT * D5 NUMBER OF BYTES FOR SENDIT * D5 =1 IF NOT TRACK 0 IN SETCOM * DRIVE PARAMETER AREA. FOR EACH KIND OF DRIVE, WE STORE THE * FOLLOWING DATA: DN EQU 0 N DTL EQU 1 DTL DATA LENGTH DBPS EQU 2 BPS CODE FOR CONTROL REG D0MF EQU 3 MF BIT FOR TRACK 0 DAMF EQU 4 MF BIT FOR OTHER TRACKS D0SECT EQU 5 SECTORS PER TRACK 0 DASECT EQU 6 SECTORS ON OTHER TRACKS D0FGAP EQU 7 TRK 0 FMT GAP 3 DAFGAP EQU 8 OTHER TRK FORMAT GAP 3 D0GAP EQU 9 TRK 0 R/W GAP 3 DAGAP EQU 10 OTHER TRK R/W GAP 3 D0SIDB EQU 11 TRK 0 SEC NUM SUB FOR SIDE B DASIDB EQU 12 OTHER TRK SEC NUM SUB FOR B DDUBL EQU 13 DOUBLE-STEP FLAG SEC128 EQU 14 128-BYTE SECTOR FLAG * THERE ARE 16 BYTES FOR EACH; THE LAST 2 ARE ZERO EVEN * 360K DRIVE 40-TRACK DRIVE TYPEB DC.B 1,$FF,2,1,1,18,18,12,12,10,10,00,00,0,0,0 DD ALL DC.B 1,$FF,2,0,0,10,10,14,14,08,08,00,00,0,0,0 SD ALL DC.B 1,$FF,2,0,1,10,18,14,12,08,10,00,00,0,0,0 0 SD, DD ALL DC.B 2,$FF,2,1,1,09,09,80,80,42,42,09,09,0,0,0 IBM 360 * 720K 80-TRACK DRIVE TYPEC DC.B 1,$FF,2,1,1,18,18,12,12,10,10,00,00,0,0,0 80 TR DD DC.B 1,$FF,2,1,1,18,18,12,12,10,10,00,00,1,0,0 40 TR DD DC.B 1,$FF,2,0,0,10,10,14,14,08,08,00,00,1,0,0 40 TR SD DC.B 2,$FF,2,1,1,09,09,80,80,42,42,09,09,1,0,0 IBM 360 * 1.1 MEG 5-1/4" DRIVE TYPED DC.B 1,$FF,0,1,1,28,28,40,40,20,20,28,28,0,0,0 80 TR HD DC.B 1,$FF,1,1,1,18,18,12,12,10,10,00,00,0,0,0 80 TR DD DC.B 1,$FF,1,1,1,18,18,12,12,10,10,00,00,1,0,0 40 TR DD DC.B 2,$FF,0,1,1,15,15,80,80,42,42,15,15,0,0,0 IBM 1.2 * 1.4 MEG 3-1/2" DRIVE TYPEE DC.B 1,$FF,0,1,1,34,34,40,40,27,27,34,34,0,0,0 80 TR HD DC.B 1,$FF,2,1,1,18,18,12,12,10,10,00,00,0,0,0 80 TR DD DC.B 2,$FF,2,1,1,09,09,80,80,42,42,09,09,0,0,0 IBM 720 DC.B 2,$FF,0,1,1,18,18,84,84,27,27,18,18,0,0,0 IBM 1.44 * 8" 1 MEG DRIVE TYPEF DC.B 1,$FF,0,1,1,26,26,54,54,14,14,00,00,0,0,0 77 TR DD DC.B 1,$FF,0,0,1,15,26,42,54,14,14,00,00,0,0,0 TR0 SD ELSE DD DC.B 1,$FF,0,0,0,15,15,42,42,14,14,00,00,0,0,0 77 TR SD DC.B 0,128,0,0,0,13,13,27,27,07,07,13,13,0,1,0 128 BYTE * PREVIOUS LINE HAS 13 FOR 13 LOGICAL SECTORS - NOT PHYSICAL * DRIVE DATA AREA FOR TWO DRIVES. FOR EACH OF THE TWO DRIVES, WE * STORE THE FOLLOWING. THERE ARE 32 BYTES EACH, 3 FREE DRVDAT EQU 0 LINE FROM ABOVE TABLE FNUMBER EQU 16 F NUMBER SUCH AS F0 PRETRK EQU 17 PREVIOUS TRACK NUMBER DRVPTR EQU 18 DSK TYP PTR TO DRIVE TYPE ABOVE DSKSEQ EQU 22 BITS 1 AND 2 SELECT 1 OF 4 DISK FMTS DSKSTP EQU 23 STEPRATE CODE * DATA FOR TWO PHYSICAL DRIVES FOR THIS CONTROLLER PADRIV DC.L 0,0,0,0 1 LINE FROM ABOVE TABLE DC.B 0 F NUMBER DC.B 255 PREVIOUS TRACK DC.L 0 POINTER TO TYPE A-F DC.B 0 DISK SEQUENCER DC.B 0 STEPRATE CODE DC.L 0,0 EMPTY PBDRIV DC.L 0,0,0,0 1 LINE FROM ABOVE TABLE DC.B 0 DATA FOR SECOND DRIVE DC.B 255 DC.L 0 DC.B 0 DC.B 0 DC.L 0,0 MFBIT DC.B 0 MF BIT IN BIT #6 RETRCT DC.B 0 RETRY COUNTER COMMAND DS.B 9 COMMAND BUFFER ST0 DS.B 1 RESULTS BUFFER ST1 DS.B 1 ST2 DS.B 1 C DS.B 1 H DS.B 1 R DS.B 1 N DS.B 1 MTIMER DS.W 1 MOTOR TIMER STCONV DC.B $A0,$40,$E0,$D0 CONVERSION FROM 1772 STEPRATES INFLAG DC.W 0 0=NEED TO INITIALIZE DOSSTP DC.B 0 COPY OF DOS'S STEPRATE ************************************** * INITIALIZE 37C65 IF NOT ALREADY DONE ************************************** * FIRST GET DATA TO FILL DRIVE AND DISK TABLES FD37IN MOVE.L A6,A5 MOVE.B (A5),D7 LOOK AT CODE LSR.B #4,D7 IS F NUMBER >0? BEQ.S FIS0 YES, THIS MUST BE FIRST LEA -4(A5),A5 STEP BACK IF NOT FIRST FIS0 LEA PADRIV(PC),A1 POINT TO PHYS DRIVE 0 ENTRY CLR.L D2 COUNTER FOR TWO DRIVES FDLOOP CLR.L D7 MOVE.B (A5),D7 PICK UP DR NUM CODE & DRIVE TYPE BEQ.S FD37EX QUIT IF NO DRIVE MOVE.L A5,D6 ADDRESS OF ENTRY SUB.L #FL0D,D6 SUBT ADDRESS OF FIRST LSR.B #2,D6 F NUMBER FOR DRIVE MOVE.B D6,FNUMBER(A1) PUT IN F NUMBER AND.B #$F,D7 AND DRIVE TYPE LSL.W #6,D7 X64 CLR.L D3 MOVE.B DSKSEQ(A1),D3 AND.B #$3,D3 KEEP TWO BITS OF SEQUENCER LSL.B #4,D3 X16 ADD.B D3,D7 POINT TO DRIVE TYPE AND SUBTYPE LEA TYPEB-64,A3 POINT TO FORMAT TABLES LEA 0(A3,D7),A3 FORMAT TABLE FOR THIS DRIVE MOVE.L A3,DRVPTR(A1) MOVE.L DRVDAT(A3),DRVDAT(A1) MOVE.L DRVDAT+4(A3),DRVDAT+4(A1) COPY OVER 1 LINE FROM TABLE MOVE.L DRVDAT+8(A3),DRVDAT+8(A1) MOVE.L DRVDAT+12(A3),DRVDAT+12(A1) CLR.L D7 MOVE.B STPRAT,D7 PICK UP 1772 STEP RATE CODE MOVE.B D7,DOSSTP SAVE IT AS LAST USED LEA STCONV,A2 POINT TO CONVERSION TABLE MOVE.B 0(A2,D7),DSKSTP(A1) CONVERTED STEP RATE FD37EX ADD.B #1,D2 BUMP COUNTER LEA 4(A5),A5 POINT TO NEXT CODE LEA PBDRIV,A1 POINT TO PBDRIV CMP.B #2,D2 DONE WITH BOTH DRIVES? BNE.S FDLOOP REPEAT IF NOT, ELSE... * NEXT INITIALIZE THE CONTROLLER LEA PADRIV(PC),A1 BACK TO PHYS DRIVE 0 ENTRY MOVE.B #$34,REGOPER MOTORS ON, NO SOFT RESET: AT MODE MOVE.B #0,REGCONT SET TO 250/500 KBPS MOVE.B #$03,COMMAND SPECIFY COMMAND MOVE.B DSKSTP(A1),D7 PICK UP STEPRATE FROM FIRST DRV ADD.B #$0F,D7 COMBINE UNLOAD TIME = MAX MOVE.B D7,COMMAND+1 STEPRATE AND HEAD UNLOAD TIME MOVE.B #$7F,COMMAND+2 HEAD LOAD=126, NON-DMA MODE MOVE.W #3,D5 THREE BYTES TO SEND MOVE.B #0,D4 DON'T TURN OFF IRQ BSR.L SENDIT SEND COMMAND TO 3765 MOVE.W #$3765,INFLAG SIGNAL INIT COMPLETED RTS RETURN TO READ OR WRITE ******************************************* * READ ROUTINE TO READ THE DISK - 37C65 ******************************************* RD3765 TST.W INFLAG DO WE NEED TO INIT? BNE.S RD3765B NO RD3765A BSR.L FD37IN YES, SO DO IT RD3765B MOVE.B STPRAT,D5 CURRENT DOS STEPRATE CMP.B DOSSTP,D5 COMPARE WITH LAST INITIALIZED BNE.S RD3765A DIFFERENT, INITIALIZE AGAIN MOVE.B #20,RETRCT SETUP RETRY COUNTER RDRETRY BSR.L SETCOM SET UP COMMAND BUFFER BNE.L RDERR2 IF ERROR BSR.L SEEK MOVE.B MFBIT,D7 MF BIT IN BIT 6 ADD.B #6,D7 INSERT READ COMMAND MOVE.B D7,COMMAND MF + READ COMMAND MOVE.W #9,D5 NINE BYTES TO SEND MOVE.B #1,D4 DO TURN OFF IRQ BSR.L SENDIT SEND TO FDC LEA REGSTAT,A2 POINT TO STATUS REG LEA REGDATA,A3 POINT TO DATA REGISTER MOVE.B (A5)+,D7 GET LAST BYTE OF COMMAND LEA FCBDAT(A4),A5 WHERE TO PUT DATA MOVE.W SR,D5 SAVE CURRENT SR OR.W #$0700,SR TURN OFF INTERRUPTS MOVE.B D7,REGDATA SEND OUT LAST BYTE OF COMMAND BSR.L WAIT12 BRA.S RDMOVE RDBLOO MOVE.B (A3),(A5)+ MOVE A BYTE RDMOVE MOVE.B (A2),D7 STATUS REGISTER BPL.S RDMOVE WAIT FOR RQM BTST #5,D7 CHECK IF STILL EXECUTING BNE.S RDBLOO NO, SO FINISHED READING RDDONE MOVE.W D5,SR RESTORE INTERRUPTS LEA ST0(PC),A5 POINT TO RESULTS BUFFER RDRESU BSR.L WAIT12 MOVE.B REGSTAT,D7 GET STATUS REGISTER AND.B #$C0,D7 LOOK AT DIO AND RQM ONLY CMP.B #$80,D7 10 MEANS WE'RE FINISHED BEQ.S FINRES CMP.B #$C0,D7 NEED 11 TO CONTINUE READING BNE.S RDRESU MOVE.B REGDATA,(A5)+ BRA.S RDRESU * FINISHED READING AND TRANSFERRING; CHECK FOR ERRORS FINRES MOVE.B ST0,D7 CHECK STATUS REG 0 AND.B #$D8,D7 CHECK BITS 3,4,6,7 BEQ.L RDISOK * FOLLOWING FOUR LINES CORRECT FOR ANOTHER 37C65 BUG CMP.B #$40,D7 CHECK FOR NON-COMPLETION BNE.S RETRYR MUST BE SOMETHING ELSE CMP.B #$80,ST1 END OF CYLINDER? BOOBOO! BEQ.L RDISOK YES, NOT REALLY AN ERROR RETRYR SUB.B #1,RETRCT BEQ.S RD7ERR ERROR OUT IF TOO MANY RETRIES MOVE.B RETRCT,D7 AND.B #3,D7 LOOK AT LAST 2 BITS BNE.S CHKRST IF <>0, DON'T SWAP DISK FORM CLR.L D6 ADD.B #1,DSKSEQ(A1) TRY THE NEXT DSK SEQUENCE MOVE.B DSKSEQ(A1),D6 AND.B #3,D6 RIGHT TWO BITS ONLY LSL.B #4,D6 X16 MOVE.L DRVPTR(A1),A2 POINTER TO DRIVE TYPE ADD.L D6,A2 POINT TO NEW SUBTYPE MOVE.L 0(A2),DRVDAT(A1) MOVE.L 4(A2),DRVDAT+4(A1) TRANSFER 16 DISK INFO BYTES MOVE.L 8(A2),DRVDAT+8(A1) MOVE.L 12(A2),DRVDAT+12(A1) CHKRST AND.B #1,D7 LOOK AT LAST BIT OF RETRCT BNE.L RDRETRY RESTORE ONLY EVERY TWO TRIES BSR.L RESTORE RESTORE MOVE.B #$30,REGOPER DO SOFT RESTORE BRA.L RDRETRY RD7ERR MOVE.B ST0,D7 CHECK STATUS REG 0 BTST.B #4,D7 RESTORE ERROR? BNE.S RDERR9 MOVE.B #14,D7 SEEK ERROR BRA.S RDERRX RDERR9 MOVE.B #9,D7 GENERAL READ ERROR RDERRX MOVE.B D7,FCBERR(A4) RDERR2 MOVE.B FCBERR(A4),ERRTYP MOVEM.L (A7)+,D0-D7/A1-A6 RTS RDISOK MOVEM.L (A7)+,D0-D7/A1-A6 RTS ***************************************** * WRITE ROUTINE TO WRITE THE DISK - 37C65 ***************************************** WR3765 TST.W INFLAG DO WE NEED TO INIT? BNE.S WR3765A NO BSR.L FD37IN YES, SO DO IT WR3765A MOVE.B #20,RETRCT SETUP RETRY COUNTER WRRETRY BSR.L SETCOM SET UP COMMAND BUFFER BNE.L WRERR2 BSR.L SEEK MOVE.B MFBIT,D7 MF BIT IN BIT 6 ADD.B #5,D7 INSERT WRITE COMMAND MOVE.B D7,COMMAND MF + WRITE COMMAND MOVE.W #9,D5 NINE BYTES TO SEND MOVE.B #1,D4 DO TURN OFF IRQ BSR.L SENDIT SEND TO FDC LEA REGSTAT,A2 POINT TO STATUS REG LEA REGDATA,A3 POINT TO DATA REGISTER MOVE.B (A5)+,D7 GET LAST BYTE OF COMMAND LEA FCBDAT(A4),A5 WHERE TO GET DATA MOVE.W SR,D5 SAVE CURRENT SR OR.W #$0700,SR TURN OFF INTERRUPTS MOVE.B D7,REGDATA SEND OUT LAST BYTE OF COMMAND BSR.L WAIT12 WRMOVE MOVE.B (A2),D7 STATUS REGISTER BPL.S WRMOVE WAIT FOR RQM BTST #5,D7 CHECK IF STILL EXECUTING BEQ.S WRDONE NO, SO FINISHED WRITING MOVE.B (A5)+,(A3) MOVE A BYTE BRA.S WRMOVE WRDONE MOVE.W D5,SR RESTORE INTERRUPTS LEA ST0(PC),A5 POINT TO RESULTS BUFFER WRRESU BSR.L WAIT12 MOVE.B REGSTAT,D7 GET STATUS REGISTER AND.B #$C0,D7 LOOK AT DIO AND RQM ONLY CMP.B #$80,D7 10 MEANS WE'RE FINISHED BEQ.S FINWES CMP.B #$C0,D7 NEED 11 TO CONTINUE WRITING BNE.S WRRESU MOVE.B REGDATA,(A5)+ BRA.S WRRESU * FINISHED WRITING AND TRANSFERRING; CHECK FOR ERRORS FINWES MOVE.B ST0,D7 CHECK STATUS REG 0 AND.B #$D8,D7 CHECK BITS 3,4,6,7 BEQ.L WRISOK * FOLLOWING FOUR LINES CORRECT FOR ANOTHER 3765 BUG CMP.B #$40,D7 CHECK FOR NON-COMPLETION BNE.S RETRYW MUST BE SOMETHING ELSE CMP.B #$80,ST1 END OF CYLINDER? BOOBOO! BEQ.L WRISOK YES, NOT REALLY AN ERROR * IN WRITE, CHECK WRITE PROTECT HERE RETRYW BTST #1,ST1 CHECK IF WRITE PROTECTED BNE.S WRPROT SUB.B #1,RETRCT BEQ.S WR7ERR ERROR OUT IF TOO MANY RETRIES MOVE.B RETRCT,D7 AND.B #3,D7 LOOK AT LAST 2 BITS BNE.S CHKWRS IF <>0, DON'T SWAP DISK FORM CLR.L D6 ADD.B #1,DSKSEQ(A1) TRY THE NEXT DSK SEQUENCE MOVE.B DSKSEQ(A1),D6 AND.B #3,D6 RIGHT TWO BITS ONLY LSL.B #4,D6 X16 MOVE.L DRVPTR(A1),A2 POINTER TO DRIVE TYPE ADD.L D6,A2 POINT TO NEW SUBTYPE MOVE.L 0(A2),0(A1) MOVE.L 4(A2),4(A1) TRANSFER 16 DISK INFO BYTES MOVE.L 8(A2),8(A1) MOVE.L 12(A2),12(A1) CHKWRS AND.B #1,D7 LOOK AT LAST BIT OF RETRCT BNE.L WRRETRY RESTORE ONLY EVERY TWO TRIES BSR.L RESTORE RESTORE WRRPTV MOVE.B #$30,REGOPER DO SOFT RESTORE BRA.L WRRETRY WR7ERR MOVE.B ST0,D7 CHECK STATUS REG 0 BTST.B #4,D7 RESTORE ERROR? BNE.S WRERR10 MOVE.B #14,D7 SEEK ERROR BRA.S WRERRX WRPROT MOVE.B #11,D7 WRITE PROTECT ERROR BRA.S WRERRX WRERR10 MOVE.B #10,D7 GENERAL WRITE ERROR WRERRX MOVE.B D7,FCBERR(A4) WRERR2 MOVE.B FCBERR(A4),ERRTYP MOVEM.L (A7)+,D0-D7/A1-A6 RTS WRISOK TST.B VERFLG VERIFY NEEDED? BEQ.S WRISEX NO, EXIT BSR.S VERIF3 YES, GO VERIFY BEQ.S WRISEX EXIT IF OK * IF THERE WAS A VERIFY ERROR, TRY TO REWRITE SUB.B #1,COMMAND CHANGE READ BACK TO WRITE SUB.B #1,RETRCT CHECK IF ANY RETRIES LEFT BNE.S WRRPTV AND TRY TO WRITE AGAIN MOVE.B #31,D7 BRA.S WRERRX ELSE RETURN ERROR 31 WRISEX MOVEM.L (A7)+,D0-D7/A1-A6 RTS * VERIF3 - ROUTINE TO VERIFY WHAT 37C65 HAS JUST WRITTEN VERIF3 ADD.B #1,COMMAND CHANGE WRITE TO READ COMMAND VERETRY MOVE.W #9,D5 NINE BYTES TO SEND MOVE.B #1,D4 DO TURN OFF IRQ BSR.L SENDIT SEND TO FDC LEA REGSTAT,A2 POINT TO STATUS REG LEA REGDATA,A3 POINT TO DATA REGISTER MOVE.B (A5)+,D7 GET LAST BYTE OF COMMAND MOVE.W SR,D5 SAVE CURRENT SR OR.W #$0700,SR TURN OFF INTERRUPTS MOVE.B D7,REGDATA SEND OUT LAST BYTE OF COMMAND BSR.L WAIT12 BRA.S VEMOVE VEBLOO MOVE.B (A3),D7 MOVE A BYTE, THROW IT AWAY VEMOVE MOVE.B (A2),D7 STATUS REGISTER BPL.S VEMOVE WAIT FOR RQM BTST #5,D7 CHECK IF STILL EXECUTING BNE.S VEBLOO NO, SO FINISHED READING VEDONE MOVE.W D5,SR RESTORE INTERRUPTS LEA ST0(PC),A5 POINT TO RESULTS BUFFER VERESU BSR.L WAIT12 MOVE.B REGSTAT,D7 GET STATUS REGISTER AND.B #$C0,D7 LOOK AT DIO AND RQM ONLY CMP.B #$80,D7 10 MEANS WE'RE FINISHED BEQ.S VERRES CMP.B #$C0,D7 NEED 11 TO CONTINUE READING BNE.S VERESU MOVE.B REGDATA,(A5)+ BRA.S VERESU * FINISHED READING AND TRANSFERRING; CHECK FOR ERRORS VERRES MOVE.B ST0,D7 CHECK STATUS REG 0 AND.B #$D8,D7 CHECK BITS 3,4,6,7 BEQ.L VERIFX * FOLLOWING THREE LINES CORRECT FOR ANOTHER 37C65 BUG CMP.B #$40,D7 CHECK FOR NON-COMPLETION BNE.S VERIFX MUST BE SOMETHING ELSE CMP.B #$80,ST1 END OF CYLINDER? BOOBOO! * RETURN WITH BEQ, OR BNE IF ERROR VERIFX RTS * SETCOM - SET UP COMMAND BUFFER WITH KNOWN DATA; SKIP COMMAND * ITSELF. ENTER WITH A4-> FCB SETCOM LEA COMMAND(PC),A5 POINT TO COMMAND BUFFER LEA PADRIV(PC),A1 TEMP ASSUME DRIVE A CLR.L D0 ASSUME UNIT 0 MOVE.B FCBPHY(A4),D7 PHYSICAL F NUMBER AND.L #$0F,D7 REMOVE 1 CMP.B FNUMBER(A1),D7 IS IT DRIVE A BEQ.S SETOK YES LEA PBDRIV(PC),A1 TRY DRIVE B MOVE.B #1,D0 AND UNIT 1 CMP.B FNUMBER(A1),D7 IS IT B? BEQ.S SETOK YES MOVE.B #15,FCBERR(A4) ELSE ERR 15 = INV DRV NO RTS * NOW A1 POINTS TO DATA FOR THIS PHYSICAL DRIVE (PA OR PBDRIV) * AND D0 HAS UNIT NUMBER 0 OR 1 SETOK MOVE.B D0,D7 UNIT NUMBER ADD.B #$34,D7 MOTOR ON BITS MOVE.B D7,REGOPER MOTOR ON AND UNIT BSR.L SETMTIM MOTOR TIMER = MAX & WAIT MOVE.B DBPS(A1),REGCONT SET FOR CORRECT BPS RATE CLR.L D5 MOVE.B FCBCTR(A4),D5 ACTUAL DESIRED TRACK MOVE.B D5,COMMAND+2 INTO COMMAND BEQ.S SETTR0 IF TRACK 0 MOVE.B #1,D5 D5=1 IF TRACK<>0 SETTR0 MOVE.B D0MF(A1,D5),D7 GET MF FOR APPROPRIATE TRK LSL.B #6,D7 MOVE.B D7,MFBIT SET UP MF BIT TST.B SEC128(A1) 128-BYTE SECTORS? BNE.S BYT128 GO DO SPECIAL IF YES * FOLLOWING SECTION DONE FOR ALL EXCEPT 128-BYTE 8" DISK MOVE.B D0SECT(A1,D5),D7 # OF SECT ON TRACK CMP.B FCBCSE(A4),D7 ACTUAL DESIRED SECTOR BCS.S SETSDB IF ON SIDE B SETSDA CLR.B COMMAND+3 H=0 FOR SIDE A MOVE.B D0,COMMAND+1 HS AND US AND.B #$1,D0 BACK TO UNIT NUMBER MOVE.B FCBCSE(A4),D7 SETBOTH MOVE.B D7,COMMAND+4 MOVE.B D7,COMMAND+6 EOT MOVE.B DN(A1),COMMAND+5 N MOVE.B D0GAP(A1,D5),COMMAND+7 GPL GAP 3 MOVE.B DTL(A1),COMMAND+8 DTL DATA LENGTH MOVE.L #0,D7 RETURN BEQ RTS SETSDB ADD.B #4,D0 INSERT HS=1 INTO DRIVE NUM MOVE.B #1,COMMAND+3 AND H=1 MOVE.B D0,COMMAND+1 HS AND US AND.B #$1,D0 BACK TO UNIT NUMBER MOVE.B FCBCSE(A4),D7 SUB.B D0SIDB(A1,D5),D7 CORRECT SECTOR FOR SIDE B BRA.S SETBOTH * FOLLOWING SECTION DONE FOR ONLY 128-BYTE 8" DISK BYT128 MOVE.B D0SECT(A1,D5),D7 # OF LOG SECT ON TRACK CMP.B FCBCSE(A4),D7 ACTUAL DESIRED SECTOR BCS.S SP128B IF ON SIDE B SP128A CLR.B COMMAND+3 H=0 FOR SIDE A MOVE.B D0,COMMAND+1 HS AND US AND.B #$1,D0 BACK TO UNIT NUMBER MOVE.B FCBCSE(A4),D7 SET128 LSL.B #1,D7 DOUBLE SECTOR NO MOVE.B D7,COMMAND+6 EOT IS 2ND SECTOR SUB.B #1,D7 AND SUB 1 FOR PHYSICAL MOVE.B D7,COMMAND+4 START AT 1ST SCTR MOVE.B DN(A1),COMMAND+5 N MOVE.B D0GAP(A1,D5),COMMAND+7 GPL GAP 3 MOVE.B DTL(A1),COMMAND+8 DTL DATA LENGTH MOVE.L #0,D7 RETURN BEQ RTS SP128B ADD.B #4,D0 INSERT HS=1 INTO DRIVE NUM MOVE.B #1,COMMAND+3 AND H=1 MOVE.B D0,COMMAND+1 HS AND US AND.B #$1,D0 BACK TO UNIT NUMBER MOVE.B FCBCSE(A4),D7 SUB.B D0SIDB(A1,D5),D7 CORRECT SECTOR FOR SIDE B BRA.S SET128 * SETMTIM - TURN ON DISK MOTORS SETMTIM TST.W MTIMER WAS MOTOR ON? BNE.S MOTREX YES BSR.L WAIT1S MOTREX MOVE.W #$7FFF,MTIMER RESET TIMER TO MAX RTS * MOTROF - TURN OFF DISK MOTORS MOTROF TST.W MTIMER IS MOTOR OFF? BEQ.S MOTRFX YES MOVE.B #$04,REGOPER TURN MOTOR OFF CLR.W MTIMER CLEAR TIMER MOTRFX RTS * SEEK COMMAND SEEK MOVE.B COMMAND+2,D7 LOG TRACK WE WANT BEQ.S SEEKT0 OK IF TRACK 0 TST.B DDUBL(A1) DOUBLE-STEPPING? BEQ.S SEEKT0 NO LSL.B #1,D7 YES, DOUBLE IT MOVE.B D7,COMMAND+2 THEN RESTORE IT SEEKT0 CMP.B PRETRK(A1),D7 SAME AS PREVIOUS? BEQ.S SEEKEX EXIT IF ALREADY THERE MOVE.B PRETRK(A1),D7 PREVIOUS TRACK CMP.B #255,D7 SEE IF CURRENT STILL 255 BNE.S SEEKGO NO, OK TO SEEK BSR.L RESTORE BNE.S SEEKER EXIT IN ERROR * PRETRK IS NOT 255, AND MUST SEEK SEEKGO MOVE.B #$0F,COMMAND SEEK COMMAND MOVE.W #3,D5 THREE BYTES IN COMMAND MOVE.B #0,D4 DON'T TURN OFF IRQ BSR.L SENDIT SEND TO FDC BNE.S SEEKER SOMETHING WRONG BSR.L SENSIN SENSE IRQ TO CLEAR CMP.B COMMAND+2,D7 CHECK IF CORRECT TRACK BNE.S SEEKER EXIT IF NO MATCH * RESTORE CORRECT TRACK NUMBER OF DOUBLE-STEPPING IF NO ERROR SEEKEX MOVE.B COMMAND+2,D7 PHYS TRACK WE ARE NOW ON MOVE.B D7,PRETRK(A1) TST.B DDUBL(A1) DOUBLE-STEPPING? BEQ.S RETZ REALLY EXIT IF NOT LSR.B #1,D7 CVT BACK TO LOGICAL TRK MOVE.B D7,COMMAND+2 THEN RESTORE IT CLR.L D7 AND RETURN ZERO RETZ RTS * RESTORE CORRECT TRACK NUMBER OF DOUBLE-STEPPING IF NO ERROR SEEKER TST.B DDUBL(A1) DOUBLE-STEPPING? BEQ.S RETNZ REALLY EXIT IF NOT MOVE.B COMMAND+2,D7 ELSE PHYS TRACK WE WANT LSR.B #1,D7 CVT BACK TO LOG MOVE.B D7,COMMAND+2 THEN RESTORE IT RETNZ MOVE.B #1,D7 RETURN NON-ZERO ON ERROR RTS * RESTORE RESTORE MOVE.B #7,COMMAND RESTORE COMMAND MOVE.B COMMAND+1,D3 SAVE OLD HS AND US MOVE.B D0,COMMAND+1 PUT IN US ONLY MOVE.W #2,D5 TWO BYTES IN COMMAND MOVE.B #0,D4 DON'T TURN OFF IRQ BSR.S SENDIT SEND TO FDC BNE.S RESTNG SOMETHING WRONG BSR.L SENSIN SENSE IRQ TO CLEAR TST.B D7 CHECK PRESENT TRACK NO BNE.S RESTNG ERROR IF NOT 0 MOVE.B D3,COMMAND+1 CLR.B PRETRK(A1) SET CURRENT TO 0 RTS RESTNG MOVE.B D3,COMMAND+1 MOVE.B #1,D7 RETURN NON-ZERO ON ERROR RTS * SENDIT ROUTINE: SEND (D5) BYTES TO 765 FROM COMMAND BUFFER * THE CALLING ROUTINE SETS D4=1 IF IT WANTS IRQ DISABLED, 0 IF NOT * IF D4=1, THEN SENDIT DOESN'T SEND THE VERY LAST BYTE OF * THE COMMAND, LETTING THE CALLING PROGRAM DO IT SENDIT MOVE.W #$FFFF,D6 REPEAT MANY TIMES SEND10 MOVE.B REGSTAT,D7 BTST #7,D7 CHECK DRQ BIT BEQ.S SEND20 WAIT IF NOT READY BTST #6,D7 DIO MUST BE 0 FOR WRITE BEQ.S SEND40 OK MOVE.B REGDATA,D7 ELSE READ DATA TO CLEAR SEND20 BSR.L WAIT12 WAIT 12 MICROSECONDS SENDER DBRA D6,SEND10 MOVE.B #1,D7 BNE MEANS ERROR RTS SEND40 BTST #4,REGSTAT CHECK BUSY BIT BNE.S SENDER IF STILL BUSY, THEN REAL BAD MOVE.B REGSTAT,D7 AND.L #$0F,D7 CHECK 4 SEEK BITS BEQ.S SEND50 OK IF NONE BSR.L SENSIN EXECUTE SENSE INTERRUPT * PRESUMABLY 765 IS NOW READY FOR COMMAND, SO GO! AT THIS POINT, * D5 CONTAINS NUMBER OF BYTES TO SEND FROM COMMAND BUFFER SEND50 LEA COMMAND(PC),A5 POINT TO COMMAND BUFFER SUB.W #1,D5 SEND ALL BYTES, EXCEPT ... SUB.B D4,D5 OMIT LAST IF D4=1 SEND60 BSR.S WAITRQ WAIT FOR OK TO WRITE MOVE.B (A5)+,D7 MOVE.B D7,REGDATA OUTPUT A COMMAND DBRA D5,SEND60 REPEAT FOR ALL BUT LAST BSR.S WAITRQ WAIT FOR OK TO WRITE, RET BEQ SENDND BSR.S WAIT12 SENDEX RTS AND RETURN WITH BEQ * SENSE INTERRUPT COMMAND - TO CLEAR IRQ AFTER SEEK OR RESTORE * RETURNS STATUS REG 0 IN D6, CYLINDER IN 7 SENSIN MOVE.W #$7FFF,D7 SENSIN1 SUB.W #1,D7 WAIT FOR BOOBOO BNE.S SENSIN1 MOVE.B #$08,REGDATA SENSE INTERRUPT STATUS CMD BSR.S WAITRQ MOVE.B REGDATA,D6 RETURN STATUS REG 0 CMP.B #$80,D6 INVALID OP CODE, ALL ELSE OK? BEQ.S SENSIN YES, REPEAT AGAIN BSR.S WAITRQ MOVE.B REGDATA,D7 GET CYLINDER NUMBER BTST #5,D6 SEEK END? BEQ.S SENSIN NO, SO WAIT SOME MORE RTS * WAIT 12 MICROSECONDS TO KEEP 765 HAPPY WAIT12 MOVE.B #50,D7 WAIT12A SUB.B #1,D7 BNE.S WAIT12A RTS * WAIT FOR STATUS REG RQM REQUEST SIGNAL WAITRQ BSR.S WAIT12 WAITRQ1 MOVE.B REGSTAT,D7 CHECK STATUS BPL.S WAITRQ1 WAIT FOR RQM=1 RTS * WAIT 1 SECOND ROUTINE FOR MOTOR TO COME ON WAIT1S MOVE.L #600000,D7 WAIT0S SUB.L #1,D7 WAIT 1 SECOND FOR MOTOR BNE.S WAIT0S RTS ********************************************* **** --- PART 1D - HARD DISK DRIVERS --- **** ********************************************* * EQUATES HARDWE EQU $FF0C0D HUMBUG HARDWARE BYTE WXDATA EQU $FA0641 DATA REGISTER WXCOMM EQU WXDATA COMMAND REGISTER WXSTAT EQU WXDATA+2 STATUS REGISTER WXRESE EQU WXDATA+2 RESET REGISTER WXSELE EQU WXDATA+4 SELECT REGISTER WDAROM EQU $D90000 CONTROLLER ROM SPACE ****************************** *** HARD DISK READ ROUTINE *** ****************************** * HARDRD - READ A SECTOR FROM DISK INTO FCB POINTED TO BY A4 * USING DATA PUT INTO WX1CYL, WX1HD, AND WX1SEC BY LPCONV HARDRD BSR.L LPCONV CONVERT LOG TO PHYS TR-SEC BNE.L HDER15 ERROR 15 BAD DR NUM LEA OL0CYL,A3 TEMP ASSUME DRIVE 0 TST.B WX1DRV BEQ.S RDIS0 YES, IT IS ZERO LEA OL1CYL,A3 NO, IT'S DRIVE 1 RDIS0 MOVE.L WX1CYL(PC),D7 DESIRED CYL/HD/SEC LSR.B #1,D7 CVT TO WX1 PHYS SCTR CMP.L 0(A3),D7 ALREADY IN WXDBUF? BEQ.S HRDYES YES, ALREADY THERE BSR.S PREAD NO, SO READ AND UPDATE OLD BNE.L HDER9 EXIT ON ERROR HRDYES LEA 4(A3),A5 POINT TO EVEN SECTOR BTST #0,WX1SEC(PC) CHECK IF EVEN OR ODD DESIRED BEQ.S HRDEVN EVEN OK ADD.L #256,A5 NO, POINT TO ODD HRDEVN MOVE.W #63,D7 COUNTER = 256/4-1 LEA FCBDAT(A4),A6 POINT TO DATA AREA HRDLOO MOVE.L (A5)+,(A6)+ READ A BYTE DBRA D7,HRDLOO REPEAT FOR 256 BYTES OR.B #$04,CCR ZERO TO SIGNAL NO ERROR MOVEM.L (A7)+,D0-D7/A1-A6 RTS EXIT WITH ZERO IF NO ERROR * PREAD - PHYSICAL READ OF A 512-BYTE SECTOR INTO AREA POINTED * TO BY (A3)+4 * RETURNS NON-ZERO IF ERROR, AND USES DATA IN WX1DRV, WX1CYL, * WX1HD, AND WX1SEC PREAD BSR.L CHBUSY WAIT FOR NOT BUSY BNE.L RDRTS IF ERROR LEA WX1TAB(PC),A5 POINT TO COMMAND TABLE MOVE.B #8,0(A5) READ SECTOR COMMAND MOVE.B WX1DRV,D7 DRIVE LSL.B #5,D7 MOVE INTO BIT 5 ADD.B WX1HD(PC),D7 COMBINE WITH HEAD NUMBER MOVE.B D7,1(A5) INTO TABLE MOVE.W WX1CYL(PC),D7 CYLINDER LSR.W #1,D7 MSB IN BITS 7-8 AND.B #$80,D7 ONLY BITS 7-8 ADD.B WX1SEC(PC),D7 COMBINE WITH SECTOR LSR.W #1,D7 DIVIDE BY 2 MOVE.B D7,2(A5) MSB OF CYL AND SECTOR MOVE.B WX1CYL+1(PC),D7 MOVE.B D7,3(A5) LSB OF CYL MOVE.B #1,4(A5) 1 SECTOR MOVE.B HSTEPR(PC),D7 MOVE.B D7,5(A5) STEPRATE BSR.S GIVE6 BSR.L CBWAIT WAIT FOR CB BNE.S RDERR EXIT ON TIMEOUT LEA 4(A3),A5 POINT TO OLn BUFFER MOVE.W #510,D7 COUNTER FOR 511 BYTES WXRDLP MOVE.B WXDATA,(A5)+ MOVE A BYTE MOVE.B WXSTAT,D6 CHECK STATUS AND.L #$0F,D6 CMP.B #$0B,D6 CHECK IF STILL WAITING BNE.S RDERR NO, ERROR DBRA D7,WXRDLP YES, CONTINUE MOVE.B WXDATA,(A5)+ GET THE LAST BYTE MOVE.L WX1CYL(PC),D7 NEW CYL/HD/SEC LSR.B #1,D7 CVT TO 512-BYTE NUMBER MOVE.L D7,(A3) MOVE TO OLDSEC RDERR BSR.L CFWAIT WAIT FOR COMPLETION MOVE.B WXDATA,D7 GET COMPLETION CODE AND.B #$DF,D7 REMOVE DRIVE BIT BEQ.S RDRTS OK IF ZERO MOVE.B #$FF,2(A4) ELSE ERASE HD NUMBER ON ERROR RDRTS RTS * GIVE6 - ROUTINE TO PASS A 6-BYTE CONTROL BLOCK FROM (A5)-> * TO THE CONTROLLER GIVE6 BSR.L CHBUSY WAIT FOR NOT BUSY MOVE.B #0,WXSELE SELECT THE CONTROLLER BSR.L CDWAIT WAIT FOR COMMAND REQUEST BNE.S GERROR ERROR IF TIMEOUT MOVE.B (A5)+,WXCOMM GIVE FIRST BYTE BSR.L CDWAIT BNE.S GERROR ERROR IF TIMEOUT MOVE.B (A5)+,WXCOMM BSR.L CDWAIT BNE.S GERROR ERROR IF TIMEOUT MOVE.B (A5)+,WXCOMM BSR.L CDWAIT GIVE REMAINING BYTES BNE.S GERROR ERROR IF TIMEOUT MOVE.B (A5)+,WXCOMM BSR.L CDWAIT BNE.S GERROR ERROR IF TIMEOUT MOVE.B (A5)+,WXCOMM BSR.L CDWAIT BNE.S GERROR ERROR IF TIMEOUT MOVE.B (A5)+,WXCOMM GERROR RTS ******************************* *** HARD DISK WRITE ROUTINE *** ******************************* * HARDWR - WRITE A SECTOR TO DISK FROM FCB POINTED TO BY A4 * USING DATA PUT INTO WX1CYL, WX1HD, AND WX1SEC BY LPCONV HARDWR TST.W FCBCTR(A4) CHECK FOR TRACK 0 SECTOR 0 BNE.S HWRITE OK TO GO ON IF NOT MOVE.B #11,D6 TR 0 SEC 0 IS WRITE PROT BRA.L HDER12 AND QUIT HWRITE BSR.L LPCONV CONVERT LOG TO PHYS TR-SEC BNE.L HDER15 BAD DR NUM LEA OL0CYL,A3 TEMP ASSUME DRIVE 0 TST.B WX1DRV BEQ.S WRIS0 YES, IT IS ZERO LEA OL1CYL,A3 NO, IT'S DRIVE 1 WRIS0 MOVE.L WX1CYL(PC),D7 DESIRED CYL/HD/SEC LSR.B #1,D7 CVT TO WX1 PHYS SCTR CMP.L 0(A3),D7 ALREADY IN WXDBUF? BEQ.S HWRYES YES, ALREADY THERE BSR.L PREAD NO, SO READ AND UPDATE OLD BNE.L HDER9 EXIT ON ERROR HWRYES LEA 4(A3),A5 POINT TO EVEN SECTOR BTST #0,WX1SEC(PC) CHECK IF EVEN OR ODD DESIRED BEQ.S HWREVN EVEN OK ADD.L #256,A5 NO, POINT TO ODD HWREVN MOVE.W #63,D7 COUNTER = 256/4-1 LEA FCBDAT(A4),A6 POINT TO DATA AREA HWRLOO MOVE.L (A6)+,(A5)+ READ A BYTE DBRA D7,HWRLOO REPEAT FOR 256 BYTES BSR.S PWRITE NOW WRITE SECTOR TO DISK MOVEM.L (A7)+,D0-D7/A1-A6 RTS EXIT WITH ZERO IF NO ERROR * PWRITE - PHYSICAL WRITE OF A 512-BYTE SECTOR FROM AREA POINTED * TO BY (A3)+4 * RETURNS NON-ZERO IF ERROR, AND USES DATA IN WX1DRV, WX1CYL, * WX1HD, AND WX1SEC PWRITE BSR.L CHBUSY WAIT FOR NOT BUSY BNE.L RDRTS IF ERROR LEA WX1TAB(PC),A5 POINT TO COMMAND TABLE MOVE.B #$0A,0(A5) WRITE SECTOR COMMAND MOVE.B WX1DRV,D7 DRIVE LSL.B #5,D7 MOVE INTO BIT 5 ADD.B WX1HD(PC),D7 COMBINE WITH HEAD NUMBER MOVE.B D7,1(A5) INTO TABLE MOVE.W WX1CYL(PC),D7 CYLINDER LSR.W #1,D7 MSB IN BITS 7-8 AND.B #$80,D7 ONLY BITS 7-8 ADD.B WX1SEC(PC),D7 COMBINE WITH SECTOR LSR.W #1,D7 DIVIDE BY 2 MOVE.B D7,2(A5) MSB OF CYL AND SECTOR MOVE.B WX1CYL+1(PC),D7 MOVE.B D7,3(A5) LSB OF CYL MOVE.B #1,4(A5) 1 SECTOR MOVE.B HSTEPR(PC),D7 MOVE.B D7,5(A5) STEPRATE BSR.L GIVE6 BSR.L C9WAIT WAIT FOR C9 BNE.S WRERR EXIT ON TIMEOUT LEA 4(A3),A5 POINT TO OLn BUFFER MOVE.W #510,D7 COUNTER FOR 511 BYTES WXWRLP MOVE.B (A5)+,WXDATA MOVE A BYTE MOVE.B WXSTAT,D6 CHECK STATUS AND.L #$0F,D6 CMP.B #$09,D6 CHECK IF STILL WAITING BNE.S WRERR NO, ERROR DBRA D7,WXWRLP YES, CONTINUE MOVE.B (A5)+,WXDATA MOVE LAST BYTE WRERR BSR.L CFWAIT WAIT FOR COMPLETION MOVE.B WXDATA,D7 GET COMPLETION CODE AND.B #$DF,D7 REMOVE DRIVE BIT RTS **************************** *** CHECK HARD DISK BUSY *** **************************** * CHBUSY - WAIT FOR CONTROLLER NOT BUSY BUT ABORT IF IT TAKES * TOO LONG. ACTUALLY LOOKS FOR $C0 (NOT BUSY, DATA, WRITE, AND * NOT REQ) RATHER THAN JUST NOT BUSY * USES D6 AND D7 CHBUSY MOVE.L #$200000,D7 SET UP COUNTER CHBUS1 SUB.L #1,D7 DEC COUNTER BEQ.S CHBER2 ERROR IF TOOK TOO LONG MOVE.B WXSTAT,D6 GET STATUS AND.L #$0F,D6 DELETE THE $C BNE.S CHBUS1 REPEAT IF STILL BUSY RTS CHBER2 MOVE.B #1,D7 SET NON-ZERO FOR ERROR RTS *********************************************** * ERROR PROCESSING FOR BOTH HARD READ AND WRITE *********************************************** * TRANSLATE INTO SK*DOS ERROR CODES AND * STORE IN FCB HDER9 MOVE.B #09,D6 READ ERROR BRA.S HDERR4 HDER10 MOVE.B #10,D6 WRITE ERROR BRA.S HDERR4 HDER12 MOVE.B #12,D6 PROTECTED TR 0 SEC 0 BRA.S HDERR4 HDER15 MOVE.B #15,D6 BAD DRIVE NUMBER HDERR4 MOVE.B D6,FCBERR(A4) PUT INTO FCB MOVE.B D6,ERRTYP MOVEM.L (A7)+,D0-D7/A1-A6 RTS *********************************** *** LOGICAL TO PHYSICAL CONVERT *** *********************************** * LPCONV - CONVERT DRIVE, TRACK, AND SECTOR DATA FOUND IN FCB INTO * THE PHYS DRIVE NUMBER, PHYSICAL TRACK, HEAD, AND SECTOR NUMBERS AND * PUT INTO COMMAND BLOCK, USING INFO IN APPROPRIATE WINTAB ENTRY LPCONV LEA WINTAB(PC),A3 POINT TO WINCHESTER TABLE CLR.L D3 MOVE.B FCBPHY(A4),D3 PHYSICAL DRIVE NUMBER MOVE.B D3,D4 TEMP SAVE ALSO IN D4 LSL.B #4,D3 E.G., CVT 21 T0 10 LEA 0(A3,D3.W),A3 POINT A3 TO THAT ENTRY CMP.B (A3),D4 COMPARE WINTAB ENTRY BNE.S LPERR ERROR IF WRONG DRIVE LSR.B #6,D3 DR NUM = 0 OR 1 MOVE.B 1(A3),HSTEPR SAVE STEPRATE FOR USE LATER MOVE.B D3,WX1DRV SAVE IT CLR.L D6 MOVE.B FCBCTR(A4),D6 LOGICAL TRACK CLR.L D7 MOVE.B 11(A3),D7 LOG SECT/TRACK ADD.W #1,D7 NUMBER PER TRACK MULU D7,D6 SECT BEFORE THIS TRACK CLR.L D7 MOVE.B FCBCSE(A4),D7 LOG SECTOR ADD.W D7,D6 BLOCK NUMBER MOVE.W 4(A3),D7 SECT/CYL ON HARD DISK DIVU D7,D6 REMAINDER | TRACK NUMBER ADD.W 8(A3),D6 PLUS START OF PARTITION MOVE.W D6,WX1CYL SAVE CYLINDER NUMBER LSR.L #8,D6 LSR.L #8,D6 REMAINDER IN RIGHT HALF CLR.L D7 MOVE.B 2(A3),D7 SECTORS PER TRACK DIVU D7,D6 SECTOR | HEAD MOVE.B D6,WX1HD HEAD NUMBER SWAP D6 MOVE SECTOR RIGHT MOVE.B D6,WX1SEC SECTOR NUMBER MOVE.B #0,D6 RETURN ZERO IF OK RTS LPERR MOVE.B #$02,D7 ERROR CODE FOR BAD DR NUM RTS * CDWAIT - WAIT FOR CONTROLLER READY TO RECEIVE A COMMAND BYTE * (STATUS RETURNS A $CD AS SIGNAL = BUSY COMMAND WRITE REQ) * USES D6 AND D7 CDWAIT MOVE.L #$100000,D7 SET UP COUNTER CDLOOP SUB.L #1,D7 DEC COUNTER BEQ.S WERROR ERROR IF TOOK TOO LONG MOVE.B WXSTAT,D6 GET STATUS REGISTER AND.B #$0F,D6 KEEP RIGHT 4 BITS CMP.B #$0D,D6 CHECK BUSY, COM, WRITE, REQ BNE.S CDLOOP WAIT FOR IT RTS WERROR AND.B #$FB,CCR NOT ZERO IF ERROR RTS * CFWAIT - WAIT FOR CONTROLLER READY TO RETURN COMPLETION CODE * (STATUS RETURNS A $CF AS SIGNAL = BUSY COMMAND READ REQUEST) * USES D6 AND D7 CFWAIT MOVE.L #$100000,D7 SET UP COUNTER CFLOOP SUB.L #1,D7 DEC COUNTER BEQ.S WERROR ERROR IF TOOK TOO LONG MOVE.B WXSTAT,D6 GET STATUS REGISTER AND.B #$0F,D6 KEEP RIGHT 4 BITS CMP.B #$0F,D6 CHECK BUSY, COM, READ, REQ BNE.S CFLOOP WAIT FOR IT RTS * C9WAIT - WAIT FOR CONTROLLER READY TO RETURN COMPLETION CODE * (STATUS RETURNS A $C9 AS SIGNAL = BUSY DATA WRITE REQUEST) * USES D6 AND D7 C9WAIT MOVE.L #$100000,D7 SET UP COUNTER C9LOOP SUB.L #1,D7 DEC COUNTER BEQ.S WERROR ERROR IF TOOK TOO LONG MOVE.B WXSTAT,D6 GET STATUS REGISTER AND.B #$0F,D6 KEEP RIGHT 4 BITS CMP.B #$09,D6 CHECK BUSY, DATA, WRITE, REQ BNE.S C9LOOP WAIT FOR IT RTS * CBWAIT - WAIT FOR CONTROLLER READY TO RETURN COMPLETION CODE * (STATUS RETURNS A $CB AS SIGNAL = BUSY DATA READ REQUEST) * USES D6 AND D7 CBWAIT MOVE.L #$100000,D7 SET UP COUNTER CBLOOP SUB.L #1,D7 DEC COUNTER BEQ.S WERROR ERROR IF TOOK TOO LONG MOVE.B WXSTAT,D6 GET STATUS REGISTER AND.B #$0F,D6 KEEP RIGHT 4 BITS CMP.B #$0B,D6 CHECK BUSY, DATA, WRITE, REQ BNE.S CBLOOP WAIT FOR IT RTS **************************************************** **** --- PART 1E - HARD DISK INITIALIZATION --- **** **************************************************** * HARD DISK INITIALIZATION * THIS SECTION FIRST CHECKS WHETHER THERE IS A DISK CONTROLLER, * THEN DOES A TEMPORARY INIT OF THE DRIVES * DOES A RESTORE ON ONE OR TWO DRIVES, * COPIES DATA FROM TRACK 0 SECTOR 0 OF 1 OR 2 DRIVES INTO WINTAB * AND DOES A FINAL INITIALIZATION ON THE CONTROLLER HDCOLD CLR.W INFLAG MAKE SURE 37C65 INITIALIZES LEA WINTAB(PC),A5 POINT TO WINNIE TABLE MOVE.W #31,D5 COUNTER = 128/4 - 1 INITCL MOVE.L #$FFFFFFFF,(A5)+ CLEAR WINTAB TO START OFF DBRA D5,INITCL TST.B NUMBHD CHECK NUMBER OF HD IN DOS BEQ.L INITEX EXIT IF IT SAYS 0 MOVE.L $0008,D5 TEMP SAVE OLD BUS ERR VECT LEA HDBUSE(PC),A5 MOVE.L A5,$0008 PUT IN NEW VECTOR CMP.B #$55,WDAROM+1 CHECK FOR PRESENCE OF CONTROLLER MOVEM.L D5-D5,$0008 RESTORE IF NO BUS ERR BNE.L INITEX NO WD1002 THERE CMP.B #$AA,WDAROM+3 BNE.L INITEX NO WD1002 THERE * PUT IN DUMMY SET OF DRIVE PARAMETERS FOR TWO DRIVES MOVE.B #0,WXRESE RESET CONTROLLER BSR.L CHBUSY LEA WX1TAB(PC),A5 POINT TO COMMAND TABLE MOVE.W #$0C00,0(A5) INIT PARAM COMMAND CLR.L 2(A5) REST IS ZEROES INIT2D BSR.L GIVE6 GIVE TO CONTROLLER BSR.L C9WAIT WAIT FOR BUSY AND REQ ONLY BNE.S NEXT2D ERROR IF TIMEOUT MOVE.B #0,WXDATA TEMPORARY DRIVE PARAMETERS BSR.L C9WAIT MOVE.B #100,WXDATA 100 CYLINDERS BSR.L C9WAIT MOVE.B #2,WXDATA 2 HEADS BSR.L C9WAIT MOVE.B #0,WXDATA BSR.L C9WAIT MOVE.B #128,WXDATA REDUCE WRITE CURR AT 128 BSR.L C9WAIT MOVE.B #0,WXDATA BSR.L C9WAIT MOVE.B #128,WXDATA WRITE PRECOMP AT 128 BSR.L C9WAIT MOVE.B #5,WXDATA ECC BURST LENGTH OF 5 BSR.L CFWAIT WAIT FOR COMPLETION MOVE.B WXDATA,D7 CHECK THE CODE AND.B #$DF,D7 IGNORE DRIVE BIT BNE.L INITRT ON ERROR NEXT2D LEA WX1TAB(PC),A5 POINT TO COMMAND TABLE MOVE.B 1(A5),D7 GET DRIVE NUMBER ADD.B #$20,D7 SWITCH TO DRIVE B MOVE.B D7,1(A5) STORE BACK CMP.B #$20,D7 CHECK IF STILL B BEQ.L INIT2D YES, GO DO IT * NOW TRY TO READ OUT THE REAL DRIVE PARAMS FROM DISK(S) MOVE.B #0,WXRESE RESET CONTROLLER BSR.L CHBUSY LEA WINTAB(PC),A6 POINT TO WIN TABLE A ENTRY MOVE.B #0,D5 DRIVE A BSR.L INITSU READ IF POSSIBLE LEA WINTAB(PC),A5 POINT TO WIN TABLE A ENTRY MOVE.B #$20,D5 DRIVE A STARTS WITH 20 BSR.L INITFX FIX THE PHYSICAL DRIVE NUMBERS MOVE.B NUMBHD,D5 CHECK NUMBER OF HARD DRIVES CMP.B #1,D5 ONLY 1 DRIVE? BEQ.S HDONL1 ONLY 1, SO SKIP SECOND LEA WINTAB+64(PC),A6 POINT TO WIN TABLE B ENTRY MOVE.B #$20,D5 DRIVE B BSR.L INITSU READ IF POSSIBLE LEA WINTAB+64(PC),A5 POINT TO WIN TABLE B ENTRY MOVE.B #$24,D5 DRIVE B STARTS WITH 24 BSR.L INITFX FIX THE PHYSICAL DRIVE NUMBERS * NOW PUT REAL DATA INTO DRIVE PARAMETERS HDONL1 LEA WINTAB(PC),A6 POINT TO DRIVE A TABLE LEA WX1TAB(PC),A5 POINT TO COMMAND TABLE MOVE.W #$0C00,0(A5) INIT PARAM COMMAND CLR.L 2(A5) REST IS ZEROES REAL2D TST.B (A6) IS THERE A DRIVE (A OR B)? BMI.L QUITNZ NO, QUIT BSR.L GIVE6 GIVE TO CONTROLLER BSR.L C9WAIT WAIT FOR BUSY AND REQ ONLY BNE.L QUIT2D ERROR IF TIMEOUT MOVE.B #$04,WXDATA BSR.L C9WAIT MOVE.B #0,WXDATA ASSUME 1024 CYLINDERS BSR.L C9WAIT MOVE.B 3(A6),WXDATA NUMBER OF HEADS BSR.L C9WAIT MOVE.B 14(A6),WXDATA BSR.L C9WAIT MOVE.B 15(A6),WXDATA REDUCE WRITE CURR AT PRECOMP BSR.L C9WAIT MOVE.B 14(A6),WXDATA BSR.L C9WAIT MOVE.B 15(A6),WXDATA WRITE PRECOMP BSR.L C9WAIT MOVE.B #5,WXDATA ECC BURST LENGTH OF 5 BSR.L CFWAIT WAIT FOR COMPLETION MOVE.B WXDATA,D7 CHECK THE CODE AND.B #$DF,D7 IGNORE DRIVE BIT BNE.S INITRT IF ERROR QUITNZ LEA WINTAB+64(PC),A6 POINT TO DRIVE B TABLE TST.B (A6) IS THERE A DRIVE B? BMI.S QUIT2D NO, QUIT LEA WX1TAB(PC),A5 POINT TO COMMAND TABLE MOVE.B 1(A5),D7 GET DRIVE NUMBER ADD.B #$20,D7 SWITCH TO DRIVE B MOVE.B D7,1(A5) STORE BACK CMP.B #$20,D7 CHECK IF STILL B BEQ.L REAL2D YES, GO DO IT QUIT2D RTS INITSU BSR.L CHBUSY WAIT FOR NOT BUSY BNE.S INITRT IF ERROR LEA WX1TAB(PC),A5 MOVE.B #8,0(A5) READ SECTOR COMMAND MOVE.B D5,1(A5) DRIVE CODE, HEAD 0 MOVE.L #$00000100,2(A5) CYL=SEC=STE=0 1 BLOCK BSR.L GIVE6 BSR.L CBWAIT WAIT FOR CB BNE.S INITRT EXIT ON TIMEOUT MOVE.W #62,D7 COUNTER FOR 63 BYTES INITLP MOVE.B WXDATA,(A6)+ MOVE A BYTE MOVE.B WXSTAT,D6 CHECK STATUS AND.B #$0F,D6 CMP.B #$0B,D6 CHECK IF STILL WAITING BNE.S INITEX NO, ERROR DBRA D7,INITLP YES, CONTINUE MOVE.B WXDATA,(A6)+ GET THE 64TH BYTE INITRT MOVE.B #0,WXRESE RESET CONTROLLER BSR.L CHBUSY WAIT FOR FINISH INITEX RTS THEN EXIT * INITFX - FIXES PHYSICAL DRIVE NUMBERS IN WINTAB SO DRIVE A * NUMBERS ARE 20-23, AND DRIVE B ARE 24-27 (THEY ARE 00-03 ON * THE DISK ITSELF, SO DRIVES CAN BE SWITCHED) * IF ENTRIES ARE NOT 00-03, THEN REPLACE WITH $FF - MUST BE * AN MSDOS DISK INITFX CMP.B #0,0(A5) CHECK FOR ENTRY 0 BNE.S INITF4 EMPTY ADD.B D5,0(A5) FIX IT CMP.B #1,16(A5) CHECK FOR ENTRY 1 BNE.S INITF3 EMPTY ADD.B D5,16(A5) FIX IT CMP.B #2,32(A5) CHECK FOR ENTRY 2 BNE.S INITF2 EMPTY ADD.B D5,32(A5) FIX IT CMP.B #3,48(A5) CHECK FOR ENTRY 3 BNE.S INITF1 EMPTY ADD.B D5,48(A5) FIX IT RTS INITF4 MOVE.B #$FF,0(A5) INITF3 MOVE.B #$FF,16(A5) INITF2 MOVE.B #$FF,32(A5) INITF1 MOVE.B #$FF,48(A5) RTS * IF WE GET A BUS ERROR ON TRYING TO ACCESS HARD DISK, COME HERE, * FIX PROBLEM, AND GRACEFULLY EXIT HDBUSE MOVEM.L D5-D5,$0008 RESTORE ERROR VECTOR ADD.L #14,A7 DELETE STACKED ERROR RTS * DATA AREA FOR HARD DISK WX1TAB DC.W 0,0,0 6-BYTE COMMAND BLOCK FOR WX1 WX1DRV DS.B 1 DESIRED DRIVE NUMBER DS.B 1 EMPTY WX1CYL DS.W 1 CYLINDER NUMBER TO USE WX1HD DS.B 1 HEAD NUMBER TO USE WX1SEC DS.B 1 SECTOR NUMBER TO USE IF 256 * DATA AREA FOR DRIVE 0 OL0CYL DC.W 0 OLD CYLINDER NOW IN WX0BUF OLD0HD DC.B 255 OLD HEAD OL0SEC DC.B 0 OLD SECTOR NUMBER WX0BUF DS.B 512 512-BYTE SEC BUFR FOR DRV 0 * DATA AREA FOR DRIVE 1 OL1CYL DC.W 0 OLD CYLINDER NOW IN WX1BUF OLD1HD DC.B 255 OLD HEAD OL1SEC DC.B 0 OLD SECTOR NUMBER WX1BUF DS.B 512 512-BYTE SEC BUFR FOR DRV 1 HSTEPR DC.B 0 STEPRATE TO USE ****************************************** **** --- PART 2 - CONSOLE DRIVERS --- **** ****************************************** * CONVENTIONS: D1-D5 AND A1-A5 MUST BE PRESERVED * (EXCEPT WHEN D5 IS FOR INPUT) * OTHER REGISTERS ARE SCRATCH * SYSTEM AND DUART PORT REFERENCES ROM EQU $F80000 HUMBUG ROM BNWADD EQU $FA0769 BNWRAM EQU $D60000 CATTR EQU $FF0C7C CCURH EQU $FF0C7F CCURV EQU $FF0C7E CCURSZ EQU $FF0C83 COLADD EQU $FA07A9 COLRAM EQU $D70000 COSTAT EQU $FA07B5 DCTLOW EQU 15 DCTUPR EQU 13 DDATAA EQU 7 DINCHG EQU 9 DOPORT EQU 27 DSTATA EQU 3 DUART1 EQU $FE0000 ICTCHR EQU $FF0CA8 ICTFLG EQU $FF0CAA INQCHR EQU $FF0C9F INQFLG EQU $FF0C9E KBA EQU $FF0C9D KBS EQU $FF0C9C KCLEAR EQU $FE01C1 KDATA EQU $FE01C3 MATTR EQU $FF0C7D MCURH EQU $FF0C81 MCURV EQU $FF0C80 MCURSZ EQU $FF0C82 PORADM EQU $FF0C00 STATSI EQU $FF0C7A STATSO EQU $FF0C7B ********************************************* * SERINI - SERIAL PORT INITIALIZATION ROUTINE * AND * KILLTA - ERASE TYPEAHEAD BUFFER ********************************************* SERINI MOVE.L $0074,A6 OLD LVL 5 POINTER MOVE.L A6,L5ADDR SAVE IT LEA KBISS,A6 POINT TO OUR INTERRUPT ROUTINE MOVE.L A6,$0074 KILLTA CLR.W KBIPTR CLEAR POINTERS CLR.W KBOPTR CLR.B INQFLG CLR.B ICTFLG RTS * CONSOLE INPUT PORT STATUS CHECK - MULTIPLE * * INPUT: NONE * OUTPUT: RETURN ZERO IF NO CHARACTER READY, * NON-ZERO IF CHARACTER IS THERE * D5=1 TO SHOW 1 CHARACTER READY * REGISTERS USED: NONE STATM BTST #0,STATSI CHECK STATUS BNE.S INCHE0 SERIAL IF BIT0=1 MOVEM.L D7-D7,-(A7) ELSE CHECK CLONE KBD MOVE.W KBOPTR,D7 CMP.W KBIPTR,D7 IS TYPEAHEAD EMPTY? MOVEM.L (A7)+,D7-D7 RTS AND RETURN * CONSOLE INPUT PORT STATUS CHECK - SINGLE CHAR * * INPUT: NONE * OUTPUT: RETURN ZERO IF NO CHARACTER READY, * NON-ZERO IF CHARACTER IS THERE * D5=1 TO SHOW 1 CHARACTER READY * REGISTERS USED: NONE STAT BTST #0,STATSI CHECK STATUS BNE.S INCHE0 SERIAL IF BIT0=1 TST.B INQFLG ELSE CHECK CLONE KEYBOARD RTS AND RETURN * CHECK SERIAL PORT INCHE0 MOVEM.L A6-A6,-(A7) MOVE.L PORADM,A6 POINT TO PORT BTST #0,DSTATA(A6) CHECK RDRF FLAG MOVEM.L (A7)+,A6-A6 RTS AND RETURN WITH IT * OUTPUT PORT STATUS CHECK. * * INPUT: NONE * OUTPUT: RETURN ZERO IF NOT READY * REGISTERS USED: NONE OSTAT BTST #2,DUART1+DSTATA CHECK TX READY BIT RTS RETURN WITH ZERO IF NOTHING * OUTPUT CHARACTER IN D5 TO TERMINAL * * INPUT: D5 HOLDS CHARACTER TO OUTPUT * OUTPUT: NONE * REGISTERS USED: NONE (MUST PRESERVE D5) OUT3ES EXG D4,D5 MOVE IT INTO D4 BTST #6,STATSO PRINT ON SER PORT? BEQ.S NOTPTR NO BSR.L OUTCHM YES NOTPTR BTST #5,STATSO PRINT ON B&W BOARD? BEQ.S NOTPTB NO BSR.L OUTCHB YES NOTPTB BTST #4,STATSO PRINT ON COLOR BOARD? BEQ.L NOTPTC NO BSR.L OUTCHC YES NOTPTC EXG D4,D5 RESTORE BOTH TST.W MTIMER CHECK IF MOTOR IS ON BEQ.S NOTPRTS NO, SO EXIT SUB.W #55,MTIMER BPL.S NOTPRTS MOVE.B #$04,REGOPER ELSE TURN MOTOR OFF CLR.W MTIMER AND SIGNAL MTIMER NOTPRTS RTS *********************************************************** * OUTPUT ON CONTROL PORT (MAIN CONSOLE) *********************************************************** OUTCHM MOVEM.L A6-A6,-(A7) MOVE.L PORADM,A6 POINT TO MAIN PORT OUTCHE BTST #2,DSTATA(A6) CHECK TDRE BEQ.S OUTCHE WAIT UNTIL READY MOVE.B D4,DDATAA(A6) PRINT IT MOVEM.L (A7)+,A6-A6 RTS *********************************************************** * OUTPUT ON MONOCHROME VIDEO BOARD *********************************************************** OUTCHB MOVEM.L D6-D7,-(A7) CMP.B #8,D4 BACKSPACE? BEQ.L BS CMP.B #$0D,D4 CARRIAGE RETURN? BEQ.L CR CMP.B #$0A,D4 LINE FEED? BEQ.S LF CMP.B #$1A,D4 CLEAR SCREEN? BEQ.L CLRSCR CMP.B #$07,D4 BELL? BEQ.L BELL CMP.B #$0B,D4 VERT TAB? BEQ.L VT CMP.B #$0C,D4 NON-DESTRUCTIVE SPACE? BEQ.S FF CMP.B #$7F,D4 RUBOUT? BEQ.L MRTS * IT'S EITHER CONTROL, NORMAL, OR >127 MOVE.B D4,D7 AND.B #$60,D7 CONTROL OR MINUS? BEQ.L MRTS YES, DON'T DO * NOW DO NORMAL CHARACTER CLR.L D7 MOVE.B MCURH,D7 MOVE.W D7,-(A7) PUSH CURH ON STACK MOVE.B MCURV,D7 NOW COMPUTE VIDRAM LOC MULU #80,D7 ADD.W (A7)+,D7 POS ON SCREEN ASL.L #2,D7 *4 ADD.L #BNWRAM+1,D7 FINALLY THE ADDRESS MOVE.L D7,A6 POINT TO IT MOVE.B D4,(A6) DISPLAY CHAR ON SCREEN MOVE.B MATTR,D7 MOVE.B D7,2(A6) AND ALSO ATTRIBUTE FF ADD.B #1,MCURH MOVE CURSOR RIGHT MOVE.B MCURH,D7 CMP.B #79,D7 END OF LINE? BLE.S MRTS NO CLR.B MCURH YES, GO TO BEG OF NEXT LF MOVE.B MCURV,D7 GET VERTICAL POSITON CMP.B #24,D7 BOTTOM OF SCREEN? BEQ.S SCROLL YES, SO GO SCROLL * NOT YET AT BOTTOM ADD.B #1,MCURV MOVE CURSOR DOWN 1 * TWO EXITS: MRTS IF CURSOR MOVES, MRTS1 IF IT DOESN'T MRTS CLR.L D6 MOVE.B MCURH,D6 CLR.L D7 MOVE.B MCURV,D7 NOW COMPUTE VIDRAM LOC MULU #80,D7 ADD.W D7,D6 POS ON SCREEN MOVE.B #15,BNWADD MOVE.B D6,BNWADD+2 LSB OF CURSOR ADDRESS LSR.W #8,D6 MOVE.B #14,BNWADD MOVE.B D6,BNWADD+2 MSB OF CURSOR ADDRESS MOVE.B #10,BNWADD MOVE.B MCURSZ,D6 MOVE.B D6,BNWADD+2 TURN ON CURSOR MRTS1 MOVEM.L (A7)+,D6-D7 RTS AND RETURN * ONCE AT BOTTOM, SCROLL SCROLL LEA BNWRAM,A6 POINT TO TOP OF SCREEN RAM MOVE.W #239,D7 DO (24*80)/8=240 TIMES SCRO1 MOVE.L 320(A6),(A6)+ MOVE.L 320(A6),(A6)+ MOVE.L 320(A6),(A6)+ MOVE UP 4 CHARACTERS MOVE.L 320(A6),(A6)+ MOVE.L 320(A6),(A6)+ MOVE.L 320(A6),(A6)+ MOVE.L 320(A6),(A6)+ MOVE.L 320(A6),(A6)+ DBRA D7,SCRO1 * FINALLY, ERASE BOTTOM LINE MOVE.L #79,D7 ERASE 80 CHARACTERS MOVE.L A5,-(A7) LEA BNWRAM+7680,A5 POINT TO BOTTOM LINE MOVE.L #$00200000,D6 SPACE MOVE.B MATTR,D6 AND ATTRIBUTE ERBOTL MOVE.L D6,(A5)+ STORE IT DBRA D7,ERBOTL REPEAT CLR.B MCURH SET UP CURSOR POSITION MOVE.B #24,MCURV AT BEG OF LAST LINE MOVE.L (A7)+,A5 BRA.L MRTS * DO BACKSPACE BS TST.B MCURH POSITION BEQ.L MRTS1 IGNORE IF AT BEG OF LINE SUB.B #1,MCURH ELSE MOVE CURSOR LEFT 1 BRA.L MRTS * DO VERTICAL TAB VT TST.B MCURV POSITION BEQ.L MRTS1 IGNORE IF AT TOP OF SCREEN SUB.B #1,MCURV ELSE MOVE UP 1 LINE BRA.L MRTS * CARRIAGE RETURN CR CLR.B MCURH BRA.L MRTS * ERASE THE SCREEN. THIS ROUTINE STORES 00'S INTO UNUSED * EVEN) BYTES OF VIDEO MEMORY, BUT THIS SHOULD BE OK - THEY * DON'T GO ANYWHERE CLRSCR MOVE.L #1999,D7 ERASE (25X80) CHARS MOVE.L A5,-(A7) LEA BNWRAM,A5 POINT TO SCREEN RAM MOVE.L #$00200000,D6 SPACE MOVE.B MATTR,D6 AND ATTRIBUTE CLSLOO MOVE.L D6,(A5)+ DBRA D7,CLSLOO REPEAT CLR.B MCURH SET UP CURSOR POSITION CLR.B MCURV AT TOP LEFT OF SCREEN MOVE.L (A7)+,A5 BRA.L MRTS * RING BELL BELL MOVE.B #$04,DUART1+DCTUPR MOVE.B #$55,DUART1+DCTLOW SET TONE FREQUENCY MOVE.B #$04,DUART1+DOPORT TURN ON CTR/TMR OUTPUT ON OP3 MOVE.W #$6000,D7 BELOOP MULU #1,D7 WAIT A BIT DBRA D7,BELOOP MOVE.B #$00,DUART1+DOPORT TURN OFF CTR/TMR OUTPUT BRA.L MRTS1 *********************************************************** * OUTPUT ON COLOR VIDEO BOARD *********************************************************** OUTCHC MOVEM.L D6-D7,-(A7) CMP.B #8,D4 BACKSPACE? BEQ.L CBS CMP.B #$0D,D4 CARRIAGE RETURN? BEQ.L COLRCR CMP.B #$0A,D4 LINE FEED? BEQ.L CLF CMP.B #$1A,D4 CLEAR SCREEN? BEQ.L CCLRSC CMP.B #$07,D4 BELL? BEQ.L CBELL CMP.B #$0B,D4 VERT TAB? BEQ.L CVT CMP.B #$0C,D4 NON-DESTRUCTIVE SPACE? BEQ.S CFF CMP.B #$7F,D4 RUBOUT? BEQ.L CRTS * IT'S EITHER CONTROL, NORMAL, OR >127 MOVE.B D4,D7 AND.B #$60,D7 CONTROL OR MINUS? BEQ.L CRTS YES, DON'T DO * NOW DO NORMAL CHARACTER CLR.L D7 MOVE.B CCURH,D7 MOVE.W D7,-(A7) PUSH CURH ON STACK MOVE.B CCURV,D7 NOW COMPUTE VIDRAM LOC MULU #80,D7 ADD.W (A7)+,D7 POS ON SCREEN ASL.L #2,D7 *4 ADD.L #COLRAM+1,D7 FINALLY THE ADDRESS MOVE.L D7,A6 POINT TO IT MOVE.B CATTR,D7 BTST #3,STATSO CHECK IF FAST OR SLOW BNE.S W1 1=SLOW * DO THIS SECTION IF DOING FAST ACCESS WITH SNOW MOVE.B D4,(A6) DISPLAY CHAR ON SCREEN BRA.S NORCON * DO THIS SECTION IF DOING SLOW ACCESS FOR NO SNOW W1 BTST #0,COSTAT CHECK IF OK TO ACCESS BEQ.S W1 NO MOVE.B D4,(A6) DISPLAY CHAR ON SCREEN W2 BTST #0,COSTAT CHECK IF OK TO ACCESS BEQ.S W2 NO * AND NOW CONTINUE NORCON MOVE.B D7,2(A6) AND ALSO ATTRIBUTE CFF ADD.B #1,CCURH MOVE CURSOR RIGHT MOVE.B CCURH,D7 CMP.B #79,D7 END OF LINE? BLE.S CRTS NO CLR.B CCURH YES, GO TO BEG OF NEXT CLF MOVE.B CCURV,D7 GET VERTICAL POSITON CMP.B #24,D7 BOTTOM OF SCREEN? BEQ.S CSCROL YES, SO GO SCROLL * NOT YET AT BOTTOM ADD.B #1,CCURV MOVE CURSOR DOWN 1 * TWO EXITS: CRTS IF CURSOR MOVES, CRTS1 IF IT DOESN'T CRTS CLR.L D6 MOVE.B CCURH,D6 CLR.L D7 MOVE.B CCURV,D7 NOW COMPUTE VIDRAM LOC MULU #80,D7 ADD.W D7,D6 POS ON SCREEN MOVE.B #15,COLADD MOVE.B D6,COLADD+2 LSB OF CURSOR ADDRESS LSR.W #8,D6 MOVE.B #14,COLADD MOVE.B D6,COLADD+2 MSB OF CURSOR ADDRESS MOVE.B #10,COLADD MOVE.B CCURSZ,D6 MOVE.B D6,COLADD+2 TURN ON CURSOR CRTS1 MOVEM.L (A7)+,D6-D7 RTS AND RETURN * ONCE AT BOTTOM, SCROLL CSCROL LEA COLRAM,A6 POINT TO TOP OF SCREEN RAM MOVE.W #1919,D7 DO (24*80)/8 TIMES BTST #3,STATSO CHECK IF FAST OR SLOW BNE.S CSCRO1 1=SLOW * DO THIS SECTION IF DOING FAST ACCESS WITH SNOW CSCRO0 MOVE.L 320(A6),(A6)+ DBRA D7,CSCRO0 BRA.S CSRCON * DO THIS SECTION IF DOING SLOW ACCESS FOR NO SNOW CSCRO1 BTST #0,COSTAT CHECK IF OK TO ACCESS BEQ.S CSCRO1 NO MOVE.L 320(A6),D6 W3 BTST #0,COSTAT CHECK IF OK TO ACCESS BEQ.S W3 NO MOVE.L D6,(A6)+ DBRA D7,CSCRO1 * AND NOW CONTINUE * FINALLY, ERASE BOTTOM LINE CSRCON MOVE.L #79,D7 ERASE 80 CHARACTERS MOVE.L A5,-(A7) LEA COLRAM+7680,A5 POINT TO BOTTOM LINE MOVE.L #$00200000,D6 SPACE MOVE.B CATTR,D6 AND ATTRIBUTE BTST #3,STATSO CHECK IF FAST OR SLOW BNE.S CERBOT 1=SLOW * DO THIS SECTION IF DOING FAST ACCESS WITH SNOW CERBO0 MOVE.L D6,(A5)+ STORE IT DBRA D7,CERBO0 REPEAT BRA.S CONCER * DO THIS SECTION IF DOING SLOW ACCESS FOR NO SNOW CERBOT BTST #0,COSTAT CHECK IF OK TO ACCESS BEQ.S CERBOT NO MOVE.L D6,(A5)+ STORE IT DBRA D7,CERBOT REPEAT CONCER CLR.B CCURH SET UP CURSOR POSITION MOVE.B #24,CCURV AT BEG OF LAST LINE MOVE.L (A7)+,A5 BRA.L CRTS * DO BACKSPACE CBS TST.B CCURH POSITION BEQ.L CRTS1 IGNORE IF AT BEG OF LINE SUB.B #1,CCURH ELSE MOVE CURSOR LEFT 1 BRA.L CRTS * DO VERTICAL TAB CVT TST.B CCURV POSITION BEQ.L CRTS1 IGNORE IF AT TOP OF SCREEN SUB.B #1,CCURV ELSE MOVE UP 1 LINE BRA.L CRTS * CARRIAGE RETURN COLRCR CLR.B CCURH BRA.L CRTS * ERASE THE SCREEN. THIS ROUTINE STORES 00'S INTO UNUSED * EVEN) BYTES OF VIDEO MEMORY, BUT THIS SHOULD BE OK - THEY * DON'T GO ANYWHERE CCLRSC MOVE.L #1999,D7 ERASE (25X80) CHARS MOVE.L A5,-(A7) LEA COLRAM,A5 POINT TO SCREEN RAM MOVE.L #$00200000,D6 SPACE MOVE.B CATTR,D6 AND ATTRIBUTE BTST #3,STATSO CHECK IF FAST OR SLOW BNE.S CCLSLO 1=SLOW * DO THIS SECTION IF DOING FAST ACCESS WITH SNOW CCLFAS MOVE.L D6,(A5)+ DBRA D7,CCLFAS REPEAT BRA.S CCLCON * DO THIS SECTION IF DOING SLOW ACCESS FOR NO SNOW CCLSLO BTST #0,COSTAT CHECK IF OK TO ACCESS BEQ.S CCLSLO NO MOVE.L D6,(A5)+ DBRA D7,CCLSLO REPEAT * NOW CONTINUE CCLCON CLR.B CCURH SET UP CURSOR POSITION CLR.B CCURV AT TOP LEFT OF SCREEN MOVE.L (A7)+,A5 BRA.L CRTS * RING BELL CBELL MOVE.B #$04,DUART1+DCTUPR MOVE.B #$55,DUART1+DCTLOW SET TONE FREQUENCY MOVE.B #$04,DUART1+DOPORT TURN ON CTR/TMR OUTPUT ON OP3 MOVE.W #$6000,D7 CBLLOO MULU #1,D7 WAIT A BIT DBRA D7,CBLLOO MOVE.B #$00,DUART1+DOPORT TURN OFF CTR/TMR OUTPUT BRA.L CRTS1 * INPUT CHARACTER INTO D5 AND ECHO IT * * INPUT: NONE * OUTPUT: D5 HOLDS 7-BIT CHARACTER INPUT * REGISTERS USED: PRESERVED (EXCEPT D5 HOLDS CHAR) INEEE BSR.L INCH8M GET INPUT CHARACTER MULTIPLE AND.B #$7F,D5 MASK OUT PARITY BRA.L OUT3ES AND THEN PRINT IT *********************************************************** * GET 8-BIT CHARACTER FROM KEYBOARD INTO D5 USING NORMAL, * ONE CHARACTER-AT-A-TIME ROUTINE *********************************************************** INCH8 BTST #0,STATSI CHECK STATUS BNE.L INCH8S SERIAL IF BIT0=1 * POSITION CURSOR IF A VIDEO BOARD EXISTS BTST #5,STATSO CHECK FOR MONO BOARD BEQ.S NOBCUR NO BW CURSOR BSR.S DOBCUR YES, GO MOVE IT NOBCUR BTST #4,STATSO CHECK FOR COLOR BOARD BEQ.S INCH8C NO COLOR CURSOR BSR.S DOCCUR YES, GO MOVE IT INCH8C TST.B INQFLG THEN CHECK CLONE KEYBOARD BEQ.S INCH8C WAIT IF NOTHING THERE MOVE.B INQCHR,D5 THEN GET CHARACTER CLR.B INQFLG CLEAR FLAGS CLR.B ICTFLG RTS AND RETURN DOBCUR MOVEM.L D6-D7,-(A7) PUSH BRA.L MRTS AND GO DO IT DOCCUR MOVEM.L D6-D7,-(A7) PUSH BRA.L CRTS AND GO DO IT *********************************************************** * GET 8-BIT CHARACTER FROM KEYBOARD INTO D5, USING TYPEAHEAD * BUFFER *********************************************************** INCH8M BTST #0,STATSI CHECK STATUS BNE.L INCH8S SERIAL IF BIT0=1 * POSITION CURSOR IF A VIDEO BOARD EXISTS BTST #5,STATSO CHECK FOR MONO BOARD BEQ.S KBBCUR NO BW CURSOR BSR.S DOBCUR YES, GO MOVE IT KBBCUR BTST #4,STATSO CHECK FOR COLOR BOARD BEQ.S KBITYC NO COLOR CURSOR BSR.S DOCCUR YES, GO MOVE IT KBITYC MOVEM.L D6/A6,-(A7) PUSH KBITYD MOVE.W KBOPTR(PC),D6 GET OUTPUT POINTER CMP.W KBIPTR(PC),D6 CHECK AGAINST INPUT BEQ.S KBITYD EMPTY IF SAME LEA KBBUFF(PC),A6 ELSE POINT TO BUFFER MOVE.B 0(A6,D6.W),D5 GET NEXT BYTE ADD.W #1,D6 BUMP POINTER AND.W #$003F,D6 MOD 64 LEA KBOPTR(PC),A6 MOVE.W D6,(A6) RESTORE IT MOVEM.L (A7)+,D6/A6 CLR.B INQFLG CLEAR FLAGS CLR.B ICTFLG RTS AND RETURN *********************************************************** * GET 8-BIT CHARACTER FROM SERIAL PORT *********************************************************** INCH8S MOVEM.L A6-A6,-(A7) MOVE.L PORADM,A6 POINT TO PORT INCH8A BTST #0,DSTATA(A6) CHECK STATUS OF PORT BEQ.S INCH8A WAIT IF NOTHING MOVE.B DDATAA(A6),D5 ELSE GET CHARACTER MOVEM.L (A7)+,A6-A6 RTS * KEYBOARD INPUT INTO D5 WITHOUT ECHO * * INPUT: NONE * OUTPUT: D5 HOLDS 8-BIT CHARACTER INPUT * REGISTERS USED: PRESERVED (EXCEPT D5 HOLDS CHAR) KINPUT TST.W MTIMER CHECK IF MOTOR IS ON BEQ.S KINPUM NO, SO EXIT MOVE.B #$04,REGOPER ELSE TURN MOTOR OFF CLR.W MTIMER AND SIGNAL MTIMER KINPUM BRA.L INCH8M USE INCH8 MULTIPLE * I CONTROL - DO FUNCTION 0005 (RETURN A SPECIAL * CHARACTER FROM DEVICE) * INPUT: D4.W CONTAINS THE ICNTRL CODE * OUTPUT: D5 HOLDS 8-BIT CHARACTER INPUT * REGISTERS USED: PRESERVED (EXCEPT D5 HOLDS CHAR) BICONT CMP.W #$0005,D4 GET SPECIAL CHARACTER? BEQ.S ICTRNL YES, GET IT CLR.L D5 ON ERROR RETURN ZERO AND.B #$FB,CCR BUT SIGNAL NON-ZERO RTS *********************************************************** * GET 8-BIT CHARACTER FROM ICNTRL KEYBOARD INTO D5. IF A * SERIAL KEYBORD IS BEING USED, THEN THIS DEFAULTS TO IT *********************************************************** ICTRNL BTST #0,STATSI CHECK STATUS BNE.L INCH8S SERIAL IF BIT0=1 * POSITION CURSOR IF A VIDEO BOARD EXISTS BTST #5,STATSO CHECK FOR MONO BOARD BEQ.S NCBCUR NO BW CURSOR BSR.S DCBCUR YES, GO MOVE IT NCBCUR BTST #4,STATSO CHECK FOR COLOR BOARD BEQ.S ICNTRC NO COLOR CURSOR BSR.S DCCCUR YES, GO MOVE IT ICNTRC TST.B ICTFLG THEN CHECK CLONE KEYBOARD BEQ.S ICNTRC WAIT IF NOTHING THERE MOVE.W ICTCHR,D5 THEN GET CHARACTER CLR.B INQFLG CLEAR FLAGS CLR.B ICTFLG RTS AND RETURN DCBCUR MOVEM.L D6-D7,-(A7) PUSH BRA.L MRTS AND GO DO IT DCCCUR MOVEM.L D6-D7,-(A7) PUSH BRA.L CRTS AND GO DO IT *************************************************** * INTERRUPT SERVICE SUBROUTINE * REMEMBER TO PRESERVE REGISTERS *************************************************** KBISS BTST #6,DUART1+DINCHG CHECK WHETHER KB CAUSED IT AND CLEAR BEQ.L LVL5IA EXIT IF NOT BTST #2,DUART1+DINCHG CHECK WHETHER HIGH OR LOW BNE.S KBRTE3 EXIT IF IT WENT HIGH MOVEM.L D5-D7/A5,-(A7) CLR.L D5 IF IT WENT LOW, GET READY MOVE.B KDATA,D5 GET SCAN CODE BEQ.S KBRTE2 SKIP IF ZERO TST.B KCLEAR CLEAR KEYBOARD BSR.L CONVERT CONVERT TO ASCII IN D5 BEQ.S MAYBD6 IGNORE IF NOTHING THERE BTST #3,KBS ALTERNATE? BEQ.S NOALT1 NO OR.B #$80,D5 YES, SET BIT 8 NOALT1 BSR.L KBSAVE SAVE NEW CHARACTER MAYBD6 TST.W D6 CHECK FOR CONTROL CODE BEQ.S KBRTE0 IGNORE IF NOTHING THERE BTST #3,KBS ALTERNATE? BEQ.S NOALT2 NO OR.B #$80,D6 YES, SET BIT 8 NOALT2 MOVE.W D6,ICTCHR ELSE PUT IN MOVE.B #1,ICTFLG AND SET THE FLAG LSL.B #1,D6 LOOK AT D6 CODE AGAIN BEQ.S DONULL NULL IF ALL ZEROES KBRTE0 MOVEM.L (A7)+,D5-D7/A5 KBRTE1 RTE THEN RETURN KBRTE2 MOVEM.L (A7)+,D5-D7/A5 KBRTE3 TST.B KCLEAR CLEAR KEYBOARD RTE THEN RETURN * ALLOW NULL CHARACTER ON VERSION 1.1 AND LATER DONULL BTST #3,KBS ALTERNATE NULL? BEQ.S NOALT3 NO OR.B #$80,D5 YES, SET BIT 7 NOALT3 BSR.L KBSAVE SAVE THE NULL BRA.S KBRTE0 AND EXIT * ROUTINE TO SAVE CHARACTER FROM D5 IN BOTH SINGLE-CHAR * MODE, AND ALSO INTO TYPEAHEAD BUFFER, ON VER 1.8 & LATER * D5.B HAS CHAR. D6 AND A5 USED, D7 FREE KBSAVE MOVE.B D5,INQCHR SAVE THE CHAR MOVE.W KBOPTR(PC),D7 OUTPUT POINTER SUB.W KBIPTR(PC),D7 SUBTRACT INPUT PTR AND.W #$3F,D7 MOD 64 CMP.W #1,D7 FULL? BEQ.S KBFULL YES MEANS BUFFER FULL MOVE.W KBIPTR(PC),D7 WHERE TO PUT LEA KBBUFF(PC),A5 BUFFER MOVE.B D5,0(A5,D7.W) PUT CHAR INTO IT ADD.W #1,D7 BUMP POINTER AND.W #$3F,D7 MOD 64 LEA KBIPTR(PC),A5 MOVE.W D7,(A5) RESTORE POINTER KBSETF MOVE.B #1,INQFLG SET THE FLAG RTS * IF BUFFER IS FULL, CHECK INDIVIDUAL CHAR FLAG TOO. IF * SET, THEN THERE'S CHARACTER OVERFLOW SO BEEP; IF NOT, THEN * MAYBE THE USER IS USING SINGLE CHAR, NOT TYPEAHEAD SO IT'S OK KBFULL TST.B INQFLG CHECK INDIVIDUAL FLAG BEQ.S KBSETF PROBABLY IS OK MOVE.B #$00,DUART1+DCTLOW LOWER BYTE = 0 MOVE.B #$20,DUART1+DCTUPR START AT 32 MOVE.B #$04,DUART1+DOPORT TURN ON CTR/TMR MOVE.B #$20,D6 OKBLOO MOVE.B D6,DUART1+DCTUPR MOVE.W #$0200,D7 IKBLOO MULU #1,D7 WAIT DBRA D7,IKBLOO DBRA D6,OKBLOO MOVE.B #$00,DUART1+DOPORT TURN OFF CTR/TIMER RTS *************************************************** * SUBROUTINE TO CONVERT CODE IN D5 INTO ASCII IN D5 *************************************************** CONVERT MOVE.B D5,D6 SAVE AND CHECK ORIG CODE BMI.L RELEAS RELEASING KEY CMP.B #70,D5 SCROLL LOCK? BEQ.L CHKSCR CHECK IF A BREAK NOTBR1 CMP.B #83,D5 DEL? BEQ.L CHKDEL CHECK IF A BREAK NOTBR2 CMP.B #55,D5 PRT-SCRN? BEQ.L CHKPRS CHECK IF A PRINT SCREEN NOTBR3 LEA KEYTAB(PC),A5 POINT TO KEY TABLE MULU #12,D5 ADD.L D5,A5 POINT TO TABLE LINE ********** * WE COME HERE WHEN WE ARE PRESSING KEY DOWN ********** TST.W 0(A5) CHECK CONVERTED CODE BEQ.L SPESHL SPECIAL IF MINUS * NORMAL KEYS WITH ASCII CODES BTST #2,KBS IN CONTROL MODE? BNE.S COLUM3 YES, USE TABLE COL 3 BTST #5,KBS IN NUMLOCK MODE? BEQ.S NOTNML NO TST.W 10(A5) CHECK 4TH COLUMN BPL.S COLUM4 USE IT IF EXISTS NOTNML BTST #0,KBS SHIFT KEY DOWN? BNE.S YSHIFT YES, MAYBE COL 2 BTST #6,KBS NO SHIFT, CHK CAPS LOCK BEQ.S COLUM1 NEITHER, USE COLUMN 1 MOVE.B 0(A5),D7 CHECK CHARACTER CMP.B #'a',D7 BCS.S COLUM1 COL 1 IF CL BUT NOT LETR CMP.B #'z',D7 BHI.S COLUM1 DITTO BRA.S COLUM2 COL 2 IF CL AND LETTER YSHIFT BTST #6,KBS SHIFT, CHK CAPS LOCK BEQ.S COLUM2 ONLY SHIFT, USE COL 2 MOVE.B 0(A5),D7 BOTH, CHECK CHARACTER CMP.B #'a',D7 BCS.S COLUM2 COL 2 BOTH BUT NOT LETR CMP.B #'z',D7 BHI.S COLUM2 DITTO * AND FALL THROUGH INTO COL 1 IF BOTH AND LETTER COLUM1 MOVE.L 0(A5),D6 LSR.L #8,D6 CONTROL CODE IN D6 MOVE.B 0(A5),D5 REGULAR CODE IN D5 RTS COLUM2 MOVE.W 4(A5),D6 CONTROL CODE IN D6 MOVE.B 3(A5),D5 REGULAR CODE IN D5 RTS COLUM3 MOVE.L 6(A5),D6 LSR.L #8,D6 CONTROL CODE IN D6 MOVE.B 6(A5),D5 REGULAR CODE IN D5 RTS COLUM4 MOVE.W 10(A5),D6 CONTROL CODE IN D6 MOVE.B 9(A5),D5 REGULAR CODE IN D5 RTS * ABNORMAL KEYS WITHOUT ASCII CODES, SIGNALLED BY NO ENTRY * IN THE KEY TABLE SPESHL TST.B D6 CHECK SCAN CODE BEQ.S CCRTS 00 = NOTHING THERE CMP.B #29,D6 BEQ.S CTRLDN CONTROL DOWN CMP.B #42,D6 BEQ.S SHFTDN LEFT SHIFT DOWN CMP.B #54,D6 BEQ.S SHFTDN RIGHT SHIFT DOWN CMP.B #56,D6 BEQ.S ALTDN ALTERNATE DOWN CMP.B #58,D6 BEQ.L CAPSDN CAPS LOCK DOWN CMP.B #69,D6 BCS.S CCRTS IGNORE ALL FUNCTION KEYS BEQ.L NUMLDN NUM LOCK DOWN RTS ELSE QUIT * CONTROL KEY WENT DOWN CTRLDN BSET #2,KBS SET CONTROL BIT IN KBS CCRTS CLR.B D5 RETURN NOTHING CLR.W D6 RTS * ALTERNATE-KEY WENT DOWN ALTDN BSET #3,KBS SET ALT BIT IN KBS BRA.S CCRTS * SHIFT KEY WENT DOWN SHFTDN BSET #0,KBS SET SHIFT BIT IN KBS BRA.S CCRTS * SCROLL-LOCK WENT DOWN - RETURN TO SK*DOS IF IN CONTROL AND * NOT CURRENTLY IN IT CHKSCR BTST #2,KBS CHECK WHETHER CONTROL BEQ.L NOTBR1 IGNORE IF NO MOVE.W $1000,D7 CMP.W #$4EF9,D7 CHECK IF SK*DOS IS LOADED BNE.L SKISNO NO, NOT LOADED TST.B INDOS YES, ARE WE IN IT CURRENTLY? BNE.S CCRTS YES, SO DON'T BREAK MOVE.B #$00,DUART1+DOPORT TURN OFF CTR/TMR OUTPUT MOVE.L BREAK,A5 GET SK*DOS BREAKA ADDR MOVE.W 20(A7),D7 SR OF INTERRUPTED PROGRAM MOVE.W D7,D6 COPY IT AND.W #$0700,D6 INTERRUPT LEVEL BITS CMP.W #$0500,D6 NEED AT LEAST LVL 5 FOR KBD BCS.S GOT4 OK IF <=4 MOVE.W #$0400,D6 IF >4 MAKE IT 4 GOT4 BSET #13,D6 ASSUME SYSTEM STATE BTST #13,D7 IS OLD SR SYSTEM STATE? BNE.S RETSYS YES, SO EXIT IN SYSTEM STATE CMP.L #$1006,A5 RETURN TO SK*DOS WARMSTART? BEQ.S RETSYS YES, SO GO IN SYSTEM STATE BCLR #13,D6 NO, SO RETURN IN USER STATE RETSYS MOVE.W D6,SR SET UP RETURN SR ADD.L #26,A7 REMOVE 26 BYTES FROM STACK JMP (A5) AND RETURN TO SK*DOS * CAPS LOCK KEY WENT DOWN - LOCK IF PREVIOUSLY UP CAPSDN BTST #6,KBA CHECK IF DOWN BNE.L CCRTS IGNORE IF ALREADY DOWN BSET #6,KBA MARK IT DOWN IF NOW UP BCHG #6,KBS AND TOGGLE IT IN STATUS BRA.L CCRTS THEN EXIT * NUM LOCK KEY WENT DOWN - LOCK IF PREVIOUSLY UP NUMLDN BTST #5,KBA CHECK IF DOWN BNE.L CCRTS IGNORE IF ALREADY DOWN BSET #5,KBA MARK IT DOWN IF NOW UP BCHG #5,KBS AND TOGGLE IT IN STATUS BRA.L CCRTS THEN EXIT * CHECK FOR CTRL - ALT - DELETE CHKDEL BTST #2,KBS CHECK CONTROL BEQ.L NOTBR2 IGNORE IF NOT BTST #3,KBS CHECK ALTERNATE BEQ.L NOTBR2 IGNORE IF NOT TST.B INDOS YES, ARE WE IN IT CURRENTLY? BNE.L CCRTS YES, SO DON'T BREAK MOVE.B #$00,DUART1+DOPORT TURN OFF CTR/TMR OUTPUT SKISNO TRAP #15 QUIT IF CTL-ALT-DEL * CHECK FOR SHIFT - PRINT SCREEN CHKPRS BTST #0,KBS CHECK SHIFT BEQ.L NOTBR3 IGNORE IF NOT MOVEM.L D0-D7/A0-A6,-(A7) PUSH BTST #5,STATSO PRINTING ON B&W BOARD? BEQ.S NPSONB NO LEA BNWRAM+1,A0 YES, POINT TO B/W RAM BRA.S NPSONC NPSONB BTST #4,STATSO PRINTING ON COLOR BOARD? BEQ.L PSISNO NO LEA COLRAM+1,A0 YES, POINT TO COL RAM NPSONC MOVE.B DEVOUT,D2 SAVE OUTPUT DEVICE MOVE.B #2,DEVOUT AND SUBSTITUTE DEVICE 2 MOVE.W #24,D0 25 LINE COUNTER OPRTSL MOVE.W #79,D1 80 CHAR PER LINE IPRTSL MOVE.B (A0),D5 GET NEXT SCREEN CHAR ADD.L #4,A0 BUMP SCREEN ADDRESS BSR.L PUTCD5 PRINT SCREEN BYTE TO PRINTER DBRA D1,IPRTSL CONTINUE LINE MOVE.B #$0D,D5 BSR.L PUTCD5 PRINT CR MOVE.B #$0A,D5 BSR.L PUTCD5 PRINT LF DBRA D0,OPRTSL THEN DO NEXT LINE MOVE.B D2,DEVOUT FINALLY RESTORE DEVICE NUMBER PSISNO MOVEM.L (A7)+,D0-D7/A0-A6 PULL BRA.L CCRTS THEN EXIT AFTER PRINT-SCREEN ********** * WE COME HERE WHEN WE ARE RELEASING A KEY ********** RELEAS CMP.B #128+29,D5 BEQ.S CTRLUP CONTROL KEY CMP.B #128+42,D5 BEQ.S SHFTUP LEFT SHIFT KEY CMP.B #128+54,D5 BEQ.S SHFTUP RIGHT SHIFT KEY CMP.B #128+56,D5 BEQ.S ALTUP ALTERNATE KEY CMP.B #128+58,D5 BEQ.S CAPSUP CAPS LOCK KEY CMP.B #128+69,D5 BEQ.S NUMLUP NUM LOCK KEY BRA.L CCRTS IGNORE ALL OTHERS * CONTROL KEY RELEASED CTRLUP BCLR #2,KBS BRA.L CCRTS * ALTERNATE KEY RELEASED ALTUP BCLR #3,KBS BRA.L CCRTS * SHIFT KEY RELEASED SHFTUP BCLR #0,KBS BRA.L CCRTS * CAPS LOCK KEY RELEASED CAPSUP BCLR #6,KBA BRA.L CCRTS * NUM LOCK KEY RELEASED NUMLUP BCLR #5,KBA BRA.L CCRTS * CLONE KEYBOARD TABLE KEYTAB DC.B $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 0 = NONEXISTEN DC.B $1B,$00,$1B,$1B,$00,$1B,$1B,$00,$1B,$FF,$FF,$FF 1 = ESCAPE DC.B $31,$00,$31,$21,$00,$21,$00,$04,$31,$FF,$FF,$FF 2 DC.B $32,$00,$32,$40,$00,$40,$00,$01,$00,$FF,$FF,$FF 3 DC.B $33,$00,$33,$23,$00,$23,$00,$04,$33,$FF,$FF,$FF 4 DC.B $34,$00,$34,$24,$00,$24,$00,$04,$34,$FF,$FF,$FF 5 DC.B $35,$00,$35,$25,$00,$25,$00,$04,$35,$FF,$FF,$FF 6 DC.B $36,$00,$36,$5E,$00,$5E,$1E,$00,$1E,$FF,$FF,$FF 7 DC.B $37,$00,$37,$26,$00,$26,$00,$04,$37,$FF,$FF,$FF 8 DC.B $38,$00,$38,$2A,$00,$2A,$00,$04,$38,$FF,$FF,$FF 9 DC.B $39,$00,$39,$28,$00,$28,$00,$04,$39,$FF,$FF,$FF 10 DC.B $30,$00,$30,$29,$00,$29,$00,$04,$30,$FF,$FF,$FF 11 DC.B $2D,$00,$2D,$5F,$00,$5F,$1F,$00,$1F,$FF,$FF,$FF 12 DC.B $3D,$00,$3D,$2B,$00,$2B,$00,$04,$3D,$FF,$FF,$FF 13 DC.B $08,$00,$08,$08,$00,$08,$7F,$00,$7F,$FF,$FF,$FF 14 = BACKSPACE DC.B $09,$00,$09,$00,$02,$1F,$00,$03,$1F,$FF,$FF,$FF 15 = TAB DC.B $71,$00,$71,$51,$00,$51,$11,$00,$11,$FF,$FF,$FF 16 DC.B $77,$00,$77,$57,$00,$57,$17,$00,$17,$FF,$FF,$FF 17 DC.B $65,$00,$65,$45,$00,$45,$05,$00,$05,$FF,$FF,$FF 18 DC.B $72,$00,$72,$52,$00,$52,$12,$00,$12,$FF,$FF,$FF 19 DC.B $74,$00,$74,$54,$00,$54,$14,$00,$14,$FF,$FF,$FF 20 DC.B $79,$00,$79,$59,$00,$59,$19,$00,$19,$FF,$FF,$FF 21 DC.B $75,$00,$75,$55,$00,$55,$15,$00,$15,$FF,$FF,$FF 22 DC.B $69,$00,$69,$49,$00,$49,$09,$00,$09,$FF,$FF,$FF 23 DC.B $6F,$00,$6F,$4F,$00,$4F,$0F,$00,$0F,$FF,$FF,$FF 24 DC.B $70,$00,$70,$50,$00,$50,$10,$00,$10,$FF,$FF,$FF 25 DC.B $5B,$00,$5B,$7B,$00,$7B,$1B,$00,$1B,$FF,$FF,$FF 26 DC.B $5D,$00,$5D,$7D,$00,$7D,$1D,$00,$1D,$FF,$FF,$FF 27 DC.B $0D,$00,$0D,$0D,$00,$0D,$0D,$00,$0D,$FF,$FF,$FF 28 = RETURN DC.B $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 29 = CONTROL DC.B $61,$00,$61,$41,$00,$41,$01,$00,$01,$FF,$FF,$FF 30 DC.B $73,$00,$73,$53,$00,$53,$13,$00,$13,$FF,$FF,$FF 31 DC.B $64,$00,$64,$44,$00,$44,$04,$00,$04,$FF,$FF,$FF 32 DC.B $66,$00,$66,$46,$00,$46,$06,$00,$06,$FF,$FF,$FF 33 DC.B $67,$00,$67,$47,$00,$47,$07,$00,$07,$FF,$FF,$FF 34 DC.B $68,$00,$68,$48,$00,$48,$08,$00,$08,$FF,$FF,$FF 35 DC.B $6A,$00,$6A,$4A,$00,$4A,$0A,$00,$0A,$FF,$FF,$FF 36 DC.B $6B,$00,$6B,$4B,$00,$4B,$0B,$00,$0B,$FF,$FF,$FF 37 DC.B $6C,$00,$6C,$4C,$00,$4C,$0C,$00,$0C,$FF,$FF,$FF 38 DC.B $3B,$00,$3B,$3A,$00,$3A,$00,$04,$3B,$FF,$FF,$FF 39 DC.B $27,$00,$27,$22,$00,$22,$00,$04,$27,$FF,$FF,$FF 40 DC.B $60,$00,$60,$7E,$00,$7E,$00,$04,$60,$FF,$FF,$FF 41 DC.B $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 42 = LEFT SHIF DC.B $5C,$00,$5C,$7C,$00,$7C,$1C,$00,$1C,$FF,$FF,$FF 43 DC.B $7A,$00,$7A,$5A,$00,$5A,$1A,$00,$1A,$FF,$FF,$FF 44 DC.B $78,$00,$78,$58,$00,$58,$18,$00,$18,$FF,$FF,$FF 45 DC.B $63,$00,$63,$43,$00,$43,$03,$00,$03,$FF,$FF,$FF 46 DC.B $76,$00,$76,$56,$00,$56,$16,$00,$16,$FF,$FF,$FF 47 DC.B $62,$00,$62,$42,$00,$42,$02,$00,$02,$FF,$FF,$FF 48 DC.B $6E,$00,$6E,$4E,$00,$4E,$0E,$00,$0E,$FF,$FF,$FF 49 DC.B $6D,$00,$6D,$4D,$00,$4D,$0D,$00,$0D,$FF,$FF,$FF 50 DC.B $2C,$00,$2C,$3C,$00,$3C,$00,$04,$2C,$FF,$FF,$FF 51 DC.B $2E,$00,$2E,$3E,$00,$3E,$00,$04,$2E,$FF,$FF,$FF 52 DC.B $2F,$00,$2F,$3F,$00,$3F,$00,$04,$2F,$FF,$FF,$FF 53 DC.B $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 54 = RIGHT SHI DC.B $2A,$01,$1D,$2A,$00,$2A,$00,$03,$1D,$2A,$00,$2A 55 = PRT SCR * DC.B $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 56 = ALT DC.B $20,$00,$20,$20,$00,$20,$20,$00,$20,$FF,$FF,$FF 57 = SPACE DC.B $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 58 = CAPS LOCK DC.B $00,$01,$01,$00,$02,$01,$00,$03,$01,$FF,$FF,$FF 59 = F1 DC.B $00,$01,$02,$00,$02,$02,$00,$03,$02,$FF,$FF,$FF 60 = F2 DC.B $00,$01,$03,$00,$02,$03,$00,$03,$03,$FF,$FF,$FF 61 = F3 DC.B $00,$01,$04,$00,$02,$04,$00,$03,$04,$FF,$FF,$FF 62 = F4 DC.B $00,$01,$05,$00,$02,$05,$00,$03,$05,$FF,$FF,$FF 63 = F5 DC.B $00,$01,$06,$00,$02,$06,$00,$03,$06,$FF,$FF,$FF 64 = F6 DC.B $00,$01,$07,$00,$02,$07,$00,$03,$07,$FF,$FF,$FF 65 = F7 DC.B $00,$01,$08,$00,$02,$08,$00,$03,$08,$FF,$FF,$FF 66 = F8 DC.B $00,$01,$09,$00,$02,$09,$00,$03,$09,$FF,$FF,$FF 67 = F9 DC.B $00,$01,$0A,$00,$02,$0A,$00,$03,$0A,$FF,$FF,$FF 68 = F10 DC.B $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 69 = NUM LOCK DC.B $00,$01,$1E,$00,$02,$1E,$00,$03,$1E,$FF,$FF,$FF 70 = SCROLL LO DC.B $00,$01,$20,$37,$00,$37,$00,$03,$20,$37,$00,$37 71 = HOME DC.B $0B,$01,$25,$38,$00,$38,$00,$03,$25,$38,$00,$38 72 = UP ARROW DC.B $00,$01,$23,$39,$00,$39,$00,$03,$23,$39,$00,$39 73 = PG UP DC.B $2D,$00,$2D,$2D,$00,$2D,$00,$03,$2D,$2D,$00,$2D 74 = GREY MINU DC.B $08,$01,$28,$34,$00,$34,$00,$03,$28,$34,$00,$34 75 = LEFT ARRO DC.B $00,$01,$27,$35,$00,$35,$00,$03,$27,$35,$00,$35 76 = 5 DC.B $09,$01,$26,$36,$00,$36,$00,$03,$26,$36,$00,$36 77 = RIGHT ARR DC.B $2B,$00,$2B,$2B,$00,$2B,$00,$03,$3B,$2B,$00,$2B 78 = GREY PLUS DC.B $00,$01,$22,$31,$00,$31,$00,$03,$22,$31,$00,$31 79 = END DC.B $0A,$01,$27,$32,$00,$32,$00,$03,$27,$32,$00,$32 80 = DOWN ARRO DC.B $00,$01,$24,$33,$00,$33,$00,$03,$24,$33,$00,$33 81 = PG DN DC.B $00,$01,$2A,$30,$00,$30,$00,$03,$2A,$30,$00,$30 82 = INSERT DC.B $00,$01,$2B,$2E,$00,$2E,$00,$03,$2B,$2E,$00,$2E 83 = DELETE * RE-ENTER MONITOR WITHOUT RESET * THIS COMMAND DOES NOT CHANGE EXCEPTION VECTORS * * INPUT: NONE * OUTPUT: NONE * REGISTERS USED: A5 MONITX MOVE.L L5ADDR,A5 MONITOR'S LVL5 ADDRESS MOVE.L A5,$0074 MOVE.L ROM+$BC,A5 MONITOR WARM-START ADDRESS MOVE.L ROM,A7 RESTART STACK POINTER JMP (A5) JUMP TO MONITOR START * RESET MONITOR/SYSTEM AS IF RESET FROM SCRATCH * THIS COMMAND RESETS EXCEPTION VECTORS TO MONITOR'S, * ERASES BREAKPOINT TABLE, RESET BAUD RATE, ETC. * * INPUT: NONE * OUTPUT: NONE * REGISTERS USED: A5 RESETX MOVE.L L5ADDR,A5 MONITOR'S LVL5 ADDRESS MOVE.L A5,$0074 MOVE.L ROM+$04,A5 MONITOR COLD-START ADDRESS MOVE.L ROM,A7 RESTART STACK POINTER JMP (A5) JUMP TO MONITOR START * TIMER ON, OFF, INIT * * INPUT: NONE * OUTPUT: NONE * REGISTERS USED: NONE TIMRTS RTS RTS DO NOTHING ***************************************** *** --- PART 3 - GET DATE ROUTINE --- *** ***************************************** * THIS ROUTINE GETS THE DATE DURING BOOTING, * AND PUTS IT INTO THE MONTH, DAY, YEAR LOCATIONS. * PROGRAM DOES NOTHING IF THE CLOCK IS NOT SET PROPERLY. CLOCK EQU $FF0FF1 CLOCK CHIP CLCONT EQU CLOCK CONTROL REG CLSEC EQU CLOCK+2 CLMIN EQU CLOCK+4 CLHOUR EQU CLOCK+6 CLDAY EQU CLOCK+8 CLDATE EQU CLOCK+10 CLMON EQU CLOCK+12 CLYEAR EQU CLOCK+14 * GET THE TIME AND DATE AND CHECK THEM INPDAT BSR.L CLKOFF TURN OFF CLOCK MOVE.B CLMIN,D5 MINUTES CMP.B #$59,D5 CHECK BHI.L NOGOOD CLOCK NOT SET IF >59 MIN MOVE.B CLHOUR,D5 GET HOURS CMP.B #$23,D5 CHECK IT BHI.L NOGOOD NG IF PAST 23 O'CLOCK MOVE.B CLDAY,D5 GET DAY OF WEEK CMP.B #7,D5 CHECK IT BHI.S NOGOOD NO 8-DAY WEEKS ALLOWED MOVE.B CLDATE,D5 GET DAY OF MONTH CMP.B #$31,D5 CHECK IT BHI.S NOGOOD MAX 31 DAYS A MONTH BSR.L BCDBIN CVT TO BINARY MOVE.B D5,CDAY GIVE IT TO SK*DOS MOVE.B CLMON,D5 GET MONTH CMP.B #$12,D5 CHECK IT BHI.S NOGOOD MAX 12 MONTHS A YEAR BSR.L BCDBIN CVT TO BINARY MOVE.B D5,CMONTH MOVE.B CLYEAR,D5 GET THE YEAR * CMP.B #$84,D5 DEL FOR Y2K * BCS.S NOGOOD DEL FOR Y2K CMP.B #$99,D5 BHI.S NOGOOD ASSUME THIS CENTURY BSR.L BCDBIN CVT TO BINARY MOVE.B D5,CYEAR GIVE IT TO SK*DOS CLKBON MOVE.L D5,-(A7) PUSH MOVE.B CLCONT,D5 AND.B #$BF,D5 TURN OFF READ BIT MOVE.B D5,CLCONT MOVE.L (A7)+,D5 PULL RTS AND THEN CONTINUE SK*DOS * SUBROUTINE TO TEMPORARILY HALT THE CLOCK CLKOFF MOVE.B CLCONT,D5 AND.B #$7F,D5 TURN OFF WRITE BIT OR.B #$40,D5 READ BIT ON MOVE.B D5,CLCONT RTS * ON INVALID DATE, GET IT FROM KEYBOARD NOGOOD BSR.S CLKBON TURN CLOCK BACK ON LEA CLKMSG(PC),A4 SAY CLOCK IS NO GOOD JSR PSTRNV ASK FOR DATE JMP ASKDAV GO USE REGULAR SK*DOS DATE ENTRY CLKMSG DC.B $D,$A DC.B "CALENDAR/CLOCK NOT PROPERLY SET -",4 * CONVERT D5.B FROM BCD TO BINARY - PRESERVE ALL, INCLUDING * TOP THREE BYTES IN D5 BCDBIN MOVE.L D5,-(A7) PUT ON STACK LSR.B #4,D5 TENS DIGIT RIGHT AND.W #$F,D5 ZERO REST OF WORD MULU #10,D5 TIMES TEN SWAP D5 SAVE IN LEFT HALF MOVE.B 3(A7),D5 GET ORIGINAL BCD NUMBER AND.B #$F,D5 UNITS DIGIT MOVE.B D5,3(A7) PUT ON STACK SWAP D5 TENS DIGIT AGAIN ADD.B 3(A7),D5 ADD BACK UNITS MOVE.B D5,3(A7) MOVE.L (A7)+,D5 FINALLY PULL AGAIN RTS AND RETURN ***************************************** *** --- PART 4 - GET TIME ROUTINE --- *** ***************************************** *************** PART 4 A ************************ * THIS ROUTINE IS CALLED EVERY TIME SK*DOS OPENS A FILE * FOR WRITING, READS THE TIME OF DAY FROM THE MK48T02 CLOCK * ON THE PT-68K BOARD, CONVERTS THE TIME INTO A * ONE-BYTE CODE, AND PUTS IT INTO D5 SO THAT * SK*DOS CAN PUT IT INTO THE DIRECTORY, NEXT TO THE DATE. * CAUTION - ALL REGISTERS MUST BE PRESERVED EXCEPT A5-A6,D5-D7. * CHECK FOR VALID TIME ON CLOCK * CHECK THAT YEAR IS 85 THRU 99 - MOD FOR Y2K SETIME BSR.L CLKOFF TURN OFF CLOCK MOVE.B CLYEAR,D5 YEAR * CMP.B #$85,D5 * BCS.S TIMENG DEL FOR Y2K CMP.B #$99,D5 BHI.S TIMENG DITTO * GET THE TIME MOVE.B CLMIN,D5 BSR.S BCDBIN CVT MINUTE TO BINARY DIVU #6,D5 DIVIDE MINUTES BY 6 MOVE.B D5,D7 SAVE MINUTES/6 IN D7 MOVE.B CLHOUR,D5 BSR.S BCDBIN GET HOURS MULU #10,D5 HOURS * 10 ADD.B D7,D5 HOURS*10 + MINUTES/6 IN D5 BNE.S QUIT IF NOT 00 MOVE.B #$F0,D5 CHANGE 00 TO F0 QUIT BSR.L CLKBON CLOCK BACK ON RTS RETURN * IF TIME IS NG, RETURN 0 TIMENG BSR.L CLKBON TURN CLOCK BACK ON MOVE.L #0,D5 RTS AND THEN QUIT *************** PART 4 B ************************ * THIS ROUTINE IS USER-CALLABLE, AND RETURNS DATE IN D5 * AS 00MMDDYY, AND TIME IN D6 AS DDHHMMSS, WHERE DD IS THE * DAY OF THE WEEK. * CAUTION - ALL REGISTERS MUST BE PRESERVED EXCEPT A5-A6,D5-D7. * CHECK FOR VALID TIME ON CLOCK * CHECK THAT YEAR IS 85 THRU 99 - MOD FOR Y2K GETDT BSR.L CLKOFF TURN OFF CLOCK CLR.L D5 MOVE.B CLYEAR,D5 YEAR BSR.S BCDBIN CVT TO BINARY * CMP.B #85,D5 * BCS.S GETDNG DEL FOR Y2K CMP.B #99,D5 BHI.S GETDNG DITTO * GET THE TIME MOVE.B CLHOUR,D5 BSR.L BCDBIN GET HOUR LSL.L #8,D5 MOVE.B CLMIN,D5 BSR.L BCDBIN GET MINUTE LSL.L #8,D5 MOVE.B CLSEC,D5 BSR.L BCDBIN GET SECOND MOVE.L D5,D6 AND INTO D6 MOVE.B CLDAY,D5 BSR.L BCDBIN GET DAY OF WEEK LSL.L #8,D5 MOVE.B CLMON,D5 BSR.L BCDBIN GET MONTH LSL.L #8,D5 MOVE.B CLDATE,D5 BSR.L BCDBIN GET DAY LSL.L #8,D5 MOVE.B CLYEAR,D5 BSR.L BCDBIN GET YEAR BSR.L CLKBON CLOCK BACK ON RTS RETURN * IF TIME IS NG, RETURN 0 GETDNG MOVE.L #0,D5 MOVE.L #0,D6 BSR.L CLKBON CLOCK BACK ON RTS AND THEN QUIT ***************************************** **** -- DATA AREA - FOR KB BUFFER ETC. ** ***************************************** KBIPTR DS.W 1 PTS TO NEXT CHAR IN KBOPTR DS.W 1 PTS TO NEXT CHAR OUT KBBUFF DS.B 64 TYPEAHEAD BUFFER L5ADDR DS.L 1 REMEMBER HUMBUG LVL5 ADDRESS ***************************************** **** --- PART 5 - OFFSET --- **** ***************************************** * THE FOLLOWING SETS "OFFSET" ABOVE THESE DRIVERS DRVEND EQU * THE END OF THESE DRIVERS ORG OFFINI DC.L DRVEND DRVEND AT OFFINI ***************************************** **** --- PART 6 - VECTORS --- **** ***************************************** * THE FOLLOWING VECTORS STEER SK*DOS TO THESE DRIVERS ORG GETDAT JMP.L INPDAT GO TO DATE PATCH TO GET DATE ORG INTIME JMP.L SETIME GO TO TIME PATCH TO GET TIME ORG DICOLD JMP.L HDCOLD COLD INIT HARD DISK DRIVERS ORG DIWARM NOTHING NEEDED ORG DIREAD JMP PRIMRD PRIMARY READ ROUTINE ORG DIWRIT JMP PRIMWR PRIMARY WRITE ROUTINE ORG DICHEK JMP CHKRDY PRIMARY DISK READY CHECK ORG DIMOFF JMP MOTROF TURN OFF MOTOR IMMED ORG DIREST JMP DREST PRIMARY DISK RESTORE ORG DISEEK JMP DSEEK PRIMARY DISK SEEK ORG SINITV JMP SERINI SERIAL PORT INITIALIZATION ROUTINE ORG STATVE JMP STATM CHECK KEYBOARD STATUS - MULTIPLE ORG OUTCHV JMP OUT3ES OUTPUT CHARACTER TO TERMINAL ORG INCHV JMP INEEE KEYBOARD INPUT WITH ECHO MULT ORG KINPUV JMP KINPUT KEYBOARD INPUT WITHOUT ECHO MULT ORG ICNTRL JMP BICONT INPUT CHANNEL CONTROL ORG OSTATV JMP OSTAT CHECK OUTPUT STATUS ORG MONITV JMP MONITX RE-ENTER MONITOR ORG RESETV JMP RESETX RESET MONITOR/SYSTEM ORG TIMINI JMP TIMRTS TIMER INITIALIZE ORG TIMOFF JMP TIMRTS TIMER OFF ORG TIMON JMP TIMRTS TIMER ON ORG GETDTV JMP GETDT GET DATE AND TIME ORG STATV1 JMP.L STAT CHECK KBD STATUS - 1 CHAR ORG KINPV1 JMP.L INCH8 KBD INPUT W/O ECHO 1 CHAR ORG KILLV1 JMP.L KILLTA ERASE TYPEAHEAD BUFFER ***************************************** **** --- PART 7 - STEPRATE -- **** ***************************************** ORG STPRAT FCB 1,1,1,1 DEFAULT 1772 TO 6 MS