Subversion Repositories Kolibri OS

Rev

Rev 3908 | Rev 4423 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3908 Rev 4287
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
7
 
8
$Revision: 3908 $
8
$Revision: 4287 $
9
 
9
 
10
 
10
 
11
; Low-level driver for HDD access
11
; Low-level driver for HDD access
12
; DMA support by Mario79
12
; DMA support by Mario79
13
; Access through BIOS by diamond
13
; Access through BIOS by diamond
14
; LBA48 support by Mario79
14
; LBA48 support by Mario79
15
;-----------------------------------------------------------------------------
15
;-----------------------------------------------------------------------------
16
struct HD_DATA
16
struct HD_DATA
17
hdbase  dd      ?
17
hdbase  dd      ?
18
hdid    dd      ?
18
hdid    dd      ?
19
hdpos   dd      ?
19
hdpos   dd      ?
20
ends
20
ends
21
 
21
 
22
iglobal
22
iglobal
23
align 4
23
align 4
24
ide_callbacks:
24
ide_callbacks:
25
        dd      ide_callbacks.end - ide_callbacks       ; strucsize
25
        dd      ide_callbacks.end - ide_callbacks       ; strucsize
26
        dd      0       ; no close function
26
        dd      0       ; no close function
27
        dd      0       ; no closemedia function
27
        dd      0       ; no closemedia function
28
        dd      ide_querymedia
28
        dd      ide_querymedia
29
        dd      ide_read
29
        dd      ide_read
30
        dd      ide_write
30
        dd      ide_write
31
        dd      0       ; no flush function
31
        dd      0       ; no flush function
32
        dd      0       ; use default cache size
32
        dd      0       ; use default cache size
33
.end:
33
.end:
34
 
34
 
35
bd_callbacks:
35
bd_callbacks:
36
        dd      bd_callbacks.end - bd_callbacks         ; strucsize
36
        dd      bd_callbacks.end - bd_callbacks         ; strucsize
37
        dd      0       ; no close function
37
        dd      0       ; no close function
38
        dd      0       ; no closemedia function
38
        dd      0       ; no closemedia function
39
        dd      bd_querymedia
39
        dd      bd_querymedia
40
        dd      bd_read_interface
40
        dd      bd_read_interface
41
        dd      bd_write_interface
41
        dd      bd_write_interface
42
        dd      0       ; no flush function
42
        dd      0       ; no flush function
43
        dd      0       ; use default cache size
43
        dd      0       ; use default cache size
44
.end:
44
.end:
45
 
45
 
46
hd0_data        HD_DATA         ?,    0, 1
46
hd0_data        HD_DATA         ?,    0, 1
47
hd1_data        HD_DATA         ?, 0x10, 2
47
hd1_data        HD_DATA         ?, 0x10, 2
48
hd2_data        HD_DATA         ?,    0, 3
48
hd2_data        HD_DATA         ?,    0, 3
49
hd3_data        HD_DATA         ?, 0x10, 4
49
hd3_data        HD_DATA         ?, 0x10, 4
-
 
50
 
-
 
51
hd_address_table:
-
 
52
        dd      0x1f0, 0x00, 0x1f0, 0x10
-
 
53
        dd      0x170, 0x00, 0x170, 0x10
50
endg
54
endg
51
 
55
 
52
uglobal
56
uglobal
53
ide_mutex               MUTEX
57
ide_mutex               MUTEX
54
ide_channel1_mutex      MUTEX
58
ide_channel1_mutex      MUTEX
55
ide_channel2_mutex      MUTEX
59
ide_channel2_mutex      MUTEX
56
endg
60
endg
57
 
61
 
58
proc ide_read stdcall uses edi, \
62
proc ide_read stdcall uses edi, \
59
        hd_data, buffer, startsector:qword, numsectors
63
        hd_data, buffer, startsector:qword, numsectors
60
        ; hd_data = pointer to hd*_data
64
        ; hd_data = pointer to hd*_data
61
        ; buffer = pointer to buffer for data
65
        ; buffer = pointer to buffer for data
62
        ; startsector = 64-bit start sector
66
        ; startsector = 64-bit start sector
63
        ; numsectors = pointer to number of sectors on input,
67
        ; numsectors = pointer to number of sectors on input,
64
        ;  must be filled with number of sectors really read
68
        ;  must be filled with number of sectors really read
65
locals
69
locals
66
sectors_todo    dd      ?
70
sectors_todo    dd      ?
67
channel_lock    dd      ?
71
channel_lock    dd      ?
68
endl
72
endl
69
; 1. Initialize number of sectors: get number of requested sectors
73
; 1. Initialize number of sectors: get number of requested sectors
70
; and say that no sectors were read yet.
74
; and say that no sectors were read yet.
71
        mov     ecx, [numsectors]
75
        mov     ecx, [numsectors]
72
        mov     eax, [ecx]
76
        mov     eax, [ecx]
73
        mov     dword [ecx], 0
77
        mov     dword [ecx], 0
74
        mov     [sectors_todo], eax
78
        mov     [sectors_todo], eax
75
; 2. Acquire the global lock.
79
; 2. Acquire the global lock.
76
        mov     ecx, ide_mutex
80
        mov     ecx, ide_mutex
77
        call    mutex_lock
81
        call    mutex_lock
78
        mov     ecx, ide_channel2_mutex
82
        mov     ecx, ide_channel2_mutex
79
        mov     eax, [hd_data]
83
        mov     eax, [hd_data]
80
        push    ecx
84
        push    ecx
81
        mov     ecx, [hd_address_table]
85
        mov     ecx, [hd_address_table]
82
        cmp     [eax+HD_DATA.hdbase], ecx ; 0x1F0
86
        cmp     [eax+HD_DATA.hdbase], ecx ; 0x1F0
83
        pop     ecx
87
        pop     ecx
84
        jne     .IDE_Channel_2
88
        jne     .IDE_Channel_2
85
        mov     ecx, ide_channel1_mutex
89
        mov     ecx, ide_channel1_mutex
86
.IDE_Channel_2:
90
.IDE_Channel_2:
87
        mov     [channel_lock], ecx
91
        mov     [channel_lock], ecx
88
        call    mutex_lock
92
        call    mutex_lock
89
; 3. Convert parameters to the form suitable for worker procedures.
93
; 3. Convert parameters to the form suitable for worker procedures.
90
; Underlying procedures do not know about 64-bit sectors.
94
; Underlying procedures do not know about 64-bit sectors.
91
; Worker procedures use global variables and edi for [buffer].
95
; Worker procedures use global variables and edi for [buffer].
92
        cmp     dword [startsector+4], 0
96
        cmp     dword [startsector+4], 0
93
        jnz     .fail
97
        jnz     .fail
94
        and     [hd_error], 0
98
        and     [hd_error], 0
95
        mov     ecx, [hd_data]
99
        mov     ecx, [hd_data]
96
        mov     eax, [ecx+HD_DATA.hdbase]
100
        mov     eax, [ecx+HD_DATA.hdbase]
97
        mov     [hdbase], eax
101
        mov     [hdbase], eax
98
        mov     eax, [ecx+HD_DATA.hdid]
102
        mov     eax, [ecx+HD_DATA.hdid]
99
        mov     [hdid], eax
103
        mov     [hdid], eax
100
        mov     eax, [ecx+HD_DATA.hdpos]
104
        mov     eax, [ecx+HD_DATA.hdpos]
101
        mov     [hdpos], eax
105
        mov     [hdpos], eax
102
        mov     eax, dword [startsector]
106
        mov     eax, dword [startsector]
103
        mov     edi, [buffer]
107
        mov     edi, [buffer]
104
; 4. Worker procedures take one sectors per time, so loop over all sectors to read.
108
; 4. Worker procedures take one sectors per time, so loop over all sectors to read.
105
.sectors_loop:
109
.sectors_loop:
106
; DMA read is permitted if [allow_dma_access]=1 or 2
110
; DMA read is permitted if [allow_dma_access]=1 or 2
107
        cmp     [allow_dma_access], 2
111
        cmp     [allow_dma_access], 2
108
        ja      .nodma
112
        ja      .nodma
109
        cmp     [dma_hdd], 1
113
        cmp     [dma_hdd], 1
110
        jnz     .nodma
114
        jnz     .nodma
111
        call    hd_read_dma
115
        call    hd_read_dma
112
        jmp     @f
116
        jmp     @f
113
.nodma:
117
.nodma:
114
        call    hd_read_pio
118
        call    hd_read_pio
115
@@:
119
@@:
116
        cmp     [hd_error], 0
120
        cmp     [hd_error], 0
117
        jnz     .fail
121
        jnz     .fail
118
        mov     ecx, [numsectors]
122
        mov     ecx, [numsectors]
119
        inc     dword [ecx]     ; one more sector is read
123
        inc     dword [ecx]     ; one more sector is read
120
        dec     [sectors_todo]
124
        dec     [sectors_todo]
121
        jz      .done
125
        jz      .done
122
        inc     eax
126
        inc     eax
123
        jnz     .sectors_loop
127
        jnz     .sectors_loop
124
; 5. Loop is done, either due to error or because everything is done.
128
; 5. Loop is done, either due to error or because everything is done.
125
; Release the global lock and return the corresponding status.
129
; Release the global lock and return the corresponding status.
126
.fail:
130
.fail:
127
        mov     ecx, [channel_lock]
131
        mov     ecx, [channel_lock]
128
        call    mutex_unlock
132
        call    mutex_unlock
129
        mov     ecx, ide_mutex
133
        mov     ecx, ide_mutex
130
        call    mutex_unlock
134
        call    mutex_unlock
131
        or      eax, -1
135
        or      eax, -1
132
        ret
136
        ret
133
.done:
137
.done:
134
        mov     ecx, [channel_lock]
138
        mov     ecx, [channel_lock]
135
        call    mutex_unlock
139
        call    mutex_unlock
136
        mov     ecx, ide_mutex
140
        mov     ecx, ide_mutex
137
        call    mutex_unlock
141
        call    mutex_unlock
138
        xor     eax, eax
142
        xor     eax, eax
139
        ret
143
        ret
140
endp
144
endp
141
 
145
 
142
proc ide_write stdcall uses esi edi, \
146
proc ide_write stdcall uses esi edi, \
143
        hd_data, buffer, startsector:qword, numsectors
147
        hd_data, buffer, startsector:qword, numsectors
144
        ; hd_data = pointer to hd*_data
148
        ; hd_data = pointer to hd*_data
145
        ; buffer = pointer to buffer with data
149
        ; buffer = pointer to buffer with data
146
        ; startsector = 64-bit start sector
150
        ; startsector = 64-bit start sector
147
        ; numsectors = pointer to number of sectors on input,
151
        ; numsectors = pointer to number of sectors on input,
148
        ;  must be filled with number of sectors really written
152
        ;  must be filled with number of sectors really written
149
locals
153
locals
150
sectors_todo    dd      ?
154
sectors_todo    dd      ?
151
channel_lock    dd      ?
155
channel_lock    dd      ?
152
endl
156
endl
153
; 1. Initialize number of sectors: get number of requested sectors
157
; 1. Initialize number of sectors: get number of requested sectors
154
; and say that no sectors were read yet.      
158
; and say that no sectors were read yet.      
155
        mov     ecx, [numsectors]
159
        mov     ecx, [numsectors]
156
        mov     eax, [ecx]
160
        mov     eax, [ecx]
157
        mov     dword [ecx], 0
161
        mov     dword [ecx], 0
158
        mov     [sectors_todo], eax
162
        mov     [sectors_todo], eax
159
; 2. Acquire the global lock.
163
; 2. Acquire the global lock.
160
        mov     ecx, ide_mutex
164
        mov     ecx, ide_mutex
161
        call    mutex_lock
165
        call    mutex_lock
162
        mov     ecx, ide_channel2_mutex
166
        mov     ecx, ide_channel2_mutex
163
        mov     eax, [hd_data]
167
        mov     eax, [hd_data]
164
        push    ecx
168
        push    ecx
165
        mov     ecx, [hd_address_table]
169
        mov     ecx, [hd_address_table]
166
        cmp     [eax+HD_DATA.hdbase], ecx ; 0x1F0
170
        cmp     [eax+HD_DATA.hdbase], ecx ; 0x1F0
167
        pop     ecx
171
        pop     ecx
168
        jne     .IDE_Channel_2
172
        jne     .IDE_Channel_2
169
        mov     ecx, ide_channel1_mutex
