Commodore 1571 firmware
Fast utility commands
.page
.subttl 'fastutl.src'
;NOTE: ALL BURST COMMANDS ARE SENT VIA KERNALO CALLS.
;
;BURST CMD ONE - READ
;
; BYTE BIT 7 6 5 4 3 2 1 0
;============================================================================
; 00 0 1 0 1 0 1 0 1
;----------------------------------------------------------------------------
; 01 0 0 1 1 0 0 0 0
;----------------------------------------------------------------------------
; 02 T E B S 0 0 0 N
;----------------------------------------------------------------------------
; 03 DESTINATION TRACK
;----------------------------------------------------------------------------
; 04 DESTINATION SECTOR
;----------------------------------------------------------------------------
; 05 NUMBER OF SECTORS
;----------------------------------------------------------------------------
; 06 NEXT TRACK (OPTIONAL)
;----------------------------------------------------------------------------
;
;
; RANGE:
;
; MFM ALL VALUES ARE DETERMINED UPON THE PARTICULAR DISK FORMAT.
; GCR SEE SOFTWARE SPECIFICATIONS.
;
;
;SWITCHES:
;
; T - TRANSFER DATA (1=NO TRANSFER)
; E - IGNORE ERROR (1=IGNORE)
; B - BUFFER TRANSFER ONLY (1=BUFFER TRANSFER ONLY)
; S - SIDE SELECT (MFM ONLY)
; N - DRIVE NUMBER
;
;
;
;PROTOCOL:
;
; BURST HANDSHAKE.
;
;
;
;CONVENTIONS:
;
; CMD ONE MUST BE PRECEEDED WITH CMD 3 OR CMD 6 ONCE AFTER
; A NEW DISK IS INSERTED.
;
;
;OUTPUT:
; ONE BURST STATUS BYTE PRECEEDING BURST DATA WILL BE SENT
; FOR EVERY SECTOR TRANSFERED. ON AN ERROR CONDITION
; DATA WILL NOT BE SENT UNLESS THE E BIT IS SET.
.page
;BURST CMD TWO - WRITE
;
; BYTE BIT 7 6 5 4 3 2 1 0
;============================================================================
; 00 0 1 0 1 0 1 0 1
;----------------------------------------------------------------------------
; 01 0 0 1 1 0 0 0 0
;----------------------------------------------------------------------------
; 02 T E B S 0 0 1 N
;----------------------------------------------------------------------------
; 03 DESTINATION TRACK
;----------------------------------------------------------------------------
; 04 DESTINATION SECTOR
;----------------------------------------------------------------------------
; 05 NUMBER OF SECTORS
;----------------------------------------------------------------------------
; 06 NEXT TRACK (OPTIONAL)
;----------------------------------------------------------------------------
;
;
; RANGE:
;
; MFM ALL VALUES ARE DETERMINED UPON THE PARTICULAR DISK FORMAT.
; GCR SEE SOFTWARE SPECIFICATIONS.
;
;
;SWITCHES:
;
; T - TRANSFER DATA (1=NO TRANSFER)
; E - IGNORE ERROR (1=IGNORE)
; B - BUFFER TRANSFER ONLY (1=BUFFER TRANSFER ONLY)
; S - SIDE SELECT (MFM ONLY)
; N - DRIVE NUMBER
;
;
;
;PROTOCOL:
;
; BURST HANDSHAKE.
;
;
;
;CONVENTIONS:
;
; CMD TWO MUST BE PRECEEDED WITH CMD 3 OR CMD 6 ONCE AFTER
; A NEW DISK IS INSERTED.
;
;
;INPUT:
; HOST MUST TRANSFER BURST DATA.
;
;
;OUTPUT:
; ONE BURST STATUS BYTE FOLLOWING EACH WRITE OPERATION.
.page
;BURST CMD THREE - INQUIRE DISK
;
;
; BYTE BIT 7 6 5 4 3 2 1 0
;============================================================================
; 00 0 1 0 1 0 1 0 1
;----------------------------------------------------------------------------
; 01 0 0 1 1 0 0 0 0
;----------------------------------------------------------------------------
; 02 X X X S 0 1 0 N
;----------------------------------------------------------------------------
;
;
;
;SWITCHES:
;
; S - SIDE SELECT (MFM ONLY)
; N - DRIVE NUMBER
;
;
;OUTPUT:
; ONE BURST STATUS BYTE FOLLOWING THE INQUIRE OPERATION.
.page
;BURST CMD FOUR - FORMAT MFM
;
;
; BYTE BIT 7 6 5 4 3 2 1 0
;============================================================================
; 00 0 1 0 1 0 1 0 1
;----------------------------------------------------------------------------
; 01 0 0 1 1 0 0 0 0
;----------------------------------------------------------------------------
; 02 P I D S 0 1 1 N
;----------------------------------------------------------------------------
; 03 M=1 T LOGICAL STARTING SECTOR
;----------------------------------------------------------------------------
; 04 INTERLEAVE (OPTIONAL DEF-0)
;----------------------------------------------------------------------------
; 05 SECTOR SIZE * (OPTIONAL 01 for 256 Byte Sectors)
;----------------------------------------------------------------------------
; 06 LAST TRACK NUMBER (OPTIONAL DEF-39)
;----------------------------------------------------------------------------
; 07 NUMBER OF SECTORS (OPTIONAL DEPENDS ON BYTE 05)
;----------------------------------------------------------------------------
; 08 LOGICAL STARTING TRACK (OPTIONAL DEF-0)
;----------------------------------------------------------------------------
; 09 STARTING TRACK OFFSET (OPTIONAL DEF-0)
;----------------------------------------------------------------------------
; 0A FILL BYTE (OPTIONAL DEF-$E5)
;----------------------------------------------------------------------------
; 0B-?? SECTOR TABLE (OPTIONAL T-BIT SET)
; ----------------------------------------------------------------------------
;
;SWITCHES:
;
; P - PARTIAL FORMAT (1=PARTIAL)
; I - INDEX ADDRESS MARK WRITTEN (1=WRITTEN)
; D - DOUBLE SIDED FLAG (1=FORMAT DOUBLE SIDED)
; S - SIDE SELECT
; T - SECTOR TABLE INCLUDED (1=INCLUDED, ALL OTHER PARMS
; MUST BE INCLUDED)
; N - DRIVE NUMBER
;
;
;PROTOCOL:
;
; CONVENTIONAL.
;
;
;
;CONVENTIONS:
;
; AFTER FORMATTING CMD 3 MUST BE SENT ON CONVENTIONAL FORMAT
; OR CMD 6 ON A NON-CONVENTIONAL FORMAT.
;
;
;OUTPUT:
; NONE. STATUS WILL BE UPDATED WITHIN THE DRIVE.
;
; * 00 - 128 byte sectors
; 01 - 256 byte sectors
; 02 - 512 byte sectors
; 03 - 1024 byte sectors
.page
;BURST CMD FOUR - FORMAT GCR (NO DIRECTORY)
;
;
; BYTE BIT 7 6 5 4 3 2 1 0
;============================================================================
; 00 0 1 0 1 0 1 0 1
;----------------------------------------------------------------------------
; 01 0 0 1 1 0 0 0 0
;----------------------------------------------------------------------------
; 02 X X X X 0 1 1 N
;----------------------------------------------------------------------------
; 03 M=0
;----------------------------------------------------------------------------
; 04 ID LOW
;----------------------------------------------------------------------------
; 05 ID HIGH
;----------------------------------------------------------------------------
;
;
;SWITCHES:
;
; N - DRIVE NUMBER
; X - DON'T CARE.
;
;PROTOCOL:
;
; CONVENTIONAL.
;
;
;CONVENTIONS:
;
; AFTER FORMATTING CMD 3 MUST BE SENT.
;
; NOTE: THIS COMMAND DOES NOT WRITE THE BAM OR THE
; DIRECTORY ENTRIES ( DOUBLE SIDED FLAG WILL NOT BE
; ON TRACK 18, SECTOR 0). IT IS SUGGESTED THAT THE
; CONVENTIONAL 'NEW' FORMAT COMMAND BE USED.
;
;OUTPUT:
; NONE. STATUS WILL BE UPDATED WITHIN THE DRIVE.
.page
;BURST CMD FIVE - SECTOR INTERLEAVE
;
;
; BYTE BIT 7 6 5 4 3 2 1 0
;============================================================================
; 00 0 1 0 1 0 1 0 1
;----------------------------------------------------------------------------
; 01 0 0 1 1 0 0 0 0
;----------------------------------------------------------------------------
; 02 W X X 0 1 0 0 N
;----------------------------------------------------------------------------
; 04 INTERLEAVE
;----------------------------------------------------------------------------
;
;
;SWITCHES:
;
; W - WRITE SWITCH
; N - DRIVE NUMBER
; X - DON'T CARE
;
;PROTOCOL:
;
; CONVENTIONAL, UNLESS THE W-BIT IS SET.
;
;
;CONVENTIONS:
;
; THIS IS A SOFT INTERLEAVE USED FOR MULTI-SECTOR BURST
; READ AND WRITE.
;
;OUTPUT:
; NONE (W=0), INTERLEAVE BURST BYTE (W=1)
.page
;BURST CMD SIX - QUERY DISK FORMAT
;
;
; BYTE BIT 7 6 5 4 3 2 1 0
;============================================================================
; 00 0 1 0 1 0 1 0 1
;----------------------------------------------------------------------------
; 01 0 0 1 1 0 0 0 0
;----------------------------------------------------------------------------
; 02 F X T S 1 0 1 N
;----------------------------------------------------------------------------
; 03 OFFSET (OPTIONAL F-BIT SET)
;----------------------------------------------------------------------------
;
;
;SWITCHES:
;
; F - FORCE FLAG (F=1, WILL STEP THE HEAD WITH THE
; T - END SECTOR TABLE (T=1, SEND)
; N - DRIVE NUMBER
; X - DON'T CARE.
;
;PROTOCOL:
;
; CONVENTIONAL.
;
;
;CONVENTIONS:
;
; THIS IS A METHOD OF DETERMINING THE FORMAT OF THE DISK ON
; ANY PARTICULAR TRACK.
;
;
;OUTPUT:
; BURST STATUS BYTE (IF THERE WAS AN ERROR OR IF THE
; FORMAT IS GCR NO BYTES WILL FOLLOW)
; BURST STATUS BYTE (IF THERE WAS AN ERROR IN COMPILING
; MFM FORMAT INFORMATION NO BYTES
; WILL FOLLOW)
; NUMBER OF SECTORS (THE NUMBER OF SECTORS ON A PARTICULAR
; TRACK)
; LOGICAL TRACK (THE LOGICAL TRACK NUMBER FOUND IN THE
; DISK HEADER)
; MINIMUM SECTOR (THE LOGICAL SECTOR WITH THE LOWEST
; VALUE ADDRESS)
; MAXIMUM SECTOR (THE LOGICAL SECTOR WITH THE HIGHEST
; VALUE ADDRESS)
; M INTERLEAVE (THE HARD INTERLEAVE FOUND ON A PARTICULAR
; TRACK)
;
.page
;BURST CMD SEVEN - INQUIRE STATUS
;
;
; BYTE BIT 7 6 5 4 3 2 1 0
;============================================================================
; 00 0 1 0 1 0 1 0 1
;----------------------------------------------------------------------------
; 01 0 0 1 1 0 0 0 0
;----------------------------------------------------------------------------
; 02 W C X 0 1 1 0 N
;----------------------------------------------------------------------------
; 03 NEW STATUS (W-BIT CLEAR)
;----------------------------------------------------------------------------
;
;SWITCHES:
;
; W - WRITE SWITCH
; C - CHANGE (C=1 & W=0 - FORCE LOGIN DISK,
; C=1 & W=1 - RETURN WHETHER DISK WAS LOGGED
; IE. $XB ERROR OR OLD STATUS)
; N - DRIVE NUMBER
; X - DON'T CARE
;
;PROTOCOL:
;
; BURST.
;
;
;CONVENTIONS:
;
; THIS IS A METHOD OF READING OR WRITING CURRENT STATUS.
;
;
;OUTPUT:
; NONE (W=0), BURST STATUS BYTE (W=1)
;
;
.page
;BURST CMD EIGHT - BACKUP DISK
;
; BYTE BIT 7 6 5 4 3 2 1 0
;============================================================================
; 00 0 1 0 1 0 1 0 1
;----------------------------------------------------------------------------
; 01 0 0 1 1 0 0 0 0
;----------------------------------------------------------------------------
; 02 ? ? ? ? 1 1 1 ?
;----------------------------------------------------------------------------
;
;SWITCHES:
;
; ? - GOT ME
;
.page
;BURST CMD NINE - CHGUTL UTILITY
;
;
; BYTE BIT 7 6 5 4 3 2 1 0
;============================================================================
; 00 0 1 0 1 0 1 0 1
;----------------------------------------------------------------------------
; 01 0 0 1 1 0 0 0 0
;----------------------------------------------------------------------------
; 02 X X X 1 1 1 1 0
;----------------------------------------------------------------------------
; 03 UTILITY COMMANDS: 'S', 'R', 'T', 'M', 'H', #DEV
;----------------------------------------------------------------------------
; 04 COMMAND PARAMETER
;----------------------------------------------------------------------------
;SWITCHES:
;
; X - DON'T CARE.
;
;
;
;UTILITY COMMANDS:
;
; 'S' - DOS SECTOR INTERLEAVE.
; 'R' - DOS RETRIES.
; 'T' - ROM SIGNATURE ANALYSIS.
; 'M' - MODE SELECT.
; 'H' - HEAD SELECT.
; 'V' - WRITE WITH VERIFY.
; #DEV - DEVICE #.
;
;
;NOTE: BYTE 02 IS EQUIVALENT TO A '>'
;
;EXAMPLES:
; "U0>S"+CHR$(SECTOR-INTERLEAVE)
; "U0>R"+CHR$(RETRIES)
; "U0>T"
; "U0>M1"=1571 MODE, "U0>M0"=1541 MODE
; "U0>H0"=SIDE ZERO, "U0>H1"=SIDE ONE (1541 MODE ONLY)
; "U0>V0"=VERIFY ON, "U0>V1"=NO VERIFY (1571 MODE ONLY)
; "U0>"+CHR$(#DEV), WHERE #DEV = 4-30
.page
;BURST CMD TEN - FASTLOAD UTILITY
;
;
; BYTE BIT 7 6 5 4 3 2 1 0
;============================================================================
; 00 0 1 0 1 0 1 0 1
;----------------------------------------------------------------------------
; 01 0 0 1 1 0 0 0 0
;----------------------------------------------------------------------------
; 02 P X X 1 1 1 1 1
;----------------------------------------------------------------------------
; 03 FILE NAME
;----------------------------------------------------------------------------
;
;SWITCHES:
;
; P - SEQUENTIAL FILE BIT (P=1, DOES NOT HAVE TO BE A PROGRAM
; FILE)
; X - DON'T CARE.
;
;PROTOCOL:
;
; BURST.
;
;
;OUTPUT:
; BURST STATUS BYTE PRECEEDING EACH SECTOR TRANSFERED.
;
;STATUS IS AS FOLLOWS:
;
; 0000000X ............. OK
; * 00000010 ............. FILE NOT FOUND
; ** 00011111 ............. EOI
;
;* VALUES BETWEEN THE RANGE 3-15 SHOULD BE CONSIDERED A FILE READ ERROR.
;** EOI STATUS BYTE, FOLLOWED BY NUMBER OF BYTES TO FOLLOW.
.page
;STATUS BYTE BREAK DOWN
;
;
; BIT 7 6 5 4 3 2 1 0
;============================================================================
; MODE DN SECTOR SIZE [ CONTROLLER STATUS ]
;----------------------------------------------------------------------------
;
; Values Represented are in Binary
;
; MODE - 1=MFM, 0=GCR
; DN - DRIVE NUMBER
;
; SECTOR SIZE - (MFM ONLY)
; 00 .... 128 BYTE SECTORS
; 01 .... 256 BYTE SECTORS
; 10 .... 512 BYTE SECTORS
; 11 .... 1024 BYTE SECTORS
;
; CONTROLLER STATUS (GCR)
; 000X .... OK
; 0010 .... SECTOR NOT FOUND
; 0011 .... NO SYNC
; 0100 .... DATA BLOCK NOT FOUND
; 0101 .... DATA BLOCK CHECKSUM ERROR
; 0110 .... FORMAT ERROR
; 0111 .... VERIFY ERROR
; 1000 .... WRITE PROTECT ERROR
; 1001 .... HEADER BLOCK CHECKSUM ERROR
; 1010 .... DATA EXTENDS INTO NEXT BLOCK
; 1011 .... DISK ID MISMAT DISK CHANGE
; 1100 .... RESERVED
; 1101 .... RESERVED
; 1110 .... SYNTAX ERROR
; 1111 .... NO DRIVE PRESENT
;
; CONTROLLER STATUS (MFM)
; 000X .... OK
; 0010 .... SECTOR NOT FOUND
; 0011 .... NO ADDRESS MARK
; 0100 .... RESERVED
; 0101 .... DATA CRC ERROR
; 0110 .... FORMAT ERROR
; 0111 .... VERIFY ERROR
; 1000 .... WRITE PROTECT ERROR
; 1001 .... HEADER BLOCK CHECKSUM ERROR
; 1010 .... RESERVED
; 1011 .... DISK CHANGE
; 1100 .... RESERVED
; 1101 .... RESERVED
; 1110 .... SYNTAX ERROR
; 1111 .... NO DRIVE PRESENT
.page
;
;EXAMPLE BURST ROUTINES WRITTEN ON C 128
; *=$1800
;
; ROUTINE TO READ N-BLOCKS OF DATA
; COMMAND CHANNEL MUST BE OPEN ON DRIVE
; OPEN 15,8,15
; BUFFER AND CMD_BUF, AND CMD_LENGTH MUST BE SETUP
; PRIOR TO CALLING THIS COMMAND.
;
;serial = $0a1c ; fast serial flag
;d2pra = $dd00
;clkout = $10
;d1icr = $dc0d
;d1sdr = $dc0c
;stat = $fa
;buffer = $fb ; $fb & $fc
;
; lda #15 ; logical file number
; ldx #8 ; device number
; ldy #15 ; secondary address
; jsr setlfs ; setup logical file
;
; lda #0 ; noname
; jsr setnam ; setup file name
;
; jsr open ; open logical channel
;
; after the command channel is open subsequent calls should be from 'read'
;
;read lda #$00
; sta stat ; clear status
; lda serial
; and #%10111111 ; clear bit 6 fast serial flag
; sta serial
; ldx #15
; jsr chkout ; open channel for output
; ldx #0
; ldy cmd_length ; length of the command
;1$ lda cmd_buf,x ; get command
; jsr bsout ; send the command
; inx
; dey
; bne 1$
;
; jsr clrchn ; send eoi
; bit serial ; check speed of drive
; bvc error ; slow serial drive
;
; sei
; bit d1icr ; clear interrupt control reg
; ldx cmd_buf+5 ; get # of sectors
; lda d2pra ; read serial port
; eor #clkout ; change state of clock
; sta d2pra ; store back
;
;read_itlda #8
;1$ bit d1icr ; wait for byte
; beq 1$
;
; lda d2pra ; read serial port
; eor #clkout ; change state of clock
; sta d2pra ; store back
;
; Code to check status byte.
;
; 1) This code will check for mode
; whether GCR or MFM.
; 2) Verify sector size.
; 3) Check for error, if ok then continue.
; On error, check error switch if set continue
; otherwise abort.
; 4) Verify switches
;
; lda d1sdr ; get data from serial data reg
; sta stat ; save status
; and #15
; cmp #2 ; just check for (3)
; bcs error
;
; ldy #0 ; even page
;top_rd lda #8
;1$ bit d1icr ; wait for byte
; beq 1$
;
; lda d2pra ; toggle clock
; eor #clkout
; sta d2pra
;
; lda d1sdr ; get data
; sta (buffer),y ; save data
; iny
; bne top_rd ; continue for buffer size
;
; dex
; beq done_read ; done ?
;
; inc buffer+1 ; next buffer
; jmp read_it
;
;done_read
; clc
; .byte $24
;error sec
; rts ; return to sender
;
;cmd_buf .byte 'U0',0,0,0,0,0
;
.page
; *=$1800
;
; ROUTINE TO WRITE N-BLOCKS OF DATA
; COMMAND CHANNEL MUST BE OPEN ON DRIVE
; OPEN 15,8,15
; BUFFER AND CMD_BUF, AND CMD_LENGTH MUST BE SETUP
; PRIOR TO CALLING THIS COMMAND.
;
;serial = $0a1c ; fast serial flag
;d2pra = $dd00
;clkout = $10
;old_clk = $fd
;clkin = $40
;d1icr = $dc0d
;d1sdr = $dc0c
;stat = $fa
;buffer = $fb ; $fb & $fc
;mmureg = $d505
;d1timh = $dc05 ; timer a high
;d1timl = $dc04 ; timer a low
;d1cra = $dc0e ; control reg a
;
; lda #15 ; logical file number
; ldx #8 ; device number
; ldy #15 ; secondary address
; jsr setlfs ; setup logical file
; jsr setnam ; setup file name
;
; jsr open ; open logical channel
;
;
; after the command channel is open subsequent calls should be from 'write'
;
;write lda #$00
; sta stat
; lda serial
; and #%10111111 ; clear bit 6 fast serial flag
; sta serial
; ldx #15
; jsr chkout ; open channel for output
;
; ldx #0
; ldy cmd_length ; length of the command
;1$ lda cmd_buf,x ; get command
; jsr bsout ; send the command
; inx
; dey
; bne 1$
;
; jsr clrchn ; send eoi
;
; bit serial ; check speed of drive
; bvc error
;
; sei
; lda #clkin
; sta old_clk ; clock starts high
;
; ldy #0 ; even page
; ldx cmd_buf+5 ; get # of sectors
;writ_itjsr spout ; serial port out
;1$ lda d2pra ; check clock
; cmp d2pra ; debounce
; bne 1$
;
; eor old_clk
; and #clkin
; beq 1$
;
; lda old_clk ; change status of old clock
; eor #clkin
; sta old_clk
;
; lda (buffer),y ; send data
; sta d1sdr
;
;********* OPTIONAL **********
;
; lda #8 ; put code here or before spin
;2$ bit d1icr ; wait for transmission time
; beq 2$
;
;*****************************
;
; iny
; bne 1$ ; continue for buffer size
;
; talker turn around
;
; WAIT CODE HERE (OPTIONAL)
;
; jsr spin ; serial port input
; bit d1icr ; clear pending
; jsr clklo ; set clk low, tell him we are ready
;
; lda #8
;3$ bit d1icr ; wait for status byte
; beq 3$
;
; lda d1sdr ; get data from serial data reg
; sta stat ; save status
; jsr clkhi ; set clock high
;
; Code to check status byte.
;
; 1) This code will check for mode
; whether GCR or MFM.
; 2) Verify sector size.
; 3) Check for error, if ok then continue.
; On error, check error switch if set continue
; otherwise abort.
; 4) Verify switches
;
; lda stat ; retrieve status
; and #15
; cmp #2 ; just chk for error only (3)
; bcs error ; finish
;
; dex
; beq done_wr ; done ?
;
; inc buffer+1 ; next buffer
; jmp wrt_it
;
;done_wr
; cli
; .byte $24
;error sec
; rts
;
;cmd_buf .byte 'U0',2,0,0,0,0
;
; subroutines
;
; NOTE: spout and spin are C128 kernal vectors (refer to C128 users manual)
;
;
;spout lda mmureg ; change serial direction to output
; ora #$08
; sta mmureg
; lda #$7f
; sta d1icr ; no irq's
; lda #$00
; sta d1timh
; lda #$03
; sta d1timl ; low 6 us bit (fastest)
; lda d1cra
; and #$80 ; keep TOD
; ora #$55
; sta d1cra ; setup CRA for output
; bit d1icr ; clr pending
; rts
;
;spin lda d1cra
; and #$80 ; save TOD
; ora #$08 ; change fast serial for input
; sta d1cra ; input for 6526
; lda mmureg
; and #$f7
; sta mmureg ; mmu serial direction in
; rts
;
;clklo lda d2pra ; set clock low
; ora #clkout
; sta d2pra
; rts
;
;clkhi lda d2pra ; set clock high
; and #$ff-clkout
; sta d2pra
; rts
;
; ****** END EXAMPLES ******
;
.page
; (1) FAST READ
fstrd sta cmd ; save command for dos
sta ctl_cmd ; save command for stbctt
lda ifr1 ; disk change
lsr a
bcc frd_00 ; br, ok
ldx #%00001011 ; no channel
.byte skip2
ndkrd ldx #%01001111 ; no drive
fail jsr upinst ; update dkmode
finbad jsr statqy ; wait for state handshake
final cpx #2
bcs exbad
rts
exbad txa ; retrieve status
and #15 ; bits 0-3 only
ldx #0 ; jobnum
jmp error ; controller error entry
frd_00 jsr spout
bit dkmode ; gcr or mfm ?
bpl rdgcr
; MFM READ
lda #9 ; read cmd
jmp prcmd
rdgcr jsr autoi ; check for auto init
frd_01 cli ; let controller run
lda switch ; check for B
and #%00100000
bne bfonly
lda cmdbuf+3 ; get track
sta hdrs
lda cmdbuf+4 ; get sector
sta hdrs+1
ldx #0 ; job #0
lda ctl_cmd ; read ($80) or fread ($88)
sta jobs,x
jsr stbctt ; hit controller hard
sei ; disable irqs
jsr upinst ; update controller status
bit switch ; check E
bvs igerr
cpx #2 ; error
bcs fail
igerr jsr hskrd ; handshake on state of clkin
lda switch ; check B
bmi notran
bfonly ldy #0 ; even page
frd_02 lda $0300,y ; get data
sta ctl_dat ; setup data
jsr hskrd ; handshake on state
iny
bne frd_02
notran dec cmdbuf+5 ; any more sectors ?
beq exrd
jsr sektr ; next sector
jmp frd_01 ; more to do
exrd cli
jmp chksee ; next track ?
.page
; (2) FAST WRITE
fstwrt
sta cmd ; save command for dos
lda ifr1 ; disk change
lsr a
bcc fwrt_0 ; br, ok
ldx #%00001011 ; no channel
.byte skip2
ndkwrt ldx #%01001111 ; no drv 1
stx ctl_dat ; save status
lda switch ; set internal switch
ora #%00001000
sta switch
fwrt_0 bit dkmode ; gcr or mfm ?
bpl wrtgcr
; MFM WRITE
lda #10
jmp prcmd
wrtgcr jsr autoi ; chk for autoi
lda switch ; transmision required
bmi notrx
fwrt_1 sei ; no irqs
ldy #0 ; even page
fwrt_2 lda pb ; debounce
eor #clkout ; toggle state of clock
bit icr ; clear pending
sta pb
fwrt_4 lda pb
bpl fwrt_3 ; br, attn not low
jsr tstatn ; chk for atn
fwrt_3 lda icr ; wait for byte
and #8
beq fwrt_4 ; chk for attn low only
lda sdr ; get data
sta $0300,y ; put away data
iny
bne fwrt_2 ; more ?
jsr clkhi ; release clock
notrx cli ; let controller run
lda switch ; check for buffer transfer only
and #%00100000
bne nowrt
lda switch ; check internal
and #%00001000
beq notrx0 ; br, ok...
ldx ctl_dat ; get error
jmp fail ; abort
notrx0 lda cmdbuf+3 ; get track
sta hdrs
lda cmdbuf+4 ; get sector
sta hdrs+1
ldx #0 ; job #0
lda #write ; get write job
sta jobs,x
jsr stbctt ; wack controller in the head
sei ; no irqs ok !
jsr spout ; go output
jsr upinst ; update status
jsr hskrd ; send it
jsr burst ; wait for reverse
jsr spinp
cli ; irqs ok now
bit switch ; check error abort switch
bvs nowrt
cpx #2 ; error on job ?
bcs fwrt_5 ; abort ?
nowrt dec cmdbuf+5 ; more sectors ?
beq fwrt_6
jsr sektr ; increment sector
jmp fwrt_1
fwrt_5 jmp exbad
fwrt_6 cli ; done
jmp chksee ; next track ?
.page
; (3) FAST SEEK
fstsek lda cmdbuf+2 ; check drive number
and #1
bne 3$ ; drive 1 - error
lda #1
sta ifr1 ; new disk
lda #5 ; read address cmd
jsr prcmd ; give it to controller
ldx mfmcmd ; get status
cpx #2 ; ok ?
bcc 2$
ldx #0
stx dkmode ; force gcr,drv0,ok
lda #seek ; seek
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
jsr ptch0c ; *** rom ds 86 ***, set track
; sta cmd ; give command to dos
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
sta jobs,x ; give job to controller
jsr stbctt ; bang the controller
.byte skip2 ; return status
3$ ldx #%01001111 ; no drv 1
2$ jmp fail ; update status
.page
; (4) BURST FORMAT MGCR
fstfmt lda cmdbuf+2 ; check drive number
and #1
bne 1$
lda cmdbuf+3 ; format gcr or mfm ?
bpl 2$
; FORMAT IN MFM
lda #8 ; format disk in mfm
jmp prcmd
2$ lda #0
sta dkmode ; force GCR,DRV0
sta nodrv ; drive ok
lda cmdbuf+4
sta dskid ; low id
lda cmdbuf+5
sta dskid+1 ; high id
jsr clrchn ; close all channels
lda #1
sta track ; track one
lda #$ff
sta jobrtn ; set error recovery
jsr ptch55 ; *** rom ds 85 ***, format
tax ; save error
.byte skip2
1$ ldx #%01001111
jsr upinst ; update status
jmp final ; finish up ...
.page
; (5) SOFT INTERLEAVE
cpmint sei
bit switch ; read ?
bpl 1$ ; br, write
jsr spout ; serial port output
lda cpmit ; get current interleave
sta ctl_dat ; send it
jmp hskrd
1$ ldx cmdsiz
cpx #4
bcs 2$
ldx #%00001110 ; syntax
jsr upinst ; update dkmode
lda #badcmd
jmp cmderr
2$ lda cmdbuf+3
sta cpmit ; save
rts
.page
; (6) QUERY DISK FORMAT
querdk jsr fstsek ; check disk format
bit dkmode ; mfm or gcr ?
bpl 2$
lda #13
jsr prcmd ; generate sector table
ldx mfmcmd ; status ok ?
cpx #2
bcs 1$
jsr maxmin ; determine lhigh sector
jsr fn_int ; determine interleave
txa ; hard interleave
pha ; save it
1$ sei ; no irq's
jsr spout ; serial port output
lda dkmode ; get status and send it
sta ctl_dat
jsr hskrd ; transmit status
ldx mfmcmd ; was status ok ?
cpx #2
bcs 3$
lda cpmsek ; get number of sectors
sta ctl_dat
jsr hskrd ; send it
lda cmd_trk ; get logical track number
sta ctl_dat
jsr hskrd ; send track
lda minsek
sta ctl_dat ; send min.
jsr hskrd ; wait for handshake
lda maxsek ; send max.
sta ctl_dat
jsr hskrd ; wait for handshake
pla ; get interleave
sta ctl_dat ; send interleave
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
jmp ptch63 ; *** rom ds 86 ***, add sector table
; jsr hskrd ; wait for handshake
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
2$ rts
3$ pla ; restore stack
jmp exbad
.page
; (7) QUEINIT STATUS
inqst bit switch ; rewrite op ?
bpl wrstat
bit switch ; wp latch ?
bvc statqy
lda ifr1
lsr a
bcc statqy ; ok, give old status
lda dkmode
and #$f0 ; clr old
ora #$0b ; disk change
sta dkmode ; updated status
statqy sei ; disable irqs
jsr spout ; serial port out
lda dkmode ; get status
sta ctl_dat
jsr hskrd ; 6526 will send it
lda #0
sta erword
exchnl jsr spinp ; serial port input
exchn2 cli
rts
wrstat lda cmdbuf+3 ; new value
sta dkmode
bit switch ; wp latch ?
bvc 1$
lda #1
sta ifr1 ; new disk
1$ rts
.page
; (8) BACKUP DISK
duplc1 ldx #%00001110
jsr upinst ; update dkmode
lda #badcmd
jmp cmderr
.page
; SUBROUTINES
chksee lda cmdsiz ; chk for next track
cmp #7
bcc 3$
lda hdrs ; where are we ?
tay ; save
sbc #1 ; one less
asl a
sta cur_trk
cpy #36
php ; save status
ldy cmdbuf+6 ; destination
sty drvtrk
dey
sty cmd_trk ; initial detent
cpy #35
ror a ; rotate carry into neg
plp
and #$80 ; sclr neg
bcc 1$ ; br, we are on side zero
bmi 2$ ; br, we are on side one & want to goto side one
clc
lda cmd_trk ; setup for pete seke
adc #35 ; select side
sta cmd_trk
bmi 2$ ; bra more or less
1$ bpl 2$ ; br, we are on side zero & want to goto side zero
sec
lda cmd_trk
sbc #35 ; select side
sta cmd_trk
2$ jmp seke ; do it
3$ rts
;******************************************************
upinst stx ctl_dat
lda dkmode ; update main status controller status
and #%11110000 ; clear old controller status
ora ctl_dat ; or in controller status
sta dkmode ; updated
sta ctl_dat
rts
;******************************************************
hsktst jsr tstatn ; test for atn
hskrd
1$ lda pb ; debounce
cmp pb
bne 1$
and #$ff ; sclr neg flag
bmi hsktst ; br, attn low
eor fastsr ; wait for state chg
and #4
beq 1$
hsksnd lda ctl_dat ; retrieve data
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
jmp ptch68 ; *** rom ds 86 ***
; sta sdr ; send it
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
lda fastsr
eor #4 ; change state of clk
sta fastsr
lda #8
1$ bit icr ; wait transmission time
beq 1$
rts
;******************************************************
sektr lda cmdbuf+3 ; get track
cmp #36 ; side one ?
bcc 1$
sbc #35 ; get offset
1$ tax
lda num_sec-1,x
tax
dex
stx ctl_dat ; save
clc
lda cmdbuf+4 ; get sector
adc cpmit ; add interleave
cmp ctl_dat ; less than maxsec ?
bcc gtsec
sbc ctl_dat ; rap around
beq oksec ; special case on max
sec
sbc #1 ; less one
.byte skip2
oksec lda ctl_dat
gtsec sta cmdbuf+4 ; new sector
lda #fread ; exread job
sta ctl_cmd
rts
;******************************************************
stbctr ldx jobnum
php
cli ; let controller run free
jsr stbctl ; strobe controller ( hit him hard )
cmp #2 ; was there an error ?
bcc 1$ ; br, nope
jsr stbret ; let DOS retry
lda jobs,x ; get error
1$ tax ; return status in .x
plp ; restore status
rts
;******************************************************
stbctt ldx #0 ; buffer zero
php
sei ; no irq's duringo access
lda ledprt
ora #8
sta ledprt ; led on
cli ; let controller run free
jsr stbctl ; strobe controller ( hit him hard )
cmp #2 ; was there an error ?
bcc 1$ ; br, nope
jsr stbret ; let DOS retry
1$ sei
lda ledprt
and #$ff-8
sta ledprt ; led off
lda jobs,x ; get error return
tax ; return status in .x
plp ; restore original status
rts
;******************************************************
stbret lda #$ff ; micro-step if you can
sta jobrtn ; set error recovery on
stx jobnum ; set job #
lda cmdbuf+2 ; get command
sta ctl_cmd ; reset command
sta cmd ; set for dos
sta lstjob,x ; set last job
sta jobs,x ; -04 fix 86 ds, give it to the controller
jsr stbctl ; wait for it
jmp watjob ; let dos clean it up
;******************************************************
burtst jsr tstatn ; test for atn
burst
1$ lda pb ; debounce
cmp pb
bne 1$ ; same ?
and #$ff ; sclr neg flag
bmi burtst ; br, attn low
eor fastsr ; wait for state chg
and #4
beq 1$
lda fastsr
eor #4
sta fastsr ; state change
rts
;******************************************************