;	Logical disk format utility for my 8080 microcomputer
;	JWD - v1.0   06/19/2024   
;
;   Formats current logical disk (directory only)
;   Runs as a CP/M utility program in the TPA area
;
;   BIOS defines track 1 sectors 0 through 255
;   as directory.  These sectors will be written
;   with character 0xe5.
;
;
	CPU 8080   ;Specify architecture for ASL
	PAGE 0     ;No page breaks in listing
;
MONITOR  equ 100h    ;System monitor start address
;
; ATA Drive Definitions
;
ATA_CS1       equ 40h        ;ATA Drive CS1 address
ATA_FEATURES  equ ATA_CS1+1	 ;ATA Drive Feature Register (Write Only)
ATA_DRV_HEAD  equ ATA_CS1+6	 ;ATA Drive Device/Head Register
ATA_STATUS    equ ATA_CS1+7	 ;ATA Drive Status Register (Read Only)
ATA_COMMAND   equ ATA_CS1+7	 ;ATA Drive Command Register (Write Only)
;
;ATA Control Commands
;
CMD_SET_FEATURES  equ 0EFh   ;Set card features (aka 8-bit mode)
;
;ATA Control Settings
;
DHR_LBA_MODE  equ 40h  ;DHR Register enable LBA mode (default is CHS)
;
;ATA Status Register Flage
;
STATUS_BSY  equ 80h    ;Device Busy
;
;ATA Feature Codes
;
FEATURE_8BIT_ON  equ 01h   ;Enable 8-bit transfers in LBA mode
;
; BIOS equates
;
ccp		equ 0de00h		;base of ccp
bdos	equ ccp+800h	;base of bdos
bios	equ ccp+1600h	;base of bios
;
;	bios access constants
;
boot	set	bios+3*0	;cold boot function
wboot	set	bios+3*1	;warm boot function
const	set	bios+3*2	;console status function
conin	set	bios+3*3	;console input function
conout	set	bios+3*4	;console output function
list	set	bios+3*5	;list output function
punch	set	bios+3*6	;punch output function
reader	set	bios+3*7	;reader input function
home	set	bios+3*8	;disk home function
seldsk	set	bios+3*9	;select disk function
settrk	set	bios+3*10	;set track function
setsec	set	bios+3*11	;set sector function
setdma	set	bios+3*12	;set dma function
read	set	bios+3*13	;read disk function
write	set	bios+3*14	;write disk function
listst	set	bios+3*15	;list status function
sectran	set	bios+3*16	;sector translate
;
;
; Disk driver variables needed
;
;
hstact equ 0f894h	;host active flag for deblocking
unacnt equ 0f896h	;unallocated record count for deblocking
disk00 equ 0ff23h	;physical disk to virtual disk translation
;
;
maxdrv equ 15
;
;
; Write types
;
wrall	equ	0   ;write to allocated
wrdir	equ	1   ;write to directory
wrual	equ	2   ;write to unallocated
;
;
   org 1000h
;
;
format  lxi d, frmtmsg  ;Point to start message
        call print      ;Print it
frmt01  call conin      ;Get yes or no
		ani 0dfh        ;Make it upper case
        cpi 'Y'         ;Is it 'Y'?
        jz frmt02       ;Do format
        cpi 'N'         ;Is it 'N'?
        jz frmt10       ;If not print abort message and exit
        jmp frmt01      ;Ask again
;
;Set drive for LBA mode and 8 bit transfers
;
frmt02  in ATA_DRV_HEAD	         ;Get current DHR bits
        ori DHR_LBA_MODE         ;Set the LBA mode bit
        out ATA_DRV_HEAD         ;Write bits to the DHR register
        mvi a, FEATURE_8BIT_ON   ;Get feature code for 8-bit mode
        out ATA_FEATURES         ;Write 8-bit feature code to features register
        mvi a, CMD_SET_FEATURES  ;Get ready for Features command
        out ATA_COMMAND          ;Request Set Features command
atabusy in ATA_STATUS            ;Get ATA status
        ani STATUS_BSY           ;Mask on busy bit
        jnz atabusy              ;If busy check again
