1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
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
|