Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
709 diamond 3
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
431 serge 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
593 mikedld 8
$Revision: 2385 $
9
 
10
 
472 serge 11
; Low-level driver for HDD access
346 diamond 12
; DMA support by Mario79
709 diamond 13
; Access through BIOS by diamond
160 diamond 14
 
15
align 4
16
hd_read:
17
;-----------------------------------------------------------
18
; input  : eax = block to read
19
;          ebx = destination
20
;-----------------------------------------------------------
256 diamond 21
        and     [hd_error], 0
2382 hidnplayr 22
        push    ecx esi edi     ; scan cache
160 diamond 23
 
580 mario79 24
;    mov   ecx,cache_max         ; entries in cache
25
;    mov   esi,HD_CACHE+8
2382 hidnplayr 26
        call    calculate_cache
27
        add     esi, 8
581 serge 28
 
2382 hidnplayr 29
        mov     edi, 1
160 diamond 30
 
31
  hdreadcache:
32
 
2382 hidnplayr 33
        cmp     dword [esi+4], 0; empty
34
        je      nohdcache
160 diamond 35
 
2382 hidnplayr 36
        cmp     [esi], eax      ; correct sector
37
        je      yeshdcache
160 diamond 38
 
39
  nohdcache:
40
 
2382 hidnplayr 41
        add     esi, 8
42
        inc     edi
43
        dec     ecx
44
        jnz     hdreadcache
160 diamond 45
 
2382 hidnplayr 46
        call    find_empty_slot ; ret in edi
47
        cmp     [hd_error], 0
48
        jne     return_01
709 diamond 49
; Read through BIOS?
50
        cmp     [hdpos], 0x80
51
        jae     .bios
2212 Serge 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
@@:
514 diamond 58
; DMA read is permitted if [allow_dma_access]=1 or 2
59
        cmp     [allow_dma_access], 2
60
        ja      .nodma
160 diamond 61
        cmp     [dma_hdd], 1
62
        jnz     .nodma
63
        call    hd_read_dma
64
        jmp     @f
65
.nodma:
66
        call    hd_read_pio
709 diamond 67
        jmp     @f
68
.bios:
69
        call    bd_read
160 diamond 70
@@:
725 diamond 71
        cmp     [hd_error], 0
72
        jne     return_01
580 mario79 73
;    lea   esi,[edi*8+HD_CACHE]
74
;    push  eax
2382 hidnplayr 75
        call    calculate_cache_1
76
        lea     esi, [edi*8+esi]
580 mario79 77
;    pop   eax
160 diamond 78
 
2382 hidnplayr 79
        mov     [esi], eax      ; sector number
80
        mov     dword [esi+4], 1; hd read - mark as same as in hd
160 diamond 81
 
82
  yeshdcache:
83
 
2382 hidnplayr 84
        mov     esi, edi
85
        shl     esi, 9
580 mario79 86
;    add   esi,HD_CACHE+65536
2382 hidnplayr 87
        push    eax
88
        call    calculate_cache_2
89
        add     esi, eax
90
        pop     eax
581 serge 91
 
2382 hidnplayr 92
        mov     edi, ebx
93
        mov     ecx, 512/4
94
        cld
95
        rep movsd               ; move data
160 diamond 96
 return_01:
2382 hidnplayr 97
        pop     edi esi ecx
98
        ret
160 diamond 99
 
100
align 4
101
hd_read_pio:
2382 hidnplayr 102
        push    eax edx
160 diamond 103
 
2382 hidnplayr 104
        call    wait_for_hd_idle
105
        cmp     [hd_error], 0
106
        jne     hd_read_error
160 diamond 107
 
2382 hidnplayr 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
160 diamond 135
 
2382 hidnplayr 136
        call    wait_for_sector_buffer
160 diamond 137
 
2382 hidnplayr 138
        cmp     [hd_error], 0
139
        jne     hd_read_error