;
;Initialize sector buffer
;
        lxi b, secbuf   ;Point to default disk buffer
        call setdma     ;Set dma to sector buffer
        mvi d, 80h      ;Disk buffer length
        mvi a, 0e5h     ;Format character
frmt03  stax b          ;Save it in disk buffer
        inx b           ;Point to next buffer character
        dcr d           ;Count down
        jnz frmt03      ;Do it again
;
;Write sector buffer to each logical disk
;
        mvi a, 0        ;Set up disk driver
        sta hstact		;host buffer inactive
        sta unacnt      ;clear unalloc count 
        sta disk00      ;Start with disk 0
        mov c, a        ;Always format drive 0 (mapped to other drives)
        call seldsk     ;Select the disk
frmt04  lxi d, frmtdrv  ;Point to drive message
        call print      ;Print it
		lda disk00      ;Get current drive
        adi 'A'         ;Calculate drive letter
        mov c, a        ;Transfer to register c
        call conout     ;Print it
        mvi c, 0dh      ;Carriage return
        call conout     ;Print it
        mvi c, 0ah      ;Line feed
        call conout     ;Print it
frmt05  lxi b, 1        ;Select track 1 (directory)
        call settrk
        lxi h, seccnt   ;Point to sector counter
        mvi c, 00       ;Select sector 0
        mov m, c        ;Save it in the counter
frmt06  call setsec     ;Select the sector
        mvi c, wrdir    ;Don't buffer
        call write      ;Write the formatted sector
        ora a           ;Did write succeed?
        jnz frmt09      ;Print error message and exit
        mvi c, '.'      ;Status character
        call conout     ;Print it
        lxi h, seccnt   ;Point to sector counter
        mov c, m        ;Get current sector
        inr c           ;Count up
		mov a, c        ;Put sector count in A
		cpi 0           ;End of directory?
        jz frmt07       ;Next drive if end of directory
        mov m, c        ;Save sector counter
        jmp frmt06      ;Do next sector        
frmt07  lda disk00      ;Get current disk
        inr a           ;Next drive
        cpi maxdrv      ;Finished last drive?
		jz frmt08       ;Done with formatting
		sta disk00      ;Otherwise do again
        jmp frmt04      ;Format next drive
;
;Print successful format message
;
frmt08  lxi d, frmtenm  ;Point to end of formatting
        call print      ;Print it
        jmp frmt11      ;Exit
;
;Print write error message
;
frmt09  lxi d, frmterr  ;Point to error message
        call print      ;Print it
        jmp frmt11
;
;Print abort message
;
frmt10  lxi d, frmtabt  ;Point to abort message
        call print
;
;Print exit message and jump to monitor
;
frmt11  lxi d, frmtexm  ;Point to exit message
        call print      ;Print it
        jmp MONITOR     ;Jump to monitor
;
;Print string utility
;Pointer to null terminated string in de
;
print:  ldax d          ;Print a message on the console
        ora a           ;End of string?
        jz pend         ;Exit if end of string
        mov c, a        ;Move shar into C for console out
        call conout     ;Print it
        inx d           ;Point to next character
        jmp print       ;Repeat
pend:   ret             ;And exit
;
;Console messages
;
frmtmsg db 'Disk formatter v1.0'
        dw 0d0ah
        db 'Warning!  This will format all logical drives.'
        dw 0d0ah
        db 'ARE YOU SURE (Y/N)?'
        dw 0d0ah
        db 0
frmtdrv dw 0d0ah
        db 'Formatting drive '
        db 0
frmterr dw 0d0ah
        db 'Error formatting drive!'
        dw 0d0ah
        db 0
frmtenm dw 0d0ah
        db 'Format completed successfully.'
        dw 0d0ah
        db 0
frmtabt db 'Format aborted.'
        dw 0d0ah
        db 0
frmtexm db 'Returning to monitor.'
        dw 0d0ah
        db 0
;
;Sector counter
;		
seccnt  db 0
;
cdisk   db 0
;
secbuf	db 128
;
   end