Subversion Repositories Kolibri OS

Rev

Rev 3762 | Rev 3870 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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