160 diamond 140
 
2382 hidnplayr 141
        cli
142
        push    edi
143
        shl     edi, 9
580 mario79 144
;    add   edi,HD_CACHE+65536
2382 hidnplayr 145
        push    eax
146
        call    calculate_cache_2
147
        add     edi, eax
148
        pop     eax
581 serge 149
 
2382 hidnplayr 150
        mov     ecx, 256
151
        mov     edx, [hdbase]
152
        cld
153
        rep insw
154
        pop     edi
155
        sti
160 diamond 156
 
2382 hidnplayr 157
        pop     edx eax
158
        ret
160 diamond 159
 
389 serge 160
disable_ide_int:
162 diamond 161
;        mov edx,[hdbase]
162
;        add edx,0x206
163
;        mov al,2
164
;        out dx,al
165
        cli
160 diamond 166
        ret
167
 
168
enable_ide_int:
162 diamond 169
;        mov edx,[hdbase]
170
;        add edx,0x206
171
;        mov al,0
172
;        out dx,al
173
        sti
160 diamond 174
        ret
175
 
176
align 4
177
hd_write:
178
;-----------------------------------------------------------
179
; input  : eax = block
180
;          ebx = pointer to memory
181
;-----------------------------------------------------------
2382 hidnplayr 182
        push    ecx esi edi
160 diamond 183
 
184
    ; check if the cache already has the sector and overwrite it
185
 
580 mario79 186
;    mov   ecx,cache_max
187
;    mov   esi,HD_CACHE+8
2382 hidnplayr 188
        call    calculate_cache
189
        add     esi, 8
581 serge 190
 
2382 hidnplayr 191
        mov     edi, 1
160 diamond 192
 
193
  hdwritecache:
194
 
2382 hidnplayr 195
        cmp     dword [esi+4], 0; if cache slot is empty
196
        je      not_in_cache_write
160 diamond 197
 
2382 hidnplayr 198
        cmp     [esi], eax      ; if the slot has the sector
199
        je      yes_in_cache_write
160 diamond 200
 
201
  not_in_cache_write:
202
 
2382 hidnplayr 203
        add     esi, 8
204
        inc     edi
205
        dec     ecx
206
        jnz     hdwritecache
160 diamond 207
 
208
    ; sector not found in cache
209
    ; write the block to a new location
210
 
2382 hidnplayr 211
        call    find_empty_slot ; ret in edi
212
        cmp     [hd_error], 0
213
        jne     hd_write_access_denied
160 diamond 214
 
580 mario79 215
;    lea   esi,[edi*8+HD_CACHE]
216
;    push  eax
2382 hidnplayr 217
        call    calculate_cache_1
218
        lea     esi, [edi*8+esi]
580 mario79 219
;    pop   eax
220
 
2382 hidnplayr 221
        mov     [esi], eax      ; sector number
160 diamond 222
 
223
  yes_in_cache_write:
224
 
2382 hidnplayr 225
        mov     dword [esi+4], 2; write - differs from hd
160 diamond 226
 
2382 hidnplayr 227
        shl     edi, 9
580 mario79 228
;    add   edi,HD_CACHE+65536
2382 hidnplayr 229
        push    eax
230
        call    calculate_cache_2
231
        add     edi, eax
232
        pop     eax
581 serge 233
 
2382 hidnplayr 234
        mov     esi, ebx
235
        mov     ecx, 512/4
236
        cld
237
        rep movsd               ; move data
160 diamond 238
 hd_write_access_denied:
2382 hidnplayr 239
        pop     edi esi ecx
240
        ret
160 diamond 241
 
242
align 4
243
cache_write_pio:
2382 hidnplayr 244
        cmp     dword[esi], 0x10000000
245
        jae     .bad
580 mario79 246
;    call  disable_ide_int
581 serge 247
 
2382 hidnplayr 248
        call    wait_for_hd_idle
