Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
2288 clevermous 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 2288 $
9
 
10
 
11
; Low-level driver for HDD access
12
; DMA support by Mario79
13
; Access through BIOS by diamond
14
 
15
align 4
16
hd_read:
17
;-----------------------------------------------------------
18
; input  : eax = block to read
19
;          ebx = destination
20
;-----------------------------------------------------------
21
        and     [hd_error], 0
22
        push    ecx esi edi     ; scan cache
23
 
24
;    mov   ecx,cache_max         ; entries in cache
25
;    mov   esi,HD_CACHE+8
26
        call    calculate_cache
27
        add     esi, 8
28
 
29
        mov     edi, 1
30
 
31
  hdreadcache:
32
 
33
        cmp     dword [esi+4], 0; empty
34
        je      nohdcache
35
 
36
        cmp     [esi], eax      ; correct sector
37
        je      yeshdcache
38
 
39
  nohdcache:
40
 
41
        add     esi, 8
42
        inc     edi
43
        dec     ecx
44
        jnz     hdreadcache
45
 
46
        call    find_empty_slot ; ret in edi
47
        cmp     [hd_error], 0
48
        jne     return_01
49
; Read through BIOS?
50
        cmp     [hdpos], 0x80
51
        jae     .bios
52
; hd_read_{dma,pio} use old ATA with 28 bit for sector number
53
        cmp     eax, 0x10000000
54
        jb      @f
55
        inc     [hd_error]
56
        jmp     return_01
57
@@:
58
; DMA read is permitted if [allow_dma_access]=1 or 2
59
        cmp     [allow_dma_access], 2
60
        ja      .nodma
61
        cmp     [dma_hdd], 1
62
        jnz     .nodma
63
        call    hd_read_dma
64
        jmp     @f
65
.nodma:
66
        call    hd_read_pio
67
        jmp     @f
68
.bios:
69
        call    bd_read
70
@@:
71
        cmp     [hd_error], 0
72
        jne     return_01
73
;    lea   esi,[edi*8+HD_CACHE]
74
;    push  eax
75
        call    calculate_cache_1
76
        lea     esi, [edi*8+esi]
77
;    pop   eax
78
 
79
        mov     [esi], eax      ; sector number
80
        mov     dword [esi+4], 1; hd read - mark as same as in hd
81
 
82
  yeshdcache:
83
 
84
        mov     esi, edi
85
        shl     esi, 9
86
;    add   esi,HD_CACHE+65536
87
        push    eax
88
        call    calculate_cache_2
89
        add     esi, eax
90
        pop     eax
91
 
92
        mov     edi, ebx
93
        mov     ecx, 512/4
94
        cld
95
        rep movsd               ; move data
96
 return_01:
97
        pop     edi esi ecx
98
        ret
99
 
100
align 4
101
hd_read_pio:
102
        push    eax edx
103
 
104
        call    wait_for_hd_idle
105
        cmp     [hd_error], 0
106
        jne     hd_read_error
107
 
108
        cli
109
        xor     eax, eax
110
        mov     edx, [hdbase]
111
        inc     edx
112
        out     dx, al; ATAFeatures регистр "особенностей"
113
        inc     edx
114
        inc     eax
115
        out     dx, al; ATASectorCount счётчик секторов
116
        inc     edx
117
        mov     eax, [esp+4]
118
        out     dx, al; ATASectorNumber регистр номера сектора
119
        shr     eax, 8
120
        inc     edx
121
        out     dx, al; ATACylinder номер цилиндра (младший байт)
122
        shr     eax, 8
123
        inc     edx
124
        out     dx, al; номер цилиндра (старший байт)
125
        shr     eax, 8
126
        inc     edx
127
        and     al, 1+2+4+8
128
        add     al, byte [hdid]
129
        add     al, 128+64+32
130
        out     dx, al; номер головки/номер диска
131
        inc     edx
132
        mov     al, 20h
133
        out     dx, al; ATACommand регистр команд
134
        sti
135
 
136
        call    wait_for_sector_buffer
137
 
138
        cmp     [hd_error], 0
139
        jne     hd_read_error
140
 
141
        cli
142
        push    edi
143
        shl     edi, 9
