home *** CD-ROM | disk | FTP | other *** search
- 'PBFORMAT.BAS by Thaddy de Koning, based on:
- 'QBFORMAT.BAS by Cornel Huth.
- '14-October-1993 - Modified to format 2.8MB Floppies by Allen Hillman
- 'format MS-DOS floppy disks using PB and BIOS
- %F360 = &HFD
- %F1200 = &HF9
- 'NOTE: Original code contained mayor BUG with 3.5 inch types
- 'Fixed that in this PB version.
- '*** %F720 media byte is NEGATIVE to differ from %F1200 ***
- %F720 = -&HF9
- %F1440 = &HF0
- '*** %F2880 media byte is negative to differ from %F1440
- %F2880 = -&HF0
- %RETRIES = 5 '%RETRIES on BIOS error
- $INCLUDE "c:\pb3\REGNAMES.INC"
- TYPE ADDRFIELDtype
- track AS STRING * 1
- head AS STRING * 1
- sector AS STRING * 1
- bytesec AS STRING * 1
- END TYPE '4
- TYPE INFOtype
- OEM AS STRING * 8 'system name
- BS AS WORD 'bytes/sector
- SC AS BYTE 'STRING * 1 'sectors/cluster
- RS AS WORD 'reserved sectors
- NF AS BYTE 'STRING * 1 'FATs
- DE AS WORD 'root directory entries
- TS AS WORD 'total sectors on volume
- MB AS STRING * 1 'media byte
- SF AS WORD 'sectors/FAT
- ST AS WORD 'sectors/track
- NH AS WORD 'heads
- HS AS WORD 'hidden sectors
- END TYPE '27
- TYPE BOOTRECtype
- jmp AS STRING * 3
- parms AS INFOtype
- code AS STRING * 482
- END TYPE '512
- DEFINT A-Z
- 'INT 1Eh disk parameter table vectors
- DIM OldDPTseg AS SHARED WORD, OldDPToff AS SHARED WORD
- DIM NewDPTseg AS SHARED WORD, NewDPToff AS SHARED WORD
- 'Number of tracks on media
- SHARED NoTracks
- 'format info for media
- DIM Info AS SHARED INFOtype
- 'interface with INTERRUPTX routine
- 'boot record buffer
- DIM BootRec AS SHARED BOOTRECtype
- 'sector buffer to write FAT & root directory sectors
- DIM SectorBuff AS SHARED STRING * 512
- $STATIC
- 'Allocate address field data to max possible sectors per track
- DIM AddrField(1 TO 36) AS SHARED ADDRFIELDtype
- BootSector:
- DATA &HEB,&H3E,&H90,&H20,&H20,&H20,&H20,&H20,&H20,&H20,&H20,&H0,&H0,&H0,&H0,&H0
- DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &HA,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &H2B,&HC0,&H8E,&HD0,&HBC,&H0,&H7C,&HB8,&HC0,&H7,&H8E,&HD8,&H8E,&HC0,&HBE,&H3
- DATA &H0,&HBF,&HAF,&H0,&HB9,&H4,&H0,&HF3,&HA5,&HBE,&HAF,&H0,&HB4,&HE,&H8A,&H4
- DATA &HA,&HC0,&H74,&H7,&H56,&HCD,&H10,&H5E,&H46,&HEB,&HF1,&HFC,&HBE,&H7A,&H0,&HBF
- DATA &H0,&H2,&HB9,&H0,&H2,&HF3,&HA4,&HE9,&H86,&H1,&HB8,&H1,&H2,&H2B,&HDB,&HB9
- DATA &H1,&H0,&HBA,&H50,&H0,&HCD,&H13,&H72,&HC,&HBB,&HFE,&H1,&H81,&H3F,&H55,&HAA
- DATA &H75,&H3,&HE9,&HE5,&HFD,&HBE,&H58,&H2,&HB4,&HE,&H8A,&H4,&HA,&HC0,&H74,&H7
- DATA &H56,&HCD,&H10,&H5E,&H46,&HEB,&HF1,&H2B,&HC0,&HCD,&H16,&HCD,&H19,&HCD,&H18,&H20
- DATA &H20,&H20,&H20,&H20,&H20,&H20,&H20,&H20,&H6E,&H6F,&H6E,&H2D,&H62,&H6F,&H6F,&H74
- DATA &H61,&H62,&H6C,&H65,&H20,&H64,&H69,&H73,&H6B,&H20,&H69,&H6E,&H20,&H41,&H3A,&HD
- DATA &HA,&H0,&H4E,&H6F,&H20,&H62,&H6F,&H6F,&H74,&H20,&H64,&H69,&H73,&H6B,&H20,&H66
- DATA &H6F,&H75,&H6E,&H64,&H2C,&H20,&H72,&H65,&H70,&H6C,&H61,&H63,&H65,&H20,&H61,&H6E
- DATA &H64,&H20,&H70,&H72,&H65,&H73,&H73,&H20,&H61,&H20,&H6B,&H65,&H79,&H20,&HD,&HA
- DATA &HD,&HA,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0
- DATA &H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H0,&H55,&HAA
- '============================================================================
- 'The following code is a sample run to format a disk
- 'All other code can be compiled and put in a library
- 'format test drive A: double-sided/36-sector media (2880K)
- drive = 0: media = %F1440
- CLS : DO: LOOP WHILE INKEY$ <> ""
- INPUT "Insert disk to format in drive A: and press a key", a$
- INPUT "Press a key to start PBFORMAT", a$
- PRINT
-
- xerr = PBFORMAT(drive, media)
- IF xerr THEN
- errl = xerr \ 256
- errc = xerr AND 255
- PRINT "*** Error level:"; errl; " code:"; errc
- ELSE
- PRINT "done."
- END IF
- STOP
-
- SUB ComputeCHS (LogSec, cyl, hd, sec)
- 'convert a DOS logical sector to BIOS form
- CylSec = Info.ST * Info.NH
- cyl = LogSec \ CylSec
- rm = LogSec - (cyl * CylSec)
- hd = rm \ Info.ST
- sec = rm - (hd * Info.ST) + 1
- END SUB
- FUNCTION FormatDisk (drive)
- 'format a track at a time a side at a time
- 'any error aborts format,diskette presumed unreliable
- 'retry format 1 or 2 more times before trashing the diskette
- y=Pos(0)
- x=CSRLIN
- FOR track = 0 TO (NoTracks - 1)
- LOCATE x,y:PRINT "Formatting track:";track
- 'This is where you insert any printed info.
- 'If you don't want it, remove it......
- FOR head = 0 TO (Info.NH - 1)
- FOR i = 1 TO %RETRIES
- xerr = FormatTrack(drive, track, head)
- IF xerr = 0 THEN EXIT FOR
- NEXT
- IF xerr THEN FormatDisk = xerr: EXIT FUNCTION
- NEXT
- NEXT
- FormatDisk = 0
- END FUNCTION
- FUNCTION FormatTrack (drive, track, head)
- 'Initialize address field for each sector on this track
- FOR sec = 1 TO Info.ST
- AddrField(sec).track = CHR$(track)
- AddrField(sec).head = CHR$(head)
- AddrField(sec).sector = CHR$(sec)
- AddrField(sec).bytesec = CHR$(2) 'bytecode 2 = 512-byte sector
- NEXT
- reg %ax, &H500 + Info.ST 'format track with sectors/track
- reg %cx, (track * 256) + 1 'track to format,start with sector 1
- Reg %dx, (head * 256) + drive 'head,drive
- Reg %es, VARSEG(AddrField(1)) 'point to address field data
- Reg %bx, VARPTR(AddrField(1))
- CALL INTERRUPT &H13
- cf = Reg (%flags) AND 1 'cf=1 if disk error
- IF cf THEN
- E?? = Reg (%ax)
- 'IF e& < 0 THEN e& = e& + 65536
- SHIFT RIGHT e??,8 ' = e& \ 256 'return with status byte
- Formattrack=e??
- ResetFDC drive
- ELSE
- Reg %ax, &H400 + Info.ST 'ok, verify track integrity-
- CALL INTERRUPT &H13 '-optional but recommended on format
- cf = Reg (%flags) AND 1 'cf=1 if disk error
- IF cf THEN
- e?? = Reg (%ax)
- SHIFT RIGHT e??,8 ' = e?? \ 256 'return with status byte
- Formattrack=e??
- ResetFDC drive
- ELSE
- FormatTrack = 0 'format ok
- END IF
- END IF
- END FUNCTION
- SUB InitFormatParms (media)
- 'set up media's format data
- Info.OEM = "IBM PB3" 'avoid changing 'IBM'
- Info.BS = 512
- Info.RS = 1
- Info.NF = 2 'CHR$(2)
- Info.NH = 2
- Info.HS = 0
- SELECT CASE media
- CASE %F360
- Info.SC = 2 'CHR$(2)
- Info.DE = 112
- Info.TS = 720
- Info.MB = CHR$(%F360)
- Info.SF = 2
- Info.ST = 9
- CASE %F1200
- Info.SC = 1 'CHR$(1)
- Info.DE = 224
- Info.TS = 2400
- Info.MB = CHR$(%F1200)
- Info.SF = 7
- Info.ST = 15
- CASE %F720
- Info.SC = 2 'CHR$(2)
- Info.DE = 112
- Info.TS = 1440
- Info.MB = CHR$(ABS(%F720))
- Info.SF = 3
- Info.ST = 9
- CASE %F1440
- Info.SC = 1 'CHR$(1)
- Info.DE = 224
- Info.TS = 2880
- Info.MB = CHR$(%F1440)
- Info.SF = 9
- Info.ST = 18
- case %F2880
- Info.SC = 2 'CHR$(2)
- Info.DE = 240
- Info.TS = 5760
- Info.MB = CHR$(ABS(%F2880))
- Info.SF = 9
- Info.ST = 36
- CASE ELSE
- Info.OEM = ""
- Info.BS = 0
- Info.RS = 0
- Info.NF = 0 'CHR$(0)
- Info.NH = 0
- Info.HS = 0
- Info.SC = 0 'CHR$(0)
- Info.DE = 0
- Info.TS = 0
- Info.MB = CHR$(0)
- Info.SF = 0
- Info.ST = 0
- END SELECT
- NoTracks = Info.TS \ Info.NH \ Info.ST
- NewDPTseg = 0 'INT 1Eh vector
- NewDPToff = 0 'new -> disk parameter table for formatted media
- OldDPTseg = 0 'original-
- OldDPToff = 0 '-vector
- END SUB
- FUNCTION PBFORMAT (drive, media)
- 'control routine
- xerr = ValidateDisk(drive, media)
- IF xerr = 0 THEN xerr = FormatDisk(drive) ELSE level = 1
- IF xerr = 0 THEN xerr = WriteBoot(drive) ELSE IF level = 0 THEN level = 2
- IF xerr = 0 THEN xerr = WriteFAT(drive) ELSE IF level = 0 THEN level = 3
- IF xerr = 0 THEN xerr = WriteDir(drive) ELSE IF level = 0 THEN level = 4
- IF xerr THEN IF level = 0 THEN level = 5
- 'reset INT 1Eh vector to original,check both for <>0
- IF OldDPTseg <> 0 OR OldDPToff <> 0 THEN
- Reg %ax, &H251E
- Reg %ds, OldDPTseg
- Reg %dx, OldDPToff
- CALL INTERRUPT &H21
- END IF
- PBFORMAT = (level * 256) + xerr
- 'sample call
- 'xerr = PBFORMAT(drive, media)
- 'IF xerr THEN errl = xerr \ 256: errc = xerr AND 255
- 'level error codes
- '0:no error
- '1:validate error
- '2:format error
- '3:boot record write error
- '4:FAT write error
- '5:directory write error
- 'floppy disk error codes (xerr,in decimal):
- '0:no error
- '1:invalid function request
- '2:address mark not found
- '3:write protected
- '4:sector not found
- '6:diskette changed
- '8:DMA overrun
- '9:DMA boundary error
- '12:media type not available
- '16:bad CRC
- '32:diskette controller failed
- '64:seek failed
- '128:time-out/drive not ready
- END FUNCTION
- SUB ResetFDC (drive)
- 'reset the controller after any BIOS FDC error
- Reg %ax, 0
- Reg %dx, drive
- CALL INTERRUPT &H13
- END SUB
- FUNCTION ValidateDisk (drive, media)
- 'check if media supported by program,by drive,and if drive is ready
- InitFormatParms media
- IF Info.ST THEN
- 'check to see if there is CMOS RAM (means we have an AT BIOS)
- OUT &H70, &H10
- CMOS = (INP(&H71) <> &HFF)
- ResetFDC drive
- IF CMOS THEN
- 'get original INT 1Eh vector to disk parameter table
- Reg %ax, &H351E
- CALL INTERRUPT &H21
- OldDPTseg = Reg (%es)
- OldDPToff = Reg (%bx)
- 'set media type for format on AT BIOS/multi-media drive
- 'let BIOS determine if drive can format media with a DPT in BIOS ROM
- 'Reg %ax, &H1800
- 'Reg %cx, ((NoTracks - 1) * 256) + Info.ST
- 'Reg %dx, drive
- FOR checks = 1 TO %RETRIES 'zerr=0 no error
- Reg %ax, &H1800
- Reg %cx, ((NoTracks - 1) * 256) + Info.ST
- Reg %dx, drive
- CALL INTERRUPT &H13
- zerr = Reg (%ax) \ 256 'zerr=&H0C unknown media/maybe invalid CMOS
- IF zerr THEN ResetFDC drive ELSE EXIT FOR
- NEXT
- 'set INT 1Eh vector to this media's disk parameter table in BIOS ROM
- IF zerr = 0 THEN
- NewDPTseg = Reg (%es)
- NewDPToff = Reg (%di)
- Reg %ax, &H251E
- Reg %ds, NewDPTseg
- Reg %dx, NewDPToff
- CALL INTERRUPT &H21
- ELSE
- OldDPTseg = 0
- OldDPToff = 0
- END IF
- END IF
- ELSE
- zerr = &HC 'media not supported by program
- END IF
- 'physical check for disk in the drive
- IF zerr = 0 THEN
- Reg %ax, &H401 'verify 1 sector from drive
- Reg %cx, &H1 'track=0 sector=1
- Reg %dx, drive 'head=0 drive=drive
- FOR checks = 1 TO %RETRIES
- CALL INTERRUPT &H13
- IF Reg ((%flags) AND 1) THEN 'bad read
- zerr = Reg (%ax)
- 'need to detect an unformatted disk
- shift right zerr,8 ' = e?? \ 256
- ResetFDC drive
- ELSE
- zerr = 0 'good read,already formatted disk in drive
- EXIT FOR
- END IF
- NEXT
- 'zerr may be any of the BIOS diskette error codes if non-zero here
- 'address mark not found(2)=unformatted disk in drive
- 'sector not found(4)=wacko disk but okay to proceed
- IF zerr = 2 OR zerr = 4 THEN zerr = 0
- END IF
- ValidateDisk = zerr
- END FUNCTION
-
- FUNCTION WriteBoot (drive)
- RESTORE BootSector
- 'read default boot record data
- DEF SEG = VARSEG(BootRec): offset = VARPTR(BootRec)
- FOR i = 0 TO 511: READ byte: POKE offset + i, byte: NEXT: DEF SEG
- 'update OEM name and BIOS parameter block
- BootRec.parms = Info
- 'write the boot record
- FOR i = 1 TO %RETRIES
- xerr = WriteBootSector(drive)
- IF xerr = 0 THEN EXIT FOR
- NEXT
- WriteBoot = xerr
- END FUNCTION
-
- FUNCTION WriteBootSector (drive)
- Reg %ax, &H300 + 1 'write 1 sector
- Reg %cx, 1 'track 0,sector 1
- Reg %dx, drive 'head 0,drive
- Reg %es, VARSEG(BootRec) 'point to boot record data
- Reg %bx, VARPTR(BootRec)
- CALL INTERRUPT &H13
- cf = Reg (%flags) AND 1 'cf=1 if disk error
- IF cf THEN
- e?? = Reg (%ax)
- WriteBootSector = e?? \ 256 'return with status byte
- ResetFDC drive
- ELSE
- WriteBootSector = 0 'ok
- END IF
- END FUNCTION
- FUNCTION WriteDir (drive)
- MID$(SectorBuff, 1, 1) = CHR$(0)
- FOR i = 2 TO 512
- IF (i - 1) MOD 32 = 0 THEN
- MID$(SectorBuff, i, 1) = CHR$(0)
- ELSE
- MID$(SectorBuff, i, 1) = CHR$(&HF6)
- END IF
- NEXT
- LogSec = Info.RS + Info.HS + (Info.SF * Info.NF) 'first logical dir sector
- FOR i = 1 TO (Info.DE \ 16) 'sectors needed for root directory
- ComputeCHS LogSec, cyl, hd, sec
- FOR k = 1 TO %RETRIES
- xerr = WriteSector(drive, cyl, hd, sec)
- IF xerr = 0 THEN EXIT FOR
- NEXT
- IF xerr THEN WriteDir = xerr: EXIT FUNCTION
- LogSec = LogSec + 1
- NEXT
- WriteDir = 0
- END FUNCTION
-
- FUNCTION WriteFAT (drive)
- ' do the hussle
- FAT1$ = Info.MB + CHR$(255) + CHR$(255)
- FAT2$ = CHR$(0) + CHR$(0) + CHR$(0)
- FOR i = 1 TO 512: MID$(SectorBuff, i, 1) = CHR$(0): NEXT
- LogSec = Info.RS + Info.HS 'first logical FAT sector
- FOR i = 1 TO Info.NF
- FOR j = 1 TO Info.SF
- IF j = 1 THEN MID$(SectorBuff, 1) = FAT1$ ELSE MID$(SectorBuff, 1) = FAT2$
- ComputeCHS LogSec, cyl, hd, sec
- FOR k = 1 TO %RETRIES
- xerr = WriteSector(drive, cyl, hd, sec)
- IF xerr = 0 THEN EXIT FOR
- NEXT
- IF xerr THEN WriteFAT = xerr: EXIT FUNCTION
- LogSec = LogSec + 1
- NEXT
- NEXT
- WriteFAT = 0
- END FUNCTION
-
- FUNCTION WriteSector (drive, cyl, hd, sec)
- 'BIOS write a FAT or directory sector
- Reg %ax, &H300 + 1
- Reg %cx, (cyl * 256) + sec
- Reg %dx, (hd * 256) + drive
- Reg %es, VARSEG(SectorBuff)
- Reg %bx, VARPTR(SectorBuff)
- CALL INTERRUPT &H13
- cf = Reg (%flags) AND 1
- IF cf THEN
- e?? = Reg (%ax)
- WriteSector = e?? \ 256
- ResetFDC drive
- ELSE
- WriteSector = 0
- END IF
- END FUNCTION
-