Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2465 Serge 3
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
431 serge 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
593 mikedld 8
$Revision: 2987 $
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
160 diamond 22
    push  ecx esi edi           ; scan cache
23
 
580 mario79 24
;    mov   ecx,cache_max         ; entries in cache
25
;    mov   esi,HD_CACHE+8
26
    call  calculate_cache
2434 Serge 27
        add     esi, 8
581 serge 28
 
2434 Serge 29
        mov     edi, 1
160 diamond 30
 
31
  hdreadcache:
32
 
2434 Serge 33
        cmp     dword [esi+4], 0; empty
160 diamond 34
    je    nohdcache
35
 
2434 Serge 36
        cmp     [esi], eax      ; correct sector
160 diamond 37
    je    yeshdcache
38
 
39
  nohdcache:
40
 
2434 Serge 41
        add     esi, 8
160 diamond 42
    inc   edi
43
    dec   ecx
44
    jnz   hdreadcache
45
 
46
    call  find_empty_slot       ; ret in edi
2434 Serge 47
        cmp     [hd_error], 0
160 diamond 48
    jne   return_01
709 diamond 49
; Read through BIOS?
50
        cmp     [hdpos], 0x80
51
        jae     .bios
2010 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
75
    call  calculate_cache_1
2434 Serge 76
        lea     esi, [edi*8+esi]
580 mario79 77
;    pop   eax
160 diamond 78
 
2434 Serge 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
 
2434 Serge 84
        mov     esi, edi
85
        shl     esi, 9
580 mario79 86
;    add   esi,HD_CACHE+65536
87
    push  eax
88
    call  calculate_cache_2
2434 Serge 89
        add     esi, eax
580 mario79 90
    pop   eax
581 serge 91
 
2434 Serge 92
        mov     edi, ebx
93
        mov     ecx, 512/4
160 diamond 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
2434 Serge 105
        cmp     [hd_error], 0
389 serge 106
    jne   hd_read_error
160 diamond 107
 
321 diamond 108
    cli
2434 Serge 109
        xor     eax, eax
110
        mov     edx, [hdbase]
160 diamond 111
    inc   edx
2434 Serge 112
        out     dx, al; ATAFeatures регистр "особенностей"
160 diamond 113
    inc   edx
114
    inc   eax
2434 Serge 115
        out     dx, al; ATASectorCount счётчик секторов
160 diamond 116
    inc   edx
2434 Serge 117
        mov     eax, [esp+4]
118
        out     dx, al; ATASectorNumber регистр номера сектора
119
        shr     eax, 8
160 diamond 120
    inc   edx
2434 Serge 121
        out     dx, al; ATACylinder номер цилиндра (младший байт)
122
        shr     eax, 8
160 diamond 123
    inc   edx
2434 Serge 124
        out     dx, al; номер цилиндра (старший байт)
125
        shr     eax, 8
160 diamond 126
    inc   edx
2434 Serge 127
        and     al, 1+2+4+8
128
        add     al, byte [hdid]
129
        add     al, 128+64+32
130
        out     dx, al; номер головки/номер диска
160 diamond 131
    inc   edx
2434 Serge 132
        mov     al, 20h
133
        out     dx, al; ATACommand регистр команд
321 diamond 134
    sti
160 diamond 135
 
136
    call  wait_for_sector_buffer
137
 
2434 Serge 138
        cmp     [hd_error], 0
160 diamond 139
    jne   hd_read_error
140
 
321 diamond 141
    cli
160 diamond 142
    push  edi
2434 Serge 143
        shl     edi, 9
580 mario79 144
;    add   edi,HD_CACHE+65536
145
    push  eax
146
    call  calculate_cache_2
2434 Serge 147
        add     edi, eax
580 mario79 148
    pop   eax
581 serge 149
 
2434 Serge 150
        mov     ecx, 256
151
        mov     edx, [hdbase]
160 diamond 152
    cld
153
    rep   insw
154
    pop   edi
321 diamond 155
    sti
160 diamond 156
 
157
    pop   edx eax
158
    ret
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
;-----------------------------------------------------------
182
    push  ecx esi edi
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
188
    call  calculate_cache
2434 Serge 189
        add     esi, 8
581 serge 190
 
2434 Serge 191
        mov     edi, 1
160 diamond 192
 
193
  hdwritecache:
194
 
2434 Serge 195
        cmp     dword [esi+4], 0; if cache slot is empty
160 diamond 196
    je    not_in_cache_write
197
 
2434 Serge 198
        cmp     [esi], eax      ; if the slot has the sector
160 diamond 199
    je    yes_in_cache_write
200
 
201
  not_in_cache_write:
202
 
2434 Serge 203
        add     esi, 8
160 diamond 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
2434 Serge 212
        cmp     [hd_error], 0
160 diamond 213
    jne   hd_write_access_denied
214
 
580 mario79 215
;    lea   esi,[edi*8+HD_CACHE]
216
;    push  eax
217
    call  calculate_cache_1