144
;    add   edi,HD_CACHE+65536
145
        push    eax
146
        call    calculate_cache_2
147
        add     edi, eax
148
        pop     eax
149
 
150
        mov     ecx, 256
151
        mov     edx, [hdbase]
152
        cld
153
        rep insw
154
        pop     edi
155
        sti
156
 
157
        pop     edx eax
158
        ret
159
 
160
disable_ide_int:
161
;        mov edx,[hdbase]
162
;        add edx,0x206
163
;        mov al,2
164
;        out dx,al
165
        cli
166
        ret
167
 
168
enable_ide_int:
169
;        mov edx,[hdbase]
170
;        add edx,0x206
171
;        mov al,0
172
;        out dx,al
173
        sti
174
        ret
175
 
176
align 4
177
hd_write:
178
;-----------------------------------------------------------
179
; input  : eax = block
180
;          ebx = pointer to memory
181
;-----------------------------------------------------------
182
        push    ecx esi edi
183
 
184
    ; check if the cache already has the sector and overwrite it
185
 
186
;    mov   ecx,cache_max
187
;    mov   esi,HD_CACHE+8
188
        call    calculate_cache
189
        add     esi, 8
190
 
191
        mov     edi, 1
192
 
193
  hdwritecache:
194
 
195
        cmp     dword [esi+4], 0; if cache slot is empty
196
        je      not_in_cache_write
197
 
198
        cmp     [esi], eax      ; if the slot has the sector
199
        je      yes_in_cache_write
200
 
201
  not_in_cache_write:
202
 
203
        add     esi, 8
204
        inc     edi
205
        dec     ecx
206
        jnz     hdwritecache
207
 
208
    ; sector not found in cache
209
    ; write the block to a new location
210
 
211
        call    find_empty_slot ; ret in edi
212
        cmp     [hd_error], 0
213
        jne     hd_write_access_denied
214
 
215
;    lea   esi,[edi*8+HD_CACHE]
216
;    push  eax
217
        call    calculate_cache_1
218
        lea     esi, [edi*8+esi]
219
;    pop   eax
220
 
221
        mov     [esi], eax      ; sector number
222
 
223
  yes_in_cache_write:
224
 
225
        mov     dword [esi+4], 2; write - differs from hd
226
 
227
        shl     edi, 9
228
;    add   edi,HD_CACHE+65536
229
        push    eax
230
        call    calculate_cache_2
231
        add     edi, eax
232
        pop     eax
233
 
234
        mov     esi, ebx
235
        mov     ecx, 512/4
236
        cld
237
        rep movsd               ; move data
238
 hd_write_access_denied:
239
        pop     edi esi ecx
240
        ret
241
 
242
align 4
243
cache_write_pio:
244
        cmp     dword[esi], 0x10000000
245
        jae     .bad
246
;    call  disable_ide_int
247
 
248
        call    wait_for_hd_idle
249
        cmp     [hd_error], 0
250
        jne     hd_write_error
251
 
252
        cli
253
        xor     eax, eax
254
        mov     edx, [hdbase]
255
        inc     edx
256
        out     dx, al
257
        inc     edx
258
        inc     eax
259
        out     dx, al
260
        inc     edx
261
        mov     eax, [esi]      ; eax = sector to write
262
        out     dx, al
263
        shr     eax, 8
264
        inc     edx
265
        out     dx, al
266
        shr     eax, 8
267
        inc     edx
268
        out     dx, al
269
        shr     eax, 8
270
        inc     edx
271
        and     al, 1+2+4+8
272
        add     al, byte [hdid]
273
        add     al, 128+64+32
274
        out     dx, al
275
        inc     edx
276
        mov     al, 30h
277
        out     dx, al
278
        sti
279
 
280
        call    wait_for_sector_buffer
281
 
282
        cmp     [hd_error], 0
283
        jne     hd_write_error
284
 
285
        push    ecx esi
286
 
287
        cli
288
        mov     esi, edi
289
        shl     esi, 9
290
;    add   esi,HD_CACHE+65536    ; esi = from memory position
291
        push    eax
292
        call    calculate_cache_2
293
        add     esi, eax
294
        pop     eax
295
 
296
        mov     ecx, 256
