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
|
;************************************************************************
;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge ==============*
;* *
;* Harddisk routinen *
;* *
;************************************************************************
device fixdisk
dtcbroutines iocontrol
routine 5,fixed_size
routine -10,fixed_tracks
routine -11,fixed_sects
routine -12,fixed_heads
routine 1,devicetype
routine -1,unknowncontrol
dtcbroutines control32
routine -2,fixed_init
routine -100,fixed_size_set
routine -101,fixed_start_set
routine -102,fixed_landing_zone
routine -1,no_channel_setup
dtcbroutines blockin
routine -1,fixed_read
dtcbroutines blockout
routine -1,fixed_write
dtcbparams nil_output,0ch ;kein output, blockio device
heads equ 4
sects equ 17
if pcxt
if at
bitte nicht at und pcxt gleichzeitig
endif
endif
if pcd
romhd equ 1
else
if at
romhd equ 1
else
romhd equ romharddisk
endif
endif
fix_ccb macro kanal
startccb hgccb&kanal,kanal
ccbentry fix_size
dw 0
db 0
ccbentry fix_firstblock
dw 0
db 0
ccbentry fix_sects
db 0
ccbentry fix_cylsize
dw 0
endm
fixed_size_set:
mov [di+fix_size],dx
mov [di+fix_size+2],bl
ret
fixed_start_set:
mov [di+fix_firstblock],dx
mov [di+fix_firstblock+2],bl
ret
fixed_init:
mov ax,0801h ;return drive type
mov dl,80h ;drive 0
int 13h
mov al,cl ;anzahl sects holen
and al,3fh ;nur sector anzahl
mov [di+fix_sects],al ;eintragen
inc dh ;anzahl koepfe (statt hoechste nummer)
mul dh ;sects pro cylinder
mov [di+fix_cylsize],ax ;eintragen
mov dl,cl ;cylinder anzahl nach dx packen
shl dx,1
shl dx,1
and dh,3 ;nur unterste zwei bits behalten
mov dl,ch ;rest cylindernummer holen
inc dx ;anzahl draus machen
mul dx ;anzahl bloecke ausrechnen
mov [di+fix_size],ax
mov [di+fix_size+2],dl
ret
fixed_tracks:
call fix_drive
rol cl,1 ;trackzahl in cx melden
rol cl,1
and cl,3 ;nur zwei bits sind noch track
xchg cl,ch
inc cx ;meldet hoechste nummer, anzahl draus
ret
fixed_sects:
call fix_drive
and cl,03fh ;nur sectorenzahl behalten
mov ch,0 ;high byte 0
ret
fixed_heads:
call fix_drive
mov cl,dh
mov ch,0
inc cx ;hoechsten head -> anzahl umrechnen
ret
fix_drive:
mov ax,0801h ;return drive type
mov dl,80h ;drive 0
int 13h
ret
fixed_landing_zone:
mov bx,0
call device_free ;auf freigabe warten
call hardware ;pruefen, ob at
cmp al,IBMat
jz fixed_at_landing
call fix_drive
mov ax,0c01h ;seek
mov dl,80h ;immer auf erstem drive
inc ch ;auf naechste spur
ifz <add cl,40h> ;hoeherwertigen bits auch zaehlen
int 13h
ret
fixed_at_landing:
sub ax,ax
mov ds,ax
les bx,dword ptr ds:[(41h*4)]
mov ax,es:[bx+12] ;landing zone
mov ch,al ;unterste byte der cylinder number
and ax,0300h ;obersten zwei bits
shr ax,1
shr ax,1
or al,1 ;immer sector 1
mov cl,al
mov dx,80h ;drive und head 0
mov ax,0c01h ;seek
int 13h
ret ;device nicht wieder freigeben
;aendern, wenn zwei laufwerke
fix_highblock:
pop bx
jmp highblock
fixed_write:
push bx
if romhd
mov bl,3
else
mov bl,0 ;auftrag schreiben nach bl
endif
jmp short fixed_rw
fixed_read:
push bx
if romhd
mov bl,2 ;lesen nach bl
else
mov bl,1
endif
fixed_rw:
cmp ch,0 ;wirklich read oder write
ifnz <jmp unknowncontrol>
cmp cl,[di+fix_size+2]
ifz <cmp dx,[di+fix_size]> ;blocknummer zu hoch?
jnc fix_highblock
push bx
mov bx,0
call device_free
pop bx
mov ax,dx ;blocknummer nach ax
add ax,[di+fix_firstblock] ;offset fuer ersten block dazu
adc cl,[di+fix_firstblock+2]
mov dx,cx ;high byte muss nach dx
if at ;translate bad blocks if at
; jetzt erstmal schlechte sectoren suchen
push es
push ds
pop es
push di
mov di,offset bb_table
cld
mov cx,[bb_anz] ;anzahl schlechte sectoren
fix_search_bb:
jcxz fix_no_translate
repnz scasw ;sieh mal nach
jnz fix_no_translate
cmp dl,byte ptr [di+max_bb*2-2] ;obere byte ebenfalls pruefen
jnz fix_search_bb
; schlechten sector gefunden
pop di
mov ax,[di+fix_firstblock] ;direkt hinter letzten block
mov dl,[di+fix_firstblock+2]
add ax,[di+fix_size]
adc dl,[di+fix_size+2]
add ax,cx
adc dl,0
push di
fix_no_translate:
pop di
pop es
endif
div word ptr (di+fix_cylsize) ;dxax / sectoren pro zylinder
;der rest passt immer in 32 bit
mov ch,al ;low byte tracknummer nach ch
ror ah,1
ror ah,1
mov cl,ah ;high bits der cylindernummer nach cl
mov ax,dx ;rest nach ax
div byte ptr (di+fix_sects)
if at
mov dh,al ;kopf nach dh
else
; jetzt erstmal schlechte spuren suchen
or cl,al ;kopf zur spur dazu
push ax ;retten
mov ax,cx ;zum suchen da rueber
push di
push es
push ds
pop es
mov di,offset bt_table
mov cx,8 ;8 moegliche schlechte spuren
cld
repnz scasw ;sieh mal nach
ifz <mov ax,word ptr [di+14]> ersatzwert holen
pop es
pop di
mov cx,ax ;zurueckgeben
and cl,0c0h ;nur cylinderbits behalten
and al,03fh ;nur kopf bits
mov dh,al ;head nach dh
pop ax
endif
mov dl,080h ;drive nach dl
or cl,ah ;sector nach cl reinbasteln
mov al,1 ;einen sector
mov ah,bl ;auftrag nach ah
pop bx
if romhd
inc cl
push es
int 13h
pop es
jc diskerr
else
push bx
mov bx,0
call device_lock
pop bx
mov byte ptr [cmd_block+1],dh ;kopfnummer
mov byte ptr [cmd_block+2],cl ;cylinder + sect
mov byte ptr [cmd_block+3],ch ;cylinder
push es
call hard_dsk
pop es
xor bx,bx ;device 0 freigeben
call device_unlock
mov ah,byte ptr [disk_status] ;haben wir fehler
or ah,ah
jnz diskerr
endif
mov byte ptr fix_err,0 ;ein aufruf war ohne fehler
mov cx,0
ret
diskerr:
inc byte ptr fix_err
cmp byte ptr fix_err,4 ;schon viermal hintereinander fehler
jnz fix_blockerr
mov byte ptr fix_err,0
push ax
mov ah,13 ;nur harddisk zuruecksetzen
mov dl,80h ;disk reset
int 13h
pop ax
fix_blockerr:
jmp blockerr
fixed_size:
mov al,[di+fix_size+2]
mov cx,[di+fix_size]
ret
fix_err db 0
ife romhd
include HDISK.ASM
endif
|