2434 Serge 218
        lea     esi, [edi*8+esi]
580 mario79 219
;    pop   eax
220
 
2434 Serge 221
        mov     [esi], eax      ; sector number
160 diamond 222
 
223
  yes_in_cache_write:
224
 
2434 Serge 225
        mov     dword [esi+4], 2; write - differs from hd
160 diamond 226
 
2434 Serge 227
        shl     edi, 9
580 mario79 228
;    add   edi,HD_CACHE+65536
229
    push  eax
230
    call  calculate_cache_2
2434 Serge 231
        add     edi, eax
580 mario79 232
    pop   eax
581 serge 233
 
2434 Serge 234
        mov     esi, ebx
235
        mov     ecx, 512/4
160 diamond 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:
2434 Serge 244
        cmp     dword[esi], 0x10000000
2010 serge 245
    jae   .bad
580 mario79 246
;    call  disable_ide_int
581 serge 247
 
160 diamond 248
    call  wait_for_hd_idle
2434 Serge 249
        cmp     [hd_error], 0
160 diamond 250
    jne   hd_write_error
251
 
580 mario79 252
    cli
2434 Serge 253
        xor     eax, eax
254
        mov     edx, [hdbase]
160 diamond 255
    inc   edx
2434 Serge 256
        out     dx, al
160 diamond 257
    inc   edx
258
    inc   eax
2434 Serge 259
        out     dx, al
160 diamond 260
    inc   edx
2434 Serge 261
        mov     eax, [esi]      ; eax = sector to write
262
        out     dx, al
263
        shr     eax, 8
160 diamond 264
    inc   edx
2434 Serge 265
        out     dx, al
266
        shr     eax, 8
160 diamond 267
    inc   edx
2434 Serge 268
        out     dx, al
269
        shr     eax, 8
160 diamond 270
    inc   edx
2434 Serge 271
        and     al, 1+2+4+8
272
        add     al, byte [hdid]
273
        add     al, 128+64+32
274
        out     dx, al
160 diamond 275
    inc   edx
2434 Serge 276
        mov     al, 30h
277
        out     dx, al
580 mario79 278
    sti
160 diamond 279
 
280
    call  wait_for_sector_buffer
281
 
2434 Serge 282
        cmp     [hd_error], 0
160 diamond 283
    jne   hd_write_error
284
 
285
    push  ecx esi
286
 
580 mario79 287
    cli
2434 Serge 288
        mov     esi, edi
289
        shl     esi, 9
580 mario79 290
;    add   esi,HD_CACHE+65536    ; esi = from memory position
291
    push  eax
292
    call  calculate_cache_2
2434 Serge 293
        add     esi, eax
580 mario79 294
    pop   eax
581 serge 295
 
2434 Serge 296
        mov     ecx, 256
297
        mov     edx, [hdbase]
160 diamond 298
    cld
299
    rep   outsw
580 mario79 300
    sti
160 diamond 301
 
580 mario79 302
;    call  enable_ide_int
160 diamond 303
    pop   esi ecx
304
 
305
    ret
2010 serge 306
.bad:
307
    inc   [hd_error]
308
    ret
160 diamond 309
 
310
save_hd_wait_timeout:
311
 
312
    push  eax
2434 Serge 313
        mov     eax, [timer_ticks]
314
        add     eax, 300        ; 3 sec timeout
315
        mov     [hd_wait_timeout], eax
160 diamond 316
    pop   eax
317
    ret
318
 
319
align 4
320
check_hd_wait_timeout:
321
 
322
    push  eax
2434 Serge 323
        mov     eax, [hd_wait_timeout]
465 serge 324
    cmp   [timer_ticks], eax
160 diamond 325
    jg    hd_timeout_error
326
    pop   eax
2434 Serge 327
        mov     [hd_error], 0
160 diamond 328
    ret
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
 
2434 Serge 345
        mov     [hd_error], 1
160 diamond 346
    pop   eax
347
    ret
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"
160 diamond 356
    pop   edx eax
161 diamond 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"
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"
383
     jmp   LBA_read_ret
160 diamond 384
 
385
 
386
align 4
387
wait_for_hd_idle:
388
 
389
    push  eax edx
390
 
391
    call  save_hd_wait_timeout
392
 
2434 Serge 393
        mov     edx, [hdbase]
394
        add     edx, 0x7
160 diamond 395
 
396
  wfhil1:
397
 
398
    call  check_hd_wait_timeout
2434 Serge 399
        cmp     [hd_error], 0
160 diamond 400
    jne   @f
401
 
2434 Serge 402
        in      al, dx
403
        test    al, 128
160 diamond 404
    jnz   wfhil1
389 serge 405
 
160 diamond 406
 @@:
407
 
408
    pop   edx eax
409
    ret
410
 
411
 
412
align 4
413
wait_for_sector_buffer:
414
 
415
    push  eax edx
416
 
2434 Serge 417
        mov     edx, [hdbase]
418
        add     edx, 0x7
