Subttl -IBM Soft_Sectored Double_Density Format (6_Jul_83) ;========================================================= ; ; Internal DJDMA Routines home equ 0a0h ;DJDMA Home Routine seek equ 0a3h ;DJDMA Seek Routine sdrive equ 0a6h ;DJDMA Select Drive Routine hsync equ 0a9h ;DJDMA Hole Sync. Routine (hard sectored disks only) ; Registers diskd equ 4001h ;Disk Data Port status equ 4003h ;Status Register Location on DJDMA board contrl equ 4007h ;Disk Control Port ; Bit Masks for the disk status port (4003h) INDEX equ 10h ;Index Pulse Mask .z80 dd: ;Define the starting address of the program in main memory .phase 1030h ddstr: ;Define the absolute starting address of this code section PAGE ;---------------------------------------------------------------------- ; Begin Tables ;------------- ; Parameter Table (8" (single-sided) Standard Format) ddpt: db 0 ;Drive Number db 77 ;Total Number of Tracks db 0 ;Current Track Number db 0 ;Side Number (0 -> 1) db 3 ;Sector Length Code (0 -> 3) db 1 ;Starting Sector Number (0 -> 1) db 9 ;Last Sector Number + 1 db 0E5h ;Fill Byte db 0 ;(Starting Track of Write Pre-Compensation) db 50h ;Pre-Index Gap (Gap-4) db 36h ;Post-Data Field Gap (Gap-3) db 0FFh ;Flag: Skip Index Mark (0=skip, not-0=write) db 0 ;Number of Sides (0=1_Side, 1=2_Sides) ds 3,0 ;Spares ; Entry Points ddjt: jp dde1 ;Fill in parameters jp dde2 ;Format Initial Entry Point jp dde3 ;Format Re:Entry Point jp dde4 ;Format Next Surface (Current Surface Plus One) jp dde5 ;Format Last Surface (Current Surface Minus One) ; Vectors to Parameters ddvt: dw dd1+1 ;Drive Number dw dd2 ;Total Number of Tracks dw dd3+1 ;Current Track Number (dtrck) d÷ dd4+± ;Current Sidå Numbeò (dside) dw dd5+1 ;Sector Length Code (dlcode) dw dd6 ;Starting Sector Number (dsect) d÷ dd7+± ;Lasô Sectoò Number « ± (dlast) dw dd8+1 ;Fill Byte dw ddnul ;Starting track of write precompensation - NULL dw dd10+1 ;Pre-Index Gap (Gap-4) dw dd11+1 ;Post-Data Field Gap (Gap-3) dw dd12+1 ;Flag: Skip Index Mark (0=skip, not-0=write) dw dd13 ;Number of Sides (0=1_Side, 1=2_Sides) dw ddnul ;Spare dw ddnul ;Spare dw ddnul ;Spare PAGE ;---------------------------------------------------------------------- ; Begin the Transfer Parameters Routine ;-------------------------------------- ; 1) This routine stuffs the values from the parameter table (xxxxpt) ; into the appropriate locations in the code. ; Save the Registers dde1: push bc ;Save The Primary registers push de push hl ld (dds1),sp ;save the stack pointer ; Set up the registers for the transfer loop ld sp,ddvt ;SP:= Vector Table ld de,ddpt ;DE:= Parameter Table ld b,16 ;Counter:= max count ; Move the parameters into the code section ddlp: ld a,(de) ;Repeat pop hl ld (hl),a ; Vector_Location:= Parameter inc de djnz ddlp ;Until (all parameters have been transferred) ; Restore the Registers ld sp,(dds1) ;Restore the stack pointer pop hl pop de pop bc ;Restore the register set ld a,40h ;Flag:= Normal Status ret ;Return PAGE ;---------------------------------------------------------------------- ; Begin the Format Routine ;------------------------- ; ; Initial Entry Point ;-------------------- ; ; Set the byte count dde2: ld de,0 ld a,(dd5+1) ld e,a ;DE:= Offset ld hl,ddbtbl ;HL:= Pointer to Table base add hl,de ld a,(hl) ld (ddint1+1),a ; Select The Drive dd1: ld a,0 ;Second byte filled with proper drive number call sdrive ;Select the new drive ret nz ;Return if wrong value ld a,(iy+2) ;Get the drive pattern bit 2,(iy+0Eh) ;If (Drive is 8") jr nz,dd5dr or 0fh ; Side 0 and no step command ld (4005h),a ; Update drive control register ld bc,50 call dwait ; Wait 50 ms for the head to load jr ddcnt1 dd5dr: and 0FEh ;Else ld (4004h),a ; Side 0 no_Step and motor on ld bc,1000 call dwait ; wait 1 sec for the motor to reach speed ddcnt1: ld (ix+0bh),0 ;Reset the index counter set 2,(ix+0eh) ;set the motor status to on call home ;Calibrate the head(s) ld hl,status ;HL:= Pointer to the status register bit 5,(hl) ;If (Track 0 Flag ne Active) jr z,nrexit ; Return Error (82h - Drive not Ready) bit 5,(iy+0Eh) ;If (drive has a ready line) jr nz,ddcnt2 bit 7,(hl) ; If (drive is not ready) nrexit: ld a,82h ; ret z ; Return Error (82h) ddcnt2: bit 6,(hl) ;If (Drive is write protected) ld a,90h ; ret nz ; Return Error (90h Write Protected) PAGE ; Re:Entry Point ;--------------- ; dde3: ld (ix+0bh),0 ;Reset index counter ;Set the starting sector number ld a,(dd6) ld (ddint2+1),a ; Find the proper track ld a,(dd3+1) ;If (Desired track ne Current Track) cp (iy+1) ; (current track) push af ; (-> Save the current track) call nz,seek ; Move the head(s) ; Set write pre-comp and low-current (written to 4006h) ld a,(iy+0fh) ;If (write pre-comp is NOT user specified) or a jr nz,ddskp3 ld a,(dd2) ; If (Drive size is 5") cp 77 jr z,ddskp2 srl a ; Default:= Highest_Track/2 jr ddskp3 ; Else ddskp2: ld a,43 ; Default:= track 43 ddskp3: ld b,a pop af ;(<- Restore the current track) cp b ;If (track ge starting track of write pre-comp) ld a,4 ; (No write precompensation) jr c,loadpc ld a,14h ; Set Write precompensation bit loadpc: bit 2,(iy+0eh) ;If (Drive is 5") jr z,ldpc2 set 5,a ; Set the 'Mini' bit in reg 4006 image ldpc2: ld (ddint3+1),a ;Setup the write precompensation byte sbc a,a ;Push carry bit throughout accumulator or 0feh ;Low current bit now set and (iy+2) ;Merge with drive pattern ; Select the proper side and 0FDè ;Deselect the side ld b,a ld a,(dd4+1) ;(must be either 0 or 1) sla a ;A:= Side-Number shifted into bit 2 and 02 xoò 0² ;(Bit_²: Side_1=1» Side_2=0© or b or 0ch ;Turn off step command ld hl,4005h ;HL:= Pointer to 8" Control Port bit 2,(iy+0Eh) ;If (Drive is 5") jr z,ddin dec hl ; HL:= Pointer to 5" Control Port ddin: ld (hl),a ;Select the Current side ld hl,diskd ;Pointer to disk shift register ld de,contrl ;Pointer to control port ; Sync with the index ddlbl1: ld a,(status) ;Wait for index pulse to come and INDEX jr nz,ddlbl1 ddlbl2: ld a,(status) ;Wait for index pulse to pass and INDEX jr z,ddlbl2 ld a,90h ;Control byte - normal write/no crc ld (de),a ;Initialize control port ddint3: ld a,0 ld (4006h),a ;Start the controller PAGE ; Write the Index Mark ;--------------------- ; 4E(80), 00(12), F6(3), FC(1), 4E(50) ; dd10: ld b,50h ;Preamble length ddlbl3: ld (hl),4eh djnz ddlbl3 ;Write the preamble dd12: ld a,0FFh ;If (flag eq skip-Index-Mark) or a jr z,dmloop ; Goto Write a Sector ld b,0ch ;Zero preamble length ddlbl4: ld (hl),0 djnz ddlbl4 ;Write the zero preamble ld a,80h ;Control byte for 16 bit write ld (de),a ;Change mode ld (hl),52h ;First half of c2 ld (hl),24h ;Second half of c2 ld (hl),52h ;Another c2 ld (hl),24h ld (hl),52h ;The third c2 ld a,90h ;Control byte 8 bit write ld (de),a ;Change mode ld (hl),24h ;Finish the sync bytes ld (hl),0fch ;Index mark ld b,32h ;Postamble length ddlbl5: ld (hl),4eh djnz ddlbl5 ;Write the postamble PAGE ; Write A Header ;--------------- ; 00(12), F5(3), FE(1), Track, Side, Sector, Size, CRC(2), 4E(22) ; dmloop: ld b,0ch ;Zero preamble length ddlbl6: ld (hl),0 djnz ddlbl6 ;Write the preamble ld a,81h ;16 bit write mode w/crc ld (de),a ;Change mode ld (hl),44h ;First half of a1 ld (hl),89h ;Second half of a1 ld (hl),44h ;Second a1 ld (hl),89h ld (hl),44h ;Third a1 ld a,91h ;8 bit write mode w/crc ld (de),a ;Change mode ld (hl),89h ;Finish sync bytes ld (hl),0feh ;Sector header id byte dd3: ld (hl),0 ;Write the track number dd4: ld (hl),0 ;Write the side ddint2: ld (hl),1 ;Write the sector number dd5: ld (hl),1 ;Sector length code ld a,0a1h ;Mode to write crc bytes ld (de),a ;Change mode ld (hl),a ld (hl),a ;Write the crc bytes ld a,90h ;Reset crc generator ld (de),a ;Change mode ld b,16h ;4e postamble length ddlbl7: ld (hl),4eh djnz ddlbl7 ;Write the postamble PAGE ; Write A Data Field ;------------------- ; 00(12), F5(3), FB(1), Fill_Byte(128-1024), CRC(2), 4E(54) ; ld b,0ch ;Data field preamble ddlbl8: ld (hl),0 djnz ddlbl8 ;Write the preamble ld a,81h ;16 bit write w/crc ld (de),a ;Change mode ld (hl),44h ;First half of a1 ld (hl),89h ;Second half of a1 ld (hl),44h ;Second a1 ld (hl),89h ld (hl),44h ;Third a1 ld a,91h ;8 bit write w/crc ld (de),a ;Change mode ld (hl),89h ;Finish the 3 sync bytes ld (hl),0fbh ;Data header ID byte dd8: ld a,0E5h ;A:= Fill Byte ddint1: ld b,40h ;Sector length divided by four ddlbl9: ld (hl),a ;Empty sector data byte ld (hl),a ld (hl),a ld (hl),a ;Write four fill bytes djnz ddlbl9 ;Test for data field write done ld a,0a1h ;Crc control byte ld (de),a ;Change mode ld (hl),a ;Write the crc bytes ld (hl),a ld a,90h ;Turn off the crc generator ld (de),a ;Change mode ld a,(ddint2+1) inc a ld (ddint2+1),a ;Sector_Number:= Sector_Number + 1 ld (hl),4eh ; dd7: cp 9 ;If (All Sectors have been written) jr z,ddlblb ; Goto Write Postamble dd11: ld b,36h ;Sector Postamble length dec b ;(adjust Length) ddlbla: ld (hl),4eh djnz ddlbla ;Write the sector postamble jp dmloop PAGE ;Write the Postamble ;------------------- ; 4E(to the start of the index) ; ddlblb: ld (hl),4eh ;Write a fill byte ld a,(status) and INDEX ;Wait for the index pulse jr z,ddlblb ddlblc: ld (hl),4eh ;Trailing fill byte ld (hl),4eh ;Trailing fill byte ld (hl),4eh ;Trailing fill byte xor a ld (de),a ;Turn off the write gate ld a,6 ld (4006h),a ;Turn off the controller call dl1ms ;Delay 1 Millisecond before returning ld a,40h ;Status code ret ;---------------------------------------------------------------------- ; Time Delay Routines ;-------------------- ; ; Wait the time Specified in the BC register pair ;------------------------------------------------ ; dwait: call dl1ms ;Repeat dec bc ; Wait a millisecond ld a,b or c jr nz,dwait ;Until (Time_Delay eq 0) ret ; Delay 1 Millisecond ;-------------------- ; dl1ms: push bc ld b,200d ;B:= Tic-Count ddllp: ld a,a ;Repeat djnz ddllp ;Until (Tic-count eq 0) pop bc ret PAGE ;---------------------------------------------------------------------- ; Format the Next Surface ;------------------------ ; dde4: ld a,(dd13) ld b,a ;B:= Max Surface Number ld a,(dd4+1) inc a ;Current_Surface:= Current_Surface + 1 cp b ;If (Current_Surface le Max_Surfaces) jp m,dds41 jp z,dds41 ld a,(dd3+1) ;Else inc a ld (dd3+1),a ; Track_Number:= Track_Number + 1 ld a,0 ; Surface:= 0 dds41: ld (dd4+1),a ;Update Surface Number call dde3 ;Format the Track ret ;Return with track value ;---------------------------------------------------------------------- ; Format the Last Surface ;------------------------ ; dde5: ld a,(dd4+1) dec a ;Current_Surface:= Current_Surface - 1 jp p,dds51 ;If (Current_Surface lt Zero) ld a,(dd3+1) dec a ; Track_Number:= Track_Number - 1 ld (dd3+1),a ld a,(dd13) ; Surface:= Max Surface Number dds51: ld (dd4+1),a ;Update Surface Number call dde3 ;Format the Track ret ;Return with track value ;---------------------------------------------------------------------- ; Data Area ;---------- ; dd2: db 77 ;Total Number of Tracks dd6: db 1 ;Starting sector number dd13: db 1 ;Number of Surfaces dds1: dw 0 ;Save location for the stack pointer ddnul: dw 0 ;Null pointer ;Table of Bytes per Sector/4 ddbtbl: db 128/4 ;20 = 128 Bytes db 256/4 ;40 = 256 Bytes db 512/4 ;80 = 512 Bytes (for Micronix) äb LOW (1024/4) ;0 = 1024 Bytes (Standard) ddend: ;Define the absolute ending address of this code section .dephase end