0100 * ATARI 1050 DISK DRIVE OPERATING SYSTEM -- part 2
0110 *
0120 * command from CPU
0130 *
0140 TKOM1 JSR RDKOM read command
0150     BIT ERROR   command ok?
0160     BVS NEXT    no, checksum error
0170     JSR PROCESS execute
0180     BIT ERROR   everything fine?
0190     BMI NEXT    other drive?
0200     BVC KOK     ok
0210     JSR SENDNAK send NAK, can't execute command
0220     LDA STATUS
0230     ORA #1      set to o.k.
0240     STA STATUS
0250     BNE NEXT    always
0260 *
0270 KOK JSR SENDA   send 'A'
0280     LDA ERROR
0290     AND #1      read sector?
0300     BEQ DOKOM   no, execute command
0310     JSR SLOAD   read sector from interface
0320     BIT ERROR   read error?
0330     BVC KOK1    br if ok
0340     JSR SENDNAK yes, send NAK
0350     LDA STATUS  and indicate error
0360     ORA #2
0370     STA STATUS
0380     BNE NEXT
0390 *
0400 KOK1 JSR SENDA  send 'A'
0410 DOKOM JSR EXECUTE execute command
0420     LDA STATUS  read sector status bits
0430     AND #$FC    reset i/o error
0440     STA STATUS
0450 NEXT LDX #4     clear buffer for new command
0460     LDA #0
0470 EBCL STA RDRIVE,X
0480     DEX 
0490     BPL EBCL
0500     RTS 
0510 *
0520 * look at command
0530 *
0540 PROCESS LDA DRA
0550     AND #3      drive number
0560     TAX         to X reg
0570     LDA DRVNR,X drive number same
0580     CMP RDRIVE  as in command frame
0590     BNE ERR80   no, error
0600     LDX #7      commands 0 - 7 are o.k.
0610     LDA RKOMND  seek in table
0620 KOMSUCH CMP READSEK,X
0630     BEQ KOMFND  br if found
0640     DEX         otherwise, continue
0650     BPL KOMSUCH until end of table
0660     BMI ERR40   unknown command
0670 KOMFND STX KOMND save command number
0680     CPX #3      command with sector number?
0690     BCS NOSEK   no
0700     LDA RSEKL   otherwise, test
0710     CLC         sector number in buffer
0720     ORA RSEKH   can't be 0
0730     BEQ ERR40
0740     LDA DRA     in single density
0750     AND #$20
0760     BEQ ZF33D
0770     LDX #$D0    max $2D0 sectors
0780     LDY #$02
0790     BNE TSANZ
0800 ZF33D LDX #$10  in enhanced density $410 sectors
0810     LDY #$04
0820 TSANZ SEC 
0830     TXA 
0840     SBC RSEKL
0850     TYA 
0860     SBC RSEKH
0870     BCC ERR40   wrong sector
0880 *
0890 NOSEK LDA RKOMND get command
0900     CMP WRITSEK write sector?
0910     BEQ LSSET   if so, set load sector flag
0920     CMP WRVESEK write with verify?
0930     BEQ LSSET   load sector, again
0940     CMP SPEZIAL special command
0950     BEQ LSSET   load sector, again
0960     LDA #0      all other commands
0970     BEQ NOLS    don't load sector
0980 *
0990 * set load sector flag
1000 *
1010 LSSET LDA #1
1020 *
1030 * reset load sector flag
1040 *
1050 NOLS STA ERROR
1060     RTS 
1070 *
1080 * indicate error
1090 *
1100 ERR80 LDA #$80
1110     STA ERROR
1120     RTS 
1130 ERR40 LDA #$40
1140     STA ERROR
1150     RTS 
1160 *
1170 * send 'A' to CPU
1180 *
1190 SENDA LDY #'A   ascii code for 'A'
1200     JSR SBYTE   send byte
1210     RTS 
1220 *
1230 * send 'NAK' to CPU
1240 *
1250 SENDNAK LDY #'N ascii code for 'N'
1260     JSR SBYTE   send
1270     RTS 
1280 *
1290 * send 'C' to CPU
1300 *
1310 SCONT LDY #'C   ascii code for 'C'
1320     JSR SBYTE   send
1330     RTS 
1340 *
1350 * send 'E' to CPU for error
1360 *
1370 SERROR LDY #'E  ascii code for 'E'
1380     JSR SBYTE   send
1390     RTS 
1400 *
1410 * read a serial byte
1420 *
1430 RDBYTE STX SBUF+2 save X reg
1440 WSB BIT DRA     wait for start bit
1450     BVC ERR1    data interrupt from floppy?
1460     BIT DRB     or DATA IN at PORT 6 high?
1470     BVC WSB     no
1480     SEC         otherwise
1490     LDA #$80    bit 7 mark for end
1500     LDX #6      wait 0.5 bit time
1510 WHB DEX 
1520     BNE WHB
1530 W32B LDX #6     wait 2/3 bit time
1540 W32B1 DEX       to get first bit in the middle
1550     BNE W32B1
1560     NOP 
1570     NOP 
1580     NOP 
1590     BIT DRB     bit 1 or 0?
1600     BVC BIT1
1610     CLC         got a zero
1620     BCC NXTBIT
1630 BIT1 SEC        got a one
1640     NOP         keep in same tempo as BCC
1650 NXTBIT ROR A    roll bit in result
1660     BCC W32B    already 8 bits?
1670     TAY         yes, result in Y reg
1680     LDX SBUF+2  restore X reg
1690     RTS 
1700 ERR1 PLA        balance stack
1710     PLA 
1720     JMP ERRSTAT indicate error
1730 *
1740 * read a command (4 chars) from serial port
1750 *
1760 RDKOM LDA #4    number of chars
1770     STA COUNT
1780     LDX #RDRIVE buffer is from addr $80
1790     JSR RDTO    read 4 bytes with TIME OUT
1800 NOTKOM BIT DRB  wait until command on zero
1810     BMI NOTKOM
1820     RTS         done
1830 *
1840 * read a sector
1850 *
1860 SLOAD LDA #$80  sector length
1870     STA COUNT
1880     LDX #SEKBUF read to addr 0
1890     JSR RDTO    from serial port
1900     LDX #9      short delay
1910     JSR DELAY1
1920     RTS 
1930 *
1940 * read bytes from serial port
1950 * number of bytes in COUNT/buffer address in X
1960 *
1970 RDTO LDA #$FF
1980     JSR TIMEOUT set TIMEOUT
1990     LDA #0      reset checksum
2000     STA SBUF
2010 RNXTB JSR RDBYTE read byte
2020     STY SEKBUF,X and store it
2030     CLC         add to checksum
2040     LDA SBUF
2050     ADC SEKBUF,X
2060     ADC #0
2070     STA SBUF
2080     INX         buffer pointer + 1
2090     DEC COUNT   job done?
2100     BNE RNXTB   no, continue
2110     JSR RDBYTE  yes, read checksum
2120     STY SEKBUF,X store
2130     LDA SBUF    and compare with accumulated value
2140     EOR SEKBUF,X
2150     BEQ NORERR  br if ok
2160 *
2170 * indicate error / no error
2180 *
2190 ERRSTAT LDA #$40
2200 NORERR STA ERROR
2210     LDA TIM64   reset TIMEOUT counter
2220     RTS 
2230 *
2240 * send bytes from address X
2250 * number of bytes in COUNT
2260 *
2270 SEND LDA #0     checksum
2280 SEND1 CLC 
2290     LDY SEKBUF,X add to checksum
2300     ADC SEKBUF,X
2310     ADC #0
2320     JSR SBYTE   send byte
2330     INX         buffer address + 1
2340     DEC COUNT   job done?
2350     BNE SEND1   no, continue
2360     TAY         send checksum
2370     JSR SBYTE
2380     RTS 
2390 *
2400 * send sector
2410 *
2420 SNDSEK LDA #$80 bytes/sector
2430     STA COUNT
2440     LDX #SEKBUF send from sector buffer
2450     JMP SEND
2460 *
2470 * send a byte to serial port
2480 *
2490 SBYTE STY SBUF  save char
2500     STA SBUF+1  save checksum
2510     STX SBUF+2  save X
2520     LDY #8      send 8 bits
2530     LDA #$FE    set start bit
2540     AND DRB     ...and send
2550     STA DRB
2560     INC SBUF+2  delay
2570 SBYTE1 ROR SBUF next data bit
2580     BCC SBIT0   send '0' bit
2590     LDA #1      send '1' bit if carry set
2600     ORA DRB
2610     BNE SBIT    send bit
2620 SBIT0 LDA #$FE  send '0' bit
2630     AND DRB
2640     NOP         keep synchronous
2650 SBIT LDX #5     send bit
2660 SBIT2 DEX       delay
2670     BNE SBIT2
2680     STA DRB     to port
2690     DEY         done?
2700     BNE SBYTE1
2710     LDX #6      delay for last bit
2720 SBIT3 DEX 
2730     BNE SBIT3
2740     NOP 
2750     DEC SBUF+2  delay
2760     LDA #1      send stop bit
2770     ORA DRB
2780     STA DRB
2790     LDX #5      delay for stop bit
2800 SBIT4 DEX 
2810     BNE SBIT4
2820     LDX SBUF+2  restore X
2830     LDY SBUF    and Y
2840     LDA SBUF+1  and A
2850     RTS         done
2860 *
2870 * execute command 0 - 7 from KOMND
2880 *
2890 EXECUTE LDX KOMND get command number
2900     LDA JMPTBL,X get low byte
2910     STA JUMPL   of command routine addr
2920     LDA JMPTBH,X and high byte
2930     STA JUMPH
2940     JMP (JUMPL) jump to routine
2950 *
2960 * calculate track & sector from logical sector number
2970 *
2980 COMTS LDY RSEKL logical sector number to SBUF
2990     STY SBUF
3000     LDY RSEKH
3010     STY SBUF+1
3020     LDY #0      reset track & sector
3030     STY TRACK
3040     STY SEKTOR
3050     INY         transfer logical sector 1 ... n
3060     JSR SUBY    to 0 ... n-1
3070     LDA #$20    single or enhanced?
3080     AND DRA
3090     BNE SINGLE
3100     LDY #$1A    number of sectors/track in MD
3110     BNE COMTS1
3120 SINGLE LDY #$12 sectors/tracks in SD
3130 COMTS1 JSR SUBY subtrackt as many times
3140     BCC TOMUCH  as possible
3150     INC TRACK   count every time
3160     BCS COMTS1  continue
3170 TOMUCH INC SEKTOR first sector is #1
3180     RTS 
3190 *
3200 * B1,B2 - Y
3210 *
3220 SUBY STY HZ95
3230     SEC 
3240     LDA SBUF    save remaining sector number
3250     STA SEKTOR
3260     SBC HZ95    subtrackt sectors/track
3270     STA SBUF    and store result
3280     LDA SBUF+1  hi byte also
3290     SBC #0
3300     STA SBUF+1
3310     RTS 
3320 *
3330 * read sector, command 'R'
3340 *
3350 READ JSR SREAD  read one sector
3360     JSR QUITT   return 'C' or 'E'
3370     JMP SNDSEK  send sector
3380 SREAD JSR SETUP set number of retries etc.
3390     BIT FCNTRL  drive ready?
3400     BPL READ1   br if ok
3410     RTS         otherwise error
3420 READ1 JSR SEEK  on right track?
3430     BEQ READ2   ok?
3440     RTS         SEEK ERROR
3450 READ2 LDA SEKTOR put sector number in register
3460     STA SEKREG
3470     JSR RDSEKTOR read sector
3480     BNE READ3   error?
3490     LDA #0      no, indicate 'no error'
3500     STA ERROR
3510     RTS         done
3520 READ3 DEC COUNT another retry?
3530     BEQ READ4   br if no more
3540     LDA FCNTRL  record not found error?
3550     AND #$10
3560     BEQ READ5   if so, try again, incl SEEK
3570     JSR RESTORE
3580     JMP READ1
3590 READ5 LDA #1    last try?
3600     CMP COUNT
3610     BNE READ1   no, do it again
3620     LDA #0      last try
3630     STA STEPCNT another half step
3640     LDA #$FF    backward
3650     STA STEPS
3660     STA DIR
3670     JSR HSTEP   make half a step
3680     LDA #1      and forward again
3690     STA DIR
3700     JSR HSTEP   make half a step
3710     LDX #$C8    delay
3720     JSR DELAY1
3730     JMP READ1   read another time
3740 READ4 RTS       done or break
3750 *
3760 * set retry number, motor on etc.
3770 *
3780 SETUP LDA #$80  assume error
3790     STA ERROR
3800     LDA #2      retries
3810     STA COUNT
3820     JSR COMTS   calculate track & sector
3830     BIT FCNTRL  drive ready?
3840     BMI SETUP1  no, exit
3850     JSR TMOTON  otherwise, motor on
3860 SETUP1 RTS 
3870 *
3880 * quit off, send 'C' or 'E'
3890 *
3900 QUITT LDX #2    delay
3910     JSR DELAY1
3920     LDA FCNTRL
3930     STA CSTAT   return floppy status
3940     BIT ERROR   error?
3950     BMI QUITTE  br if so
3960     LDA STATUS
3970     AND #$9B    reset error bit in STATUS
3980     STA STATUS
3990     JSR SCONT   send 'C'
4000     RTS 
4010 QUITTE LDA STATUS set error bit
4020     ORA #4
4030     STA STATUS
4040     JSR SERROR  send 'E'
4050     RTS 
4060 *
4070 * read a sector, head already on right track
4080 *
4090 RDSEKTOR LDX #0 set timeout
4100     LDA #$E6
4110     JSR TIMEOUT
4120     LDA #$82    read sector command for controller
4130     STA FCNTRL
4140 READSE1 BIT DRA IRQ controller?
4150     BVC READSE2
4160     BPL READSE1 DRQ controller?
4170     LDA DATREG  yes, read data byte
4180     EOR #$FF    invert
4190     STA SEKBUF,X and put in sector buffer
4200     LDA TIM64   reset timer
4210     INX         sector buffer pointer + 1
4220     BPL READSE1 continue until 128 bytes read
4230     LDA #1
4240 READSE3 BIT FCNTRL wait until controller ready
4250     BNE READSE3
4260     LDA FCNTRL  mask status bits for READ SECTOR
4270     AND #$2C
4280     RTS         done
4290 READSE2 LDA FCNTRL
4300     AND #1      controller still busy?
4310     BEQ READSE4 br if not
4320     LDA #$E6    otherwise, set timer again
4330     JSR TIMEOUT
4340     BNE READSE1 and read again
4350 READSE4 LDA TIM64 reset timer
4360     LDA FCNTRL  lost data?
4370     AND #4
4380     BNE RDSEKTOR yes, read again
4390     LDA #1      otherwise error
4400     RTS         and exit
4410 *
4420 * execute 'read address' command
4430 *
4440 RDADR LDX #$7A  buffer for address info
4450     LDA #$80    set timeout
4460     JSR TIMEOUT
4470     LDA #$C0    'read address' command to controller
4480     STA FCNTRL
4490 RDADR1 BIT DRA  wait for IRQ
4500     BVC RDADR3
4510     BPL RDADR1  or DRQ from controller
4520     LDA DATREG  read / store data at DRQ
4530     STA SEKBUF,X
4540     LDA TIM64   reset timer
4550     INX 
4560     BPL RDADR1  until done
4570     LDA #1      and wait
4580 RDADR2 BIT FCNTRL for controller ready
4590     BNE RDADR2
4600     LDA FCNTRL  read status
4610     AND #$0C    mask relevant bits
4620     RTS         done
4630 RDADR3 JSR DFORCE force interrupt
4640     LDA #1      return error
4650     RTS 
4660 *
4670 * set timeout, value in A
4680 *
4690 TIMEOUT STA TIM64 set timeout value
4700     STA T1024I
4710     RTS 
4720 *
4730 * write sector without verify -- command 'P'
4740 *
4750 WRITE JSR WRITE1 write sector
4760     JSR QUITT   return result
4770     RTS 
4780 *
4790 WRITE1 JSR SETUP set retries etc.
4800     BIT FCNTRL  drive ready?
4810     BPL WRITE2  br if so
4820     RTS 
4830 WRITE2 JSR SEEK goto track
4840     BEQ WRITE3  ok?
4850     RTS         no, error
4860 WRITE3 LDA SEKTOR set sector
4870     STA SEKREG
4880     JSR WRSEKTOR write sector
4890     BNE WRITE4  br if error
4900     LDA #0      indicate no error
4910     STA ERROR
4920     RTS         done
4930 WRITE4 DEC COUNT another retry?
4940     BEQ WRITE5  no, error
4950     JSR RESTORE otherwise, do it all over
4960     JMP WRITE2
4970 WRITE5 RTS      done or break
4980 *
4990 * write sector, head already on track
5000 *
5010 WRSEKTOR LDX #0
5020     LDA #$E6    set timeout
5030     JSR TIMEOUT
5040     LDA #$A2    'write sector' command for controller
5050     STA FCNTRL
5060 WRITSE1 LDA SEKBUF,X read data byte from buffer
5070     EOR #$FF    invert
5080 WRITSE2 BIT DRA IRQ from controller?
5090     BVC WRITSE3 yes, error
5100     BPL WRITSE2 DRQ from controller?
5110     STA DATREG  yes, put byte
5120     LDA TIM64   reset timer
5130     INX         next byte
5140     BPL WRITSE1 if any
5150     LDA #1      otherwise,
5160 WRITSE4 BIT FCNTRL wait for controller ready
5170     BNE WRITSE4
5180     LDA FCNTRL  read status
5190     AND #$0C    mask relevant bits
5200     RTS         done
5210 WRITSE3 LDA FCNTRL error
5220     AND #1      wait for controller ready
5230     BEQ WRITSE5
5240     LDA #$E6    set timeout
5250     JSR TIMEOUT
5260     BNE WRITSE1 continue
5270 WRITSE5 LDA TIM64 reset timer
5280     LDA FCNTRL
5290     AND #4      lost data?
5300     BNE WRSEKTOR do it again
5310     LDA FCNTRL  otherwise, return error
5320     RTS 
5330 *
5340 * write sector with verify -- command 'W'
5350 *
5360 VWRITE JSR WRITE1 write sector, same as 'P'
5370     BIT ERROR   test for error
5380     BMI VWRITE1
5390     LDA #2      set retry to 2
5400     STA COUNT
5410     JSR VERIFY  check sector
5420 VWRITE1 JSR QUITT return result
5430     RTS 