173
        mov     ecx, ide_channel1_mutex
170
.IDE_Channel_2:
174
.IDE_Channel_2:
171
        mov     [channel_lock], ecx
175
        mov     [channel_lock], ecx
172
        call    mutex_lock
176
        call    mutex_lock
173
; 3. Convert parameters to the form suitable for worker procedures.
177
; 3. Convert parameters to the form suitable for worker procedures.
174
; Underlying procedures do not know about 64-bit sectors.
178
; Underlying procedures do not know about 64-bit sectors.
175
; Worker procedures use global variables and esi for [buffer].
179
; Worker procedures use global variables and esi for [buffer].
176
        cmp     dword [startsector+4], 0
180
        cmp     dword [startsector+4], 0
177
        jnz     .fail
181
        jnz     .fail
178
        and     [hd_error], 0
182
        and     [hd_error], 0
179
        mov     ecx, [hd_data]
183
        mov     ecx, [hd_data]
180
        mov     eax, [ecx+HD_DATA.hdbase]
184
        mov     eax, [ecx+HD_DATA.hdbase]
181
        mov     [hdbase], eax
185
        mov     [hdbase], eax
182
        mov     eax, [ecx+HD_DATA.hdid]
186
        mov     eax, [ecx+HD_DATA.hdid]
183
        mov     [hdid], eax
187
        mov     [hdid], eax
184
        mov     eax, [ecx+HD_DATA.hdpos]
188
        mov     eax, [ecx+HD_DATA.hdpos]
185
        mov     [hdpos], eax
189
        mov     [hdpos], eax
186
        mov     esi, [buffer]
190
        mov     esi, [buffer]
187
        lea     edi, [startsector]
191
        lea     edi, [startsector]
188
        mov     [cache_chain_ptr], edi
192
        mov     [cache_chain_ptr], edi
189
; 4. Worker procedures take max 16 sectors per time,
193
; 4. Worker procedures take max 16 sectors per time,
190
; loop until all sectors will be processed.
194
; loop until all sectors will be processed.
191
.sectors_loop:
195
.sectors_loop:
192
        mov     ecx, 16
196
        mov     ecx, 16
193
        cmp     ecx, [sectors_todo]
197
        cmp     ecx, [sectors_todo]
194
        jbe     @f
198
        jbe     @f
195
        mov     ecx, [sectors_todo]
199
        mov     ecx, [sectors_todo]
196
@@:
200
@@:
197
        mov     [cache_chain_size], cl
201
        mov     [cache_chain_size], cl
198
; DMA write is permitted only if [allow_dma_access]=1
202
; DMA write is permitted only if [allow_dma_access]=1
199
        cmp     [allow_dma_access], 2
203
        cmp     [allow_dma_access], 2
200
        jae     .nodma
204
        jae     .nodma
201
        cmp     [dma_hdd], 1
205
        cmp     [dma_hdd], 1
202
        jnz     .nodma
206
        jnz     .nodma
203
        call    cache_write_dma
207
        call    cache_write_dma
204
        jmp     .common
208
        jmp     .common
205
.nodma:
209
.nodma:
206
        mov     [cache_chain_size], 1
210
        mov     [cache_chain_size], 1
207
        call    cache_write_pio
211
        call    cache_write_pio
208
.common:
212
.common:
209
        cmp     [hd_error], 0
213
        cmp     [hd_error], 0
210
        jnz     .fail
214
        jnz     .fail
211
        movzx   ecx, [cache_chain_size]
215
        movzx   ecx, [cache_chain_size]
212
        mov     eax, [numsectors]
216
        mov     eax, [numsectors]
213
        add     [eax], ecx
217
        add     [eax], ecx
214
        sub     [sectors_todo], ecx
218
        sub     [sectors_todo], ecx
215
        jz      .done
219
        jz      .done
216
        add     [edi], ecx
220
        add     [edi], ecx
217
        jc      .fail
221
        jc      .fail
218
        shl     ecx, 9
222
        shl     ecx, 9
219
        add     esi, ecx
223
        add     esi, ecx
220
        jmp     .sectors_loop
224
        jmp     .sectors_loop
221
; 5. Loop is done, either due to error or because everything is done.
225
; 5. Loop is done, either due to error or because everything is done.
222
; Release the global lock and return the corresponding status.
226
; Release the global lock and return the corresponding status.
223
.fail:
227
.fail:
224
        mov     ecx, [channel_lock]
228
        mov     ecx, [channel_lock]
225
        call    mutex_unlock
229
        call    mutex_unlock
226
        mov     ecx, ide_mutex
230
        mov     ecx, ide_mutex
227
        call    mutex_unlock
231
        call    mutex_unlock
228
        or      eax, -1
232
        or      eax, -1
229
        ret
233
        ret
230
.done:
234
.done:
231
        mov     ecx, [channel_lock]
235
        mov     ecx, [channel_lock]
232
        call    mutex_unlock
236
        call    mutex_unlock
233
        mov     ecx, ide_mutex
237
        mov     ecx, ide_mutex
234
        call    mutex_unlock
238
        call    mutex_unlock
235
        xor     eax, eax
239
        xor     eax, eax
236
        ret
240
        ret
237
endp
241
endp
238
 
242
 
239
; This is a stub.
243
; This is a stub.
240
proc ide_querymedia stdcall, hd_data, mediainfo
244
proc ide_querymedia stdcall, hd_data, mediainfo
241
        mov     eax, [mediainfo]
245
        mov     eax, [mediainfo]
242
        mov     [eax+DISKMEDIAINFO.Flags], 0
246
        mov     [eax+DISKMEDIAINFO.Flags], 0
243
        mov     [eax+DISKMEDIAINFO.SectorSize], 512
247
        mov     [eax+DISKMEDIAINFO.SectorSize], 512
244
        or      dword [eax+DISKMEDIAINFO.Capacity], 0xFFFFFFFF
248
        or      dword [eax+DISKMEDIAINFO.Capacity], 0xFFFFFFFF
245
        or      dword [eax+DISKMEDIAINFO.Capacity+4], 0xFFFFFFFF
249
        or      dword [eax+DISKMEDIAINFO.Capacity+4], 0xFFFFFFFF
246
        xor     eax, eax
250
        xor     eax, eax
247
        ret
251
        ret
248
endp
252
endp
249
 
253
 
250
proc bd_read_interface stdcall uses edi, \
254
proc bd_read_interface stdcall uses edi, \
251
        userdata, buffer, startsector:qword, numsectors
255
        userdata, buffer, startsector:qword, numsectors
252
        ; userdata = old [hdpos] = 80h + index in NumBiosDisks
256
        ; userdata = old [hdpos] = 80h + index in NumBiosDisks
253
        ; buffer = pointer to buffer for data
257
        ; buffer = pointer to buffer for data
254
        ; startsector = 64-bit start sector
258
        ; startsector = 64-bit start sector
255
        ; numsectors = pointer to number of sectors on input,
259
        ; numsectors = pointer to number of sectors on input,
256
        ;  must be filled with number of sectors really read
260
        ;  must be filled with number of sectors really read
257
locals
261
locals
258
sectors_todo    dd      ?
262
sectors_todo    dd      ?
259
endl
263
endl
260
; 1. Initialize number of sectors: get number of requested sectors
264
; 1. Initialize number of sectors: get number of requested sectors
261
; and say that no sectors were read yet.
265
; and say that no sectors were read yet.
262
        mov     ecx, [numsectors]
266
        mov     ecx, [numsectors]
263
        mov     eax, [ecx]
267
        mov     eax, [ecx]
264
        mov     dword [ecx], 0
268
        mov     dword [ecx], 0
265
        mov     [sectors_todo], eax
269
        mov     [sectors_todo], eax
266
; 2. Acquire the global lock.
270
; 2. Acquire the global lock.
267
        mov     ecx, ide_mutex
271
        mov     ecx, ide_mutex
268
        call    mutex_lock
272
        call    mutex_lock
269
; 3. Convert parameters to the form suitable for worker procedures.
273
; 3. Convert parameters to the form suitable for worker procedures.
270
; Underlying procedures do not know about 64-bit sectors.
274
; Underlying procedures do not know about 64-bit sectors.
271
; Worker procedures use global variables and edi for [buffer].
275
; Worker procedures use global variables and edi for [buffer].
272
        cmp     dword [startsector+4], 0
276
        cmp     dword [startsector+4], 0
273
        jnz     .fail
277
        jnz     .fail
274
        and     [hd_error], 0
278
        and     [hd_error], 0
275
        mov     eax, [userdata]
279
        mov     eax, [userdata]
276
        mov     [hdpos], eax
280
        mov     [hdpos], eax
277
        mov     eax, dword [startsector]
281
        mov     eax, dword [startsector]
278
        mov     edi, [buffer]
282
        mov     edi, [buffer]
279
; 4. Worker procedures take one sectors per time, so loop over all sectors to read.
283
; 4. Worker procedures take one sectors per time, so loop over all sectors to read.
280
.sectors_loop:
284
.sectors_loop:
281
        call    bd_read
285
        call    bd_read
282
        cmp     [hd_error], 0
286
        cmp     [hd_error], 0
283
        jnz     .fail
287
        jnz     .fail
284
        mov     ecx, [numsectors]
288
        mov     ecx, [numsectors]
285
        inc     dword [ecx]     ; one more sector is read
289
        inc     dword [ecx]     ; one more sector is read
286
        dec     [sectors_todo]
290
        dec     [sectors_todo]
287
        jz      .done
291
        jz      .done
288
        inc     eax
292
        inc     eax
289
        jnz     .sectors_loop
293
        jnz     .sectors_loop
290
; 5. Loop is done, either due to error or because everything is done.
294
; 5. Loop is done, either due to error or because everything is done.
291
; Release the global lock and return the corresponding status.
295
; Release the global lock and return the corresponding status.
292
.fail:
296
.fail:
293
        mov     ecx, ide_mutex
297
        mov     ecx, ide_mutex
294
        call    mutex_unlock
298
        call    mutex_unlock
295
        or      eax, -1
299
        or      eax, -1
296
        ret
300
        ret
297
.done:
301
.done:
298
        mov     ecx, ide_mutex
302
        mov     ecx, ide_mutex
299
        call    mutex_unlock
303
        call    mutex_unlock
300
        xor     eax, eax
304
        xor     eax, eax
301
        ret
305
        ret
302
endp
306
endp
303
 
307
 
304
proc bd_write_interface stdcall uses esi edi, \
308
proc bd_write_interface stdcall uses esi edi, \
305
        userdata, buffer, startsector:qword, numsectors
309
        userdata, buffer, startsector:qword, numsectors
306
        ; userdata = old [hdpos] = 80h + index in NumBiosDisks
310
        ; userdata = old [hdpos] = 80h + index in NumBiosDisks
307
        ; buffer = pointer to buffer with data
311
        ; buffer = pointer to buffer with data
308
        ; startsector = 64-bit start sector
312
        ; startsector = 64-bit start sector
309
        ; numsectors = pointer to number of sectors on input,
313
        ; numsectors = pointer to number of sectors on input,
310
        ;  must be filled with number of sectors really written
314
        ;  must be filled with number of sectors really written
311
locals
315
locals
312
sectors_todo    dd      ?
316
sectors_todo    dd      ?
313
endl
317
endl
314
; 1. Initialize number of sectors: get number of requested sectors
318
; 1. Initialize number of sectors: get number of requested sectors
315
; and say that no sectors were read yet.      
319
; and say that no sectors were read yet.      
316
        mov     ecx, [numsectors]
320
        mov     ecx, [numsectors]
317
        mov     eax, [ecx]
321
        mov     eax, [ecx]
318
        mov     dword [ecx], 0
322
        mov     dword [ecx], 0
319
        mov     [sectors_todo], eax
323
        mov     [sectors_todo], eax
320
; 2. Acquire the global lock.
324
; 2. Acquire the global lock.
321
        mov     ecx, ide_mutex
325
        mov     ecx, ide_mutex
322
        call    mutex_lock
326
        call    mutex_lock
323
; 3. Convert parameters to the form suitable for worker procedures.
327
; 3. Convert parameters to the form suitable for worker procedures.
324
; Underlying procedures do not know about 64-bit sectors.
328
; Underlying procedures do not know about 64-bit sectors.
325
; Worker procedures use global variables and esi for [buffer].
329
; Worker procedures use global variables and esi for [buffer].
326
        cmp     dword [startsector+4], 0
