Subversion Repositories Kolibri OS

Rev

Rev 2987 | Rev 3555 | 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: 3500 $
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
3500 Serge 343
    if lang eq sp
344
    DEBUGF 1,"K : FS - HD tiempo de espera agotado\n"
345
    else
465 serge 346
    DEBUGF 1,"K : FS - HD timeout\n"
3500 Serge 347
    end if
465 serge 348
 
2434 Serge 349
        mov     [hd_error], 1
160 diamond 350
    pop   eax
351
    ret
352
 
353
hd_read_error:
354
 
321 diamond 355
;    call  clear_hd_cache
356
;    call  clear_application_table_status
358 mikedld 357
;    mov   esi,hd_read_str
358
;    call  sys_msg_board_str
3500 Serge 359
    if lang eq sp
360
    DEBUGF 1,"K : FS - HD error de lectura\n"
361
    else
465 serge 362
    DEBUGF 1,"K : FS - HD read error\n"
3500 Serge 363
    end if
160 diamond 364
    pop   edx eax
161 diamond 365
    ret
160 diamond 366
 
367
hd_write_error:
368
 
321 diamond 369
;    call  clear_hd_cache
370
;    call  clear_application_table_status
465 serge 371
;     mov   esi,hd_write_str
372
;     call  sys_msg_board_str
3500 Serge 373
    if lang eq sp
374
    DEBUGF 1,"K : FS - HD error de escritura\n"
375
    else
465 serge 376
    DEBUGF 1,"K : FS - HD write error\n"
3500 Serge 377
    end if
465 serge 378
     ret
160 diamond 379
 
380
hd_write_error_dma:
321 diamond 381
;        call    clear_hd_cache
382
;        call    clear_application_table_status
358 mikedld 383
;        mov     esi, hd_write_str
384
;        call    sys_msg_board_str
3500 Serge 385
        if lang eq sp
386
        DEBUGF 1,"K : FS - HD error de escritura\n"
387
        else
388
        DEBUGF 1,"K : FS - HD write error\n"
389
        end if
160 diamond 390
        pop     esi
161 diamond 391
        ret
160 diamond 392
 
393
hd_lba_error:
321 diamond 394
;    call  clear_hd_cache
395
;    call  clear_application_table_status
358 mikedld 396
;    mov   esi,hd_lba_str
397
;    call  sys_msg_board_str
3500 Serge 398
     if lang eq sp
399
     DEBUGF 1,"K : FS - HD error en LBA\n"
400
     else
465 serge 401
     DEBUGF 1,"K : FS - HD LBA error\n"
3500 Serge 402
     end if
465 serge 403
     jmp   LBA_read_ret
160 diamond 404
 
405
 
406
align 4
407
wait_for_hd_idle:
408
 
409
    push  eax edx
410
 
411
    call  save_hd_wait_timeout
412
 
2434 Serge 413
        mov     edx, [hdbase]
414
        add     edx, 0x7
160 diamond 415
 
416
  wfhil1:
417
 
418
    call  check_hd_wait_timeout
2434 Serge 419
        cmp     [hd_error], 0
160 diamond 420
    jne   @f
421
 
2434 Serge 422
        in      al, dx
423
        test    al, 128
160 diamond 424
    jnz   wfhil1
389 serge 425
 
160 diamond 426
 @@:
427
 
428
    pop   edx eax
429
    ret
430
 
431
 
432
align 4
433
wait_for_sector_buffer:
434
 
435
    push  eax edx
436
 
2434 Serge 437
        mov     edx, [hdbase]
438
        add     edx, 0x7
160 diamond 439
 
440
    call  save_hd_wait_timeout
441
 
442
  hdwait_sbuf:                  ; wait for sector buffer to be ready
443
 
444
    call  check_hd_wait_timeout
2434 Serge 445
        cmp     [hd_error], 0
160 diamond 446
    jne   @f
447
 
2434 Serge 448
        in      al, dx
449
        test    al, 8
160 diamond 450
    jz    hdwait_sbuf
451
 
2434 Serge 452
        mov     [hd_error], 0