297
        mov     edx, [hdbase]
298
        cld
299
        rep outsw
300
        sti
301
 
302
;    call  enable_ide_int
303
        pop     esi ecx
304
 
305
        ret
306
.bad:
307
        inc     [hd_error]
308
        ret
309
 
310
save_hd_wait_timeout:
311
 
312
        push    eax
313
        mov     eax, [timer_ticks]
314
        add     eax, 300        ; 3 sec timeout
315
        mov     [hd_wait_timeout], eax
316
        pop     eax
317
        ret
318
 
319
align 4
320
check_hd_wait_timeout:
321
 
322
        push    eax
323
        mov     eax, [hd_wait_timeout]
324
        cmp     [timer_ticks], eax
325
        jg      hd_timeout_error
326
        pop     eax
327
        mov     [hd_error], 0
328
        ret
329
 
330
;iglobal
331
;  hd_timeout_str   db 'K : FS - HD timeout',0
332
;  hd_read_str      db 'K : FS - HD read error',0
333
;  hd_write_str     db 'K : FS - HD write error',0
334
;  hd_lba_str       db 'K : FS - HD LBA error',0
335
;endg
336
 
337
hd_timeout_error:
338
 
339
;    call  clear_hd_cache
340
;    call  clear_application_table_status
341
;    mov   esi,hd_timeout_str
342
;    call  sys_msg_board_str
343
    DEBUGF 1,"K : FS - HD timeout\n"
344
 
345
        mov     [hd_error], 1
346
        pop     eax
347
        ret
348
 
349
hd_read_error:
350
 
351
;    call  clear_hd_cache
352
;    call  clear_application_table_status
353
;    mov   esi,hd_read_str
354
;    call  sys_msg_board_str
355
    DEBUGF 1,"K : FS - HD read error\n"
356
        pop     edx eax
357
        ret
358
 
359
hd_write_error:
360
 
361
;    call  clear_hd_cache
362
;    call  clear_application_table_status
363
;     mov   esi,hd_write_str
364
;     call  sys_msg_board_str
365
    DEBUGF 1,"K : FS - HD write error\n"
366
        ret
367
 
368
hd_write_error_dma:
369
;        call    clear_hd_cache
370
;        call    clear_application_table_status
371
;        mov     esi, hd_write_str
372
;        call    sys_msg_board_str
373
        DEBUGF 1,"K : FS - HD read error\n"
374
        pop     esi
375
        ret
376
 
377
hd_lba_error:
378
;    call  clear_hd_cache
379
;    call  clear_application_table_status
380
;    mov   esi,hd_lba_str
381
;    call  sys_msg_board_str
382
     DEBUGF 1,"K : FS - HD LBA error\n"
383
        jmp     LBA_read_ret
384
 
385
 
386
align 4
387
wait_for_hd_idle:
388
 
389
        push    eax edx
390
 
391
        call    save_hd_wait_timeout
392
 
393
        mov     edx, [hdbase]
394
        add     edx, 0x7
395
 
396
  wfhil1:
397
 
398
        call    check_hd_wait_timeout
399
        cmp     [hd_error], 0
400
        jne     @f
401
 
402
        in      al, dx
403
        test    al, 128
404
        jnz     wfhil1
405
 
406
 @@:
407
 
408
        pop     edx eax
409
        ret
410
 
411
 
412
align 4
413
wait_for_sector_buffer:
414
 
415
        push    eax edx
416
 
417
        mov     edx, [hdbase]
418
        add     edx, 0x7
419
 
420
        call    save_hd_wait_timeout
421
 
422
  hdwait_sbuf:                  ; wait for sector buffer to be ready
423
 
424
        call    check_hd_wait_timeout
425
        cmp     [hd_error], 0
426
        jne     @f
427
 
428
        in      al, dx
429
        test    al, 8
430
        jz      hdwait_sbuf
431
 
432
        mov     [hd_error], 0
433
 
434
        cmp     [hd_setup], 1   ; do not mark error for setup request
435
        je      buf_wait_ok
436
 
437
        test    al, 1           ; previous command ended up with an error
438
        jz      buf_wait_ok
439
 @@:
440
        mov     [hd_error], 1
441
 