160 diamond 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
2434 Serge 425
        cmp     [hd_error], 0
160 diamond 426
    jne   @f
427
 
2434 Serge 428
        in      al, dx
429
        test    al, 8
160 diamond 430
    jz    hdwait_sbuf
431
 
2434 Serge 432
        mov     [hd_error], 0
160 diamond 433
 
2434 Serge 434
        cmp     [hd_setup], 1   ; do not mark error for setup request
160 diamond 435
    je    buf_wait_ok
436
 
2434 Serge 437
        test    al, 1           ; previous command ended up with an error
160 diamond 438
    jz    buf_wait_ok
439
 @@:
2434 Serge 440
        mov     [hd_error], 1
160 diamond 441
 
442
  buf_wait_ok:
443
 
444
    pop   edx eax
445
    ret
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
2434 Serge 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
598
        push  eax
599
        call  calculate_cache_2
2434 Serge 600
        add     edi, eax
580 mario79 601
        pop   eax
581 serge 602
 
160 diamond 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:
465 serge 611
        mov     eax, IDE_descriptor_table
581 serge 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
2434 Serge 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:
2434 Serge 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
2434 Serge 700
        mov     eax, [cache_chain_ptr]
701
        cmp     dword[eax], 0x10000000
2010 serge 702
        jae     .bad
160 diamond 703
        push    esi
704
        mov     eax, IDE_descriptor_table
2434 Serge 705
        mov     edx, eax
580 mario79 706
        pusha
2434 Serge 707
        mov     esi, [cache_chain_pos]
580 mario79 708
        shl     esi, 9
709
        call    calculate_cache_2
2434 Serge 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
2434 Serge 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
2010 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
831
        push  eax
832
        call  calculate_cache_2
2434 Serge 833
        add     edi, eax
709 diamond 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
820 diamond 871
        mov     edi, OS_BASE + 0x9A000
709 diamond 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
2434 Serge 894
int13_regs_in   rb      sizeof.v86_regs
895
int13_regs_out  rb      sizeof.v86_regs
709 diamond 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'
1448 diamond 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
709 diamond 907
        push    ebx ecx esi edi
908
        mov     ebx, int13_regs_in
909
        mov     edi, ebx
2434 Serge 910
        mov     ecx, sizeof.v86_regs/4
709 diamond 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
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
2010 serge 936
        push fs
709 diamond 937
        call    v86_start
2010 serge 938
        pop  fs
709 diamond 939
        and     [bios_hdpos], 0
940
        pop     edi esi ecx ebx
1448 diamond 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}
2987 Serge 948
 
949
reserve_hd1:
950
 
951
        cli
952
        cmp     [hd1_status], 0
953
        je      reserve_ok1
954
 
955
        sti
956
        call    change_task
957
        jmp     reserve_hd1
958
 
959
  reserve_ok1:
960
 
961
        push    eax
962
        mov     eax, [CURRENT_TASK]
963
        shl     eax, 5
964
        mov     eax, [eax+CURRENT_TASK+TASKDATA.pid]
965
        mov     [hd1_status], eax
966
        pop     eax
967
        sti
968
        ret
969
;********************************************
970
 
971
uglobal
972
hd_in_cache db ?
973
endg
974
 
975
reserve_hd_channel:
976
; BIOS disk accesses are protected with common mutex hd1_status
977
; This must be modified when hd1_status will not be valid!
978
        cmp     [hdpos], 0x80
979
        jae     .ret
980
        cmp     [hdbase], 0x1F0
981
        jne     .IDE_Channel_2
982
.IDE_Channel_1:
983
        cli
984
        cmp     [IDE_Channel_1], 0
985
        je      .reserve_ok_1
986
        sti
987
        call    change_task
988
        jmp     .IDE_Channel_1
989
.IDE_Channel_2:
990
        cli
991
        cmp     [IDE_Channel_2], 0
992
        je      .reserve_ok_2
993
        sti
994
        call    change_task
995
        jmp     .IDE_Channel_2
996
.reserve_ok_1:
997
        mov     [IDE_Channel_1], 1
998
        push    eax
999
        mov     al, 1
1000
        jmp     @f
1001
.reserve_ok_2:
1002
        mov     [IDE_Channel_2], 1
1003
        push    eax
1004
        mov     al, 3
1005
@@:
1006
        cmp     [hdid], 1
1007
        sbb     al, -1
1008
        mov     [hd_in_cache], al
1009
        pop     eax
1010
        sti
1011
.ret:
1012
        ret
1013
 
1014
free_hd_channel:
1015
; see comment at reserve_hd_channel
1016
        cmp     [hdpos], 0x80
1017
        jae     .ret
1018
        cmp     [hdbase], 0x1F0
1019
        jne     .IDE_Channel_2
1020
.IDE_Channel_1:
1021
        mov     [IDE_Channel_1], 0
1022
.ret:
1023
        ret
1024
.IDE_Channel_2:
1025
        mov     [IDE_Channel_2], 0
1026
        ret
1027
;********************************************