330
        cmp     dword [startsector+4], 0
327
        jnz     .fail
331
        jnz     .fail
328
        and     [hd_error], 0
332
        and     [hd_error], 0
329
        mov     eax, [userdata]
333
        mov     eax, [userdata]
330
        mov     [hdpos], eax
334
        mov     [hdpos], eax
331
        mov     esi, [buffer]
335
        mov     esi, [buffer]
332
        lea     edi, [startsector]
336
        lea     edi, [startsector]
333
        mov     [cache_chain_ptr], edi
337
        mov     [cache_chain_ptr], edi
334
; 4. Worker procedures take max 16 sectors per time,
338
; 4. Worker procedures take max 16 sectors per time,
335
; loop until all sectors will be processed.
339
; loop until all sectors will be processed.
336
.sectors_loop:
340
.sectors_loop:
337
        mov     ecx, 16
341
        mov     ecx, 16
338
        cmp     ecx, [sectors_todo]
342
        cmp     ecx, [sectors_todo]
339
        jbe     @f
343
        jbe     @f
340
        mov     ecx, [sectors_todo]
344
        mov     ecx, [sectors_todo]
341
@@:
345
@@:
342
        mov     [cache_chain_size], cl
346
        mov     [cache_chain_size], cl
343
        call    bd_write_cache_chain
347
        call    bd_write_cache_chain
344
        cmp     [hd_error], 0
348
        cmp     [hd_error], 0
345
        jnz     .fail
349
        jnz     .fail
346
        movzx   ecx, [cache_chain_size]
350
        movzx   ecx, [cache_chain_size]
347
        mov     eax, [numsectors]
351
        mov     eax, [numsectors]
348
        add     [eax], ecx
352
        add     [eax], ecx
349
        sub     [sectors_todo], ecx
353
        sub     [sectors_todo], ecx
350
        jz      .done
354
        jz      .done
351
        add     [edi], ecx
355
        add     [edi], ecx
352
        jc      .fail
356
        jc      .fail
353
        shl     ecx, 9
357
        shl     ecx, 9
354
        add     esi, ecx
358
        add     esi, ecx
355
        jmp     .sectors_loop
359
        jmp     .sectors_loop
356
; 5. Loop is done, either due to error or because everything is done.
360
; 5. Loop is done, either due to error or because everything is done.
357
; Release the global lock and return the corresponding status.
361
; Release the global lock and return the corresponding status.
358
.fail:
362
.fail:
359
        mov     ecx, ide_mutex
363
        mov     ecx, ide_mutex
360
        call    mutex_unlock
364
        call    mutex_unlock
361
        or      eax, -1
365
        or      eax, -1
362
        ret
366
        ret
363
.done:
367
.done:
364
        mov     ecx, ide_mutex
368
        mov     ecx, ide_mutex
365
        call    mutex_unlock
369
        call    mutex_unlock
366
        xor     eax, eax
370
        xor     eax, eax
367
        ret
371
        ret
368
endp
372
endp
369
 
373
 
370
; This is a stub.
374
; This is a stub.
371
proc bd_querymedia stdcall, hd_data, mediainfo
375
proc bd_querymedia stdcall, hd_data, mediainfo
372
        mov     eax, [mediainfo]
376
        mov     eax, [mediainfo]
373
        mov     [eax+DISKMEDIAINFO.Flags], 0
377
        mov     [eax+DISKMEDIAINFO.Flags], 0
374
        mov     [eax+DISKMEDIAINFO.SectorSize], 512
378
        mov     [eax+DISKMEDIAINFO.SectorSize], 512
375
        or      dword [eax+DISKMEDIAINFO.Capacity], 0xFFFFFFFF
379
        or      dword [eax+DISKMEDIAINFO.Capacity], 0xFFFFFFFF
376
        or      dword [eax+DISKMEDIAINFO.Capacity+4], 0xFFFFFFFF
380
        or      dword [eax+DISKMEDIAINFO.Capacity+4], 0xFFFFFFFF
377
        xor     eax, eax
381
        xor     eax, eax
378
        ret
382
        ret
379
endp
383
endp
380
 
384
 
381
;-----------------------------------------------------------------------------
385
;-----------------------------------------------------------------------------
382
align 4
386
align 4
383
; input: eax = sector, edi -> buffer
387
; input: eax = sector, edi -> buffer
384
; output: edi = edi + 512
388
; output: edi = edi + 512
385
hd_read_pio:
389
hd_read_pio:
386
        push    eax edx
390
        push    eax edx
387
 
391
 
388
; Select the desired drive
392
; Select the desired drive
389
        mov     edx, [hdbase]
393
        mov     edx, [hdbase]
390
        add     edx, 6   ;адрес регистра головок
394
        add     edx, 6   ;адрес регистра головок
391
        mov     al, byte [hdid]
395
        mov     al, byte [hdid]
392
        add     al, 128+64+32
396
        add     al, 128+64+32
393
        out     dx, al; номер головки/номер диска
397
        out     dx, al; номер головки/номер диска
394
        
398
        
395
        call    wait_for_hd_idle
399
        call    wait_for_hd_idle
396
        cmp     [hd_error], 0
400
        cmp     [hd_error], 0
397
        jne     hd_read_error
401
        jne     hd_read_error
398
        
402
        
399
; ATA with 28 or 48 bit for sector number?
403
; ATA with 28 or 48 bit for sector number?
400
        mov     eax, [esp+4]
404
        mov     eax, [esp+4]
401
        cmp     eax, 0x10000000
405
        cmp     eax, 0x10000000
402
        jae     .lba48
406
        jae     .lba48
403
;--------------------------------------
407
;--------------------------------------
404
.lba28:
408
.lba28:
405
        pushfd
409
        pushfd
406
        cli
410
        cli
407
        xor     eax, eax
411
        xor     eax, eax
408
        mov     edx, [hdbase]
412
        mov     edx, [hdbase]
409
        inc     edx
413
        inc     edx
410
        out     dx, al ; ATA Features регистр "особенностей"
414
        out     dx, al ; ATA Features регистр "особенностей"
411
        inc     edx
415
        inc     edx
412
        inc     eax
416
        inc     eax
413
        out     dx, al ; ATA Sector Counter счётчик секторов
417
        out     dx, al ; ATA Sector Counter счётчик секторов
414
        inc     edx
418
        inc     edx
415
        mov     eax, [esp+4+4]
419
        mov     eax, [esp+4+4]
416
        out     dx, al ; LBA Low LBA (7:0)
420
        out     dx, al ; LBA Low LBA (7:0)
417
        shr     eax, 8
421
        shr     eax, 8
418
        inc     edx
422
        inc     edx
419
        out     dx, al ; LBA Mid LBA (15:8)
423
        out     dx, al ; LBA Mid LBA (15:8)
420
        shr     eax, 8
424
        shr     eax, 8
421
        inc     edx
425
        inc     edx
422
        out     dx, al ; LBA High LBA (23:16)
426
        out     dx, al ; LBA High LBA (23:16)
423
        shr     eax, 8
427
        shr     eax, 8
424
        inc     edx
428
        inc     edx
425
        and     al, 1+2+4+8 ; LBA (27:24)
429
        and     al, 1+2+4+8 ; LBA (27:24)
426
        add     al, byte [hdid]
430
        add     al, byte [hdid]
427
        add     al, 128+64+32
431
        add     al, 128+64+32
428
        out     dx, al ; номер головки/номер диска
432
        out     dx, al ; номер головки/номер диска
429
        inc     edx
433
        inc     edx
430
        mov     al, 20h ; READ SECTOR(S)
434
        mov     al, 20h ; READ SECTOR(S)
431
        out     dx, al ; ATACommand регистр команд
435
        out     dx, al ; ATACommand регистр команд
432
        popfd
436
        popfd
433
        jmp     .continue
437
        jmp     .continue
434
;--------------------------------------
438
;--------------------------------------
435
.lba48:
439
.lba48:
436
        pushfd
440
        pushfd
437
        cli
441
        cli
438
        xor     eax, eax
442
        xor     eax, eax
439
        mov     edx, [hdbase]
443
        mov     edx, [hdbase]
440
        inc     edx
444
        inc     edx
441
        out     dx, al ; Features Previous Reserved
445
        out     dx, al ; Features Previous Reserved
442
        out     dx, al ; Features Current Reserved
446
        out     dx, al ; Features Current Reserved
443
        inc     edx
447
        inc     edx
444
        out     dx, al ; Sector Count Previous Sector count (15:8)
448
        out     dx, al ; Sector Count Previous Sector count (15:8)
445
        inc     eax
449
        inc     eax
446
        out     dx, al ; Sector Count Current Sector count (7:0)
450
        out     dx, al ; Sector Count Current Sector count (7:0)
447
        inc     edx
451
        inc     edx
448
        mov     eax, [esp+4+4]
452
        mov     eax, [esp+4+4]
449
        rol     eax, 8
453
        rol     eax, 8
450
        out     dx, al ; LBA Low Previous LBA (31:24)
454
        out     dx, al ; LBA Low Previous LBA (31:24)
451
        xor     eax, eax ; because only 32 bit cache
455
        xor     eax, eax ; because only 32 bit cache
452
        inc     edx
456
        inc     edx
453
        out     dx, al ; LBA Mid Previous LBA (39:32)
457
        out     dx, al ; LBA Mid Previous LBA (39:32)
454
        inc     edx
458
        inc     edx
455
        out     dx, al ; LBA High Previous LBA (47:40)
459
        out     dx, al ; LBA High Previous LBA (47:40)
456
        sub     edx, 2
460
        sub     edx, 2
457
        mov     eax, [esp+4+4]
461
        mov     eax, [esp+4+4]
458
        out     dx, al ; LBA Low Current LBA (7:0)
462
        out     dx, al ; LBA Low Current LBA (7:0)
459
        shr     eax, 8
463
        shr     eax, 8
460
        inc     edx
464
        inc     edx
461
        out     dx, al ; LBA Mid Current LBA (15:8)
465
        out     dx, al ; LBA Mid Current LBA (15:8)
462
        shr     eax, 8
466
        shr     eax, 8
463
        inc     edx
467
        inc     edx
464
        out     dx, al ; LBA High Current LBA (23:16)
468
        out     dx, al ; LBA High Current LBA (23:16)
465
        inc     edx
469
        inc     edx
466
        mov     al, byte [hdid]
470
        mov     al, byte [hdid]
467
        add     al, 128+64+32
471
        add     al, 128+64+32
468
        out     dx, al ; номер головки/номер диска
472
        out     dx, al ; номер головки/номер диска
469
        inc     edx
473
        inc     edx
470
        mov     al, 24h ; READ SECTOR(S) EXT
474
        mov     al, 24h ; READ SECTOR(S) EXT
471
        out     dx, al ; ATACommand регистр команд
475
        out     dx, al ; ATACommand регистр команд
472
        popfd
476
        popfd
473
;--------------------------------------
477
;--------------------------------------
474
.continue:
478
.continue:
475
        call    wait_for_sector_buffer
479
        call    wait_for_sector_buffer
476
 
480
 
477
        cmp     [hd_error], 0
481
        cmp     [hd_error], 0
478
        jne     hd_read_error
482
        jne     hd_read_error
479
 
483
 
480
        pushfd
484
        pushfd
481
        cli
485
        cli
482
 
486
 
483
        mov     ecx, 256
487
        mov     ecx, 256
484
        mov     edx, [hdbase]
488
        mov     edx, [hdbase]
485
        cld
489
        cld
486
        rep insw
490
        rep insw
487
        popfd
491
        popfd
488
 
492
 
489
        pop     edx eax
493
        pop     edx eax
490
        ret
494
        ret
491
;-----------------------------------------------------------------------------
495
;-----------------------------------------------------------------------------
492
align 4
496
align 4
493
; edi -> sector, esi -> data
497
; edi -> sector, esi -> data
494
cache_write_pio:
498
cache_write_pio:
495
; Select the desired drive
499
; Select the desired drive
496
        mov     edx, [hdbase]
500
        mov     edx, [hdbase]
497
        add     edx, 6   ;адрес регистра головок
501
        add     edx, 6   ;адрес регистра головок
498
        mov     al, byte [hdid]
502
        mov     al, byte [hdid]
499
        add     al, 128+64+32
503
        add     al, 128+64+32
500
        out     dx, al ; номер головки/номер диска
504
        out     dx, al ; номер головки/номер диска
501
 
505
 