160 diamond 453
 
2434 Serge 454
        cmp     [hd_setup], 1   ; do not mark error for setup request
160 diamond 455
    je    buf_wait_ok
456
 
2434 Serge 457
        test    al, 1           ; previous command ended up with an error
160 diamond 458
    jz    buf_wait_ok
459
 @@:
2434 Serge 460
        mov     [hd_error], 1
160 diamond 461
 
462
  buf_wait_ok:
463
 
464
    pop   edx eax
465
    ret
466
 
346 diamond 467
; \begin{Mario79}
160 diamond 468
align 4
469
wait_for_sector_dma_ide0:
470
        push    eax
471
        push    edx
472
        call    save_hd_wait_timeout
473
.wait:
474
        call    change_task
475
        cmp     [irq14_func], hdd_irq14
476
        jnz     .done
477
        call    check_hd_wait_timeout
478
        cmp     [hd_error], 0
479
        jz      .wait
480
        mov     [irq14_func], hdd_irq_null
481
        mov     dx, [IDEContrRegsBaseAddr]
482
        mov     al, 0
483
        out     dx, al
484
.done:
485
        pop     edx
486
        pop     eax
487
        ret
488
 
489
align 4
490
wait_for_sector_dma_ide1:
491
        push    eax
492
        push    edx
493
        call    save_hd_wait_timeout
494
.wait:
495
        call    change_task
496
        cmp     [irq15_func], hdd_irq15
497
        jnz     .done
498
        call    check_hd_wait_timeout
499
        cmp     [hd_error], 0
500
        jz      .wait
501
        mov     [irq15_func], hdd_irq_null
502
        mov     dx, [IDEContrRegsBaseAddr]
503
        add     dx, 8
504
        mov     al, 0
505
        out     dx, al
506
.done:
507
        pop     edx
508
        pop     eax
509
        ret
510
 
511
iglobal
512
align 4
513
; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary
514
IDE_descriptor_table:
581 serge 515
        dd      IDE_DMA
465 serge 516
        dw      0x2000
517
        dw      0x8000
160 diamond 518
 
519
dma_cur_sector  dd      not 40h
597 mario79 520
dma_hdpos       dd      0
160 diamond 521
irq14_func      dd      hdd_irq_null
522
irq15_func      dd      hdd_irq_null
523
endg
524
 
525
uglobal
526
; all uglobals are zeroed at boot
527
dma_process     dd      0
528
dma_slot_ptr    dd      0
529
cache_chain_pos dd      0
530
cache_chain_ptr dd      0
531
cache_chain_size        db      0
532
cache_chain_started     db      0
533
dma_task_switched       db      0
534
dma_hdd         db      0
514 diamond 535
allow_dma_access db      0
160 diamond 536
endg
537
 
538
align 4
539
hdd_irq14:
540
        pushfd
541
        cli
542
        pushad
543
        mov     [irq14_func], hdd_irq_null
544
        mov     dx, [IDEContrRegsBaseAddr]
545
        mov     al, 0
546
        out     dx, al
465 serge 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
160 diamond 561
.noswitch:
562
        popad
563
        popfd
564
align 4
565
hdd_irq_null:
566
        ret
567
 
568
align 4
569
hdd_irq15:
570
        pushfd
571
        cli
572
        pushad
573
        mov     [irq15_func], hdd_irq_null
574
        mov     dx, [IDEContrRegsBaseAddr]
575
        add     dx, 8
576
        mov     al, 0
577
        out     dx, al
465 serge 578
;        call    update_counters
579
;        mov     ebx, [dma_process]
580
;        cmp     [CURRENT_TASK], ebx
581
;        jz      .noswitch
582
;        mov     [dma_task_switched], 1
583
;        mov     edi, [dma_slot_ptr]
584
;        mov     eax, [CURRENT_TASK]
585
;        mov     [dma_process], eax
586
;        mov     eax, [TASK_BASE]
587
;        mov     [dma_slot_ptr], eax
588
;        mov     [CURRENT_TASK], ebx
589
;        mov     [TASK_BASE], edi
590
;        mov     byte [DONT_SWITCH], 1
591
;        call    do_change_task
160 diamond 592
.noswitch:
593
        popad