442
  buf_wait_ok:
443
 
444
        pop     edx eax
445
        ret
446
 
447
; \begin{Mario79}
448
align 4
449
wait_for_sector_dma_ide0:
450
        push    eax
451
        push    edx
452
        call    save_hd_wait_timeout
453
.wait:
454
        call    change_task
455
        cmp     [irq14_func], hdd_irq14
456
        jnz     .done
457
        call    check_hd_wait_timeout
458
        cmp     [hd_error], 0
459
        jz      .wait
460
        mov     [irq14_func], hdd_irq_null
461
        mov     dx, [IDEContrRegsBaseAddr]
462
        mov     al, 0
463
        out     dx, al
464
.done:
465
        pop     edx
466
        pop     eax
467
        ret
468
 
469
align 4
470
wait_for_sector_dma_ide1:
471
        push    eax
472
        push    edx
473
        call    save_hd_wait_timeout
474
.wait:
475
        call    change_task
476
        cmp     [irq15_func], hdd_irq15
477
        jnz     .done
478
        call    check_hd_wait_timeout
479
        cmp     [hd_error], 0
480
        jz      .wait
481
        mov     [irq15_func], hdd_irq_null
482
        mov     dx, [IDEContrRegsBaseAddr]
483
        add     dx, 8
484
        mov     al, 0
485
        out     dx, al
486
.done:
487
        pop     edx
488
        pop     eax
489
        ret
490
 
491
iglobal
492
align 4
493
; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary
494
IDE_descriptor_table:
495
        dd      IDE_DMA
496
        dw      0x2000
497
        dw      0x8000
498
 
499
dma_cur_sector  dd      not 40h
500
dma_hdpos       dd      0
501
irq14_func      dd      hdd_irq_null
502
irq15_func      dd      hdd_irq_null
503
endg
504
 
505
uglobal
506
; all uglobals are zeroed at boot
507
dma_process     dd      0
508
dma_slot_ptr    dd      0
509
cache_chain_pos dd      0
510
cache_chain_ptr dd      0
511
cache_chain_size        db      0
512
cache_chain_started     db      0
513
dma_task_switched       db      0
514
dma_hdd         db      0
515
allow_dma_access db      0
516
endg
517
 
518
align 4
519
hdd_irq14:
520
        pushfd
521
        cli
522
        pushad
523
        mov     [irq14_func], hdd_irq_null
524
        mov     dx, [IDEContrRegsBaseAddr]
525
        mov     al, 0
526
        out     dx, al
527
;        call    update_counters
528
;        mov     ebx, [dma_process]
529
;        cmp     [CURRENT_TASK], ebx
530
;        jz      .noswitch
531
;        mov     [dma_task_switched], 1
532
;        mov     edi, [dma_slot_ptr]
533
;        mov     eax, [CURRENT_TASK]
534
;        mov     [dma_process], eax
535
;        mov     eax, [TASK_BASE]
536
;        mov     [dma_slot_ptr], eax
537
;        mov     [CURRENT_TASK], ebx
538
;        mov     [TASK_BASE], edi
539
;        mov     byte [DONT_SWITCH], 1
540
;        call    do_change_task
541
.noswitch:
542
        popad
543
        popfd
544
align 4
545
hdd_irq_null:
546
        ret
547
 
548
align 4
549
hdd_irq15:
550
        pushfd
551
        cli
552
        pushad
553
        mov     [irq15_func], hdd_irq_null
554
        mov     dx, [IDEContrRegsBaseAddr]
555
        add     dx, 8
556
        mov     al, 0
557
        out     dx, al
558
;        call    update_counters
559
;        mov     ebx, [dma_process]
560
;        cmp     [CURRENT_TASK], ebx
561
;        jz      .noswitch
562
;        mov     [dma_task_switched], 1
563
;        mov     edi, [dma_slot_ptr]
564
;        mov     eax, [CURRENT_TASK]
565
;        mov     [dma_process], eax
566
;        mov     eax, [TASK_BASE]
567
;        mov     [dma_slot_ptr], eax
568
;        mov     [CURRENT_TASK], ebx
569
;        mov     [TASK_BASE], edi
570
;        mov     byte [DONT_SWITCH], 1
571
;        call    do_change_task
572
.noswitch:
573
        popad