502
        call    wait_for_hd_idle
506
        call    wait_for_hd_idle
503
        cmp     [hd_error], 0
507
        cmp     [hd_error], 0
504
        jne     hd_write_error
508
        jne     hd_write_error
505
 
509
 
506
; ATA with 28 or 48 bit for sector number?
510
; ATA with 28 or 48 bit for sector number?
507
        mov     eax, [edi]
511
        mov     eax, [edi]
508
        cmp     eax, 0x10000000
512
        cmp     eax, 0x10000000
509
        jae     .lba48
513
        jae     .lba48
510
;--------------------------------------
514
;--------------------------------------
511
.lba28:
515
.lba28:
512
        pushfd
516
        pushfd
513
        cli
517
        cli
514
        xor     eax, eax
518
        xor     eax, eax
515
        mov     edx, [hdbase]
519
        mov     edx, [hdbase]
516
        inc     edx
520
        inc     edx
517
        out     dx, al ; ATA Features регистр "особенностей"
521
        out     dx, al ; ATA Features регистр "особенностей"
518
        inc     edx
522
        inc     edx
519
        inc     eax
523
        inc     eax
520
        out     dx, al ; ATA Sector Counter счётчик секторов
524
        out     dx, al ; ATA Sector Counter счётчик секторов
521
        inc     edx
525
        inc     edx
522
        mov     eax, [edi]      ; eax = sector to write
526
        mov     eax, [edi]      ; eax = sector to write
523
        out     dx, al ; LBA Low LBA (7:0)
527
        out     dx, al ; LBA Low LBA (7:0)
524
        shr     eax, 8
528
        shr     eax, 8
525
        inc     edx
529
        inc     edx
526
        out     dx, al ; LBA Mid LBA (15:8)
530
        out     dx, al ; LBA Mid LBA (15:8)
527
        shr     eax, 8
531
        shr     eax, 8
528
        inc     edx
532
        inc     edx
529
        out     dx, al ; LBA High LBA (23:16)
533
        out     dx, al ; LBA High LBA (23:16)
530
        shr     eax, 8
534
        shr     eax, 8
531
        inc     edx
535
        inc     edx
532
        and     al, 1+2+4+8 ; LBA (27:24)
536
        and     al, 1+2+4+8 ; LBA (27:24)
533
        add     al, byte [hdid]
537
        add     al, byte [hdid]
534
        add     al, 128+64+32
538
        add     al, 128+64+32
535
        out     dx, al ; номер головки/номер диска
539
        out     dx, al ; номер головки/номер диска
536
        inc     edx
540
        inc     edx
537
        mov     al, 30h ; WRITE SECTOR(S)
541
        mov     al, 30h ; WRITE SECTOR(S)
538
        out     dx, al ; ATACommand регистр команд
542
        out     dx, al ; ATACommand регистр команд
539
        jmp     .continue
543
        jmp     .continue
540
;--------------------------------------
544
;--------------------------------------
541
.lba48:
545
.lba48:
542
        pushfd
546
        pushfd
543
        cli
547
        cli
544
        xor     eax, eax
548
        xor     eax, eax
545
        mov     edx, [hdbase]
549
        mov     edx, [hdbase]
546
        inc     edx
550
        inc     edx
547
        out     dx, al ; Features Previous Reserved
551
        out     dx, al ; Features Previous Reserved
548
        out     dx, al ; Features Current Reserved
552
        out     dx, al ; Features Current Reserved
549
        inc     edx
553
        inc     edx
550
        out     dx, al ; Sector Count Previous Sector count (15:8)
554
        out     dx, al ; Sector Count Previous Sector count (15:8)
551
        inc     eax
555
        inc     eax
552
        out     dx, al ; Sector Count Current Sector count (7:0)
556
        out     dx, al ; Sector Count Current Sector count (7:0)
553
        inc     edx
557
        inc     edx
554
        mov     eax, [edi]
558
        mov     eax, [edi]
555
        rol     eax, 8
559
        rol     eax, 8
556
        out     dx, al ; LBA Low Previous LBA (31:24)
560
        out     dx, al ; LBA Low Previous LBA (31:24)
557
        xor     eax, eax ; because only 32 bit cache
561
        xor     eax, eax ; because only 32 bit cache
558
        inc     edx
562
        inc     edx
559
        out     dx, al ; LBA Mid Previous LBA (39:32)
563
        out     dx, al ; LBA Mid Previous LBA (39:32)
560
        inc     edx
564
        inc     edx
561
        out     dx, al ; LBA High Previous LBA (47:40)
565
        out     dx, al ; LBA High Previous LBA (47:40)
562
        sub     edx, 2
566
        sub     edx, 2
563
        mov     eax, [edi]
567
        mov     eax, [edi]
564
        out     dx, al ; LBA Low Current LBA (7:0)
568
        out     dx, al ; LBA Low Current LBA (7:0)
565
        shr     eax, 8
569
        shr     eax, 8
566
        inc     edx
570
        inc     edx
567
        out     dx, al ; LBA Mid Current LBA (15:8)
571
        out     dx, al ; LBA Mid Current LBA (15:8)
568
        shr     eax, 8
572
        shr     eax, 8
569
        inc     edx
573
        inc     edx
570
        out     dx, al ; LBA High Current LBA (23:16)
574
        out     dx, al ; LBA High Current LBA (23:16)
571
        inc     edx
575
        inc     edx
572
        mov     al, byte [hdid]
576
        mov     al, byte [hdid]
573
        add     al, 128+64+32
577
        add     al, 128+64+32
574
        out     dx, al ; номер головки/номер диска
578
        out     dx, al ; номер головки/номер диска
575
        inc     edx
579
        inc     edx
576
        mov     al, 34h ; WRITE SECTOR(S) EXT
580
        mov     al, 34h ; WRITE SECTOR(S) EXT
577
        out     dx, al ; ATACommand регистр команд
581
        out     dx, al ; ATACommand регистр команд
578
;--------------------------------------
582
;--------------------------------------
579
.continue:
583
.continue:
580
        popfd
584
        popfd
581
        call    wait_for_sector_buffer
585
        call    wait_for_sector_buffer
582
 
586
 
583
        cmp     [hd_error], 0
587
        cmp     [hd_error], 0
584
        jne     hd_write_error
588
        jne     hd_write_error
585
 
589
 
586
        push    ecx esi
590
        push    ecx esi
587
 
591
 
588
        pushfd
592
        pushfd
589
        cli
593
        cli
590
        mov     ecx, 256
594
        mov     ecx, 256
591
        mov     edx, [hdbase]
595
        mov     edx, [hdbase]
592
        cld
596
        cld
593
        rep outsw
597
        rep outsw
594
        popfd
598
        popfd
595
 
599
 
596
        pop     esi ecx
600
        pop     esi ecx
597
        ret
601
        ret
598
;-----------------------------------------------------------------------------
602
;-----------------------------------------------------------------------------
599
align 4
603
align 4
600
save_hd_wait_timeout:
604
save_hd_wait_timeout:
601
        push    eax
605
        push    eax
602
        mov     eax, [timer_ticks]
606
        mov     eax, [timer_ticks]
603
        add     eax, 300        ; 3 sec timeout
607
        add     eax, 300        ; 3 sec timeout
604
        mov     [hd_wait_timeout], eax
608
        mov     [hd_wait_timeout], eax
605
        pop     eax
609
        pop     eax
606
        ret
610
        ret
607
;-----------------------------------------------------------------------------
611
;-----------------------------------------------------------------------------
608
align 4
612
align 4
609
check_hd_wait_timeout:
613
check_hd_wait_timeout:
610
        push    eax
614
        push    eax
611
        mov     eax, [hd_wait_timeout]
615
        mov     eax, [hd_wait_timeout]
612
        cmp     [timer_ticks], eax
616
        cmp     [timer_ticks], eax
613
        jg      hd_timeout_error
617
        jg      hd_timeout_error
614
 
618
 
615
        pop     eax
619
        pop     eax
616
        mov     [hd_error], 0
620
        mov     [hd_error], 0
617
        ret
621
        ret
618
;-----------------------------------------------------------------------------
622
;-----------------------------------------------------------------------------
619
hd_timeout_error:
623
hd_timeout_error:
620
        if lang eq sp
624
        if lang eq sp
621
        DEBUGF 1,"K : FS - HD tiempo de espera agotado\n"
625
        DEBUGF 1,"K : FS - HD tiempo de espera agotado\n"
622
        else
626
        else
623
        DEBUGF 1,"K : FS - HD timeout\n"
627
        DEBUGF 1,"K : FS - HD timeout\n"
624
        end if
628
        end if
625
        mov     [hd_error], 1
629
        mov     [hd_error], 1
626
        pop     eax
630
        pop     eax
627
        ret
631
        ret
628
;-----------------------------------------------------------------------------
632
;-----------------------------------------------------------------------------
629
hd_read_error:
633
hd_read_error:
630
        if lang eq sp
634
        if lang eq sp
631
        DEBUGF 1,"K : FS - HD error de lectura\n"
635
        DEBUGF 1,"K : FS - HD error de lectura\n"
632
        else
636
        else
633
        DEBUGF 1,"K : FS - HD read error\n"
637
        DEBUGF 1,"K : FS - HD read error\n"
634
        end if
638
        end if
635
        pop     edx eax
639
        pop     edx eax
636
        ret
640
        ret
637
;-----------------------------------------------------------------------------
641
;-----------------------------------------------------------------------------
638
hd_write_error_dma:
642
hd_write_error_dma:
639
        pop     esi
643
        pop     esi
640
hd_write_error:
644
hd_write_error:
641
        if lang eq sp
645
        if lang eq sp
642
        DEBUGF 1,"K : FS - HD error de escritura\n"
646
        DEBUGF 1,"K : FS - HD error de escritura\n"
643
        else
647
        else
644
        DEBUGF 1,"K : FS - HD write error\n"
648
        DEBUGF 1,"K : FS - HD write error\n"
645
        end if
649
        end if
646
        ret
650
        ret
647
;-----------------------------------------------------------------------------
651
;-----------------------------------------------------------------------------
648
hd_lba_error:
-
 
649
        if lang eq sp
-
 
650
        DEBUGF 1,"K : FS - HD error en LBA\n"
-
 
651
        else
-
 
652
        DEBUGF 1,"K : FS - HD LBA error\n"
-
 
653
        end if
-
 
654
        jmp     LBA_read_ret
-
 
655
;-----------------------------------------------------------------------------
-
 
656
align 4
652
align 4
657
wait_for_hd_idle:
653
wait_for_hd_idle:
658
        push    eax edx
654
        push    eax edx
659
 
655
 
660
        call    save_hd_wait_timeout
656
        call    save_hd_wait_timeout
661
 
657
 
662
        mov     edx, [hdbase]
658
        mov     edx, [hdbase]
663
        add     edx, 0x7
659
        add     edx, 0x7
664
;--------------------------------------
660
;--------------------------------------
665
align 4
661
align 4
666
wfhil1:
662
wfhil1:
667
        call    check_hd_wait_timeout
663
        call    check_hd_wait_timeout
668
        cmp     [hd_error], 0
664
        cmp     [hd_error], 0
669
        jne     @f
665
        jne     @f
670
 
666
 
671
        in      al, dx
667
        in      al, dx
672
        test    al, 128
668
        test    al, 128
673
        jnz     wfhil1
669
        jnz     wfhil1
674
 
670
 
675
@@:
671
@@:
676
        pop     edx eax
672
        pop     edx eax
677
        ret
673
        ret
678
;-----------------------------------------------------------------------------
674
;-----------------------------------------------------------------------------
679
align 4
675
align 4
680
wait_for_sector_buffer:
676
wait_for_sector_buffer:
681
        push    eax edx
677
        push    eax edx
682
 
678
 
683
        mov     edx, [hdbase]
679
        mov     edx, [hdbase]
684
        add     edx, 0x7
680
        add     edx, 0x7
685
 
681
 
686
        call    save_hd_wait_timeout
682
        call    save_hd_wait_timeout
687
;--------------------------------------
683
;--------------------------------------
688
align 4
684
align 4
689
hdwait_sbuf:                  ; wait for sector buffer to be ready
685
hdwait_sbuf:                  ; wait for sector buffer to be ready
690
        call    check_hd_wait_timeout
686
        call    check_hd_wait_timeout
691
        cmp     [hd_error], 0
687
        cmp     [hd_error], 0
692
        jne     @f