249
        cmp     [hd_error], 0
250
        jne     hd_write_error
160 diamond 251
 
2382 hidnplayr 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
160 diamond 279
 
2382 hidnplayr 280
        call    wait_for_sector_buffer
160 diamond 281
 
2382 hidnplayr 282
        cmp     [hd_error], 0
283
        jne     hd_write_error
160 diamond 284
 
2382 hidnplayr 285
        push    ecx esi
160 diamond 286
 
2382 hidnplayr 287
        cli
288
        mov     esi, edi
289
        shl     esi, 9
580 mario79 290
;    add   esi,HD_CACHE+65536    ; esi = from memory position
2382 hidnplayr 291
        push    eax
292
        call    calculate_cache_2
293
        add     esi, eax
294
        pop     eax
581 serge 295
 
2382 hidnplayr 296
        mov     ecx, 256
297
        mov     edx, [hdbase]
298
        cld
299
        rep outsw
300
        sti
160 diamond 301
 
580 mario79 302
;    call  enable_ide_int
2382 hidnplayr 303
        pop     esi ecx
160 diamond 304
 
2382 hidnplayr 305
        ret
2212 Serge 306
.bad:
2382 hidnplayr 307
        inc     [hd_error]
308
        ret
160 diamond 309
 
310
save_hd_wait_timeout:
311
 
2382 hidnplayr 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
160 diamond 318
 
319
align 4
320
check_hd_wait_timeout:
321
 
2382 hidnplayr 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
160 diamond 329
 
358 mikedld 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
160 diamond 336
 
337
hd_timeout_error:
338
 
321 diamond 339
;    call  clear_hd_cache
340
;    call  clear_application_table_status
358 mikedld 341
;    mov   esi,hd_timeout_str
342
;    call  sys_msg_board_str
465 serge 343
    DEBUGF 1,"K : FS - HD timeout\n"
344
 
2382 hidnplayr 345
        mov     [hd_error], 1
346
        pop     eax
347
        ret
160 diamond 348
 
349
hd_read_error:
350
 
321 diamond 351
;    call  clear_hd_cache
352
;    call  clear_application_table_status
358 mikedld 353
;    mov   esi,hd_read_str
354
;    call  sys_msg_board_str
465 serge 355
    DEBUGF 1,"K : FS - HD read error\n"
2382 hidnplayr 356
        pop     edx eax
357
        ret
160 diamond 358
 
359
hd_write_error:
360
 
321 diamond 361
;    call  clear_hd_cache
362
;    call  clear_application_table_status
465 serge 363
;     mov   esi,hd_write_str
364
;     call  sys_msg_board_str
365
    DEBUGF 1,"K : FS - HD write error\n"
2382 hidnplayr 366
        ret
160 diamond 367
 
368
hd_write_error_dma:
321 diamond 369
;        call    clear_hd_cache
370
;        call    clear_application_table_status
358 mikedld 371
;        mov     esi, hd_write_str
372
;        call    sys_msg_board_str
465 serge 373
        DEBUGF 1,"K : FS - HD read error\n"
160 diamond 374
        pop     esi
161 diamond 375
        ret
160 diamond 376
 
377
hd_lba_error:
321 diamond 378
;    call  clear_hd_cache
379
;    call  clear_application_table_status
358 mikedld 380
;    mov   esi,hd_lba_str
381
;    call  sys_msg_board_str
465 serge 382
     DEBUGF 1,"K : FS - HD LBA error\n"
2382 hidnplayr 383
        jmp     LBA_read_ret
160 diamond 384
 
385
 
386
align 4
387
wait_for_hd_idle:
388
 
2382 hidnplayr 389
        push    eax edx
160 diamond 390
 
2382 hidnplayr 391
        call    save_hd_wait_timeout
160 diamond 392
 
2382 hidnplayr 393
        mov     edx, [hdbase]
394
        add     edx, 0x7
160 diamond 395
 