574
        popfd
575
        ret
576
 
577
align 4
578
hd_read_dma:
579
        push    eax
580
        push    edx
581
        mov     edx, [dma_hdpos]
582
        cmp     edx, [hdpos]
583
        jne     .notread
584
        mov     edx, [dma_cur_sector]
585
        cmp     eax, edx
586
        jb      .notread
587
        add     edx, 15
588
        cmp     [esp+4], edx
589
        ja      .notread
590
        mov     eax, [esp+4]
591
        sub     eax, [dma_cur_sector]
592
        shl     eax, 9
593
        add     eax, (OS_BASE+IDE_DMA)
594
        push    ecx esi edi
595
        mov     esi, eax
596
        shl     edi, 9
597
;        add     edi, HD_CACHE+0x10000
598
        push    eax
599
        call    calculate_cache_2
600
        add     edi, eax
601
        pop     eax
602
 
603
        mov     ecx, 512/4
604
        cld
605
        rep movsd
606
        pop     edi esi ecx
607
        pop     edx
608
        pop     eax
609
        ret
610
.notread:
611
        mov     eax, IDE_descriptor_table
612
        mov     dword [eax], IDE_DMA
613
        mov     word [eax+4], 0x2000
614
        sub     eax, OS_BASE
615
        mov     dx, [IDEContrRegsBaseAddr]
616
        cmp     [hdbase], 0x1F0
617
        jz      @f
618
        add     edx, 8
619
@@:
620
        push    edx
621
        add     edx, 4
622
        out     dx, eax
623
        pop     edx
624
        mov     al, 0
625
        out     dx, al
626
        add     edx, 2
627
        mov     al, 6
628
        out     dx, al
629
        call    wait_for_hd_idle
630
        cmp     [hd_error], 0
631
        jnz     hd_read_error
632
        call    disable_ide_int
633
        xor     eax, eax
634
        mov     edx, [hdbase]
635
        inc     edx
636
        out     dx, al
637
        inc     edx
638
        mov     eax, 10h
639
        out     dx, al
640
        inc     edx
641
        mov     eax, [esp+4]
642
        out     dx, al
643
        shr     eax, 8
644
        inc     edx
645
        out     dx, al
646
        shr     eax, 8
647
        inc     edx
648
        out     dx, al
649
        shr     eax, 8
650
        inc     edx
651
        and     al, 0xF
652
        add     al, byte [hdid]
653
        add     al, 11100000b
654
        out     dx, al
655
        inc     edx
656
        mov     al, 0xC8
657
        out     dx, al
658
        mov     dx, [IDEContrRegsBaseAddr]
659
        cmp     [hdbase], 0x1F0
660
        jz      @f
661
        add     dx, 8
662
@@:
663
        mov     al, 9
664
        out     dx, al
665
        mov     eax, [CURRENT_TASK]
666
        mov     [dma_process], eax
667
        mov     eax, [TASK_BASE]
668
        mov     [dma_slot_ptr], eax
669
        cmp     [hdbase], 0x1F0
670
        jnz     .ide1
671
        mov     [irq14_func], hdd_irq14
672
        jmp     @f
673
.ide1:
674
        mov     [irq15_func], hdd_irq15
675
@@:
676
        call    enable_ide_int
677
        cmp     [hdbase], 0x1F0
678
        jnz     .wait_ide1
679
        call    wait_for_sector_dma_ide0
680
        jmp     @f
681
.wait_ide1:
682
        call    wait_for_sector_dma_ide1
683
@@:
684
        cmp     [hd_error], 0
685
        jnz     hd_read_error
686
        mov     eax, [hdpos]
687
        mov     [dma_hdpos], eax
688
        pop     edx
689
        pop     eax
690
        mov     [dma_cur_sector], eax
691
        jmp     hd_read_dma
692
 
693
align 4
694
write_cache_sector:
695
        mov     [cache_chain_size], 1
696
        mov     [cache_chain_pos], edi
697
write_cache_chain:
698
        cmp     [hdpos], 0x80
699
        jae     bd_write_cache_chain
700
        mov     eax, [cache_chain_ptr]