688
        jne     @f
693
 
689
 
694
        in      al, dx
690
        in      al, dx
695
        test    al, 8
691
        test    al, 8
696
        jz      hdwait_sbuf
692
        jz      hdwait_sbuf
697
 
693
 
698
        mov     [hd_error], 0
694
        mov     [hd_error], 0
699
 
695
 
700
        cmp     [hd_setup], 1   ; do not mark error for setup request
696
        cmp     [hd_setup], 1   ; do not mark error for setup request
701
        je      buf_wait_ok
697
        je      buf_wait_ok
702
 
698
 
703
        test    al, 1           ; previous command ended up with an error
699
        test    al, 1           ; previous command ended up with an error
704
        jz      buf_wait_ok
700
        jz      buf_wait_ok
705
@@:
701
@@:
706
        mov     [hd_error], 1
702
        mov     [hd_error], 1
707
 
703
 
708
buf_wait_ok:
704
buf_wait_ok:
709
        pop     edx eax
705
        pop     edx eax
710
        ret
706
        ret
711
;-----------------------------------------------------------------------------
707
;-----------------------------------------------------------------------------
712
irq14_num equ byte 14
708
irq14_num equ byte 14
713
irq15_num equ byte 15
709
irq15_num equ byte 15
714
;-----------------------------------------------------------------------------
710
;-----------------------------------------------------------------------------
715
align 4
711
align 4
716
wait_for_sector_dma_ide0:
712
wait_for_sector_dma_ide0:
717
        push    eax
713
        push    eax
718
        push    edx
714
        push    edx
719
        call    save_hd_wait_timeout
715
        call    save_hd_wait_timeout
720
;--------------------------------------
716
;--------------------------------------
721
align 4
717
align 4
722
.wait:
718
.wait:
723
        call    change_task
719
        call    change_task
724
        cmp     [IDE_common_irq_param], 0
720
        cmp     [IDE_common_irq_param], 0
725
        jz      .done
721
        jz      .done
726
 
722
 
727
        call    check_hd_wait_timeout
723
        call    check_hd_wait_timeout
728
        cmp     [hd_error], 0
724
        cmp     [hd_error], 0
729
        jz      .wait
725
        jz      .wait
730
; clear Bus Master IDE Command register
726
; clear Bus Master IDE Command register
731
        pushfd
727
        pushfd
732
        cli
728
        cli
733
        mov     [IDE_common_irq_param], 0
729
        mov     [IDE_common_irq_param], 0
734
        mov     dx, [IDEContrRegsBaseAddr]
730
        mov     dx, [IDEContrRegsBaseAddr]
735
        mov     al, 0
731
        mov     al, 0
736
        out     dx, al
732
        out     dx, al
737
        popfd
733
        popfd
738
;--------------------------------------
734
;--------------------------------------
739
align 4
735
align 4
740
.done:
736
.done:
741
        pop     edx
737
        pop     edx
742
        pop     eax
738
        pop     eax
743
        ret
739
        ret
744
;-----------------------------------------------------------------------------
740
;-----------------------------------------------------------------------------
745
align 4
741
align 4
746
wait_for_sector_dma_ide1:
742
wait_for_sector_dma_ide1:
747
        push    eax
743
        push    eax
748
        push    edx
744
        push    edx
749
        call    save_hd_wait_timeout
745
        call    save_hd_wait_timeout
750
;--------------------------------------
746
;--------------------------------------
751
align 4
747
align 4
752
.wait:
748
.wait:
753
        call    change_task
749
        call    change_task
754
        cmp     [IDE_common_irq_param], 0
750
        cmp     [IDE_common_irq_param], 0
755
        jz      .done
751
        jz      .done
756
 
752
 
757
        call    check_hd_wait_timeout
753
        call    check_hd_wait_timeout
758
        cmp     [hd_error], 0
754
        cmp     [hd_error], 0
759
        jz      .wait
755
        jz      .wait
760
; clear Bus Master IDE Command register
756
; clear Bus Master IDE Command register
761
        pushfd
757
        pushfd
762
        cli
758
        cli
763
        mov     [IDE_common_irq_param], 0
759
        mov     [IDE_common_irq_param], 0
764
        mov     dx, [IDEContrRegsBaseAddr]
760
        mov     dx, [IDEContrRegsBaseAddr]
765
        add     dx, 8
761
        add     dx, 8
766
        mov     al, 0
762
        mov     al, 0
767
        out     dx, al
763
        out     dx, al
768
        popfd
764
        popfd
769
;--------------------------------------
765
;--------------------------------------
770
align 4
766
align 4
771
.done:
767
.done:
772
        pop     edx
768
        pop     edx
773
        pop     eax
769
        pop     eax
774
        ret
770
        ret
775
;-----------------------------------------------------------------------------
771
;-----------------------------------------------------------------------------
776
iglobal
772
iglobal
777
align 4
773
align 4
778
; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary
774
; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary
779
IDE_descriptor_table:
775
IDE_descriptor_table:
780
        dd IDE_DMA
776
        dd IDE_DMA
781
        dw 0x2000
777
        dw 0x2000
782
        dw 0x8000
778
        dw 0x8000
783
 
779
 
784
dma_cur_sector  dd not 40h
780
dma_cur_sector  dd not 40h
785
dma_hdpos       dd 0
781
dma_hdpos       dd 0
786
IDE_common_irq_param db 0
782
IDE_common_irq_param db 0
787
endg
783
endg
788
;-----------------------------------------------------------------------------
784
;-----------------------------------------------------------------------------
789
uglobal
785
uglobal
790
; all uglobals are zeroed at boot
786
; all uglobals are zeroed at boot
791
dma_process         dd 0
787
dma_process         dd 0
792
dma_slot_ptr        dd 0
788
dma_slot_ptr        dd 0
793
cache_chain_pos     dd 0
789
cache_chain_pos     dd 0
794
cache_chain_ptr     dd 0
790
cache_chain_ptr     dd 0
795
cache_chain_size    db 0
791
cache_chain_size    db 0
796
cache_chain_started db 0
792
cache_chain_started db 0
797
dma_task_switched   db 0
793
dma_task_switched   db 0
798
dma_hdd             db 0
794
dma_hdd             db 0
799
allow_dma_access    db 0
795
allow_dma_access    db 0
800
endg
796
endg
801
;-----------------------------------------------------------------------------
797
;-----------------------------------------------------------------------------
802
align 4
798
align 4
803
IDE_irq_14_handler:
799
IDE_irq_14_handler:
804
        cmp     [IDE_common_irq_param], irq14_num
800
        cmp     [IDE_common_irq_param], irq14_num
805
        jne     .exit
801
        jne     .exit
806
 
802
 
807
        pushfd
803
        pushfd
808
        cli
804
        cli
809
        pushad
805
        pushad
810
; clear Bus Master IDE Command register
806
; clear Bus Master IDE Command register
811
        mov     [IDE_common_irq_param], 0
807
        mov     [IDE_common_irq_param], 0
812
        mov     dx, [IDEContrRegsBaseAddr]
808
        mov     dx, [IDEContrRegsBaseAddr]
813
        mov     al, 0
809
        mov     al, 0
814
        out     dx, al
810
        out     dx, al
815
; clear Bus Master IDE Status register
811
; clear Bus Master IDE Status register
816
; clear Interrupt bit
812
; clear Interrupt bit
817
        add     edx, 2
813
        add     edx, 2
818
        mov     al, 4 ; 100b
814
        mov     al, 4 ; 100b
819
        out     dx, al
815
        out     dx, al
820
 
816
 
821
        popad
817
        popad
822
        popfd
818
        popfd
823
;--------------------------------------
819
;--------------------------------------
824
align 4
820
align 4
825
.exit:
821
.exit:
826
        mov     al, 1
822
        mov     al, 1
827
        ret
823
        ret
828
;-----------------------------------------------------------------------------
824
;-----------------------------------------------------------------------------
829
align 4
825
align 4
830
IDE_irq_15_handler:
826
IDE_irq_15_handler:
831
        cmp     [IDE_common_irq_param], irq15_num
827
        cmp     [IDE_common_irq_param], irq15_num
832
        jne     .exit
828
        jne     .exit
833
 
829
 
834
        pushfd
830
        pushfd
835
        cli
831
        cli
836
        pushad
832
        pushad
837
; clear Bus Master IDE Command register
833
; clear Bus Master IDE Command register
838
        mov     [IDE_common_irq_param], 0
834
        mov     [IDE_common_irq_param], 0
839
        mov     dx, [IDEContrRegsBaseAddr]
835
        mov     dx, [IDEContrRegsBaseAddr]
840
        add     dx, 8
836
        add     dx, 8
841
        mov     al, 0
837
        mov     al, 0
842
        out     dx, al
838
        out     dx, al
843
; clear Bus Master IDE Status register
839
; clear Bus Master IDE Status register
844
; clear Interrupt bit
840
; clear Interrupt bit
845
        add     edx, 2
841
        add     edx, 2
846
        mov     al, 4 ; 100b
842
        mov     al, 4 ; 100b
847
        out     dx, al
843
        out     dx, al
848
 
844
 
849
        popad
845
        popad
850
        popfd
846
        popfd
851
;--------------------------------------
847
;--------------------------------------
852
align 4
848
align 4
853
.exit:
849
.exit:
854
        mov     al, 1
850
        mov     al, 1
855
        ret
851
        ret
856
;-----------------------------------------------------------------------------
852
;-----------------------------------------------------------------------------
857
align 4
853
align 4
858
IDE_common_irq_handler:
854
IDE_common_irq_handler:
859
        cmp     [IDE_common_irq_param], 0
855
        cmp     [IDE_common_irq_param], 0
860
        je      .exit
856
        je      .exit
861
 
857
 
862
        pushfd
858
        pushfd
863
        cli
859
        cli
864
        pushad
860
        pushad
865
; clear Bus Master IDE Command register
861
; clear Bus Master IDE Command register
866
        xor     ebx, ebx
862
        xor     ebx, ebx
867
        mov     dx, [IDEContrRegsBaseAddr]
863
        mov     dx, [IDEContrRegsBaseAddr]
868
        mov     eax, IDE_common_irq_param
864
        mov     eax, IDE_common_irq_param
869
        cmp     [eax], irq14_num
865
        cmp     [eax], irq14_num
870
        mov     [eax], bl
866
        mov     [eax], bl
871
        xor     eax, eax
867
        xor     eax, eax
872
        je      @f
868
        je      @f
873
 
869
 
874
        add     dx, 8
870
        add     dx, 8
875
;--------------------------------------
871
;--------------------------------------
876
align 4
872
align 4
877
@@:
873
@@:
878
        out     dx, al
874
        out     dx, al
879
; clear Bus Master IDE Status register
875
; clear Bus Master IDE Status register
880
; clear Interrupt bit
876
; clear Interrupt bit
881
        add     edx, 2
877
        add     edx, 2
882
        mov     al, 4 ; 100b
878
        mov     al, 4 ; 100b
883
        out     dx, al
879
        out     dx, al
884
 
880
 
885
        popad
881
        popad
886
        popfd
882
        popfd
887
;--------------------------------------
883
;--------------------------------------
888
align 4
884
align 4
889
.exit:
885
.exit:
890
        mov     al, 1
886
        mov     al, 1
891
        ret
887
        ret
892
;-----------------------------------------------------------------------------
888
;-----------------------------------------------------------------------------
893
align 4
889
align 4
894
hd_read_dma:
890
hd_read_dma:
895
        push    eax
891
        push    eax
896
        push    edx
892
        push    edx
897
        mov     edx, [dma_hdpos]
893
        mov     edx, [dma_hdpos]
898
        cmp     edx, [hdpos]
894
        cmp     edx, [hdpos]
899
        jne     .notread
895
        jne     .notread
900
        mov     edx, [dma_cur_sector]
896
        mov     edx, [dma_cur_sector]
901
        cmp     eax, edx
897
        cmp     eax, edx
902
        jb      .notread
898
        jb      .notread
903
        add     edx, 15
899
        add     edx, 15
904
        cmp     [esp+4], edx
900
        cmp     [esp+4], edx
905
        ja      .notread
901
        ja      .notread
906
        mov     eax, [esp+4]
902
        mov     eax, [esp+4]
907
        sub     eax, [dma_cur_sector]
903
        sub     eax, [dma_cur_sector]
908
        shl     eax, 9
904
        shl     eax, 9
909
        add     eax, (OS_BASE+IDE_DMA)
