1000 * RECDOS1.M65 1010 .PAGE "author notice" 1020 * 1030 * Atari FMS was originally written in the second half of 1978 1040 * by Paul Laughton, assisted by Paul and Kathleen O'Brien 1050 * It was updated (19 Aug. 1980) by Paul Laughton for 1060 * the Atari DOS 2.0S. 1070 * The DOS 2.5 version (adapted for enhanced density 1080 * by Bill Wilkinson???) was released in late 1984. 1090 * 1100 * This is a reconstructed & commented version of the 1110 * enhanced density DOS.SYS source file. 1120 * 1130 * A description of Atari DOS is published by COMPUTE! 1140 * as INSIDE ATARI DOS. 1150 * 1160 * system equates 1170 * 1180 ZICB = $20 zero page i/o control block 1190 FMSZPG = $43 DOS zero page registers (7 bytes) 1200 STAK = $0102 stack loc for put byte 1210 DSKTIM = $0246 addr of o.s. worst case disk time out 1220 LMADR = $02E7 pointer to bottom of free memory (called MEMLO by the o.s.) 1230 DVSTAT = $02EA device status registers (4 bytes) 1240 DCBORG = $0300 device control block 1250 DEVTAB = $031A device table (called HATABS by the o.s.) 1260 IOCBORG = $0340 i/o control blocks 1270 FMSORG = $0700 start of DOS 1280 OSBTM = >$E000-1 hi byte of addr less than (Rev.1/2) o.s.space 1290 DHADR = $E453 device handler vector address (called DSKINV by the o.s.) 1300 EOL = $9B Atari end of line char 1310 LMASK = 3 link mask 1320 TIMOUT = 15 time out value of 15 secs. 1330 * 1340 * more equates (from o.s. source) 1350 * 1360 RTCLOK = $12 realtime clock 1370 BUFRLO = $32 pointer to data buffer, used for ramdisk 1380 BUFRHI = $33 1390 CRITIC = $42 critical i/o flag 1400 PORTB = $D301 memory management register (XL/XE only) 1410 NMIEN = $D40E non-maskable interrupt enable 1420 SIOV = $E459 serial i/o utility entry point 1430 .PAGE "IOCB" 1440 *= IOCBORG 1450 * 1460 * IOCB - i/o control block. There are 8 i/o control blocks, 1 iocb is 1470 * required for each currently open device or file. 1480 * 1490 IOCB 1500 ICHID *= *+1 device handler 1510 ICDNO *= *+1 device number 1520 ICCOM *= *+1 i/o command 1530 ICSTA *= *+1 i/o status 1540 ICBAL *= *+1 1550 ICBAH *= *+1 buffer addr (L,H) 1560 ICPUT *= *+2 put char DH addr 1570 ICBLL *= *+1 1580 ICBLH *= *+1 buffer len (L,H) 1590 ICAUX1 *= *+1 aux 1 1600 *= *+1 aux 2 (unused) 1610 ICAUX3 *= *+1 aux 3 1620 ICAUX4 *= *+1 aux 4 1630 ICAUX5 *= *+1 aux 5 1640 *= *+1 aux 6 (unused) 1650 ICLEN = *-IOCB 1660 *= *+ICLEN*7 space for 7 more iocb's 1670 * 1680 * zero page iocb labels 1690 * 1700 ICDNOZ = ICDNO-IOCB+ZICB 1710 ICBLLZ = ICBLL-IOCB+ZICB buff len 1720 ICBLHZ = ICBLH-IOCB+ZICB 1730 ICBALZ = ICBAL-IOCB+ZICB buff addr 1740 ICBAHZ = ICBAH-IOCB+ZICB 1750 ICCOMZ = ICCOM-IOCB+ZICB 1760 ICAX1Z = ICAUX1-IOCB+ZICB 1770 .PAGE "DCB" 1780 *= DCBORG 1790 * 1800 * DCB - data control block. The DCB is an iocb like control block used 1810 * to interface the disk file management system to the disk handler. 1820 * 1830 DCBSBI *= *+1 serial bus id 1840 DCBDRV *= *+1 disk drive # 1850 DCBCMD *= *+1 command 1860 DCBSTA *= *+1 i/o status 1870 DCBBUF *= *+2 i/o buffer addr (L,H) 1880 DCBTO *= *+2 time out count 1890 DCBCNT *= *+2 i/o byte count 1900 DCBSEC *= *+2 i/o sector number 1910 * 1920 * DCBCMD value equates 1930 * 1940 DCBCRS = 'R read sector 1950 DCBCWS = 'P put sector 1960 DCBCST = 'S status request 1970 DCBCFS = '! format diskette single 1980 DCBCFE = '" format diskette enhanced 1990 * 2000 * ** special note: 2010 * DCBCWS may be changed to 'W ($57) if desired to have disk perform a 2020 * verifying read after each write. Disk write ('W) operations will 2030 * take longer, but will be more reliable. 2040 * 2050 * zero page cells 2060 * 2070 *= FMSZPG 2080 ZBUFP *= *+2 buffer pointer 2090 ZDRVA *= *+2 zero page drive pointer 2100 ZSBA *= *+2 zero pg sector buff ptr 2110 CURFCB *= *+1 current FCB (iocb also) 2120 .PAGE "BOOT RECORD" 2130 * 2140 * The following bytes are stored on disk sector 1. They comprise the 2150 * boot load record. 2160 * 2170 .LOCAL 2180 *= FMSORG 2190 BFLG .BYTE 0 boot flag unused = 0 2200 BRCNT .BYTE 3 no. consective boot records to read 2210 BLDADR .WORD FMSORG boot load addr 2220 BINTADR .WORD DUPINIT init addr 2230 BCONT JMP XBCONT boot read cont. pt. 2240 * 2250 * The following bytes are set by the console processor. They are acted 2260 * upon during FMS init only. They are part of the boot record thus 2270 * defining the default initialization parms. 2280 * 2290 SABYTE .BYTE 3 max # concurrent open files 2300 DRVBYT .BYTE $83 drive bits 2310 SAFBFW .BYTE 0 storage allocation dir sw (unused) 2320 SASA .WORD ENDFMS storage allocation start addr 2330 * 2340 * The following code reads the FMS and console processor (DOS) from 2350 * the DOS.SYS file. 2360 * 2370 DFSFLG .BYTE 0 DOS flag (00 no DOS file, 01 128 byte sector disk) 2380 DFLINK .WORD 4 DOS file start sector number 2390 BLDISP .BYTE 125 displ to sector link 2400 DFLADR .WORD DFMSDH addr start of DOS.SYS file 2410 * 2420 XBCONT LDY DFSFLG get DOS flag 2430 BEQ BFAIL br if no DOS.SYS file 2440 JSR MVSA move load addr to pointer 2450 LDA DFLINK+1 get 1st sector # 2460 LDY DFLINK 2470 XBC1 LDX ICBALZ move zero page ptr 2480 STX DCBBUF to DCB 2490 LDX ICBAHZ 2500 STX DCBBUF+1 2510 CLC 2520 JSR BSIO go read DOS sector 2530 BMI BFAIL 2540 LDY BLDISP point to link 2550 LDA (ICBALZ),Y get hi link 2560 AND #LMASK mask to link bits 2570 TAX 2580 INY 2590 ORA (ICBALZ),Y 2600 BEQ XBRTN done if link = 0 2610 LDA (ICBALZ),Y get low link 2620 PHA 2630 INY 2640 LDA (ICBALZ),Y get # bytes in sector 2650 JSR INCBA go increment buff addr (by # bytes in sector) 2660 PLA low link to Y reg 2670 TAY 2680 TXA hi link to accu 2690 JMP XBC1 go read next sector 2700 BFAIL LDA #$C0 set for carry set 2710 XBRTN ASL A prepare carry & Y reg for rtn 2720 TAY 2730 RTS back to operating system 2740 * 2750 INCB LDA #$80 2760 INCBA CLC incr buffer pointer by # in accu 2770 ADC ICBALZ 2780 STA ICBALZ 2790 BCC EXBT 2800 INC ICBAHZ 2810 EXBT RTS 2820 * 2830 MVSA LDA DFLADR move load start addr 2840 STA ICBALZ to zero page ptr 2850 LDA DFLADR+1 2860 STA ICBAHZ 2870 RTS 2880 .BYTE 0,0 filler bytes 2890 .PAGE "SECTOR I/O" 2900 * 2910 * BSIO - do sector i/o 2920 * on entry: Y/A - sector number, X - doesn't matter 2930 * carry clear for read, set for write 2940 * 2950 BSIO STA DCBSEC+1 set sector hi 2960 STY DCBSEC sector lo 2970 BSIOR LDA #DCBCRS assume read sector 2980 LDY #$40 and get data 2990 BCC :BSIO3 br if read 3000 LDA #DCBCWS else load write sector (change this operand to $57 for write with verify) 3010 LDY #$80 and put data 3020 :BSIO3 PHP save processor status word 3030 LDX ICDNOZ check for drive 8 3040 CPX #8 3050 BNE DSIO1 br if not 3060 PLP restore PSW 3070 JSR DRIVE8 use DRIVE8 routine for drive #8 3080 JMP DSIOE exit 3090 DSIO1 PLP restore processor status word 3100 STA DCBCMD set command 3110 LDA #TIMOUT timeout default loaded 3120 DSIO2 STA DCBTO set time out 3130 STY TEMP3 save SIO cmd 3140 LDA #$31 disk serial bus id 3150 STA DCBSBI set id 3160 LDA #3 set retry count 3170 STA RETRY 3180 LDA #$80 set i/o byte count 3190 STA DCBCNT 3200 ASL A shift accu to zero 3210 STA DCBCNT+1 set byte count hi to zero 3220 DSIOX LDA TEMP3 recall SIO cmd 3230 STA DCBSTA set SIO cmd 3240 JSR SIOV call serial i/o 3250 BPL DSIOE if good i/o then rts 3260 DEC RETRY test if another retry available 3270 BPL DSIOX retry the i/o 3280 DSIOE LDX CURFCB reload current FCB 3290 TYA i/o status set flags 3300 RTS 3310 .PAGE "STATUS" 3320 * 3330 * DFMSTA - get a file status 3340 * 3350 DFMSTA JSR SETUP setup 3360 JSR XSTAT go decode file name and search for file 3370 JSR TSTLOCK test locked 3380 JMP GREAT file exists and unlocked 3390 .BYTE 0,0 filler bytes 3400 .PAGE "FILE MANAGER ENTRY POINT" 3410 * 3420 * DFMSDH - disk file management disk vector table 3430 * (entered into the handler address table) 3440 * 3450 DFMSDH 3460 .WORD DFMOPN-1 open file 3470 .WORD DFMCLS-1 close file 3480 .WORD DFMGET-1 get file 3490 .WORD DFMPUT-1 put byte 3500 .WORD DFMSTA-1 status 3510 .WORD DFMDDC-1 device dependent cmd 3520 * 3530 * bit value table for FRESECT & GETSECTOR 3540 * 3550 SECTAB .BYTE $80,$40,$20,$10,8,4,2,1 3560 * following byte is read, but never changed by DOS/DUP 3570 XBFLG .BYTE $FF skip delay loop in bank switch routine if FF 3580 * 3590 *= $07E0 insure fixed init addr 3600 * 3610 * set up drive info 3620 * DRVTBL - 8 bytes, one for each possible drive (0 = no drive, set to mark drive) 3630 * DBUFA(L,H) - 8 two byte entries for the drive (VTOC) buffer addr for a drive 3640 * 3650 DINIT LDA SASA move start of alloc 3660 STA ICBALZ area to ICBAL/HZ 3670 LDA SASA+1 3680 STA ICBAHZ 3690 LDA DRVBYT move drive excess bits from boot 3700 STA ZBUFP 3710 LDX #7 dr # minus 1 3720 DIA LDA #0 assume no drive 3730 ASL ZBUFP shift dr bit to carry 3740 BCC DIB br if dr doesn't exist 3750 LDY #DVDWRQ set write required off 3760 STA (ICBALZ),Y in the drive VTOC buffer 3770 LDA ICBALZ move current alloc addr to DBUFA 3780 STA DBUFAL,X 3790 LDA ICBAHZ 3800 STA DBUFAH,X 3810 LDA #$90 go incr buff alloc by $90 3820 JSR INCBA 3830 LDA #100 indicate drive present 3840 DIB STA DRVTBL,X set drive into table 3850 DEX dec drive 3860 BPL DIA br if more to test 3870 LDA ICBALZ save start of sector buffs 3880 STA SABUFL 3890 LDA ICBAHZ 3900 STA SABUFH 3910 * 3920 * Set up sector allocation table. The sector allocation table (SECTBL) 3930 * has 8 one byte entries, one for each possible 128 byte buffer. 3940 * SABYTE in the boot record determines the number of entries to 3950 * allocate. Non allocated byte are minus. 3960 * 3970 LDY SABYTE get count 3980 LDX #0 3990 DINXTS DEY dec count of allocated 4000 TYA if plus allocate, else de allocate 4010 STA SECTBL,X set allocate byte 4020 BMI DIC if not allocated, then don't allocate buffer 4030 JSR INCB else, incr buff ptr by $80 4040 DIC INX incr buffer # 4050 CPX #8 if not all 8 4060 BNE DINXTS do again 4070 * 4080 * NOTE: The non-resident part of DUP starts at $1D7F (labeled 4090 * NDOS), giving only limited room for drive & sector buffers. 4100 * With a gap of only $3B0 bytes between ENDFMS and NDOS only 4110 * 3 drives (including ramdisk!) & 4 simultaneously open files 4120 * (or 4 drives & 2 files) are possible. Althrough DOS itself 4130 * will be fine, the DOS menu will not work properly with more 4140 * buffer space used. 4150 * 4160 * set low mem 4170 * 4180 LDA ICBALZ move final addr 4190 STA LMADR to low mem ptr 4200 LDA ICBAHZ 4210 STA LMADR+1 4220 * 4230 * clear FCB's to zero 4240 * 4250 LDA #0 4260 TAY 4270 CFCBX STA FCB,Y 4280 INY 4290 BPL CFCBX loop until all 128 cleared 4300 * 4310 * set device handler table entry 4320 * 4330 TAY reset index 4340 ADI1 LDA DEVTAB,Y find an unused 4350 BEQ ADI2 4360 CMP #'D or disk entry 4370 BEQ ADI2 4380 INY 4390 INY 4400 INY 4410 CPY #30 4420 BNE ADI1 4430 BRK else break 4440 ADI2 LDA #'D set disk 4450 STA DEVTAB,Y 4460 LDA # DFMSDH 4490 STA DEVTAB+2,Y 4500 RTS