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