701
        cmp     dword[eax], 0x10000000
702
        jae     .bad
703
        push    esi
704
        mov     eax, IDE_descriptor_table
705
        mov     edx, eax
706
        pusha
707
        mov     esi, [cache_chain_pos]
708
        shl     esi, 9
709
        call    calculate_cache_2
710
        add     esi, eax
711
        mov     edi, (OS_BASE+IDE_DMA)
712
        mov     dword [edx], IDE_DMA
713
        movzx   ecx, [cache_chain_size]
714
        shl     ecx, 9
715
        mov     word [edx+4], cx
716
        shr     ecx, 2
717
        cld
718
        rep movsd
719
        popa
720
        sub     eax, OS_BASE
721
        mov     dx, [IDEContrRegsBaseAddr]
722
        cmp     [hdbase], 0x1F0
723
        jz      @f
724
        add     edx, 8
725
@@:
726
        push    edx
727
        add     edx, 4
728
        out     dx, eax
729
        pop     edx
730
        mov     al, 0
731
        out     dx, al
732
        add     edx, 2
733
        mov     al, 6
734
        out     dx, al
735
        call    wait_for_hd_idle
736
        cmp     [hd_error], 0
737
        jnz     hd_write_error_dma
738
        call    disable_ide_int
739
        xor     eax, eax
740
        mov     edx, [hdbase]
741
        inc     edx
742
        out     dx, al
743
        inc     edx
744
        mov     al, [cache_chain_size]
745
        out     dx, al
746
        inc     edx
747
        mov     esi, [cache_chain_ptr]
748
        mov     eax, [esi]
749
        out     dx, al
750
        shr     eax, 8
751
        inc     edx
752
        out     dx, al
753
        shr     eax, 8
754
        inc     edx
755
        out     dx, al
756
        shr     eax, 8
757
        inc     edx
758
        and     al, 0xF
759
        add     al, byte [hdid]
760
        add     al, 11100000b
761
        out     dx, al
762
        inc     edx
763
        mov     al, 0xCA
764
        out     dx, al
765
        mov     dx, [IDEContrRegsBaseAddr]
766
        cmp     [hdbase], 0x1F0
767
        jz      @f
768
        add     dx, 8
769
@@:
770
        mov     al, 1
771
        out     dx, al
772
        mov     eax, [CURRENT_TASK]
773
        mov     [dma_process], eax
774
        mov     eax, [TASK_BASE]
775
        mov     [dma_slot_ptr], eax
776
        cmp     [hdbase], 0x1F0
777
        jnz     .ide1
778
        mov     [irq14_func], hdd_irq14
779
        jmp     @f
780
.ide1:
781
        mov     [irq15_func], hdd_irq15
782
@@:
783
        call    enable_ide_int
784
        mov     [dma_cur_sector], not 0x40
785
        cmp     [hdbase], 0x1F0
786
        jnz     .wait_ide1
787
        call    wait_for_sector_dma_ide0
788
        jmp     @f
789
.wait_ide1:
790
        call    wait_for_sector_dma_ide1
791
@@:
792
        cmp     [hd_error], 0
793
        jnz     hd_write_error_dma
794
        pop     esi
795
        ret
796
.bad:
797
        inc     [hd_error]
798
        ret
799
 
800
uglobal
801
IDEContrRegsBaseAddr    dw      ?
802
endg
803
; \end{Mario79}
804
 
805
; \begin{diamond}
806
uglobal
807
bios_hdpos      dd      0       ; 0 is invalid value for [hdpos]
808
bios_cur_sector dd      ?
809
bios_read_len   dd      ?
810
endg
811
bd_read:
812
        push    eax
813
        push    edx
814
        mov     edx, [bios_hdpos]
815
        cmp     edx, [hdpos]
816
        jne     .notread
817
        mov     edx, [bios_cur_sector]
818
        cmp     eax, edx
819
        jb      .notread
820
        add     edx, [bios_read_len]
821
        dec     edx
822
        cmp     eax, edx
823
        ja      .notread
824
        sub     eax, [bios_cur_sector]
825
        shl     eax, 9
826
        add     eax, (OS_BASE+0x9A000)
827
        push    ecx esi edi
828
        mov     esi, eax