905
        add     eax, (OS_BASE+IDE_DMA)
910
        push    ecx esi
906
        push    ecx esi
911
        mov     esi, eax
907
        mov     esi, eax
912
 
908
 
913
        mov     ecx, 512/4
909
        mov     ecx, 512/4
914
        cld
910
        cld
915
        rep movsd
911
        rep movsd
916
        pop     esi ecx
912
        pop     esi ecx
917
        pop     edx
913
        pop     edx
918
        pop     eax
914
        pop     eax
919
        ret
915
        ret
920
.notread:
916
.notread:
921
; set data for PRD Table
917
; set data for PRD Table
922
        mov     eax, IDE_descriptor_table
918
        mov     eax, IDE_descriptor_table
923
        mov     dword [eax], IDE_DMA
919
        mov     dword [eax], IDE_DMA
924
        mov     word [eax+4], 0x2000
920
        mov     word [eax+4], 0x2000
925
        sub     eax, OS_BASE
921
        sub     eax, OS_BASE
926
; select controller Primary or Secondary
922
; select controller Primary or Secondary
927
        mov     dx, [IDEContrRegsBaseAddr]
923
        mov     dx, [IDEContrRegsBaseAddr]
928
        push    eax
924
        push    eax
929
        mov     eax, [hd_address_table]
925
        mov     eax, [hd_address_table]
930
        cmp     [hdbase], eax ; 0x1F0
926
        cmp     [hdbase], eax ; 0x1F0
931
        pop     eax
927
        pop     eax
932
        jz      @f
928
        jz      @f
933
        add     edx, 8
929
        add     edx, 8
934
@@:
930
@@:
935
        push    edx
931
        push    edx
936
; Bus Master IDE PRD Table Address
932
; Bus Master IDE PRD Table Address
937
        add     edx, 4
933
        add     edx, 4
938
; save IDE_descriptor_table
934
; save IDE_descriptor_table
939
        out     dx, eax
935
        out     dx, eax
940
        pop     edx
936
        pop     edx
941
; clear Bus Master IDE Command register
937
; clear Bus Master IDE Command register
942
        mov     al, 0
938
        mov     al, 0
943
        out     dx, al
939
        out     dx, al
944
; clear Bus Master IDE Status register
940
; clear Bus Master IDE Status register
945
; clear Error bit and Interrupt bit
941
; clear Error bit and Interrupt bit
946
        add     edx, 2
942
        add     edx, 2
947
        mov     al, 6 ; 110b
943
        mov     al, 6 ; 110b
948
        out     dx, al
944
        out     dx, al
949
; Select the desired drive
945
; Select the desired drive
950
        mov     edx, [hdbase]
946
        mov     edx, [hdbase]
951
        add     edx, 6   ; адрес регистра головок
947
        add     edx, 6   ; адрес регистра головок
952
        mov     al, byte [hdid]
948
        mov     al, byte [hdid]
953
        add     al, 128+64+32
949
        add     al, 128+64+32
954
        out     dx, al ; номер головки/номер диска
950
        out     dx, al ; номер головки/номер диска
955
 
951
 
956
        call    wait_for_hd_idle
952
        call    wait_for_hd_idle
957
        cmp     [hd_error], 0
953
        cmp     [hd_error], 0
958
        jnz     hd_read_error
954
        jnz     hd_read_error
959
 
955
 
960
; ATA with 28 or 48 bit for sector number?
956
; ATA with 28 or 48 bit for sector number?
961
        mov     eax, [esp+4]
957
        mov     eax, [esp+4]
962
; -10h because the PreCache hits the boundary between lba28 and lba48
958
; -10h because the PreCache hits the boundary between lba28 and lba48
963
; 10h = 16  - size of PreCache
959
; 10h = 16  - size of PreCache
964
        cmp     eax, 0x10000000-10h
960
        cmp     eax, 0x10000000-10h
965
        jae     .lba48
961
        jae     .lba48
966
;--------------------------------------
962
;--------------------------------------
967
.lba28:
963
.lba28:
968
        pushfd
964
        pushfd
969
        cli
965
        cli
970
        xor     eax, eax
966
        xor     eax, eax
971
        mov     edx, [hdbase]
967
        mov     edx, [hdbase]
972
        inc     edx
968
        inc     edx
973
        out     dx, al ; ATA Features регистр "особенностей"
969
        out     dx, al ; ATA Features регистр "особенностей"
974
        inc     edx
970
        inc     edx
975
        mov     eax, 10h ; Sector Counter = 16 ; PreCache
971
        mov     eax, 10h ; Sector Counter = 16 ; PreCache
976
        out     dx, al ; ATA Sector Counter счётчик секторов
972
        out     dx, al ; ATA Sector Counter счётчик секторов
977
        inc     edx
973
        inc     edx
978
        mov     eax, [esp+4+4]
974
        mov     eax, [esp+4+4]
979
        out     dx, al ; LBA Low LBA (7:0)
975
        out     dx, al ; LBA Low LBA (7:0)
980
        shr     eax, 8
976
        shr     eax, 8
981
        inc     edx
977
        inc     edx
982
        out     dx, al ; LBA Mid LBA (15:8)
978
        out     dx, al ; LBA Mid LBA (15:8)
983
        shr     eax, 8
979
        shr     eax, 8
984
        inc     edx
980
        inc     edx
985
        out     dx, al ; LBA High LBA (23:16)
981
        out     dx, al ; LBA High LBA (23:16)
986
        shr     eax, 8
982
        shr     eax, 8
987
        inc     edx
983
        inc     edx
988
        and     al, 0xF ; LBA (27:24)
984
        and     al, 0xF ; LBA (27:24)
989
        add     al, byte [hdid]
985
        add     al, byte [hdid]
990
        add     al, 11100000b
986
        add     al, 11100000b
991
        out     dx, al ; номер головки/номер диска
987
        out     dx, al ; номер головки/номер диска
992
        inc     edx
988
        inc     edx
993
        mov     al, 0xC8 ; READ DMA
989
        mov     al, 0xC8 ; READ DMA
994
        out     dx, al ; ATACommand регистр команд
990
        out     dx, al ; ATACommand регистр команд
995
        jmp     .continue
991
        jmp     .continue
996
;--------------------------------------
992
;--------------------------------------
997
.lba48:
993
.lba48:
998
        pushfd
994
        pushfd
999
        cli
995
        cli
1000
        xor     eax, eax
996
        xor     eax, eax
1001
        mov     edx, [hdbase]
997
        mov     edx, [hdbase]
1002
        inc     edx
998
        inc     edx
1003
        out     dx, al ; Features Previous Reserved
999
        out     dx, al ; Features Previous Reserved
1004
        out     dx, al ; Features Current Reserved
1000
        out     dx, al ; Features Current Reserved
1005
        inc     edx
1001
        inc     edx
1006
        out     dx, al ; Sector Count Previous Sector count (15:8)
1002
        out     dx, al ; Sector Count Previous Sector count (15:8)
1007
        mov     eax, 10h ; Sector Counter = 16 PreCache
1003
        mov     eax, 10h ; Sector Counter = 16 PreCache
1008
        out     dx, al ; Sector Count Current Sector count (7:0)
1004
        out     dx, al ; Sector Count Current Sector count (7:0)
1009
        inc     edx
1005
        inc     edx
1010
        mov     eax, [esp+4+4]
1006
        mov     eax, [esp+4+4]
1011
        rol     eax, 8
1007
        rol     eax, 8
1012
        out     dx, al ; LBA Low Previous LBA (31:24)
1008
        out     dx, al ; LBA Low Previous LBA (31:24)
1013
        xor     eax, eax ; because only 32 bit cache
1009
        xor     eax, eax ; because only 32 bit cache
1014
        inc     edx
1010
        inc     edx
1015
        out     dx, al ; LBA Mid Previous LBA (39:32)
1011
        out     dx, al ; LBA Mid Previous LBA (39:32)
1016
        inc     edx
1012
        inc     edx
1017
        out     dx, al ; LBA High Previous LBA (47:40)
1013
        out     dx, al ; LBA High Previous LBA (47:40)
1018
        sub     edx, 2
1014
        sub     edx, 2
1019
        mov     eax, [esp+4+4]
1015
        mov     eax, [esp+4+4]
1020
        out     dx, al ; LBA Low Current LBA (7:0)
1016
        out     dx, al ; LBA Low Current LBA (7:0)
1021
        shr     eax, 8
1017
        shr     eax, 8
1022
        inc     edx
1018
        inc     edx
1023
        out     dx, al ; LBA Mid Current LBA (15:8)
1019
        out     dx, al ; LBA Mid Current LBA (15:8)
1024
        shr     eax, 8
1020
        shr     eax, 8
1025
        inc     edx
1021
        inc     edx
1026
        out     dx, al ; LBA High Current LBA (23:16)
1022
        out     dx, al ; LBA High Current LBA (23:16)
1027
        inc     edx
1023
        inc     edx
1028
        mov     al, byte [hdid]
1024
        mov     al, byte [hdid]
1029
        add     al, 128+64+32
1025
        add     al, 128+64+32
1030
        out     dx, al ; номер головки/номер диска
1026
        out     dx, al ; номер головки/номер диска
1031
        inc     edx
1027
        inc     edx
1032
        mov     al, 25h ; READ DMA EXT
1028
        mov     al, 25h ; READ DMA EXT
1033
        out     dx, al ; ATACommand регистр команд
1029
        out     dx, al ; ATACommand регистр команд
1034
;--------------------------------------
1030
;--------------------------------------
1035
.continue:
1031
.continue:
1036
; select controller Primary or Secondary
1032
; select controller Primary or Secondary
1037
        mov     dx, [IDEContrRegsBaseAddr]
1033
        mov     dx, [IDEContrRegsBaseAddr]
1038
        mov     eax, [hd_address_table]
1034
        mov     eax, [hd_address_table]
1039
        cmp     [hdbase], eax ; 0x1F0
1035
        cmp     [hdbase], eax ; 0x1F0
1040
        jz      @f
1036
        jz      @f
1041
        add     dx, 8
1037
        add     dx, 8
1042
@@:
1038
@@:
1043
; set write to memory and Start Bus Master
1039
; set write to memory and Start Bus Master
1044
        mov     al, 9
1040
        mov     al, 9
1045
        out     dx, al
1041
        out     dx, al
1046
 
1042
 
1047
        mov     eax, [CURRENT_TASK]
1043
        mov     eax, [CURRENT_TASK]
1048
        mov     [dma_process], eax
1044
        mov     [dma_process], eax
1049
 
1045
 
1050
        mov     eax, [TASK_BASE]
1046
        mov     eax, [TASK_BASE]
1051
        mov     [dma_slot_ptr], eax
1047
        mov     [dma_slot_ptr], eax
1052
 
1048
 
1053
        mov     eax, [hd_address_table]
1049
        mov     eax, [hd_address_table]
1054
        cmp     [hdbase], eax ; 0x1F0
1050
        cmp     [hdbase], eax ; 0x1F0
1055
        jnz     .ide1
1051
        jnz     .ide1
1056
 
1052
 
1057
        mov     [IDE_common_irq_param], irq14_num
1053
        mov     [IDE_common_irq_param], irq14_num
1058
        jmp     @f
1054
        jmp     @f
1059
.ide1:
1055
.ide1:
1060
        mov     [IDE_common_irq_param], irq15_num
1056
        mov     [IDE_common_irq_param], irq15_num
1061
@@:
1057
@@:
1062
        popfd
1058
        popfd
1063
; wait for interrupt
1059
; wait for interrupt
1064
        mov     eax, [hd_address_table]
1060
        mov     eax, [hd_address_table]
1065
        cmp     [hdbase], eax ; 0x1F0
1061
        cmp     [hdbase], eax ; 0x1F0
1066
        jnz     .wait_ide1
1062
        jnz     .wait_ide1
1067
        call    wait_for_sector_dma_ide0
1063
        call    wait_for_sector_dma_ide0
1068
        jmp     @f
1064
        jmp     @f
1069
.wait_ide1:
1065
.wait_ide1:
1070
        call    wait_for_sector_dma_ide1
1066
        call    wait_for_sector_dma_ide1
1071
@@:
1067
@@:
1072
        cmp     [hd_error], 0
1068
        cmp     [hd_error], 0
1073
        jnz     hd_read_error
1069
        jnz     hd_read_error
1074
        mov     eax, [hdpos]