594
        popfd
595
        ret
596
 
597
align 4
598
hd_read_dma:
599
        push    eax
600
        push    edx
2434 Serge 601
        mov     edx, [dma_hdpos]
602
        cmp     edx, [hdpos]
597 mario79 603
        jne     .notread
160 diamond 604
        mov     edx, [dma_cur_sector]
605
        cmp     eax, edx
606
        jb      .notread
607
        add     edx, 15
608
        cmp     [esp+4], edx
609
        ja      .notread
610
        mov     eax, [esp+4]
611
        sub     eax, [dma_cur_sector]
612
        shl     eax, 9
581 serge 613
        add     eax, (OS_BASE+IDE_DMA)
160 diamond 614
        push    ecx esi edi
615
        mov     esi, eax
616
        shl     edi, 9
580 mario79 617
;        add     edi, HD_CACHE+0x10000
618
        push  eax
619
        call  calculate_cache_2
2434 Serge 620
        add     edi, eax
580 mario79 621
        pop   eax
581 serge 622
 
160 diamond 623
        mov     ecx, 512/4
624
        cld
625
        rep     movsd
626
        pop     edi esi ecx
627
        pop     edx
628
        pop     eax
629
        ret
630
.notread:
465 serge 631
        mov     eax, IDE_descriptor_table
581 serge 632
        mov     dword [eax],  IDE_DMA
465 serge 633
        mov     word [eax+4], 0x2000
634
        sub     eax, OS_BASE
160 diamond 635
        mov     dx, [IDEContrRegsBaseAddr]
636
        cmp     [hdbase], 0x1F0
637
        jz      @f
638
        add     edx, 8
639
@@:
640
        push    edx
641
        add     edx, 4
642
        out     dx, eax
643
        pop     edx
644
        mov     al, 0
645
        out     dx, al
646
        add     edx, 2
647
        mov     al, 6
648
        out     dx, al
649
        call    wait_for_hd_idle
650
        cmp     [hd_error], 0
651
        jnz     hd_read_error
652
        call    disable_ide_int
653
        xor     eax, eax
654
        mov     edx, [hdbase]
655
        inc     edx
656
        out     dx, al
657
        inc     edx
658
        mov     eax, 10h
659
        out     dx, al
660
        inc     edx
661
        mov     eax, [esp+4]
662
        out     dx, al
663
        shr     eax, 8
664
        inc     edx
665
        out     dx, al
666
        shr     eax, 8
667
        inc     edx
668
        out     dx, al
669
        shr     eax, 8
670
        inc     edx
671
        and     al, 0xF
672
        add     al, byte [hdid]
673
        add     al, 11100000b
674
        out     dx, al
675
        inc     edx
676
        mov     al, 0xC8
677
        out     dx, al
678
        mov     dx, [IDEContrRegsBaseAddr]
679
        cmp     [hdbase], 0x1F0
680
        jz      @f
681
        add     dx, 8
682
@@:
683
        mov     al, 9
684
        out     dx, al
389 serge 685
        mov     eax, [CURRENT_TASK]
160 diamond 686
        mov     [dma_process], eax
389 serge 687
        mov     eax, [TASK_BASE]
160 diamond 688
        mov     [dma_slot_ptr], eax
689
        cmp     [hdbase], 0x1F0
690
        jnz     .ide1
691
        mov     [irq14_func], hdd_irq14
692
        jmp     @f
693
.ide1:
694
        mov     [irq15_func], hdd_irq15
695
@@:
696
        call    enable_ide_int
697
        cmp     [hdbase], 0x1F0
698
        jnz     .wait_ide1
699
        call    wait_for_sector_dma_ide0
700
        jmp     @f
701
.wait_ide1:
702
        call    wait_for_sector_dma_ide1
703
@@:
704
        cmp     [hd_error], 0
705
        jnz     hd_read_error
2434 Serge 706
        mov     eax, [hdpos]
