
***************************************************************
* WRITE TRACK ROUTINE                                         *
***************************************************************
* THIS SUBROUTINE MUST BE USER SUPPLIED.                      *
* IT SIMPLY WRITES THE DATA FOUND AT "WORK" ($0800) TO THE    *
* CURRENT TRACK ON THE DISK.  NOTE THAT THE SEEK TO TRACK     *
* OPERATION HAS ALREADY BEEN PERFORMED.  IF SINGLE DENSITY,   *
* "TKSZ" BYTES SHOULD BE WRITTEN.  IF DOUBLE, "TKSZ*2"        *
* BYTES SHOULD BE WRITTEN.  THIS ROUTINE SHOULD PERFORM       *
* ANY NECESSARY DENSITY SELECTION BEFORE WRITING.  DOUBLE     *
* DENSITY IS INDICATED BY THE BYTE "DNSITY" BEING NON-ZERO.   *
* THERE ARE NO ENTRY PARAMETERS AND ALL REGISTERS MAY BE      *
* DESTROYED ON EXIT.  THE CODE FOR THIS ROUTINE MUST NOT      *
* EXTEND PAST $0800 SINCE THE TRACK DATA IS STORED THERE.     *
***************************************************************

*********************************************
* WESTERN DIGITAL PARAMETERS
* ******* ******* *********
* REGISTERS:
COMREG EQU $8018 COMMAND REGISTER
TRKREG EQU $8019 TRACK REGISTER
SECREG EQU $801A SECTOR REGISTER
DATREG EQU $801B DATA REGISTER
* COMMANDS:
WTCMD EQU $F4 WRITE TRACK COMMAND
*********************************************

*********************************************
* CONTROLLER DEPENDENT PARAMETERS
* ********** ********* **********
DRVREG EQU $8014 DRIVE SELECT REGISTER
*********************************************


WRTTRK LDX #WORK POINT TO DATA
 LDAA #WTCMD SETUP WRITE TRACK COMMAND
 STAA COMREG ISSUE COMMAND
 JSR DELAY
WRTTR2 LDAA COMREG CHECK WD STATUS
 BITA #$02 IS WD READY FOR DATA ?
 BNE WRTTR4 SKIP IF READY
 BITA #$01 IS WD BUSY ?
 BNE WRTTR2 LOOP IF BUSY
 BRA WRTTR8 EXIT IF NOT
WRTTR4 LDAA 0,X GET A DATA BYTE
 STAA DATREG SEND TO DISK
 INX BUMP POINTER
 CPX #SWKEND OUT OF DATA ?
 BNE WRTTR2 REPEAT IF NOT
WRTTR6 BSR WAIT WAIT TIL WD IS DONE
WRTTR8 RTS RETURN

WAIT LDAA COMREG CHECK WD STATUS
 BITA #$01 IS IT BUSY?
 BNE WAIT LOOP IF SO
 RTS

DELAY JSR DELAY2
DELAY2 JSR DELAY4
DELAY4 RTS

**********************************************************
*
* BOOTSTRAP FLEX LOADER
*
* THE CODE FOR THE BOOTSTRAP FLEX LOADER MUST BE IN MEMORY
* AT $A100 WHEN NEWDISK IS RUN.  THERE ARE TWO WAYS IT CAN
* BE PLACED THERE. ONE IS TO ASSEMBLE THE LOADER AS A
* SEPERATE FILE AND APPEND IT ONTO THE END OF THE NEWDISK
* FILE.  THE SECOND IS TO SIMPLY PUT THE SOURCE FOR THE
* LOADER IN-LINE HERE WITH AN ORG TO $A100.  THE FIRST FEW
* LINES OF CODE FOR THE LATTER METHOD ARE GIVEN HERE TO
* GIVE THE USER AN IDEA OF HOW TO SETUP THE LOADER SOURCE.
*
* IT IS NOT NECESSARY TO HAVE THE LOADER AT $A100 IN ORDER
* FOR THE NEWDISK TO RUN.  IT SIMPLY MEANS THAT WHATEVER
* HAPPENS TO BE IN MEMORY AT $A100 WHEN NEWDISK IS RUN
* WOULD BE WRITTEN OUT AS A BOOT.  AS LONG AS THE CREATED
* DISK WAS FOR USE AS A DATA DISK ONLY AND WOULD NOT BE
* BOOTED FROM, THERE WOULD BE NO PROBLEM
*
**********************************************************

* 6800 BOOTSTRAP FLEX LOADER

* EQUATES

STACK EQU $A07F
SCTBUF EQU $A300 DATA SECTOR BUFFER

* START OF UTILITY

 ORG $A100
BOOT LDS #STACK SETUP STACK
 BRA LOAD0