396
  wfhil1:
397
 
2382 hidnplayr 398
        call    check_hd_wait_timeout
399
        cmp     [hd_error], 0
400
        jne     @f
160 diamond 401
 
2382 hidnplayr 402
        in      al, dx
403
        test    al, 128
404
        jnz     wfhil1
389 serge 405
 
160 diamond 406
 @@:
407
 
2382 hidnplayr 408
        pop     edx eax
409
        ret
160 diamond 410
 
411
 
412
align 4
413
wait_for_sector_buffer:
414
 
2382 hidnplayr 415
        push    eax edx
160 diamond 416
 
2382 hidnplayr 417
        mov     edx, [hdbase]
418
        add     edx, 0x7
160 diamond 419
 
2382 hidnplayr 420
        call    save_hd_wait_timeout
160 diamond 421
 
422
  hdwait_sbuf:                  ; wait for sector buffer to be ready
423
 
2382 hidnplayr 424
        call    check_hd_wait_timeout
425
        cmp     [hd_error], 0
426
        jne     @f
160 diamond 427
 
2382 hidnplayr 428
        in      al, dx
429
        test    al, 8
430
        jz      hdwait_sbuf
160 diamond 431
 
2382 hidnplayr 432
        mov     [hd_error], 0
160 diamond 433
 
2382 hidnplayr 434
        cmp     [hd_setup], 1   ; do not mark error for setup request
435
        je      buf_wait_ok
160 diamond 436
 
2382 hidnplayr 437
        test    al, 1           ; previous command ended up with an error
438
        jz      buf_wait_ok
160 diamond 439
 @@:
2382 hidnplayr 440
        mov     [hd_error], 1
160 diamond 441
 
442
  buf_wait_ok:
443
 
2382 hidnplayr 444
        pop     edx eax
445
        ret
160 diamond 446
 
346 diamond 447
; \begin{Mario79}
160 diamond 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:
581 serge 495
        dd      IDE_DMA
465 serge 496
        dw      0x2000
497
        dw      0x8000
160 diamond 498
 
499
dma_cur_sector  dd      not 40h
597 mario79 500
dma_hdpos       dd      0
160 diamond 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
514 diamond 515
allow_dma_access db      0
160 diamond 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
465 serge 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
160 diamond 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
465 serge 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
160 diamond 572
.noswitch:
573
        popad
574
        popfd
575
        ret
576
 
577
align 4
578
hd_read_dma:
579
        push    eax
580
        push    edx
2382 hidnplayr 581
        mov     edx, [dma_hdpos]
582
        cmp     edx, [hdpos]
597 mario79 583
        jne     .notread
160 diamond 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
581 serge 593
        add     eax, (OS_BASE+IDE_DMA)
160 diamond 594
        push    ecx esi edi
595
        mov     esi, eax
596
        shl     edi, 9
580 mario79 597
;        add     edi, HD_CACHE+0x10000
2382 hidnplayr 598
        push    eax
599
        call    calculate_cache_2
600
        add     edi, eax
601
        pop     eax
581 serge 602
 
160 diamond 603
        mov     ecx, 512/4
604
        cld
2382 hidnplayr 605
        rep movsd
160 diamond 606
        pop     edi esi ecx
607
        pop     edx
608
        pop     eax
609
        ret
610
.notread:
465 serge 611
        mov     eax, IDE_descriptor_table
2382 hidnplayr 612
        mov     dword [eax], IDE_DMA
465 serge 613
        mov     word [eax+4], 0x2000
614
        sub     eax, OS_BASE
160 diamond 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
389 serge 665
        mov     eax, [CURRENT_TASK]
160 diamond 666
        mov     [dma_process], eax
389 serge 667
        mov     eax, [TASK_BASE]
160 diamond 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
2382 hidnplayr 686
        mov     eax, [hdpos]
687
        mov     [dma_hdpos], eax