707
        mov     [dma_hdpos], eax
160 diamond 708
        pop     edx
709
        pop     eax
710
        mov     [dma_cur_sector], eax
711
        jmp     hd_read_dma
712
 
713
align 4
714
write_cache_sector:
2434 Serge 715
        mov     [cache_chain_size], 1
716
        mov     [cache_chain_pos], edi
581 serge 717
write_cache_chain:
709 diamond 718
        cmp     [hdpos], 0x80
719
        jae     bd_write_cache_chain
2434 Serge 720
        mov     eax, [cache_chain_ptr]
721
        cmp     dword[eax], 0x10000000
2010 serge 722
        jae     .bad
160 diamond 723
        push    esi
724
        mov     eax, IDE_descriptor_table
2434 Serge 725
        mov     edx, eax
580 mario79 726
        pusha
2434 Serge 727
        mov     esi, [cache_chain_pos]
580 mario79 728
        shl     esi, 9
729
        call    calculate_cache_2
2434 Serge 730
        add     esi, eax
581 serge 731
        mov     edi, (OS_BASE+IDE_DMA)
732
        mov     dword [edx], IDE_DMA
580 mario79 733
        movzx   ecx, [cache_chain_size]
734
        shl     ecx, 9
735
        mov     word [edx+4], cx
2434 Serge 736
        shr     ecx, 2
580 mario79 737
        cld
738
        rep movsd
739
        popa
465 serge 740
        sub     eax, OS_BASE
160 diamond 741
        mov     dx, [IDEContrRegsBaseAddr]
742
        cmp     [hdbase], 0x1F0
743
        jz      @f
744
        add     edx, 8
745
@@:
746
        push    edx
747
        add     edx, 4
748
        out     dx, eax
749
        pop     edx
750
        mov     al, 0
751
        out     dx, al
752
        add     edx, 2
753
        mov     al, 6
754
        out     dx, al
755
        call    wait_for_hd_idle
756
        cmp     [hd_error], 0
757
        jnz     hd_write_error_dma
758
        call    disable_ide_int
759
        xor     eax, eax
760
        mov     edx, [hdbase]
761
        inc     edx
762
        out     dx, al
763
        inc     edx
764
        mov     al, [cache_chain_size]
765
        out     dx, al
766
        inc     edx
767
        mov     esi, [cache_chain_ptr]
768
        mov     eax, [esi]
769
        out     dx, al
770
        shr     eax, 8
771
        inc     edx
772
        out     dx, al
773
        shr     eax, 8
774
        inc     edx
775
        out     dx, al
776
        shr     eax, 8
777
        inc     edx
778
        and     al, 0xF
779
        add     al, byte [hdid]
780
        add     al, 11100000b
781
        out     dx, al
782
        inc     edx
783
        mov     al, 0xCA
784
        out     dx, al
785
        mov     dx, [IDEContrRegsBaseAddr]
786
        cmp     [hdbase], 0x1F0
787
        jz      @f
788
        add     dx, 8
789
@@:
790
        mov     al, 1
791
        out     dx, al
389 serge 792
        mov     eax, [CURRENT_TASK]
160 diamond 793
        mov     [dma_process], eax
389 serge 794
        mov     eax, [TASK_BASE]
160 diamond 795
        mov     [dma_slot_ptr], eax
796
        cmp     [hdbase], 0x1F0
797
        jnz     .ide1
798
        mov     [irq14_func], hdd_irq14
799
        jmp     @f
800
.ide1:
801
        mov     [irq15_func], hdd_irq15
802
@@:
803
        call    enable_ide_int
804
        mov     [dma_cur_sector], not 0x40
805
        cmp     [hdbase], 0x1F0
806
        jnz     .wait_ide1
807
        call    wait_for_sector_dma_ide0
808
        jmp     @f
809
.wait_ide1:
810
        call    wait_for_sector_dma_ide1
811
@@:
812
        cmp     [hd_error], 0
813
        jnz     hd_write_error_dma
814
        pop     esi
815
        ret
2010 serge 816
.bad:
817
        inc     [hd_error]