1070
        mov     eax, [hdpos]
1075
        mov     [dma_hdpos], eax
1071
        mov     [dma_hdpos], eax
1076
        pop     edx
1072
        pop     edx
1077
        pop     eax
1073
        pop     eax
1078
        mov     [dma_cur_sector], eax
1074
        mov     [dma_cur_sector], eax
1079
        jmp     hd_read_dma
1075
        jmp     hd_read_dma
1080
;-----------------------------------------------------------------------------
1076
;-----------------------------------------------------------------------------
1081
cache_write_dma:
1077
cache_write_dma:
1082
        mov     eax, [cache_chain_ptr] ; for what?
1078
        mov     eax, [cache_chain_ptr] ; for what?
1083
        push    esi
1079
        push    esi
1084
; set data for PRD Table
1080
; set data for PRD Table
1085
        mov     eax, IDE_descriptor_table
1081
        mov     eax, IDE_descriptor_table
1086
        mov     edx, eax
1082
        mov     edx, eax
1087
        pusha
1083
        pusha
1088
        mov     edi, (OS_BASE+IDE_DMA)
1084
        mov     edi, (OS_BASE+IDE_DMA)
1089
        mov     dword [edx], IDE_DMA
1085
        mov     dword [edx], IDE_DMA
1090
        movzx   ecx, [cache_chain_size]
1086
        movzx   ecx, [cache_chain_size]
1091
        shl     ecx, 9
1087
        shl     ecx, 9
1092
        mov     word [edx+4], cx
1088
        mov     word [edx+4], cx
1093
        shr     ecx, 2
1089
        shr     ecx, 2
1094
        cld
1090
        cld
1095
        rep movsd
1091
        rep movsd
1096
        popa
1092
        popa
1097
        sub     eax, OS_BASE
1093
        sub     eax, OS_BASE
1098
; select controller Primary or Secondary
1094
; select controller Primary or Secondary
1099
        mov     dx, [IDEContrRegsBaseAddr]
1095
        mov     dx, [IDEContrRegsBaseAddr]
1100
        push    eax
1096
        push    eax
1101
        mov     eax, [hd_address_table]
1097
        mov     eax, [hd_address_table]
1102
        cmp     [hdbase], eax ; 0x1F0
1098
        cmp     [hdbase], eax ; 0x1F0
1103
        pop     eax
1099
        pop     eax
1104
        jz      @f
1100
        jz      @f
1105
        add     edx, 8
1101
        add     edx, 8
1106
@@:
1102
@@:
1107
        push    edx
1103
        push    edx
1108
; Bus Master IDE PRD Table Address
1104
; Bus Master IDE PRD Table Address
1109
        add     edx, 4
1105
        add     edx, 4
1110
; save IDE_descriptor_table
1106
; save IDE_descriptor_table
1111
        out     dx, eax
1107
        out     dx, eax
1112
        pop     edx
1108
        pop     edx
1113
; clear Bus Master IDE Command register
1109
; clear Bus Master IDE Command register
1114
        mov     al, 0
1110
        mov     al, 0
1115
        out     dx, al
1111
        out     dx, al
1116
; clear Bus Master IDE Status register
1112
; clear Bus Master IDE Status register
1117
; clear Error bit and Interrupt bit
1113
; clear Error bit and Interrupt bit
1118
        add     edx, 2
1114
        add     edx, 2
1119
        mov     al, 6
1115
        mov     al, 6
1120
        out     dx, al
1116
        out     dx, al
1121
; Select the desired drive
1117
; Select the desired drive
1122
        mov     edx, [hdbase]
1118
        mov     edx, [hdbase]
1123
        add     edx, 6   ; адрес регистра головок
1119
        add     edx, 6   ; адрес регистра головок
1124
        mov     al, byte [hdid]
1120
        mov     al, byte [hdid]
1125
        add     al, 128+64+32
1121
        add     al, 128+64+32
1126
        out     dx, al ; номер головки/номер диска
1122
        out     dx, al ; номер головки/номер диска
1127
 
1123
 
1128
        call    wait_for_hd_idle
1124
        call    wait_for_hd_idle
1129
        cmp     [hd_error], 0
1125
        cmp     [hd_error], 0
1130
        jnz     hd_write_error_dma
1126
        jnz     hd_write_error_dma
1131
 
1127
 
1132
; ATA with 28 or 48 bit for sector number?
1128
; ATA with 28 or 48 bit for sector number?
1133
        mov     esi, [cache_chain_ptr]
1129
        mov     esi, [cache_chain_ptr]
1134
        mov     eax, [esi]
1130
        mov     eax, [esi]
1135
; -40h because the PreCache hits the boundary between lba28 and lba48
1131
; -40h because the PreCache hits the boundary between lba28 and lba48
1136
; 40h = 64  - the maximum number of sectors to be written for one command
1132
; 40h = 64  - the maximum number of sectors to be written for one command
1137
        cmp     eax, 0x10000000-40h
1133
        cmp     eax, 0x10000000-40h
1138
        jae     .lba48
1134
        jae     .lba48
1139
;--------------------------------------
1135
;--------------------------------------
1140
.lba28:
1136
.lba28:
1141
        pushfd
1137
        pushfd
1142
        cli
1138
        cli
1143
        xor     eax, eax
1139
        xor     eax, eax
1144
        mov     edx, [hdbase]
1140
        mov     edx, [hdbase]
1145
        inc     edx
1141
        inc     edx
1146
        out     dx, al ; ATA Features регистр "особенностей"
1142
        out     dx, al ; ATA Features регистр "особенностей"
1147
        inc     edx
1143
        inc     edx
1148
        mov     al, [cache_chain_size] ; Sector Counter
1144
        mov     al, [cache_chain_size] ; Sector Counter
1149
        out     dx, al ; ATA Sector Counter счётчик секторов
1145
        out     dx, al ; ATA Sector Counter счётчик секторов
1150
        inc     edx
1146
        inc     edx
1151
        mov     eax, [esi]
1147
        mov     eax, [esi]
1152
        out     dx, al ; LBA Low LBA (7:0)
1148
        out     dx, al ; LBA Low LBA (7:0)
1153
        shr     eax, 8
1149
        shr     eax, 8
1154
        inc     edx
1150
        inc     edx
1155
        out     dx, al ; LBA Mid LBA (15:8)
1151
        out     dx, al ; LBA Mid LBA (15:8)
1156
        shr     eax, 8
1152
        shr     eax, 8
1157
        inc     edx
1153
        inc     edx
1158
        out     dx, al ; LBA High LBA (23:16)
1154
        out     dx, al ; LBA High LBA (23:16)
1159
        shr     eax, 8
1155
        shr     eax, 8
1160
        inc     edx
1156
        inc     edx
1161
        and     al, 0xF ; LBA (27:24)
1157
        and     al, 0xF ; LBA (27:24)
1162
        add     al, byte [hdid]
1158
        add     al, byte [hdid]
1163
        add     al, 11100000b
1159
        add     al, 11100000b
1164
        out     dx, al ; номер головки/номер диска
1160
        out     dx, al ; номер головки/номер диска
1165
        inc     edx
1161
        inc     edx
1166
        mov     al, 0xCA ; WRITE DMA
1162
        mov     al, 0xCA ; WRITE DMA
1167
        out     dx, al ; ATACommand регистр команд
1163
        out     dx, al ; ATACommand регистр команд
1168
        jmp     .continue
1164
        jmp     .continue
1169
;--------------------------------------
1165
;--------------------------------------
1170
.lba48:
1166
.lba48:
1171
        pushfd
1167
        pushfd
1172
        cli
1168
        cli
1173
        xor     eax, eax
1169
        xor     eax, eax
1174
        mov     edx, [hdbase]
1170
        mov     edx, [hdbase]
1175
        inc     edx
1171
        inc     edx
1176
        out     dx, al ; Features Previous Reserved
1172
        out     dx, al ; Features Previous Reserved
1177
        out     dx, al ; Features Current Reserved
1173
        out     dx, al ; Features Current Reserved
1178
        inc     edx
1174
        inc     edx
1179
        out     dx, al ; Sector Count Previous Sector count (15:8)
1175
        out     dx, al ; Sector Count Previous Sector count (15:8)
1180
        mov     al, [cache_chain_size] ; Sector Counter
1176
        mov     al, [cache_chain_size] ; Sector Counter
1181
        out     dx, al ; Sector Count Current Sector count (7:0)
1177
        out     dx, al ; Sector Count Current Sector count (7:0)
1182
        inc     edx
1178
        inc     edx
1183
        mov     eax, [esi]
1179
        mov     eax, [esi]
1184
        rol     eax, 8
1180
        rol     eax, 8
1185
        out     dx, al ; LBA Low Previous LBA (31:24)
1181
        out     dx, al ; LBA Low Previous LBA (31:24)
1186
        xor     eax, eax ; because only 32 bit cache
1182
        xor     eax, eax ; because only 32 bit cache
1187
        inc     edx
1183
        inc     edx
1188
        out     dx, al ; LBA Mid Previous LBA (39:32)
1184
        out     dx, al ; LBA Mid Previous LBA (39:32)
1189
        inc     edx
1185
        inc     edx
1190
        out     dx, al ; LBA High Previous LBA (47:40)
1186
        out     dx, al ; LBA High Previous LBA (47:40)
1191
        sub     edx, 2
1187
        sub     edx, 2
1192
        mov     eax, [esi]
1188
        mov     eax, [esi]
1193
        out     dx, al ; LBA Low Current LBA (7:0)
1189
        out     dx, al ; LBA Low Current LBA (7:0)
1194
        shr     eax, 8
1190
        shr     eax, 8
1195
        inc     edx
1191
        inc     edx
1196
        out     dx, al ; LBA Mid Current LBA (15:8)
1192
        out     dx, al ; LBA Mid Current LBA (15:8)
1197
        shr     eax, 8
1193
        shr     eax, 8
1198
        inc     edx
1194
        inc     edx
1199
        out     dx, al ; LBA High Current LBA (23:16)
1195
        out     dx, al ; LBA High Current LBA (23:16)
1200
        inc     edx
1196
        inc     edx
1201
        mov     al, byte [hdid]
1197
        mov     al, byte [hdid]
1202
        add     al, 128+64+32
1198
        add     al, 128+64+32
1203
        out     dx, al ; номер головки/номер диска
1199
        out     dx, al ; номер головки/номер диска
1204
        inc     edx
1200
        inc     edx
1205
        mov     al, 35h ; WRITE DMA EXT
1201
        mov     al, 35h ; WRITE DMA EXT
1206
        out     dx, al ; ATACommand регистр команд
1202
        out     dx, al ; ATACommand регистр команд
1207
;--------------------------------------
1203
;--------------------------------------
1208
.continue:
1204
.continue:
1209
; select controller Primary or Secondary
1205
; select controller Primary or Secondary
1210
        mov     dx, [IDEContrRegsBaseAddr]
1206
        mov     dx, [IDEContrRegsBaseAddr]
1211
        mov     eax, [hd_address_table]
1207
        mov     eax, [hd_address_table]
1212
        cmp     [hdbase], eax ; 0x1F0
1208
        cmp     [hdbase], eax ; 0x1F0
1213
        jz      @f
1209
        jz      @f
1214
        add     dx, 8
1210
        add     dx, 8
1215
@@:
1211
@@:
1216
; set write to device and Start Bus Master
1212
; set write to device and Start Bus Master
1217
        mov     al, 1
1213
        mov     al, 1
1218
        out     dx, al
1214
        out     dx, al
1219
        mov     eax, [CURRENT_TASK]
1215
        mov     eax, [CURRENT_TASK]
1220
        mov     [dma_process], eax
1216
        mov     [dma_process], eax
1221
        mov     eax, [TASK_BASE]
1217
        mov     eax, [TASK_BASE]
1222
        mov     [dma_slot_ptr], eax
1218
        mov     [dma_slot_ptr], eax
1223
        mov     eax, [hd_address_table]
1219
        mov     eax, [hd_address_table]
1224
        cmp     [hdbase], eax ; 0x1F0
1220
        cmp     [hdbase], eax ; 0x1F0
1225
        jnz     .ide1
1221
        jnz     .ide1
1226
 
1222
 
1227
        mov     [IDE_common_irq_param], irq14_num
1223
        mov     [IDE_common_irq_param], irq14_num
1228
        jmp     @f
1224
        jmp     @f
1229
.ide1:
1225
.ide1:
1230
        mov     [IDE_common_irq_param], irq15_num