TRK FCB 0 FILE START TRACK
SCT FCB 0 FILE START SECTOR
DNS FCB 0 DENSITY FLAG
TADR FDB $A100 TRANSFER ADDRESS
LADR FDB 0 LOAD ADDRESS
SBFPTR FDB 0 SECTOR BUFFER POINTER

LOAD0 LDAA TRK SETUP STARTING TRK & SCT
 STAA SCTBUF
 LDAA SCT
 STAA SCTBUF+1
 LDX #SCTBUF+256
 STX SBFPTR

* PERFORM ACTUAL FILE LOAD

LOAD1 BSR GETCH GET A CHARACTER
 CMPA #$02 DATA RECORD HEADER?
 BEQ LOAD2 SKIP IF SO
 CMPA #$16 XFR ADDRESS HEADER?
 BNE LOAD1 LOOP IF NEITHER
 BSR GETCH GET TRANSFER ADDRESS
 STAA TADR
 BSR GETCH
 STAA TADR+1
 BRA LOAD1 CONTINUE LOAD
LOAD2 BSR GETCH GET LOAD ADDRESS
 STAA LADR
 BSR GETCH
 STAA LADR+1
 BSR GETCH GET BYTE COUNT
 TAB PUT IN B
 BEQ LOAD1 LOOP IF COUNT=0
LOAD3 PSHB
 BSR GETCH GET A DATA CHARACTER
 PULB
 LDX LADR GET LOAD ADDRESS
 STAA 0,X PUT CHARACTER
 INX
 STX LADR
 DECB END OF DATA IN RECORD?
 BNE LOAD3 LOOP IF NOT
 BRA LOAD1 GET ANOTHER RECORD

* GET CHARACTER ROUTINE - READS A SECTOR IF NECESSARY

GETCH LDX SBFPTR CHECK SECTOR BUFFER POINTER
 CPX #SCTBUF+256 OUT OF DATA?
 BEQ GETCH2 GO READ SECTOR IF SO
GETCH1 LDAA 0,X ELSE, GET A CHARACTER
 INX
 STX SBFPTR UPDATE POINTER
 RTS
GETCH2 LDX #SCTBUF POINT TO BUFFER
 LDAA 0,X GET FORWARD LINK (TRACK)
 BEQ GO IF ZERO, FILE IS LOADED
 LDAB 1,X ELSE, GET SECTOR
 BSR READ READ NEXT SECTOR
 BNE BOOT START OVER IF ERROR
 LDX #SCTBUF+4 POINT PAST LINK
 BRA GETCH1 GO GET A CHARACTER

* FILE IS LOADED, JUMP TO IT

GO LDX TADR GET TRANSFER ADDRESS
 JMP  0,X JUMP THERE

* WESTERN DIGITAL EQUATES FOR READ

DRQ EQU 2 DRQ BIT MASK
BUSY EQU 1 BUSY MASK
RDMSK EQU $1C READ ERROR MASK
RDCMND EQU $8C READ COMMAND
SKCMND EQU $1B SEEK COMMAND

* READ ONE SECTOR

READ BSR XSEEK SEEK TO TRACK
 LDAA #RDCMND SETUP READ SECTOR COMMAND
 STAA COMREG ISSUE READ COMMAND
 BSR DEL28 DELAY
 CLRB GET SECTOR LENGTH (=256)
 LDX #SCTBUF POINT TO SECTOR BUFFER
READ3 LDAA COMREG GET WD STATUS
 BITA #DRQ CHECK FOR DATA
 BNE READ5 BRANCH IF DATA PRESENT
 BITA #BUSY CHECK IF BUSY
 BNE READ3 LOOP IF SO
 TAB  SAVE ERROR CONDITION
 BRA  READ6
READ5 LDAA DATREG GET DATA BYTE
 STAA 0,X PUT IN MEMORY
 INX BUMP THE POINTER
 DECB DEC THE COUNTER
 BNE READ3 LOOP TIL DONE
 BSR XWAIT WAIT TIL WD IS FINISHED
READ6 BITB #RDMSK MASK ERRORS
 RTS RETURN

* WAIT FOR 1771 TO FINISH COMMAND

XWAIT LDAB COMREG GET WD STATUS
 BITB #BUSY CHECK IF BUSY
 BNE XWAIT LOOP TIL NOT BUSY
 RTS RETURN

* SEEK THE SPECIFIED TRACK

XSEEK STAB SECREG SET SECTOR
 CMPA TRKREG DIF THAN LAST?
 BEQ DEL28 EXIT IF NOT
 STAA DATREG SET NEW WD TRACK
 BSR DEL28 GO DELAY
 LDAA #SKCMND SETUP SEEK COMMAND
 STAA COMREG ISSUE SEEK COMMAND
 BSR DEL28 GO DELAY
 BSR XWAIT WAIT TIL DONE

* DELAY

DEL28 JSR DEL14
DEL14 JSR DEL
DEL RTS

 END NEWDISK
