Subversion Repositories Kolibri OS

Rev

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

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