1226
        mov     [IDE_common_irq_param], irq15_num
1231
@@:
1227
@@:
1232
        popfd
1228
        popfd
1233
; wait for interrupt
1229
; wait for interrupt
1234
        mov     [dma_cur_sector], not 0x40
1230
        mov     [dma_cur_sector], not 0x40
1235
        mov     eax, [hd_address_table]
1231
        mov     eax, [hd_address_table]
1236
        cmp     [hdbase], eax ; 0x1F0
1232
        cmp     [hdbase], eax ; 0x1F0
1237
        jnz     .wait_ide1
1233
        jnz     .wait_ide1
1238
        call    wait_for_sector_dma_ide0
1234
        call    wait_for_sector_dma_ide0
1239
        jmp     @f
1235
        jmp     @f
1240
.wait_ide1:
1236
.wait_ide1:
1241
        call    wait_for_sector_dma_ide1
1237
        call    wait_for_sector_dma_ide1
1242
@@:
1238
@@:
1243
        cmp     [hd_error], 0
1239
        cmp     [hd_error], 0
1244
        jnz     hd_write_error_dma
1240
        jnz     hd_write_error_dma
1245
        pop     esi
1241
        pop     esi
1246
        ret
1242
        ret
1247
;-----------------------------------------------------------------------------
1243
;-----------------------------------------------------------------------------
1248
uglobal
1244
uglobal
1249
align 4
1245
align 4
1250
IDE_Interrupt   dw ?
1246
IDE_Interrupt   dw ?
1251
IDEContrRegsBaseAddr         dw ?
1247
IDEContrRegsBaseAddr         dw ?
1252
IDEContrProgrammingInterface dw ?
1248
IDEContrProgrammingInterface dw ?
1253
IDE_BAR0_val    dw ?
1249
IDE_BAR0_val    dw ?
1254
IDE_BAR1_val    dw ?
1250
IDE_BAR1_val    dw ?
1255
IDE_BAR2_val    dw ?
1251
IDE_BAR2_val    dw ?
1256
IDE_BAR3_val    dw ?
1252
IDE_BAR3_val    dw ?
1257
endg
1253
endg
1258
;-----------------------------------------------------------------------------
1254
;-----------------------------------------------------------------------------
1259
; \begin{diamond}
1255
; \begin{diamond}
1260
uglobal
1256
uglobal
1261
bios_hdpos      dd 0       ; 0 is invalid value for [hdpos]
1257
bios_hdpos      dd 0       ; 0 is invalid value for [hdpos]
1262
bios_cur_sector dd ?
1258
bios_cur_sector dd ?
1263
bios_read_len   dd ?
1259
bios_read_len   dd ?
1264
endg
1260
endg
1265
;-----------------------------------------------------------------------------
1261
;-----------------------------------------------------------------------------
1266
align 4
1262
align 4
1267
bd_read:
1263
bd_read:
1268
        push    eax
1264
        push    eax
1269
        push    edx
1265
        push    edx
1270
        mov     edx, [bios_hdpos]
1266
        mov     edx, [bios_hdpos]
1271
        cmp     edx, [hdpos]
1267
        cmp     edx, [hdpos]
1272
        jne     .notread
1268
        jne     .notread
1273
        mov     edx, [bios_cur_sector]
1269
        mov     edx, [bios_cur_sector]
1274
        cmp     eax, edx
1270
        cmp     eax, edx
1275
        jb      .notread
1271
        jb      .notread
1276
        add     edx, [bios_read_len]
1272
        add     edx, [bios_read_len]
1277
        dec     edx
1273
        dec     edx
1278
        cmp     eax, edx
1274
        cmp     eax, edx
1279
        ja      .notread
1275
        ja      .notread
1280
        sub     eax, [bios_cur_sector]
1276
        sub     eax, [bios_cur_sector]
1281
        shl     eax, 9
1277
        shl     eax, 9
1282
        add     eax, (OS_BASE+0x9A000)
1278
        add     eax, (OS_BASE+0x9A000)
1283
        push    ecx esi
1279
        push    ecx esi
1284
        mov     esi, eax
1280
        mov     esi, eax
1285
        mov     ecx, 512/4
1281
        mov     ecx, 512/4
1286
        cld
1282
        cld
1287
        rep movsd
1283
        rep movsd
1288
        pop     esi ecx
1284
        pop     esi ecx
1289
        pop     edx
1285
        pop     edx
1290
        pop     eax
1286
        pop     eax
1291
        ret
1287
        ret
1292
.notread:
1288
.notread:
1293
        push    ecx
1289
        push    ecx
1294
        mov     dl, 42h
1290
        mov     dl, 42h
1295
        mov     ecx, 16
1291
        mov     ecx, 16
1296
        call    int13_call
1292
        call    int13_call
1297
        pop     ecx
1293
        pop     ecx
1298
        test    eax, eax
1294
        test    eax, eax
1299
        jnz     .v86err
1295
        jnz     .v86err
1300
        test    edx, edx
1296
        test    edx, edx
1301
        jz      .readerr
1297
        jz      .readerr
1302
        mov     [bios_read_len], edx
1298
        mov     [bios_read_len], edx
1303
        mov     edx, [hdpos]
1299
        mov     edx, [hdpos]
1304
        mov     [bios_hdpos], edx
1300
        mov     [bios_hdpos], edx
1305
        pop     edx
1301
        pop     edx
1306
        pop     eax
1302
        pop     eax
1307
        mov     [bios_cur_sector], eax
1303
        mov     [bios_cur_sector], eax
1308
        jmp     bd_read
1304
        jmp     bd_read
1309
.readerr:
1305
.readerr:
1310
.v86err:
1306
.v86err:
1311
        mov     [hd_error], 1
1307
        mov     [hd_error], 1
1312
        jmp     hd_read_error
1308
        jmp     hd_read_error
1313
;-----------------------------------------------------------------------------
1309
;-----------------------------------------------------------------------------
1314
align 4
1310
align 4
1315
bd_write_cache_chain:
1311
bd_write_cache_chain:
1316
        pusha
1312
        pusha
1317
        mov     edi, OS_BASE + 0x9A000
1313
        mov     edi, OS_BASE + 0x9A000
1318
        movzx   ecx, [cache_chain_size]
1314
        movzx   ecx, [cache_chain_size]
1319
        push    ecx
1315
        push    ecx
1320
        shl     ecx, 9-2
1316
        shl     ecx, 9-2
1321
        rep movsd
1317
        rep movsd
1322
        pop     ecx
1318
        pop     ecx
1323
        mov     dl, 43h
1319
        mov     dl, 43h
1324
        mov     eax, [cache_chain_ptr]
1320
        mov     eax, [cache_chain_ptr]
1325
        mov     eax, [eax]
1321
        mov     eax, [eax]
1326
        call    int13_call
1322
        call    int13_call
1327
        test    eax, eax
1323
        test    eax, eax
1328
        jnz     .v86err
1324
        jnz     .v86err
1329
        cmp     edx, ecx
1325
        cmp     edx, ecx
1330
        jnz     .writeerr
1326
        jnz     .writeerr
1331
        popa
1327
        popa
1332
        ret
1328
        ret
1333
.v86err:
1329
.v86err:
1334
.writeerr:
1330
.writeerr:
1335
        popa
1331
        popa
1336
        mov     [hd_error], 1
1332
        mov     [hd_error], 1
1337
        jmp     hd_write_error
1333
        jmp     hd_write_error
1338
;-----------------------------------------------------------------------------
1334
;-----------------------------------------------------------------------------
1339
uglobal
1335
uglobal
1340
int13_regs_in   rb sizeof.v86_regs
1336
int13_regs_in   rb sizeof.v86_regs
1341
int13_regs_out  rb sizeof.v86_regs
1337
int13_regs_out  rb sizeof.v86_regs
1342
endg
1338
endg
1343
;-----------------------------------------------------------------------------
1339
;-----------------------------------------------------------------------------
1344
align 4
1340
align 4
1345
int13_call:
1341
int13_call:
1346
; Because this code uses fixed addresses,
1342
; Because this code uses fixed addresses,
1347
; it can not be run simultaniously by many threads.
1343
; it can not be run simultaniously by many threads.
1348
; In current implementation it is protected by common mutex 'ide_status'
1344
; In current implementation it is protected by common mutex 'ide_status'
1349
        mov     word [OS_BASE + 510h], 10h             ; packet length
1345
        mov     word [OS_BASE + 510h], 10h             ; packet length
1350
        mov     word [OS_BASE + 512h], cx              ; number of sectors
1346
        mov     word [OS_BASE + 512h], cx              ; number of sectors
1351
        mov     dword [OS_BASE + 514h], 9A000000h      ; buffer 9A00:0000
1347
        mov     dword [OS_BASE + 514h], 9A000000h      ; buffer 9A00:0000
1352
        mov     dword [OS_BASE + 518h], eax
1348
        mov     dword [OS_BASE + 518h], eax
1353
        and     dword [OS_BASE + 51Ch], 0
1349
        and     dword [OS_BASE + 51Ch], 0
1354
        push    ebx ecx esi edi
1350
        push    ebx ecx esi edi
1355
        mov     ebx, int13_regs_in
1351
        mov     ebx, int13_regs_in
1356
        mov     edi, ebx
1352
        mov     edi, ebx
1357
        mov     ecx, sizeof.v86_regs/4
1353
        mov     ecx, sizeof.v86_regs/4
1358
        xor     eax, eax
1354
        xor     eax, eax
1359
        rep stosd
1355
        rep stosd
1360
        mov     byte [ebx+v86_regs.eax+1], dl
1356
        mov     byte [ebx+v86_regs.eax+1], dl
1361
        mov     eax, [hdpos]
1357
        mov     eax, [hdpos]
1362
        lea     eax, [BiosDisksData+(eax-80h)*4]
1358
        lea     eax, [BiosDisksData+(eax-80h)*4]
1363
        mov     dl, [eax]
1359
        mov     dl, [eax]
1364
        mov     byte [ebx+v86_regs.edx], dl
1360
        mov     byte [ebx+v86_regs.edx], dl
1365
        movzx   edx, byte [eax+1]
1361
        movzx   edx, byte [eax+1]
1366
;        mov     dl, 5
1362
;        mov     dl, 5
1367
        test    edx, edx
1363
        test    edx, edx
1368
        jnz     .hasirq
1364
        jnz     .hasirq
1369
        dec     edx
1365
        dec     edx
1370
        jmp     @f
1366
        jmp     @f
1371
.hasirq:
1367
.hasirq:
1372
        pushad
1368
        pushad
1373
        stdcall enable_irq, edx
1369
        stdcall enable_irq, edx
1374
        popad
1370
        popad
1375
@@:
1371
@@:
1376
        mov     word [ebx+v86_regs.esi], 510h
1372
        mov     word [ebx+v86_regs.esi], 510h
1377
        mov     word [ebx+v86_regs.ss], 9000h
1373
        mov     word [ebx+v86_regs.ss], 9000h
1378
        mov     word [ebx+v86_regs.esp], 0A000h
1374
        mov     word [ebx+v86_regs.esp], 0A000h
1379
        mov     word [ebx+v86_regs.eip], 500h
1375
        mov     word [ebx+v86_regs.eip], 500h
1380
        mov     [ebx+v86_regs.eflags], 20200h
1376
        mov     [ebx+v86_regs.eflags], 20200h
1381
        mov     esi, [sys_v86_machine]
1377
        mov     esi, [sys_v86_machine]
1382
        mov     ecx, 0x502
1378
        mov     ecx, 0x502
1383
        push    fs
1379
        push    fs
1384
        call    v86_start
1380
        call    v86_start
1385
        pop     fs
1381
        pop     fs
1386
        and     [bios_hdpos], 0
1382
        and     [bios_hdpos], 0
1387
        pop     edi esi ecx ebx
1383
        pop     edi esi ecx ebx
1388
        movzx   edx, byte [OS_BASE + 512h]
1384
        movzx   edx, byte [OS_BASE + 512h]
1389
        test    byte [int13_regs_out+v86_regs.eflags], 1
1385
        test    byte [int13_regs_out+v86_regs.eflags], 1
1390
        jnz     @f
1386
        jnz     @f
1391
        mov     edx, ecx
1387
        mov     edx, ecx
1392
@@:
1388
@@:
1393
        ret
1389
        ret
1394
; \end{diamond}
1390
; \end{diamond}