160 diamond 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:
2382 hidnplayr 695
        mov     [cache_chain_size], 1
696
        mov     [cache_chain_pos], edi
581 serge 697
write_cache_chain:
709 diamond 698
        cmp     [hdpos], 0x80
699
        jae     bd_write_cache_chain
2382 hidnplayr 700
        mov     eax, [cache_chain_ptr]
701
        cmp     dword[eax], 0x10000000
2212 Serge 702
        jae     .bad
160 diamond 703
        push    esi
704
        mov     eax, IDE_descriptor_table
2382 hidnplayr 705
        mov     edx, eax
580 mario79 706
        pusha
2382 hidnplayr 707
        mov     esi, [cache_chain_pos]
580 mario79 708
        shl     esi, 9
709
        call    calculate_cache_2
2382 hidnplayr 710
        add     esi, eax
581 serge 711
        mov     edi, (OS_BASE+IDE_DMA)
712
        mov     dword [edx], IDE_DMA
580 mario79 713
        movzx   ecx, [cache_chain_size]
714
        shl     ecx, 9
715
        mov     word [edx+4], cx
2382 hidnplayr 716
        shr     ecx, 2
580 mario79 717
        cld
718
        rep movsd
719
        popa
465 serge 720
        sub     eax, OS_BASE
160 diamond 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
389 serge 772
        mov     eax, [CURRENT_TASK]
160 diamond 773
        mov     [dma_process], eax
389 serge 774
        mov     eax, [TASK_BASE]
160 diamond 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
2212 Serge 796
.bad:
797
        inc     [hd_error]
798
        ret
160 diamond 799
 
800
uglobal
801
IDEContrRegsBaseAddr    dw      ?
802
endg
346 diamond 803
; \end{Mario79}
709 diamond 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
820 diamond 826
        add     eax, (OS_BASE+0x9A000)
709 diamond 827
        push    ecx esi edi
828
        mov     esi, eax
829
        shl     edi, 9
830
;        add     edi, HD_CACHE+0x10000
2382 hidnplayr 831
        push    eax
832
        call    calculate_cache_2
833
        add     edi, eax
834
        pop     eax
709 diamond 835
 
836
        mov     ecx, 512/4
837
        cld
2382 hidnplayr 838
        rep movsd
709 diamond 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
820 diamond 871
        mov     edi, OS_BASE + 0x9A000
709 diamond 872
        movzx   ecx, [cache_chain_size]
873
        push    ecx
874
        shl     ecx, 9-2
2382 hidnplayr 875
        rep movsd
709 diamond 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
2385 hidnplayr 891
        jmp     hd_write_error
892
 
893
uglobal
894
int13_regs_in   rb      sizeof.v86_regs
895
int13_regs_out  rb      sizeof.v86_regs
896
endg
897
 
898
int13_call:
709 diamond 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'
2212 Serge 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
2385 hidnplayr 907
        push    ebx ecx esi edi
908
        mov     ebx, int13_regs_in
909
        mov     edi, ebx
910
        mov     ecx, sizeof.v86_regs/4
911
        xor     eax, eax
912
        rep stosd
913
        mov     byte [ebx+v86_regs.eax+1], dl
709 diamond 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
770 diamond 930
        mov     word [ebx+v86_regs.ss], 9000h
820 diamond 931
        mov     word [ebx+v86_regs.esp], 0A000h
709 diamond 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
2382 hidnplayr 936
        push    fs
709 diamond 937
        call    v86_start
2382 hidnplayr 938
        pop     fs
709 diamond 939
        and     [bios_hdpos], 0
940
        pop     edi esi ecx ebx
2212 Serge 941
        movzx   edx, byte [OS_BASE + 512h]
709 diamond 942
        test    byte [int13_regs_out+v86_regs.eflags], 1
943
        jnz     @f
944
        mov     edx, ecx
945
@@:
946
        ret
947
; \end{diamond}