summaryrefslogtreecommitdiff
path: root/system/shard-x86-at/7/src/HDISK.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'system/shard-x86-at/7/src/HDISK.ASM')
-rw-r--r--system/shard-x86-at/7/src/HDISK.ASM482
1 files changed, 482 insertions, 0 deletions
diff --git a/system/shard-x86-at/7/src/HDISK.ASM b/system/shard-x86-at/7/src/HDISK.ASM
new file mode 100644
index 0000000..67044d4
--- /dev/null
+++ b/system/shard-x86-at/7/src/HDISK.ASM
@@ -0,0 +1,482 @@
+;shard segment
+; assume cs: shard
+; assume ds: shard, es:nothing, ss:nothing
+
+;================================================================
+; modul hdisk.asm
+; hard - disk - treiber
+;
+; Status:
+; 0.0 13.11.84 erste Testversion
+;================================================================
+
+TIMEOUT1 equ 20h ; warten auf Disk-Interrupt
+ ; (20.0000h Tests)
+
+;-------------------------------------------------------;
+; Fehlercodes
+; Bem: 11h ist eigentlich k e i n Fehler !
+;-------------------------------------------------------;
+
+;sense_fail equ 0ffh ; sense operation
+;undef_err equ 0bbf ; undefined error occurred
+;time_out equ 80h ; attachment failed to respond
+;bad_seek equ 40h ; seek operation failed
+;bad_cntlr equ 20h ; controller has failed
+;data_corrected equ 11h ; ecc corrected data error
+;bad_ecc equ 10h ; bad ecc on disk read
+;bad_track equ 0bh ; bad track flag detected
+;dma_boundary equ 9 ; attempt to dma across 64k
+;init_fail equ 7 ; drive parameter activity failed
+;bad_reset equ 5 ; reset failed
+;record_not_fnd equ 4 ; requested sector not found
+;bad_addr_mark equ 2 ; address mark not found
+;bad_cmd equ 1 ; bad command passed to disk i/o
+
+;-------------------------------------------------------;
+; interrrupt and status area ;
+;-------------------------------------------------------;
+
+dummy segment at 0
+
+ org 0dh *4
+hdisk_int label dword
+
+ org 13h * 4
+org_vector label dword
+ org 19h *4
+hf_tbl_vec label dword
+dummy ends
+
+;-----------------------------------------------------------------------;
+; cmd_block
+;
+; +0 Kommando
+; +1 Kopfnummer Aufrufparameter 1
+; +2 2-Bit Zylinder & Rest Sektor Aufrufparameter 2
+; +3 Zylinder Aufrufparameter 3
+; +4 Block - Count (ist immer 1 )
+; +5 Control-Byte (Step - Option)
+;-----------------------------------------------------------------------;
+
+cmd_block label byte
+hd_error db 7 dup(?)
+disk_status db ?
+
+;-------------------------------------------------------;
+; hardware specific values ;
+; ;
+; - Controller i/o port ;
+; > when ready from: ;
+; hf_port+0 - read data (from controller to cpu ;
+; hf_port+1 - read controller hardware status ;
+; (controller to cpu) ;
+; hf_port+2 - read configuration switches ;
+; hf_port+3 - not used ;
+; < when written to: ;
+; hf_port+0 - write data (from cpu to controller) ;
+; hf_port+1 - controller reset ;
+; hf_port+2 - generate controller select pulse ;
+; hf_port+3 - write pattern to dma and interrupt ;
+; mask register ;
+;-------------------------------------------------------;
+
+hf_port equ 320h ; disk port
+r1_busy equ 00001000b ; disk port 1 busy bit
+r1_bus equ 00000100b ; command/data bit
+r1_iomode equ 00000010b ; mode bit
+r1_req equ 00000001b ; request bit
+
+dma_read equ 01000111b ; channel 3 (47h)
+dma_write equ 01001011b ; channel 3 (4bh)
+dma equ 0 ; dma address
+dma_high equ 82h ; port for high 4 bits of dma
+
+tst_rdy_cmd equ 0 ; cntrl ready (00h)
+recal_cmd equ 00000001b ; recal (01h)
+sense_cmd equ 00000011b ; sense (03h)
+fmtdrv_cmd equ 00000100b ; drive (04h)
+chk_trk_cmd equ 00000101b ; t chk (05h)
+fmttrk_cmd equ 00000110b ; track (06h)
+fmtbad_cmd equ 00000111b ; bad (07h)
+read_cmd equ 00001000b ; read (08h)
+write_cmd equ 00001010b ; write (0ah)
+seek_cmd equ 00001011b ; seek (0bh)
+init_drv_cmd equ 00001100b ; init (0ch)
+rd_ecc_cmd equ 00001101b ; burst (00h)
+rd_buff_cmd equ 00001110b ; buffr (0eh)
+wr_buff_cmd equ 00001111b ; buffr (0fh)
+ram_diag_cmd equ 11100000b ; ram (e0h)
+chk_drv_cmd equ 11100011b ; drv (e3h)
+cntrl_diag_cmd equ 11100100b ; cntlr (e4h)
+rd_long_cmd equ 11100101b ; rlong (e5h)
+wr_long_cmd equ 11100110b ; wlong (e6h)
+
+int_ctl_port equ 20h ; 8259 control port
+eoi equ 20h ; end of interrupt command
+
+ page
+
+;===============================================================;
+; MAIN - Routine
+; Input:
+; ah - 0 write disk
+; - 1 read disk
+; (es:bx) - Datenadresse
+; cmd_block
+; Output:
+; disk_status 0 - alles OK
+;===============================================================;
+
+hard_dsk proc
+; mov ax,0 ; interrupt initiieren
+; mov es,ax
+; mov word ptr es:[hdisk_int+2],cs
+; mov word ptr es:[hdisk_int],offset hd_int
+
+ sti ; enable interrupts
+ mov disk_status,0 ; noch alles ok !
+ mov cmd_block+5,5 ; 70 ysec steprate
+ cmp ah,0 ; ah = 0 --> write disk
+ jz a4 ; ah <> 0 --> read disk
+ call disk_read
+ jmp short dsbl
+a4: call disk_write
+
+;-------------------------------------------------------;
+; dsbl
+; make shure that all housekeeping is done
+; before exit
+;-------------------------------------------------------;
+
+dsbl:
+ mov dx,hf_port+3
+ sub al,al
+ out dx,al ; reset int/dma mask
+ mov al,7
+ out dma+10,al ; set dma - mode to disable
+ cli ; disable interrupts
+ in al,21h
+ or al,20h
+ out 21h,al ; disable interrupt 5
+ sti ; enable interrupts
+ ret
+
+hard_dsk endp
+
+;========================================================
+; disk read routine
+; Input:
+; (es:bx) - Datenadresse
+; cmd_block
+;========================================================
+
+disk_read proc near
+ mov al,dma_read ; mode byte for dma read
+ mov cmd_block+0,read_cmd
+ jmp do_io
+disk_read endp
+
+;========================================================
+; disk write routine
+; Input:
+; (es:bx) - Datenadresse
+; cmd_block
+;========================================================
+
+disk_write proc near
+ mov al,dma_write ; mode byte for dma write
+ mov cmd_block+0, write_cmd
+ jmp do_io
+disk_write endp
+ page
+;========================================================
+; do_io
+; gemeinsame Routine fuer alle Kommandos
+; Input:
+; (es:bx) - Datenadresse
+; al - mode (dma_read/dma_write)
+; cmd_block
+;========================================================
+
+do_io proc near
+
+ mov cmd_block+4,1 ; Blockzahl immer 1
+
+;-------------------------------------------------------;
+; DMA_SETUP
+; diese Routine dressiert den DMA
+;-------------------------------------------------------;
+
+ cli ; keine Interrupts mehr
+ out dma+12,al ; first/last ff setzen
+ push ax ; warten ?
+ pop ax
+ out dma+11,al ; mode setzen
+
+;-----phys. Adresse zum DMA ausgeben:
+
+ mov ax,es
+ mov cl,4
+ rol ax,cl ; h - nibble von es nach al
+ mov ch,al
+ and al,0f0h
+ add ax,bx
+ jnc j33
+ inc ch ; Uebertrag notieren
+j33: out dma+6,al ; a0 - a7 ausgeben
+ push ax ; fuer Ueberlauftest merken
+ mov al,ah
+ out dma+6,al ; a8 - a15 ausgeben
+ mov al,ch
+ and al,0fh
+ out dma_high,al ; a16 - a19 ausgeben
+
+;-----Blocklaenge zum DMA ausgeben:
+
+ mov ax,511 ; Blocklaenge
+ out dma+7,al ; Blocklaenge ausgeben
+ mov al,ah
+ out dma+7,al
+ sti ; Interrupts scharfmachen
+ pop ax
+ add ax,511 ; 64k Overflow testen
+ jnc gx ; wenn kein Overflow
+ mov disk_status, dma_boundary
+ ret
+
+gx: call command
+ jc error_chk ; wenn was schiefgelaufen ist
+
+ mov al,3 ; controller dma/interrupt register mask
+ out dma+10,al ; initialize the disk channel
+g3:
+ in al,21h
+ and al,0dfh
+ out 21h,al
+
+;-------------------------------------------------------;
+; wait_int
+; this routine waits for the fixed disk
+; controller to signal, that an interrupt
+; has occured
+;-------------------------------------------------------;
+
+ sti ; muss das nochmal sein ???
+ push es
+ push si
+
+;----- set timeout values
+ sub bh,bh
+ mov bl,TIMEOUT1 ; timout Zaehler setzen (high word)
+ sub cx,cx
+
+;----- wait for interrupt
+w1:
+ push ds
+ push bx
+ push cx
+ call cs:warte ; nicht dumm rumloopen, sondern
+ pop cx ; arbeiten !!
+ pop bx
+ pop ds
+
+ mov dx,hf_port+1
+ in al,dx
+ and al,20h
+ cmp al,20h
+ jz w2
+ loop w1
+ dec bx
+ jnz w1
+ mov disk_status,time_out
+
+w2: mov dx, hf_port
+ in al,dx
+ and al,2
+ or disk_status,al ; Fehler merken
+ mov dx,hf_port+3
+ xor al,al
+ out dx,al
+ pop si
+ pop es
+
+;-----------------------------------------------;
+; error_chk ;
+;-----------------------------------------------;
+
+error_chk:
+ ret ; zunaechst keine Fehler- Auswertung
+ mov al,disk_status
+ or al,al
+ jnz g21
+ ret
+
+;-----perform sense status
+
+g21: mov ax, shard
+ mov es,ax
+ sub ax,ax
+ mov di,ax
+ mov cmd_block+0, sense_cmd
+ sub al,al
+ call command
+ jc sense_abort
+ mov cx,4
+g22:
+ call hd_wait_req
+ jc g24
+ mov dx,hf_port
+ in al,dx
+ mov hd_error[di],al
+ inc di
+ mov dx,hf_port+1
+ loop g22
+ call hd_wait_req
+ jc g24
+ mov dx,hf_port
+ in al,dx
+ test al,2
+ jz stat_err
+sense_abort:
+ mov disk_status, sense_fail
+g24:
+ stc
+ ret
+do_io endp
+
+;========================================================
+; command
+; erklaert dem controller, was zu tun ist
+; input
+; cmd_block
+;========================================================
+
+command proc near
+
+ mov dx,hf_port+2
+ out dx,al ; controller select pulse ausgeben
+ mov dx,hf_port+3
+ mov al,3 ; controller dma/interrupt register mask
+ out dx,al ; DMA und Interrupt-Maske setzen
+
+; eigentlich ist es nicht normal, wenn der Controller an dieser
+; Stelle beschaeftigt ist, aber wer weiss ...
+
+ sub cx,cx ; timeout - Zaehler setzen
+ mov dx,hf_port+1
+wait_busy:
+ in al,dx ; status lesen
+ and al,0fh
+ cmp al,r1_busy or r1_bus or r1_req
+ je weiter_gehts ; weiter, wenn controller frei
+ loop wait_busy ; warten...
+ mov disk_status, time_out ; is nix
+ stc
+ ret
+
+weiter_gehts:
+ cld ; clear direction flag
+ mov cx,6 ; Blocklaenge fuer move
+ mov si, offset cmd_block
+
+cm3: mov dx,hf_port ; Command-Block ausgeben
+ lodsb ;
+ out dx,al
+ loop cm3
+
+ inc dx ; weiter nach hf_port+1
+ in al,dx ; status lesen
+ test al,r1_req
+ jz cm7 ; wenn alles ok
+ mov disk_status, bad_cntlr ; war nix
+ stc
+cm7:
+ ret
+command endp
+
+
+;================================================================
+; hd_int
+;================================================================
+
+hd_int proc near
+ push ax
+ mov al,eoi ; end of interrupt
+ out int_ctl_port,al
+ mov al,7 ; set dma mode to disable
+ out dma+10,al
+ in al,21h
+ or al,20h
+ out 21h,al
+ pop ax
+ iret
+hd_int endp
+
+
+t_0 dw type_0
+t_1 dw type_1
+t_2 dw type_2
+t_3 dw type_3
+
+
+stat_err:
+ mov bl,es:hd_error ; get error byte
+ mov al,bl
+ and al,0fh
+ and bl,00110000b
+ sub bh,bh
+ mov cl,3
+ shr bx,cl
+ jmp word ptr cs:[bx + offset t_0]
+
+type0_table label byte
+ db 0, bad_cntlr, bad_seek, bad_cntlr, time_out, 0, bad_cntlr
+ db 0, bad_seek
+type0_len equ $-type0_table
+
+type1_table label byte
+ db bad_ecc, bad_ecc, bad_addr_mark, 0, record_not_fnd
+ db bad_seek, 0, 0, data_corrected, bad_track
+type1_len equ $-type1_table
+
+type2_table label byte
+ db bad_cmd, bad_addr_mark
+type2_len equ $-type2_table
+
+type3_table label byte
+ db bad_cntlr, bad_cntlr, bad_ecc
+type3_len equ $-type3_table
+
+type_0:
+ ret
+type_1:
+ ret
+type_2:
+ ret
+type_3:
+ ret
+
+;================================================================
+; hd_wait_req
+;================================================================
+
+hd_wait_req proc near
+ push cx
+ sub cx,cx ; timeout - Zaehler setzen
+ mov dx,hf_port + 1
+l1:
+ in al,dx
+ test al,r1_req
+ jnz l2 ; wenn ok
+ loop l1
+ mov disk_status, time_out
+ stc
+l2:
+ pop cx
+ ret
+hd_wait_req endp
+
+
+; end
+ \ No newline at end of file