title '512-byte Format of 6-10-84' ; For 512 x 16 on 8-inch, or 512 x 10 on 5-inch diskettes. ; For Tarbell Duplex 816 (tm) 80186/Z80H CPU Board. ; Copyright (c) 1984 Tarbell Electronics. ; ; TRUE EQU 0FFFFH FALSE EQU NOT TRUE M EQU Byte Ptr 0[BX] ; mini equ false ; true for 5-inch floppies. if mini ; if minifloppy, tracks equ 40 ; 40 tracks. sdspt equ 18 ; single density sectors/trk. sdbps equ 128 ; single density bytes per sector. sdinff equ 24 ; post-index ff's (gap 1). sdin00 equ 4 ; post-index 00's (gap 1). sdidff equ 8 ; pre-id ff's. sdid00 equ 6 ; pre-id 00's. sddaff equ 11 ; pre-data ff's. sdda00 equ 6 ; pre-data 00's. sdfill equ 0e5h ; single-density fill byte. ddbps equ 512 ; double density bytes per sector. ddspt equ 10 ; double density sectors per track. ddin4e equ 32 ; post-index 4e's. ddid00 equ 12 ; pre-id 00's. ddidf5 equ 3 ; pre-id f5's. ddda4e equ 22 ; pre-data 4e's. ddda00 equ 12 ; pre-data 00's. dddaf5 equ 3 ; pre-data f5's. ddid4e equ 32 ; pre-id 4e's. ddfill equ 0e5h ; double-density fill byte. endif if not mini ; if not minifloppy, tracks equ 77 ; 77 tracks. sdbps equ 128 ; single density bytes per sector. sdspt equ 26 ; single density sectors/trk. sdinff equ 40 ; post-index ff's (gap 1). sdin00 equ 6 ; post-index 00's (gap 1). sdidff equ 26 ; pre-id ff's. sdid00 equ 6 ; pre-id 00's. sddaff equ 11 ; pre-data ff's. sdda00 equ 6 ; pre-data 00's. sdfill equ 0e5h ; single-density fill byte. ddbps equ 512 ; double density bytes per sector. ddspt equ 16 ; double density sectors/trk. ddin4e equ 40 ; post-index 4e's. ddid00 equ 12 ; pre-id 00's. ddidf5 equ 3 ; pre-id f5's. ddda4e equ 22 ; pre-data 4e's. ddda00 equ 12 ; pre-data 00's. dddaf5 equ 3 ; pre-data f5's. ddid4e equ 54 ; pre-id 4e's. ddfill equ 0e5h ; double-density fill byte. endif ; Codes for Duplex 816 Board. ; Floppy controller port addresses and command words. fbase equ 0f080h ; floppy controller base adr. fstat equ fbase ; controller status. fcom equ fbase ; command port adr. ftrk equ fbase+2 ; track port. fsect equ fbase+4 ; sector port. fdata equ fbase+6 ; data port. fcont equ 0f100h ; control latch port. if mini ; if minifloppy, fsize equ 00h ; code for latch. pctrk equ 80 ; pre-compensation track. endif if not mini ; if it's an 8-inch floppy, fsize equ 0ch ; code for latch. pctrk equ 43 ; pre-compensation track. endif sngden equ 10h ; single density latch bit. wrtprc equ 20h ; write-precompensation bit. side1 equ 40h ; side one latch bit. stprat equ 0 ; step rate: 0=3ms, 1=6ms. restore equ 08h+stprat ; 08 loads head first. seek equ 18h+stprat ; code for seek with head load. wrtrak equ 0f4h ; write track command. errmsk equ 09dh ; floppy error mask. ; Floppy DMA port addresses and command words. dmabas equ 0ffc0h ; dma controller base address. dmacon0 equ dmabas+0ah ; control port. dmatc0 equ dmabas+08h ; transfer count register. dmadpu0 equ dmabas+06h ; destination pointer upper. dmadpl0 equ dmabas+04h ; destination pointer lower. dmaspu0 equ dmabas+02h ; source pointer upper. dmaspl0 equ dmabas ; source pointer lower. fdmard equ 0a266h ; floppy-to-memory command. fdmawt equ 016a6h ; memory-to-floppy command. ; RCB EQU 10 cr equ 0dh ; carriage-return. lf equ 0ah ; line-feed. ORG 100H ; START: MOV BX,0 ;clear h,l MOV DX,(Offset MSG1) call print ; sign on. COMPLT: XOR AL,AL ;get a zero mov Byte Ptr clatch,fsize+sngden ; init latch code. MOV Byte Ptr XFER,AL ;clear to dma type xfer. MOV Byte Ptr SIDED,AL ;default = single sided INC AL ;flag <> 0,= format all the disk MOV Byte Ptr FLAG,AL MOV Byte Ptr fcode,0deh ; set format code. MOV DX,(Offset MSG2) call print CALL INPUT CMP AL,'Q' ;quit? JZ WEXIT ;yes, exit to system AND AL,3 ;make upper case DEC AL ;make cpm drive number MOV CL,AL ;save it in reg c MOV AL,Byte Ptr CLATCH ;get clatch value OR AL,CL ;select the drive MOV Byte Ptr CLATCH,AL ;save drive code MOV DX,(Offset MSG2C) ;format doub sided? call print CALL INPUT CMP AL,'Y' JNZ NOTSID MOV Byte Ptr SIDED,AL ;flag = yes mov Byte Ptr fcode,0dch ; set format code. NOTSID: DSEL: MOV DX,(Offset MSG2A) ;tracks to format message call print CALL INPUT CMP AL,'A' ;all tracks? JZ START1 CMP AL,'S' ;system tracks? JZ SYSTEM CMP AL,'Q' ;quit? JNZ DSEL WEXIT: mov cx,0 ; do return to system. int 224 ; ;input routine - get a character from keyboard ; ;enter: none ;exit: reg a = char from keyboard ; stored at seld ;registers used: d,e h,l c ; INPUT: MOV AL,3 ;reset buffer length MOV BX,0 MOV Word Ptr KEYBUF+1,BX ;clear buffer MOV Byte Ptr KEYBUF,AL MOV DX,(Offset KEYBUF) ;point to buffer MOV CL,RCB ;read buffer function INT 224 ;get character MOV AL,Byte Ptr KEYBUF+2 ;get the first char only CMP AL,'a' ;check for lower case JNB L_1 RET L_1: CMP AL,'z'+1 JNAE L_2 RET L_2: AND AL,5FH ;make into upper case RET ; DSIDE0: MOV AL,Byte Ptr CLATCH ;get current latch code and al,not side1 ; force side 0 active. JMPS SAVEL ;save it ; DSIDE1: MOV AL,Byte Ptr CLATCH ;get current latch code OR AL,SIDE1 ;force side 1 SAVEL: MOV Byte Ptr CLATCH,AL ;save it setlat: push dx ; save dx. mov dx,fcont ; get control latch port. out dx,al pop dx ; restore dx. RET ; SYSTEM: XOR AL,AL MOV Byte Ptr FLAG,AL ;set system only START1: MOV AL,Byte Ptr CLATCH ;get latch value call setlat ; set latch. MOV AL,RESTORE push dx ; save dx. mov dx,fcom ; get floppy command port. out dx,al ; send command. pop dx ; restore dx. call waitio ; wait till done. MOV DH,0 ;set for track 0 MOV DL,1 ;sector MOV BX,(Offset BUFF) ;dma buffer MOV AL,0FFH mov ch,sdinff ; post-index ff's. CALL PUT XOR AL,AL mov ch,sdin00 ; post-index 00's. CALL PUT mov m,0fch ; index mark. INC BX sloop: mov ch,sdidff ; pre-id ff's. MOV AL,0FFH CALL PUT XOR AL,AL mov ch,sdid00 ; pre-id 00's. CALL PUT mov m,0feh ; id address mark. INC BX MOV M,DH ;track INC BX MOV M,0 ;side 0 INC BX mov m,dl ; sector. INC BX MOV M,0 INC BX mov m,0f7h ; generate id crc. INC BX MOV AL,0FFH mov ch,sddaff ; pre-data ff's. CALL PUT mov ch,sdda00 ; pre-data 00's. XOR AL,AL CALL PUT mov m,0fbh ; data address mark. INC BX mov al,sdfill ; fill byte for data area. mov ch,sdbps ; get bytes per sector. CALL PUT ;data 128 bytes cmp dl,1 ; are we on sector 1? JNZ NOT1 ;no, skip special id byte PUSH BX ;yes, put in DEC BX DEC BX mov ah,Byte Ptr fcode ; get format code. mov m,ah ; put into buffer. not ah ; complement format code. dec bx ; put into buffer. mov m,ah POP BX not1: mov m,0f7h ; generate data crc. INC BX INC DL cmp dl,sdspt+1 ; past last sector yet? jnz sloop ; loop back if not. MOV CL,3 SLOOP3: MOV CH,0 MOV AL,0FFH CALL PUT DEC CL JNZ SLOOP3 PUSH DX CALL DMA ;write the disk with dma POP DX call rdstat ; read floppy status. JZ L_3 JMP ERROR L_3: MOV AL,Byte Ptr SIDED ;doing doub sided? OR AL,AL ;= to 0? JNZ START2 ;if not, we are doing d.s INC DH MOV AL,DH push dx ; save dx. mov dx,fdata ; get floppy data port adr. out dx,al ; send data. pop dx ; restore dx. MOV AL,SEEK push dx ; save dx. mov dx,fcom ; get floppy command port adr. out dx,al ; do seek. pop dx ; restore dx. call waitio ; wait until done. JMPS START3 ; ;here starts the double density formatting ; START2: MOV AL,1 ;doing trk 0 side 1 d.d. MOV Byte Ptr SFLAG,AL ;set the flag START3: MOV AL,Byte Ptr CLATCH ;get the current latch condition and al,not sngden ; clear single density latch bit. call savel ; set latch and save it. MOV BX,(Offset TABLE) ;point to sequential table for trk 1 LOOP2: MOV Word Ptr tptr,BX ;reset table pointer MOV DL,M ;sector number. MOV BX,(Offset BUFF) ;dma buffer MOV CH,ddin4e ;gap 1 MOV AL,4EH CALL PUT LOOP: CALL PUTZERO MOV AL,0F5H MOV CH,ddidf5 CALL PUT MOV M,0FEH INC BX MOV M,DH ;track INC BX MOV M,0 ;side 0 INC BX MOV M,DL INC BX MOV M,2 INC BX MOV M,0F7H INC BX MOV AL,4EH MOV CH,ddda4e CALL PUT CALL PUTZERO MOV AL,0F5H MOV CH,dddaf5 CALL PUT MOV M,0FBH INC BX MOV AL,ddfill MOV CH,00 CALL PUT ;data 128 bytes MOV CH,00 CALL PUT MOV M,0F7H INC BX MOV AL,4EH MOV CH,ddid4e ;this = 54 when doing 512 byte CALL PUT CALL NEXTSECT JNZ LOOP MOV CL,5 LOOP3: MOV CH,0 MOV AL,4EH CALL PUT DEC CL JNZ LOOP3 MOV AL,Byte Ptr SIDED OR AL,AL JZ NOTSID1 CALL DSIDE1 PUSH DX PUSH BX CALL DMA POP BX POP DX call rdstat ; read floppy status. JNZ ERROR CALL DSIDE0 MOV AL,Byte Ptr FLAG OR AL,AL JNZ L_4 JMP COMPLT L_4: MOV AL,Byte Ptr SFLAG ;doing trk 0 side 1? CMP AL,1 ;if = 1 then yes. MOV AL,0 ;reset the flag MOV Byte Ptr SFLAG,AL ; JZ S1DONE ;this special side done NOTSID1:PUSH DX PUSH BX CALL DMA POP BX POP DX call rdstat ; read floppy status. JNZ ERROR MOV AL,Byte Ptr FLAG ;are we doing all the disk ? OR AL,AL ;yes if not = 0 JNZ L_5 JMP COMPLT ;no, just first 2 tracks if = 0 L_5: S1DONE: INC DH MOV AL,DH cmp al,tracks ; last track? JNZ L_6 JMP COMPLT L_6: push dx ; save dx. mov dx,fdata ; get floppy data port. out dx,al ; write track number. mov dx,fcom ; get floppy command port. mov al,seek ; get seek command. out dx,al ; do seek. pop dx ; restore dx. call waitio ; wait until done. MOV BX,(Offset STABLE) ;reset sector pointer JMP LOOP2 ; Read floppy status and mask error bits. rdstat: push dx ; save dx. mov dx,fstat ; get status port adr. in al,dx ; read status. pop dx ; restore dx. and al,errmsk ; look at error bits. ret ; PUT: MOV M,AL INC BX DEC CH JNZ PUT RET ; PUTZERO:MOV CH,ddid00 XOR AL,AL JMPS PUT ; ERROR: MOV DX,(Offset MSG3) call print JMP COMPLT ; ; Write a track from BUFF to disk. ; DMA: ; Make sure the pre-compensation bit is set right. mov al,clatch ; get latch byte. cmp dh,pctrk ; is it past precomp track? jc dmanpc ; hop if not. or al,wrtprc ; set pre-comp bit if so. jmps dmasl ; set latch. dmanpc: and al,not wrtprc ; clear pre-comp bit. dmasl: call savel ; save and set latch. ; figure physical address from segment and offset. mov bx,(offset buff) ; get buffer offset. mov ax,cs ; get segment. mov cl,4 ; get shift count. rol ax,cl ; rotate segment 4 left. mov cl,al ; save top 4 bits. and cl,0fh ; mask for 4 bits only. and ax,0fff0h add bx,ax ; add shifted segment. mov al,0 ; clear. adc al,cl ; add top 4 & carry. ; set source and destination addresses in dma controller. mov dx,dmaspu0 ; get source upper. out dx,ax ; set it. mov dx,dmaspl0 ; get source lower. mov ax,bx ; get the address. out dx,ax ; set it. mov dx,dmadpu0 ; get destination upper. mov ax,0 ; no upper bits on floppy. out dx,ax mov dx,dmadpl0 ; get destination lower. mov ax,fdata ; get floppy data port. out dx,ax ; destination = data port. ; set transfer count register in dma controller. mov ax,16000 ; get transfer count. mov dx,dmatc0 ; get dma count port. out dx,ax ; set count. ; initiate dma write operation. mov dx,dmacon0 ; get dma control port. mov ax,fdmawt ; get dma write command. out dx,ax ; set it. ; send write track command to floppy controller. mov al,wrtrak ; get write track command. mov dx,fcom ; get floppy command port. out dx,al ; start write track operation. call waitio ; wait till done. jmp fdelay ; wait a little more. ; wait here until done with operation. waitio: call fdelay ; wait for valid status. push dx ; save dx. mov dx,fstat ; get floppy status port. waitil: in al,dx ; read floppy status. test al,1 ; is operation done yet? jnz waitil ; loop till it is. pop dx ; restore dx. ret ; return from waitio & dma. ; Provide a delay after commands for status to become valid. fdelay: push cx ; save cx. mov cx,80h ; get count. fdloop: loop fdloop ; decrement cx until zero. pop cx ; restore cx. ret ; NEXTSECT: PUSH BX MOV BX,Word Ptr tptr INC BX ;bump pointer MOV Word Ptr tptr,BX ;and get next byte MOV DL,M ;save sector number in reg e MOV AL,DL ;check for end of table POP BX OR AL,AL ;set flags RET ; print message on crt. print: mov cl,9 ; get print code. int 224 ; call bdos. ret ; Messages. ; MSG1 DB cr,lf,'512-byte Format Program for Duplex 816' DB cr,lf,'Copyright (c) 1984 Tarbell Electronics' db cr,lf,'Last changed June 10, 1984',cr,lf db cr,lf if mini ; if minifloppy, db '5-inch floppy format:',cr,lf db 'Track 0 = 18 , 128-byte sectors',cr,lf db 'Tracks 1 - 39 = 10 , 512-byte sectors',cr,lf endif if not mini ; if 8-inch, db '8-inch floppy format:',cr,lf DB 'Track 0 = 26 , 128-byte sectors',cr,lf DB 'Tracks 1 - 76 = 16 , 512-byte sectors',cr,lf endif DB cr,lf,'$' MSG2 DB cr,lf,'Drive ? (A,B,C,D) or Q to Quit $' MSG2A DB cr,lf,'Format System or All or Quit? (S,A, or Q) $' MSG2C DB cr,lf,'Format double sided (Y or N) $' MSG3 DB cr,lf,7,'ERROR- Check for write protected disk',cr,lf,'$' ; FLAG DB 0 TPTR DW (Offset TABLE) ; ;table for 512 x 16 sectors ; TABLE DB 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 DB 0 ; STABLE: if not mini db 1,9,2,10,3,11,4,12,5,13,6,14,7,15,8,16 endif if mini db 1,6,2,7,3,8,4,9,5,10 endif db 0 ; end of stable. CLATCH DB 0 ;current hardware latch value fcode db 0 ; disk format code. SFLAG DB 0 ;if 1, doing trk 0 side 1 doub den SIDED DB 0 ;0= sing.sided, <> 0 = doub.sided XFER DB 0 ;type xfer flag byte KEYBUF RS 6 BUFF RS 16000 ; allow plenty of space. eop db 0 ; end of program. END