818
        ret
160 diamond 819
 
820
uglobal
821
IDEContrRegsBaseAddr    dw      ?
822
endg
346 diamond 823
; \end{Mario79}
709 diamond 824
 
825
; \begin{diamond}
826
uglobal
827
bios_hdpos      dd      0       ; 0 is invalid value for [hdpos]
828
bios_cur_sector dd      ?
829
bios_read_len   dd      ?
830
endg
831
bd_read:
832
        push    eax
833
        push    edx
834
        mov     edx, [bios_hdpos]
835
        cmp     edx, [hdpos]
836
        jne     .notread
837
        mov     edx, [bios_cur_sector]
838
        cmp     eax, edx
839
        jb      .notread
840
        add     edx, [bios_read_len]
841
        dec     edx
842
        cmp     eax, edx
843
        ja      .notread
844
        sub     eax, [bios_cur_sector]
845
        shl     eax, 9
820 diamond 846
        add     eax, (OS_BASE+0x9A000)
709 diamond 847
        push    ecx esi edi
848
        mov     esi, eax
849
        shl     edi, 9
850
;        add     edi, HD_CACHE+0x10000
851
        push  eax
852
        call  calculate_cache_2
2434 Serge 853
        add     edi, eax
709 diamond 854
        pop   eax
855
 
856
        mov     ecx, 512/4
857
        cld
858
        rep     movsd
859
        pop     edi esi ecx
860
        pop     edx
861
        pop     eax
862
        ret
863
.notread:
864
        push    ecx
865
        mov     dl, 42h
866
        mov     ecx, 16
867
        call    int13_call
868
        pop     ecx
869
        test    eax, eax
870
        jnz     .v86err
871
        test    edx, edx
872
        jz      .readerr
873
        mov     [bios_read_len], edx
874
        mov     edx, [hdpos]
875
        mov     [bios_hdpos], edx
876
        pop     edx
877
        pop     eax
878
        mov     [bios_cur_sector], eax
879
        jmp     bd_read
880
.readerr:
881
.v86err:
882
        mov     [hd_error], 1
883
        jmp     hd_read_error
884
 
885
bd_write_cache_chain:
886
        pusha
887
        mov     esi, [cache_chain_pos]
888
        shl     esi, 9
889
        call    calculate_cache_2
890
        add     esi, eax
820 diamond 891
        mov     edi, OS_BASE + 0x9A000
709 diamond 892
        movzx   ecx, [cache_chain_size]
893
        push    ecx
894
        shl     ecx, 9-2
895
        rep     movsd
896
        pop     ecx
897
        mov     dl, 43h
898
        mov     eax, [cache_chain_ptr]
899
        mov     eax, [eax]
900
        call    int13_call
901
        test    eax, eax
902
        jnz     .v86err
903
        cmp     edx, ecx
904
        jnz     .writeerr
905
        popa
906
        ret
907
.v86err:
908
.writeerr:
909
        popa
910
        mov     [hd_error], 1
911
        jmp     hd_write_error
912
 
913
uglobal
2434 Serge 914
int13_regs_in   rb      sizeof.v86_regs
915
int13_regs_out  rb      sizeof.v86_regs
709 diamond 916
endg
917
 
918
int13_call:
919
; Because this code uses fixed addresses,
920
; it can not be run simultaniously by many threads.
921
; In current implementation it is protected by common mutex 'hd1_status'
1448 diamond 922
        mov     word [OS_BASE + 510h], 10h             ; packet length
923
        mov     word [OS_BASE + 512h], cx              ; number of sectors
924
        mov     dword [OS_BASE + 514h], 9A000000h      ; buffer 9A00:0000
925
        mov     dword [OS_BASE + 518h], eax
926
        and     dword [OS_BASE + 51Ch], 0
709 diamond 927
        push    ebx ecx esi edi
928
        mov     ebx, int13_regs_in
929
        mov     edi, ebx
2434 Serge 930
        mov     ecx, sizeof.v86_regs/4
709 diamond 931
        xor     eax, eax
932
        rep     stosd