829
        shl     edi, 9
830
;        add     edi, HD_CACHE+0x10000
831
        push    eax
832
        call    calculate_cache_2
833
        add     edi, eax
834
        pop     eax
835
 
836
        mov     ecx, 512/4
837
        cld
838
        rep movsd
839
        pop     edi esi ecx
840
        pop     edx
841
        pop     eax
842
        ret
843
.notread:
844
        push    ecx
845
        mov     dl, 42h
846
        mov     ecx, 16
847
        call    int13_call
848
        pop     ecx
849
        test    eax, eax
850
        jnz     .v86err
851
        test    edx, edx
852
        jz      .readerr
853
        mov     [bios_read_len], edx
854
        mov     edx, [hdpos]
855
        mov     [bios_hdpos], edx
856
        pop     edx
857
        pop     eax
858
        mov     [bios_cur_sector], eax
859
        jmp     bd_read
860
.readerr:
861
.v86err:
862
        mov     [hd_error], 1
863
        jmp     hd_read_error
864
 
865
bd_write_cache_chain:
866
        pusha
867
        mov     esi, [cache_chain_pos]
868
        shl     esi, 9
869
        call    calculate_cache_2
870
        add     esi, eax
871
        mov     edi, OS_BASE + 0x9A000
872
        movzx   ecx, [cache_chain_size]
873
        push    ecx
874
        shl     ecx, 9-2
875
        rep movsd
876
        pop     ecx
877
        mov     dl, 43h
878
        mov     eax, [cache_chain_ptr]
879
        mov     eax, [eax]
880
        call    int13_call
881
        test    eax, eax
882
        jnz     .v86err
883
        cmp     edx, ecx
884
        jnz     .writeerr
885
        popa
886
        ret
887
.v86err:
888
.writeerr:
889
        popa
890
        mov     [hd_error], 1
891
        jmp     hd_write_error
892
 
893
uglobal
894
int13_regs_in   rb      v86_regs.size
895
int13_regs_out  rb      v86_regs.size
896
endg
897
 
898
int13_call:
899
; Because this code uses fixed addresses,
900
; it can not be run simultaniously by many threads.
901
; In current implementation it is protected by common mutex 'hd1_status'
902
        mov     word [OS_BASE + 510h], 10h             ; packet length
903
        mov     word [OS_BASE + 512h], cx              ; number of sectors
904
        mov     dword [OS_BASE + 514h], 9A000000h      ; buffer 9A00:0000
905
        mov     dword [OS_BASE + 518h], eax
906
        and     dword [OS_BASE + 51Ch], 0
907
        push    ebx ecx esi edi
908
        mov     ebx, int13_regs_in
909
        mov     edi, ebx
910
        mov     ecx, v86_regs.size/4
911
        xor     eax, eax
912
        rep stosd
913
        mov     byte [ebx+v86_regs.eax+1], dl
914
        mov     eax, [hdpos]
915
        lea     eax, [BiosDisksData+(eax-80h)*4]
916
        mov     dl, [eax]
917
        mov     byte [ebx+v86_regs.edx], dl
918
        movzx   edx, byte [eax+1]
919
;        mov     dl, 5
920
        test    edx, edx
921
        jnz     .hasirq
922
        dec     edx
923
        jmp     @f
924
.hasirq:
925
        pushad
926
        stdcall enable_irq, edx
927
        popad
928
@@:
929
        mov     word [ebx+v86_regs.esi], 510h
930
        mov     word [ebx+v86_regs.ss], 9000h
931
        mov     word [ebx+v86_regs.esp], 0A000h
932
        mov     word [ebx+v86_regs.eip], 500h
933
        mov     [ebx+v86_regs.eflags], 20200h
934
        mov     esi, [sys_v86_machine]
935
        mov     ecx, 0x502
936
        push    fs
937
        call    v86_start
938
        pop     fs
939
        and     [bios_hdpos], 0
940
        pop     edi esi ecx ebx
941
        movzx   edx, byte [OS_BASE + 512h]
942
        test    byte [int13_regs_out+v86_regs.eflags], 1
943
        jnz     @f
944
        mov     edx, ecx
945
@@:
946
        ret
947
; \end{diamond}