From 98cab31fc3659e33aef260efca55bf9f1753164c Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Mon, 11 Feb 2019 11:49:19 +0100 Subject: Add source files from Michael --- system/shard-x86-at/7/src/FDISK.ASM | 839 ++++++++++++++++++++++++++++++++++++ 1 file changed, 839 insertions(+) create mode 100644 system/shard-x86-at/7/src/FDISK.ASM (limited to 'system/shard-x86-at/7/src/FDISK.ASM') diff --git a/system/shard-x86-at/7/src/FDISK.ASM b/system/shard-x86-at/7/src/FDISK.ASM new file mode 100644 index 0000000..1ada045 --- /dev/null +++ b/system/shard-x86-at/7/src/FDISK.ASM @@ -0,0 +1,839 @@ +;----------------------------------------------------------------------- +; Disketten I/O +; Input: +; (ah)=0 Reset Diskette System +; hard reset to nec, prepare command, recal rquired +; on all drives +; (ah)=1 read the status of the system into (al) +; diskette_status from last operation is used +; +; Registers for read/write/verify/format +; (dl) drive number (0-3 allowed, vlue checked) +; (dh) head number (0-1 allowed, not value checked) +; (ch) track number (0-39, not value checked) +; (cl) sektor number (1-8, not value checked, +; not used for format) +; (al) number of sektors ( max = 8, not value checked, +; not used for format +; (es:bx) address of buffer (not required for verify) +; (ah)=2 read the desired sektors into memory +; =3 write +; =4 verify +; =5 format +; for the format operation, the buffer pointer (es,bx) +; must point to the collektion of desired address fields +; for the track. Each field is composed of 4 Bytes, +; (c,h,r,n) where c = track number, h=head number, +; r = sektor number, n = number of bytes per sektor +; (00=128, 01=256, 02=512, 03=1024). There must be one +; entry for every sektor on the track. This information +; is used to find the requested sektor during read/write +; access. +; +; Data Variable -- disk_pointer +; double word pointer to the current set of diskette parameters +; Output +; ah = status of Operation +; Status bits are defined in the equates for +; Diskette_status variable in the data segment of this +; module. +; cy = 0 successful operation (ah = 0 on return) +; cy = 1 failed operation (ah has error reason) +; for read/write/verify +; ds,bx,dx,ch,cl reserved +; al = number of sektors actually read +; ***** al may not be correkt if time out error occurs +; note: if an error is reported by the diskette code, the +; appropriate action is to reset the diskette, then retry +; the operation, on read access, no motor start delay +; is taken, so that three retries are required on reads +; to ensure that the problem is not due to motor +; start-up. +;----------------------------------------------------------------------- + + data segment at 40h + org 3eh +seek_status db ? +int_flag equ 80h +motor_status db ? +motor_count db ? +motor_wait equ 37 +diskette_status db ? +nec_status db 7 dup(?) + + data ends + + assume ds:data + + ife withhd +dma equ 0 ; dma address +dma_high equ 82h ; port for high 4 bits of dma + endif + + +diskette_io proc near + sti + push bx + push cx + push ds + push si + push di + push bp + push dx + mov bp,sp ; set up pointer to head parm + mov si,data + mov ds,si + call j1 ; call the rest to ensure ds restored + mov bx,4 ; get the motor wait parameter + call get_parm + mov motor_count,ah ; set the timer count for the motor + mov ah,diskette_status ; get status of operation + cmp ah,1 ; set the carry flag to indicate + cmc ; success or failure + pop dx + pop bp + pop di + pop si + pop ds + pop cx + pop bx + ret +diskette_io endp + +j1 proc near + mov dh,al + and motor_status,07fh + or ah,ah + jz disk_reset + dec ah + jz fdisk_status + mov diskette_status,0 + cmp dl,4 + jae j3 + dec ah + jz fdisk_read + dec ah + jnz j2 + jmp fdisk_write +j2: + dec ah + jz disk_verf + dec ah + jz disk_format +j3: + mov diskette_status,bad_cmd + ret +j1 endp + +;----- reset the diskette system + +disk_reset proc near + mov dx,03f2h + cli + mov al,motor_status + mov cl,4 + sal al,cl + test al,20h + jnz j5 + test al,40h + jnz j4 + test al,80h + jz j6 + inc al +j4: + inc al +j5: + inc al +j6: + or al,8 + out dx,al + mov seek_status,0 + mov diskette_status,0 + or al,4 + out dx,al + sti + call chk_stat_2 + + mov al,nec_status + cmp al,0c0h + jz j7 + or diskette_status,bad_cntlr + ret + +;----- send specific command to nec + +j7: + mov ah,3 + call nec_output + mov bx,1 + call get_parm + mov bx,3 + call get_parm +j8: + ret +disk_reset endp + + +;-----diskette status routine + +fdisk_status proc near + mov al,diskette_status + ret +fdisk_status endp + + +;-----diskette read + +fdisk_read proc near + mov al,046h +j9: + call dma_setup + mov ah,0e6h + jmp short rw_opn +fdisk_read endp + + +;----- diskette verify + +disk_verf proc near + mov al,042h + jmp j9 +disk_verf endp + + +;----- diskette format + +disk_format proc near + or motor_status,80h + mov al,04ah + call dma_setup + mov ah,04dh + jmp short rw_opn +j10: + mov bx,7 + call get_parm + mov bx,9 + call get_parm + mov bx,15 + call get_parm + mov bx,17 + jmp j16 +disk_format endp + + +;-----diskette write routine + +fdisk_write proc near + or motor_status,80h + mov al,04ah + call dma_setup + mov ah,0c5h +fdisk_write endp + +;-----allow write routine to fall into rw_opn + +;----------------------------------------------------------------------- +; rw_opn +; this routine performs the read/write/verify operation +;----------------------------------------------------------------------- + +rw_opn proc near + jnc j11 + mov diskette_status,dma_boundary + mov al,0 + ret +j11: + push ax + +;----- turn on the motor and select the drive + + push cx + mov cl,dl + mov al,1 + sal al,cl + cli + + mov motor_count,0ffh + test al,motor_status + jnz j14 + and motor_status,0f0h + or motor_status,al + sti + mov al,10h + sal al,cl + or al,dl + or al,0ch + push dx + mov dx,03f2h + out dx,al + pop dx + +;----- wait for motor if write operation + + test motor_status,80h + jz j14 + + clc + mov ax,090fdh + int 15h + jc j14 + + + mov bx,20 + call get_parm + or ah,ah +j12: + jz j14 + sub cx,cx +j13: + loop j13 + dec ah + jmp j12 +j14: + sti + pop cx + +;----- do the seek operation + + call seek + pop ax + mov bh,ah + mov dh,0 + jc j17 + mov si,offset j17 + push si + +;----- send out the parameters to the controller + + call nec_output + mov ah,[bp+1] + sal ah,1 + sal ah,1 + and ah,4 + or ah,dl + call nec_output + +;----- test for format command + + cmp bh,04dh + jne j15 + jmp j10 +j15: + mov ah,ch + call nec_output + mov ah,[bp+1] + call nec_output + mov ah,cl + call nec_output + mov bx,7 + call get_parm + mov bx,9 + call get_parm + mov bx,11 + call get_parm + mov bx,13 +j16: + call get_parm + pop si + +;----- let the operation happen + + call wait_int +j17: + jc j21 + call results + jc j20 + +;----- check the results returned by the controller + + cld + mov si,offset nec_status + lods nec_status + and al,0c0h + jz j22 + cmp al,040h + jnz j18 + +;----- abnormal termination, find out wy + + lods nec_status + sal al,1 + mov ah,record_not_fnd + jc j19 + sal al,1 + sal al,1 + mov ah,bad_crc + jc j19 + sal al,1 + mov ah,bad_dma + jc j19 + sal al,1 + sal al,1 + mov ah,record_not_fnd + jc j19 + sal al,1 + mov ah,write_protect + jc j19 + sal al,1 + mov ah,bad_addr_mark + jc j19 + +;----- nec must have failed + +j18: + mov ah,bad_cntlr +j19: + or diskette_status,ah + call num_trans ; how many were really transferred +j20: + ret +j21: + call results + ret + +;----- operation was successfull + +j22: + call num_trans + xor ah,ah + ret +rw_opn endp + +;----------------------------------------------------------------------- +; nec_output +; This routine sends a byte to the nec controller after testing +; for correct direction and controller ready. This routine will +; time out if the byte is not accepted within a reasonable +; amount of time, setting the diskette status on completion. +; Input +; (ah) byte to be output +; Output +; cy=0 success +; cy=1 failure -- diskette status updated +; If a failure has occured, the return is made one level +; higher than the caller of nec_output. (!Schweinkram) +; This removes the requirement of testing after every +; call of nec_output +; (al) destroyed +;----------------------------------------------------------------------- + +nec_output proc near + push dx + push cx + mov dx,03f4h + xor cx,cx +j23: + in al,dx + test al,040h + jz j25 + loop j23 +j24: + or diskette_status,time_out + pop cx + pop dx + pop ax ; discard the return address + stc + ret +j25: + xor cx,cx +j26: + in al,dx + test al,080h + jnz j27 + loop j26 + jmp j24 +j27: + mov al,ah + mov dl,0f5h + out dx,al + pop cx + pop dx + ret +nec_output endp + +;----------------------------------------------------------------------- +; get_parm +; This routine fetches the indext pointer from the disk_bas +; block pointed at by the data variable disk_pointer. A byte from +; that table is then moved into ah, the index of that byte being +; the parm in bx +; Input: +; bx index of byte to be fetched *2 +; if the low bit of bx is on, the byte is immediately output +; to the nec controller +; Exit +; am that byte from block +;----------------------------------------------------------------------- + +disk_pointer equ 1eh * 4 + +get_parm proc near + push ds + push si + sub ax,ax + mov ds,ax + + lds si,dword ptr ds:disk_pointer + shr bx,1 + + mov ah,[si+bx] + pop si + pop ds + jc nec_output + ret +get_parm endp + +;----------------------------------------------------------------------- +; seek +; Thi routine will move the head on the named drive to the +; named track. If the drive has not been accessed since the +; drive reset command was issued, the drive will be recalibrated. +; Input: +; (dl) = Drive to seek on +; (ch) = track t seek to +; Output: +; cy = 0 success +; cy = 1 failure -- diskette_status set accordingly +; (ax) destroyed +;----------------------------------------------------------------------- + +seek proc near + mov al,1 + push cx + mov cl,dl + rol al,cl + pop cx + test al,seek_status + jnz j28 + or seek_status,al + mov ah,07h + call nec_output + mov ah,dl + call nec_output + call chk_stat_2 + jc j32 + +;----- drive is in synch with controller, seek to track + +j28: + mov ah,0fh + call nec_output + mov ah,dl + call nec_output + mov ah,ch + call nec_output + call chk_stat_2 + +;----- wait for head settle + + pushf + mov bx,18 + call get_parm + push cx +j29: + mov cx,550 + or ah,ah + jz j31 +j30: + loop j30 + dec ah + jmp j29 +j31: + pop cx + popf +j32: + ret +seek endp + +;----------------------------------------------------------------------- +; dma_setup +; this routine sets up the dma for read/write/verify operations +; input: +; (al) = mode byte for the dma +; (es:bx) - address to read/write the data +; output: +; (ax) destroyed +;----------------------------------------------------------------------- + +dma_setup proc near + push cx + cli + out dma+12,al + push ax + pop ax + out dma+11,al + mov ax,es + mov cl,4 + rol ax,cl + mov ch,al + and al,0f0h + add ax,bx + jnc jj33 + inc ch +jj33: + push ax + out dma+4,al + mov al,ah + out dma+4,al + mov al,ch + and al,0fh + out 081h,al + +;----- determine count + + mov ah,dh + sub al,al + shr ax,1 + push ax + mov bx,6 + call get_parm + mov cl,ah + pop ax + shl ax,cl + dec ax + push ax + out dma+5,al + mov al,ah + out dma+5,al + sti + pop cx + pop ax + add ax,cx + pop cx + mov al,2 + out dma+10,al + ret +dma_setup endp + +;----------------------------------------------------------------------- +; chk_stat_2 +; This routine handles the interrupt received after a +; recalibrate, seek, or reset to the adapter. +; The interrupt is waited for, the interrupt sensed, +; and the result returned to the caller. +; input: +; none +; output: +; cy = 0 success +; cy = 1 failure -- error is in diskette_status +; (ax) destroyed +;----------------------------------------------------------------------- + +chk_stat_2 proc near + call wait_int + jc j34 + mov ah,08h + call nec_output + call results + jc j34 + mov al,nec_status + and al,060h + cmp al,060h + jz j35 + clc +j34: + ret +j35: + or diskette_status,bad_seek + stc + ret +chk_stat_2 endp + +;----------------------------------------------------------------------- +; wait_int +; This routine waits for an interrupt to occur. A time out +; routine takes place during the wait, so that an error may be +; returned if the drive is not ready. +; input: +; none +; output: +; cy = 0 success +; cy = 1 failure -- diskette_status is set accordingly +; (ax) destroyed +;----------------------------------------------------------------------- + +wait_int proc near + sti + push ax + push bx + push cx + clc + mov ax,09001h + int 15h + sti + jc j36a +; + mov bl,2 + xor cx,cx +j36: + test seek_status,int_flag + jnz j37 +; push cx +; push bx +; push ds +; push es +; push ax +; push dx +; push si +; push di +; push bp +; call cs:warte +; pop bp +; pop di +; pop si +; pop dx +; pop ax +; pop es +; pop ds +; pop bx +; pop cx + loop j36 + dec bl + jnz j36 + +j36a: or diskette_status, time_out + stc +j37: + pushf + and seek_status, not int_flag + popf + pop cx + pop bx + pop ax + ret +wait_int endp + +;----------------------------------------------------------------------- +; disk_int +; This routine handles the diskette interrupt +; Input +; none +; output: +; The interrupt flag is set is seek_status +;----------------------------------------------------------------------- + +;************** +;org 0ef57h +;************** +disk_int proc far + sti + push ds + push ax + push si + mov si,data + mov ds,si + or seek_status, int_flag + mov al,20h + out 20h,al + mov ax,09101h + int 15h + pop si + pop ax + pop ds + iret +disk_int endp + +;----------------------------------------------------------------------- +; results +; This routine will read anything that the nec controller has +; to say following an interrupt. +; input: +; none +; output: +; cy = 0 successful transfer +; cy = 1 failure -- time out in waiting for status +; nec_status area has status byte loaded into it +; (ah) destroyed +;----------------------------------------------------------------------- + +results proc near + cld + mov di,offset nec_status + push cx + push dx + push bx + mov bl,7 + +;-----wait for request for master + +j38: + xor cx,cx + mov dx,03f4h +j39: + in al,dx + test al,80h + jnz j40a + loop j39 + or diskette_status, time_out +j40: + stc + pop bx + pop dx + pop cx + ret + +;----- test the direction bit + +j40a: + in al,dx + test al,40h + jnz j42 +j41: + or diskette_status,bad_cntlr + jmp j40 + +;-----read in the status + +j42: + inc dx + in al,dx + mov [di],al + inc di + mov cx,10 +j43: loop j43 + dec dx + in al,dx + test al,10h + jz j44 + dec bl + jnz j38 + jmp j41 + +;----- result operation is done + +j44: + pop bx + pop dx + pop cx + ret + +;----------------------------------------------------------------------- +; num_trans +; This routine calculates the number of sectors that were +; actually transferred to/from the diskette +; input +; (ch) = cylinder of operation +; (cl) = start sector of operation +; output +; (al) = number actually transferred +; no other registers modified +;----------------------------------------------------------------------- + +num_trans proc near + mov al,nec_status+3 + cmp al,ch + mov al,nec_status+5 + jz j45 + mov bx,8 + call get_parm + mov al,ah + inc al +j45: + sub al,cl + ret +num_trans endp +results endp + + assume ds:shard + + \ No newline at end of file -- cgit v1.2.3