933
        mov     byte [ebx+v86_regs.eax+1], dl
934
        mov     eax, [hdpos]
935
        lea     eax, [BiosDisksData+(eax-80h)*4]
936
        mov     dl, [eax]
937
        mov     byte [ebx+v86_regs.edx], dl
938
        movzx   edx, byte [eax+1]
939
;        mov     dl, 5
940
        test    edx, edx
941
        jnz     .hasirq
942
        dec     edx
943
        jmp     @f
944
.hasirq:
945
        pushad
946
        stdcall enable_irq, edx
947
        popad
948
@@:
949
        mov     word [ebx+v86_regs.esi], 510h
770 diamond 950
        mov     word [ebx+v86_regs.ss], 9000h
820 diamond 951
        mov     word [ebx+v86_regs.esp], 0A000h
709 diamond 952
        mov     word [ebx+v86_regs.eip], 500h
953
        mov     [ebx+v86_regs.eflags], 20200h
954
        mov     esi, [sys_v86_machine]
955
        mov     ecx, 0x502
2010 serge 956
        push fs
709 diamond 957
        call    v86_start
2010 serge 958
        pop  fs
709 diamond 959
        and     [bios_hdpos], 0
960
        pop     edi esi ecx ebx
1448 diamond 961
        movzx   edx, byte [OS_BASE + 512h]
709 diamond 962
        test    byte [int13_regs_out+v86_regs.eflags], 1
963
        jnz     @f
964
        mov     edx, ecx
965
@@:
966
        ret
967
; \end{diamond}
2987 Serge 968
 
969
reserve_hd1:
970
 
971
        cli
972
        cmp     [hd1_status], 0
973
        je      reserve_ok1
974
 
975
        sti
976
        call    change_task
977
        jmp     reserve_hd1
978
 
979
  reserve_ok1:
980
 
981
        push    eax
982
        mov     eax, [CURRENT_TASK]
983
        shl     eax, 5
984
        mov     eax, [eax+CURRENT_TASK+TASKDATA.pid]
985
        mov     [hd1_status], eax
986
        pop     eax
987
        sti
988
        ret
989
;********************************************
990
 
991
uglobal
992
hd_in_cache db ?
993
endg
994
 
995
reserve_hd_channel:
996
; BIOS disk accesses are protected with common mutex hd1_status
997
; This must be modified when hd1_status will not be valid!
998
        cmp     [hdpos], 0x80
999
        jae     .ret
1000
        cmp     [hdbase], 0x1F0
1001
        jne     .IDE_Channel_2
1002
.IDE_Channel_1:
1003
        cli
1004
        cmp     [IDE_Channel_1], 0
1005
        je      .reserve_ok_1
1006
        sti
1007
        call    change_task
1008
        jmp     .IDE_Channel_1
1009
.IDE_Channel_2:
1010
        cli
1011
        cmp     [IDE_Channel_2], 0
1012
        je      .reserve_ok_2
1013
        sti
1014
        call    change_task
1015
        jmp     .IDE_Channel_2
1016
.reserve_ok_1:
1017
        mov     [IDE_Channel_1], 1
1018
        push    eax
1019
        mov     al, 1
1020
        jmp     @f
1021
.reserve_ok_2:
1022
        mov     [IDE_Channel_2], 1
1023
        push    eax
1024
        mov     al, 3
1025
@@:
1026
        cmp     [hdid], 1
1027
        sbb     al, -1
1028
        mov     [hd_in_cache], al
1029
        pop     eax
1030
        sti
1031
.ret:
1032
        ret
1033
 
1034
free_hd_channel:
1035
; see comment at reserve_hd_channel
1036
        cmp     [hdpos], 0x80
1037
        jae     .ret
1038
        cmp     [hdbase], 0x1F0
1039
        jne     .IDE_Channel_2
1040
.IDE_Channel_1:
1041
        mov     [IDE_Channel_1], 0
1042
.ret:
1043
        ret
1044
.IDE_Channel_2:
1045
        mov     [IDE_Channel_2], 0
1046
        ret
1047
;********************************************