Subversion Repositories Kolibri OS

Rev

Rev 3555 | Rev 3908 | 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: 3725 $
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
3725 Serge 14
; LBA48 support by Mario79
15
;-----------------------------------------------------------------------------
160 diamond 16
align 4
17
hd_read:
18
;-----------------------------------------------------------
19
; input  : eax = block to read
20
;          ebx = destination
21
;-----------------------------------------------------------
256 diamond 22
        and     [hd_error], 0
3555 Serge 23
        push    ecx esi edi     ; scan cache
160 diamond 24
 
3555 Serge 25
        call    calculate_cache
2434 Serge 26
        add     esi, 8
581 serge 27
 
2434 Serge 28
        mov     edi, 1
160 diamond 29
 
3725 Serge 30
hdreadcache:
31
        cmp     dword [esi+4], 0 ; empty
3555 Serge 32
        je      nohdcache
160 diamond 33
 
2434 Serge 34
        cmp     [esi], eax      ; correct sector
3555 Serge 35
        je      yeshdcache
160 diamond 36
 
3725 Serge 37
nohdcache:
2434 Serge 38
        add     esi, 8
3555 Serge 39
        inc     edi
40
        dec     ecx
41
        jnz     hdreadcache
160 diamond 42
 
3555 Serge 43
        call    find_empty_slot ; ret in edi
2434 Serge 44
        cmp     [hd_error], 0
3555 Serge 45
        jne     return_01
709 diamond 46
; Read through BIOS?
47
        cmp     [hdpos], 0x80
48
        jae     .bios
514 diamond 49
; DMA read is permitted if [allow_dma_access]=1 or 2
50
        cmp     [allow_dma_access], 2
51
        ja      .nodma
160 diamond 52
        cmp     [dma_hdd], 1
53
        jnz     .nodma
54
        call    hd_read_dma
55
        jmp     @f
56
.nodma:
57
        call    hd_read_pio
709 diamond 58
        jmp     @f
59
.bios:
60
        call    bd_read
160 diamond 61
@@:
725 diamond 62
        cmp     [hd_error], 0
63
        jne     return_01
3725 Serge 64
 
3555 Serge 65
        call    calculate_cache_1
2434 Serge 66
        lea     esi, [edi*8+esi]
160 diamond 67
 
2434 Serge 68
        mov     [esi], eax      ; sector number
3725 Serge 69
        mov     dword [esi+4], 1 ; hd read - mark as same as in hd
160 diamond 70
 
3725 Serge 71
yeshdcache:
2434 Serge 72
        mov     esi, edi
73
        shl     esi, 9
3725 Serge 74
 
3555 Serge 75
        push    eax
76
        call    calculate_cache_2
2434 Serge 77
        add     esi, eax
3555 Serge 78
        pop     eax
581 serge 79
 
2434 Serge 80
        mov     edi, ebx
81
        mov     ecx, 512/4
3555 Serge 82
        cld
83
        rep movsd               ; move data
3725 Serge 84
 
85
return_01:
3555 Serge 86
        pop     edi esi ecx
87
        ret
3725 Serge 88
;-----------------------------------------------------------------------------
160 diamond 89
align 4
90
hd_read_pio:
3555 Serge 91
        push    eax edx
160 diamond 92
 
3725 Serge 93
; Select the desired drive
94
        mov     edx, [hdbase]
95
        add     edx, 6   ;адрес регистра головок
96
        mov     al, byte [hdid]
97
        add     al, 128+64+32
98
        out     dx, al; номер головки/номер диска
99
 
3555 Serge 100
        call    wait_for_hd_idle
2434 Serge 101
        cmp     [hd_error], 0
3555 Serge 102
        jne     hd_read_error
160 diamond 103
 
3725 Serge 104
; ATA with 28 or 48 bit for sector number?
105
        mov     eax, [esp+4]
106
        cmp     eax, 0x10000000
107
        jae     .lba48
108
;--------------------------------------
109
.lba28:
110
        pushfd
3555 Serge 111
        cli
2434 Serge 112
        xor     eax, eax
113
        mov     edx, [hdbase]
3555 Serge 114
        inc     edx
3725 Serge 115
        out     dx, al ; ATA Features регистр "особенностей"
3555 Serge 116
        inc     edx
117
        inc     eax
3725 Serge 118
        out     dx, al ; ATA Sector Counter счётчик секторов
3555 Serge 119
        inc     edx
3725 Serge 120
        mov     eax, [esp+4+4]
121
        out     dx, al ; LBA Low LBA (7:0)
2434 Serge 122
        shr     eax, 8
3555 Serge 123
        inc     edx
3725 Serge 124
        out     dx, al ; LBA Mid LBA (15:8)
2434 Serge 125
        shr     eax, 8
3555 Serge 126
        inc     edx
3725 Serge 127
        out     dx, al ; LBA High LBA (23:16)
2434 Serge 128
        shr     eax, 8
3555 Serge 129
        inc     edx
3725 Serge 130
        and     al, 1+2+4+8 ; LBA (27:24)
2434 Serge 131
        add     al, byte [hdid]
132
        add     al, 128+64+32
3725 Serge 133
        out     dx, al ; номер головки/номер диска
3555 Serge 134
        inc     edx
3725 Serge 135
        mov     al, 20h ; READ SECTOR(S)
136
        out     dx, al ; ATACommand регистр команд
137
        popfd
138
        jmp     .continue
139
;--------------------------------------
140
.lba48:
141
        pushfd
142
        cli
143
        xor     eax, eax
144
        mov     edx, [hdbase]
145
        inc     edx
146
        out     dx, al ; Features Previous Reserved
147
        out     dx, al ; Features Current Reserved
148
        inc     edx
149
        out     dx, al ; Sector Count Previous Sector count (15:8)
150
        inc     eax
151
        out     dx, al ; Sector Count Current Sector count (7:0)
152
        inc     edx
153
        mov     eax, [esp+4+4]
154
        rol     eax, 8
155
        out     dx, al ; LBA Low Previous LBA (31:24)
156
        xor     eax, eax ; because only 32 bit cache
157
        inc     edx
158
        out     dx, al ; LBA Mid Previous LBA (39:32)
159
        inc     edx
160
        out     dx, al ; LBA High Previous LBA (47:40)
161
        sub     edx, 2
162
        mov     eax, [esp+4+4]
163
        out     dx, al ; LBA Low Current LBA (7:0)
164
        shr     eax, 8
165
        inc     edx
166
        out     dx, al ; LBA Mid Current LBA (15:8)
167
        shr     eax, 8
168
        inc     edx
169
        out     dx, al ; LBA High Current LBA (23:16)
170
        inc     edx
171
        mov     al, byte [hdid]
172
        add     al, 128+64+32
173
        out     dx, al ; номер головки/номер диска
174
        inc     edx
175
        mov     al, 24h ; READ SECTOR(S) EXT
176
        out     dx, al ; ATACommand регистр команд
177
        popfd
178
;--------------------------------------
179
.continue:
3555 Serge 180
        call    wait_for_sector_buffer
160 diamond 181
 
2434 Serge 182
        cmp     [hd_error], 0
3555 Serge 183
        jne     hd_read_error
160 diamond 184
 
3725 Serge 185
        pushfd
3555 Serge 186
        cli
187
        push    edi
2434 Serge 188
        shl     edi, 9
3725 Serge 189
 
3555 Serge 190
        push    eax
191
        call    calculate_cache_2
2434 Serge 192
        add     edi, eax
3555 Serge 193
        pop     eax
581 serge 194
 
2434 Serge 195
        mov     ecx, 256
196
        mov     edx, [hdbase]
3555 Serge 197
        cld
198
        rep insw
199
        pop     edi
3725 Serge 200
        popfd
160 diamond 201
 
3555 Serge 202
        pop     edx eax
203
        ret
3725 Serge 204
;-----------------------------------------------------------------------------
160 diamond 205
align 4
206
hd_write:
207
;-----------------------------------------------------------
208
; input  : eax = block
209
;          ebx = pointer to memory
210
;-----------------------------------------------------------
3555 Serge 211
        push    ecx esi edi
160 diamond 212
 
3725 Serge 213
; check if the cache already has the sector and overwrite it
3555 Serge 214
        call    calculate_cache
2434 Serge 215
        add     esi, 8
216
        mov     edi, 1
160 diamond 217
 
3725 Serge 218
hdwritecache:
219
        cmp     dword [esi+4], 0 ; if cache slot is empty
3555 Serge 220
        je      not_in_cache_write
160 diamond 221
 
2434 Serge 222
        cmp     [esi], eax      ; if the slot has the sector
3555 Serge 223
        je      yes_in_cache_write
160 diamond 224
 
3725 Serge 225
not_in_cache_write:
2434 Serge 226
        add     esi, 8
3555 Serge 227
        inc     edi
228
        dec     ecx
229
        jnz     hdwritecache
160 diamond 230
 
3725 Serge 231
; sector not found in cache
232
; write the block to a new location
3555 Serge 233
        call    find_empty_slot ; ret in edi
2434 Serge 234
        cmp     [hd_error], 0
3555 Serge 235
        jne     hd_write_access_denied
160 diamond 236
 
3555 Serge 237
        call    calculate_cache_1
2434 Serge 238
        lea     esi, [edi*8+esi]
239
        mov     [esi], eax      ; sector number
160 diamond 240
 
3725 Serge 241
yes_in_cache_write:
242
        mov     dword [esi+4], 2 ; write - differs from hd
160 diamond 243
 
3725 Serge 244
        shl     edi, 9
160 diamond 245
 
3555 Serge 246
        push    eax
247
        call    calculate_cache_2
2434 Serge 248
        add     edi, eax
3555 Serge 249
        pop     eax
581 serge 250
 
2434 Serge 251
        mov     esi, ebx
252
        mov     ecx, 512/4
3555 Serge 253
        cld
254
        rep movsd               ; move data
3725 Serge 255
 
256
hd_write_access_denied:
3555 Serge 257
        pop     edi esi ecx
258
        ret
3725 Serge 259
;-----------------------------------------------------------------------------
160 diamond 260
align 4
261
cache_write_pio:
3725 Serge 262
; Select the desired drive
263
        mov     edx, [hdbase]
264
        add     edx, 6   ;адрес регистра головок
265
        mov     al, byte [hdid]
266
        add     al, 128+64+32
267
        out     dx, al ; номер головки/номер диска
581 serge 268
 
3555 Serge 269
        call    wait_for_hd_idle
2434 Serge 270
        cmp     [hd_error], 0
3555 Serge 271
        jne     hd_write_error
160 diamond 272
 
3725 Serge 273
; ATA with 28 or 48 bit for sector number?
274
        mov     eax, [esi]
275
        cmp     eax, 0x10000000
276
        jae     .lba48
277
;--------------------------------------
278
.lba28:
279
        pushfd
3555 Serge 280
        cli
2434 Serge 281
        xor     eax, eax
282
        mov     edx, [hdbase]
3555 Serge 283
        inc     edx
3725 Serge 284
        out     dx, al ; ATA Features регистр "особенностей"
3555 Serge 285
        inc     edx
286
        inc     eax
3725 Serge 287
        out     dx, al ; ATA Sector Counter счётчик секторов
3555 Serge 288
        inc     edx
2434 Serge 289
        mov     eax, [esi]      ; eax = sector to write
3725 Serge 290
        out     dx, al ; LBA Low LBA (7:0)
2434 Serge 291
        shr     eax, 8
3555 Serge 292
        inc     edx
3725 Serge 293
        out     dx, al ; LBA Mid LBA (15:8)
2434 Serge 294
        shr     eax, 8
3555 Serge 295
        inc     edx
3725 Serge 296
        out     dx, al ; LBA High LBA (23:16)
2434 Serge 297
        shr     eax, 8
3555 Serge 298
        inc     edx
3725 Serge 299
        and     al, 1+2+4+8 ; LBA (27:24)
2434 Serge 300
        add     al, byte [hdid]
301
        add     al, 128+64+32
3725 Serge 302
        out     dx, al ; номер головки/номер диска
3555 Serge 303
        inc     edx
3725 Serge 304
        mov     al, 30h ; WRITE SECTOR(S)
305
        out     dx, al ; ATACommand регистр команд
306
        popfd
307
        jmp     .continue
308
;--------------------------------------
309
.lba48:
310
        pushfd
311
        cli
312
        xor     eax, eax
313
        mov     edx, [hdbase]
314
        inc     edx
315
        out     dx, al ; Features Previous Reserved
316
        out     dx, al ; Features Current Reserved
317
        inc     edx
318
        out     dx, al ; Sector Count Previous Sector count (15:8)
319
        inc     eax
320
        out     dx, al ; Sector Count Current Sector count (7:0)
321
        inc     edx
322
        mov     eax, [esi]
323
        rol     eax, 8
324
        out     dx, al ; LBA Low Previous LBA (31:24)
325
        xor     eax, eax ; because only 32 bit cache
326
        inc     edx
327
        out     dx, al ; LBA Mid Previous LBA (39:32)
328
        inc     edx
329
        out     dx, al ; LBA High Previous LBA (47:40)
330
        sub     edx, 2
331
        mov     eax, [esi]
332
        out     dx, al ; LBA Low Current LBA (7:0)
333
        shr     eax, 8
334
        inc     edx
335
        out     dx, al ; LBA Mid Current LBA (15:8)
336
        shr     eax, 8
337
        inc     edx
338
        out     dx, al ; LBA High Current LBA (23:16)
339
        inc     edx
340
        mov     al, byte [hdid]
341
        add     al, 128+64+32
342
        out     dx, al ; номер головки/номер диска
343
        inc     edx
344
        mov     al, 34h ; WRITE SECTOR(S) EXT
345
        out     dx, al ; ATACommand регистр команд
346
        popfd
347
;--------------------------------------
348
.continue:
3555 Serge 349
        call    wait_for_sector_buffer
160 diamond 350
 
2434 Serge 351
        cmp     [hd_error], 0
3555 Serge 352
        jne     hd_write_error
160 diamond 353
 
3555 Serge 354
        push    ecx esi
160 diamond 355
 
3725 Serge 356
        pushfd
3555 Serge 357
        cli
2434 Serge 358
        mov     esi, edi
359
        shl     esi, 9
3725 Serge 360
 
3555 Serge 361
        push    eax
362
        call    calculate_cache_2
2434 Serge 363
        add     esi, eax
3555 Serge 364
        pop     eax
581 serge 365
 
2434 Serge 366
        mov     ecx, 256
367
        mov     edx, [hdbase]
3555 Serge 368
        cld
369
        rep outsw
3725 Serge 370
        popfd
160 diamond 371
 
3555 Serge 372
        pop     esi ecx
373
        ret
3725 Serge 374
;-----------------------------------------------------------------------------
375
align 4
160 diamond 376
save_hd_wait_timeout:
3555 Serge 377
        push    eax
2434 Serge 378
        mov     eax, [timer_ticks]
379
        add     eax, 300        ; 3 sec timeout
380
        mov     [hd_wait_timeout], eax
3555 Serge 381
        pop     eax
382
        ret
3725 Serge 383
;-----------------------------------------------------------------------------
160 diamond 384
align 4
385
check_hd_wait_timeout:
3555 Serge 386
        push    eax
2434 Serge 387
        mov     eax, [hd_wait_timeout]
3555 Serge 388
        cmp     [timer_ticks], eax
389
        jg      hd_timeout_error
3725 Serge 390
 
3555 Serge 391
        pop     eax
2434 Serge 392
        mov     [hd_error], 0
3555 Serge 393
        ret
3725 Serge 394
;-----------------------------------------------------------------------------
160 diamond 395
hd_timeout_error:
3500 Serge 396
    if lang eq sp
397
    DEBUGF 1,"K : FS - HD tiempo de espera agotado\n"
398
    else
465 serge 399
    DEBUGF 1,"K : FS - HD timeout\n"
3500 Serge 400
    end if
2434 Serge 401
        mov     [hd_error], 1
3555 Serge 402
        pop     eax
403
        ret
3725 Serge 404
;-----------------------------------------------------------------------------
160 diamond 405
hd_read_error:
3500 Serge 406
    if lang eq sp
407
    DEBUGF 1,"K : FS - HD error de lectura\n"
408
    else
465 serge 409
    DEBUGF 1,"K : FS - HD read error\n"
3500 Serge 410
    end if
3555 Serge 411
        pop     edx eax
412
        ret
3725 Serge 413
;-----------------------------------------------------------------------------
414
hd_write_error_dma:
415
        pop     esi
160 diamond 416
hd_write_error:
3500 Serge 417
    if lang eq sp
418
    DEBUGF 1,"K : FS - HD error de escritura\n"
419
    else
465 serge 420
    DEBUGF 1,"K : FS - HD write error\n"
3500 Serge 421
    end if
3555 Serge 422
        ret
3725 Serge 423
;-----------------------------------------------------------------------------
160 diamond 424
hd_lba_error:
3500 Serge 425
     if lang eq sp
426
     DEBUGF 1,"K : FS - HD error en LBA\n"
427
     else
465 serge 428
     DEBUGF 1,"K : FS - HD LBA error\n"
3500 Serge 429
     end if
3555 Serge 430
        jmp     LBA_read_ret
3725 Serge 431
;-----------------------------------------------------------------------------
160 diamond 432
align 4
433
wait_for_hd_idle:
3555 Serge 434
        push    eax edx
160 diamond 435
 
3555 Serge 436
        call    save_hd_wait_timeout
160 diamond 437
 
2434 Serge 438
        mov     edx, [hdbase]
439
        add     edx, 0x7
3725 Serge 440
;--------------------------------------
441
align 4
442
wfhil1:
3555 Serge 443
        call    check_hd_wait_timeout
2434 Serge 444
        cmp     [hd_error], 0
3555 Serge 445
        jne     @f
160 diamond 446
 
2434 Serge 447
        in      al, dx
448
        test    al, 128
3555 Serge 449
        jnz     wfhil1
389 serge 450
 
3725 Serge 451
@@:
3555 Serge 452
        pop     edx eax
453
        ret
3725 Serge 454
;-----------------------------------------------------------------------------
160 diamond 455
align 4
456
wait_for_sector_buffer:
3555 Serge 457
        push    eax edx
160 diamond 458
 
2434 Serge 459
        mov     edx, [hdbase]
460
        add     edx, 0x7
160 diamond 461
 
3555 Serge 462
        call    save_hd_wait_timeout
3725 Serge 463
;--------------------------------------
464
align 4
465
hdwait_sbuf:                  ; wait for sector buffer to be ready
3555 Serge 466
        call    check_hd_wait_timeout
2434 Serge 467
        cmp     [hd_error], 0
3555 Serge 468
        jne     @f
160 diamond 469
 
2434 Serge 470
        in      al, dx
471
        test    al, 8
3555 Serge 472
        jz      hdwait_sbuf
160 diamond 473
 
2434 Serge 474
        mov     [hd_error], 0
160 diamond 475
 
2434 Serge 476
        cmp     [hd_setup], 1   ; do not mark error for setup request
3555 Serge 477
        je      buf_wait_ok
160 diamond 478
 
2434 Serge 479
        test    al, 1           ; previous command ended up with an error
3555 Serge 480
        jz      buf_wait_ok
3725 Serge 481
@@:
2434 Serge 482
        mov     [hd_error], 1
160 diamond 483
 
3725 Serge 484
buf_wait_ok:
3555 Serge 485
        pop     edx eax
486
        ret
3725 Serge 487
;-----------------------------------------------------------------------------
160 diamond 488
align 4
489
wait_for_sector_dma_ide0:
490
        push    eax
491
        push    edx
492
        call    save_hd_wait_timeout
3725 Serge 493
;--------------------------------------
494
align 4
160 diamond 495
.wait:
496
        call    change_task
497
        cmp     [irq14_func], hdd_irq14
498
        jnz     .done
499
        call    check_hd_wait_timeout
500
        cmp     [hd_error], 0
501
        jz      .wait
502
        mov     [irq14_func], hdd_irq_null
503
        mov     dx, [IDEContrRegsBaseAddr]
504
        mov     al, 0
505
        out     dx, al
506
.done:
507
        pop     edx
508
        pop     eax
509
        ret
3725 Serge 510
;-----------------------------------------------------------------------------
160 diamond 511
align 4
512
wait_for_sector_dma_ide1:
513
        push    eax
514
        push    edx
515
        call    save_hd_wait_timeout
3725 Serge 516
;--------------------------------------
517
align 4
160 diamond 518
.wait:
519
        call    change_task
520
        cmp     [irq15_func], hdd_irq15
521
        jnz     .done
522
        call    check_hd_wait_timeout
523
        cmp     [hd_error], 0
524
        jz      .wait
525
        mov     [irq15_func], hdd_irq_null
526
        mov     dx, [IDEContrRegsBaseAddr]
527
        add     dx, 8
528
        mov     al, 0
529
        out     dx, al
530
.done:
531
        pop     edx
532
        pop     eax
533
        ret
3725 Serge 534
;-----------------------------------------------------------------------------
160 diamond 535
iglobal
536
align 4
537
; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary
538
IDE_descriptor_table:
581 serge 539
        dd      IDE_DMA
465 serge 540
        dw      0x2000
541
        dw      0x8000
160 diamond 542
 
543
dma_cur_sector  dd      not 40h
597 mario79 544
dma_hdpos       dd      0
160 diamond 545
irq14_func      dd      hdd_irq_null
546
irq15_func      dd      hdd_irq_null
547
endg
3725 Serge 548
;-----------------------------------------------------------------------------
160 diamond 549
uglobal
550
; all uglobals are zeroed at boot
551
dma_process     dd      0
552
dma_slot_ptr    dd      0
553
cache_chain_pos dd      0
554
cache_chain_ptr dd      0
555
cache_chain_size        db      0
556
cache_chain_started     db      0
557
dma_task_switched       db      0
558
dma_hdd         db      0
514 diamond 559
allow_dma_access db      0
160 diamond 560
endg
3725 Serge 561
;-----------------------------------------------------------------------------
160 diamond 562
align 4
563
hdd_irq14:
564
        pushfd
565
        cli
566
        pushad
567
        mov     [irq14_func], hdd_irq_null
568
        mov     dx, [IDEContrRegsBaseAddr]
569
        mov     al, 0
570
        out     dx, al
571
        popad
572
        popfd
573
align 4
574
hdd_irq_null:
575
        ret
3725 Serge 576
;-----------------------------------------------------------------------------
160 diamond 577
align 4
578
hdd_irq15:
579
        pushfd
580
        cli
581
        pushad
582
        mov     [irq15_func], hdd_irq_null
583
        mov     dx, [IDEContrRegsBaseAddr]
584
        add     dx, 8
585
        mov     al, 0
586
        out     dx, al
587
        popad
588
        popfd
589
        ret
3725 Serge 590
;-----------------------------------------------------------------------------
160 diamond 591
align 4
592
hd_read_dma:
593
        push    eax
594
        push    edx
2434 Serge 595
        mov     edx, [dma_hdpos]
596
        cmp     edx, [hdpos]
597 mario79 597
        jne     .notread
160 diamond 598
        mov     edx, [dma_cur_sector]
599
        cmp     eax, edx
600
        jb      .notread
601
        add     edx, 15
602
        cmp     [esp+4], edx
603
        ja      .notread
604
        mov     eax, [esp+4]
605
        sub     eax, [dma_cur_sector]
606
        shl     eax, 9
581 serge 607
        add     eax, (OS_BASE+IDE_DMA)
160 diamond 608
        push    ecx esi edi
609
        mov     esi, eax
610
        shl     edi, 9
3725 Serge 611
 
3555 Serge 612
        push    eax
613
        call    calculate_cache_2
2434 Serge 614
        add     edi, eax
3555 Serge 615
        pop     eax
581 serge 616
 
160 diamond 617
        mov     ecx, 512/4
618
        cld
3555 Serge 619
        rep movsd
160 diamond 620
        pop     edi esi ecx
621
        pop     edx
622
        pop     eax
623
        ret
624
.notread:
465 serge 625
        mov     eax, IDE_descriptor_table
3555 Serge 626
        mov     dword [eax], IDE_DMA
465 serge 627
        mov     word [eax+4], 0x2000
628
        sub     eax, OS_BASE
160 diamond 629
        mov     dx, [IDEContrRegsBaseAddr]
630
        cmp     [hdbase], 0x1F0
631
        jz      @f
632
        add     edx, 8
633
@@:
634
        push    edx
635
        add     edx, 4
636
        out     dx, eax
637
        pop     edx
638
        mov     al, 0
639
        out     dx, al
640
        add     edx, 2
641
        mov     al, 6
642
        out     dx, al
3725 Serge 643
 
644
; Select the desired drive
645
        mov     edx, [hdbase]
646
        add     edx, 6   ; адрес регистра головок
647
        mov     al, byte [hdid]
648
        add     al, 128+64+32
649
        out     dx, al ; номер головки/номер диска
650
 
160 diamond 651
        call    wait_for_hd_idle
652
        cmp     [hd_error], 0
653
        jnz     hd_read_error
3725 Serge 654
 
655
; ATA with 28 or 48 bit for sector number?
656
        mov     eax, [esp+4]
657
; -10h because the PreCache hits the boundary between lba28 and lba48
658
; 10h = 16  - size of PreCache
659
        cmp     eax, 0x10000000-10h
660
        jae     .lba48
661
;--------------------------------------
662
.lba28:
663
        pushfd
664
        cli
160 diamond 665
        xor     eax, eax
666
        mov     edx, [hdbase]
667
        inc     edx
3725 Serge 668
        out     dx, al ; ATA Features регистр "особенностей"
160 diamond 669
        inc     edx
3725 Serge 670
        mov     eax, 10h ; Sector Counter = 16 ; PreCache
671
        out     dx, al ; ATA Sector Counter счётчик секторов
160 diamond 672
        inc     edx
3725 Serge 673
        mov     eax, [esp+4+4]
674
        out     dx, al ; LBA Low LBA (7:0)
160 diamond 675
        shr     eax, 8
676
        inc     edx
3725 Serge 677
        out     dx, al ; LBA Mid LBA (15:8)
160 diamond 678
        shr     eax, 8
679
        inc     edx
3725 Serge 680
        out     dx, al ; LBA High LBA (23:16)
160 diamond 681
        shr     eax, 8
682
        inc     edx
3725 Serge 683
        and     al, 0xF ; LBA (27:24)
160 diamond 684
        add     al, byte [hdid]
685
        add     al, 11100000b
3725 Serge 686
        out     dx, al ; номер головки/номер диска
160 diamond 687
        inc     edx
3725 Serge 688
        mov     al, 0xC8 ; READ DMA
689
        out     dx, al ; ATACommand регистр команд
690
        jmp     .continue
691
;--------------------------------------
692
.lba48:
693
        pushfd
694
        cli
695
        xor     eax, eax
696
        mov     edx, [hdbase]
697
        inc     edx
698
        out     dx, al ; Features Previous Reserved
699
        out     dx, al ; Features Current Reserved
700
        inc     edx
701
        out     dx, al ; Sector Count Previous Sector count (15:8)
702
        mov     eax, 10h ; Sector Counter = 16 PreCache
703
        out     dx, al ; Sector Count Current Sector count (7:0)
704
        inc     edx
705
        mov     eax, [esp+4+4]
706
        rol     eax, 8
707
        out     dx, al ; LBA Low Previous LBA (31:24)
708
        xor     eax, eax ; because only 32 bit cache
709
        inc     edx
710
        out     dx, al ; LBA Mid Previous LBA (39:32)
711
        inc     edx
712
        out     dx, al ; LBA High Previous LBA (47:40)
713
        sub     edx, 2
714
        mov     eax, [esp+4+4]
715
        out     dx, al ; LBA Low Current LBA (7:0)
716
        shr     eax, 8
717
        inc     edx
718
        out     dx, al ; LBA Mid Current LBA (15:8)
719
        shr     eax, 8
720
        inc     edx
721
        out     dx, al ; LBA High Current LBA (23:16)
722
        inc     edx
723
        mov     al, byte [hdid]
724
        add     al, 128+64+32
725
        out     dx, al ; номер головки/номер диска
726
        inc     edx
727
        mov     al, 25h ; READ DMA EXT
728
        out     dx, al ; ATACommand регистр команд
729
;--------------------------------------
730
.continue:
160 diamond 731
        mov     dx, [IDEContrRegsBaseAddr]
3725 Serge 732
        mov     eax, [hd_address_table]
733
        cmp     [hdbase], eax ; 0x1F0
160 diamond 734
        jz      @f
735
        add     dx, 8
736
@@:
737
        mov     al, 9
738
        out     dx, al
389 serge 739
        mov     eax, [CURRENT_TASK]
160 diamond 740
        mov     [dma_process], eax
389 serge 741
        mov     eax, [TASK_BASE]
160 diamond 742
        mov     [dma_slot_ptr], eax
3725 Serge 743
        mov     eax, [hd_address_table]
744
        cmp     [hdbase], eax ; 0x1F0
160 diamond 745
        jnz     .ide1
746
        mov     [irq14_func], hdd_irq14
747
        jmp     @f
748
.ide1:
749
        mov     [irq15_func], hdd_irq15
750
@@:
3725 Serge 751
        popfd
752
        mov     eax, [hd_address_table]
753
        cmp     [hdbase], eax ; 0x1F0
160 diamond 754
        jnz     .wait_ide1
755
        call    wait_for_sector_dma_ide0
756
        jmp     @f
757
.wait_ide1:
758
        call    wait_for_sector_dma_ide1
759
@@:
760
        cmp     [hd_error], 0
761
        jnz     hd_read_error
2434 Serge 762
        mov     eax, [hdpos]
763
        mov     [dma_hdpos], eax
160 diamond 764
        pop     edx
765
        pop     eax
766
        mov     [dma_cur_sector], eax
767
        jmp     hd_read_dma
3725 Serge 768
;-----------------------------------------------------------------------------
160 diamond 769
align 4
770
write_cache_sector:
2434 Serge 771
        mov     [cache_chain_size], 1
772
        mov     [cache_chain_pos], edi
3725 Serge 773
;--------------------------------------
774
align 4
581 serge 775
write_cache_chain:
709 diamond 776
        cmp     [hdpos], 0x80
777
        jae     bd_write_cache_chain
2434 Serge 778
        mov     eax, [cache_chain_ptr]
160 diamond 779
        push    esi
780
        mov     eax, IDE_descriptor_table
2434 Serge 781
        mov     edx, eax
580 mario79 782
        pusha
2434 Serge 783
        mov     esi, [cache_chain_pos]
580 mario79 784
        shl     esi, 9
785
        call    calculate_cache_2
2434 Serge 786
        add     esi, eax
581 serge 787
        mov     edi, (OS_BASE+IDE_DMA)
788
        mov     dword [edx], IDE_DMA
580 mario79 789
        movzx   ecx, [cache_chain_size]
790
        shl     ecx, 9
791
        mov     word [edx+4], cx
2434 Serge 792
        shr     ecx, 2
580 mario79 793
        cld
794
        rep movsd
795
        popa
465 serge 796
        sub     eax, OS_BASE
160 diamond 797
        mov     dx, [IDEContrRegsBaseAddr]
798
        cmp     [hdbase], 0x1F0
799
        jz      @f
800
        add     edx, 8
801
@@:
802
        push    edx
803
        add     edx, 4
804
        out     dx, eax
805
        pop     edx
806
        mov     al, 0
807
        out     dx, al
808
        add     edx, 2
809
        mov     al, 6
810
        out     dx, al
3725 Serge 811
 
812
; Select the desired drive
813
        mov     edx, [hdbase]
814
        add     edx, 6   ; адрес регистра головок
815
        mov     al, byte [hdid]
816
        add     al, 128+64+32
817
        out     dx, al ; номер головки/номер диска
818
 
160 diamond 819
        call    wait_for_hd_idle
820
        cmp     [hd_error], 0
821
        jnz     hd_write_error_dma
3725 Serge 822
 
823
; ATA with 28 or 48 bit for sector number?
824
        mov     esi, [cache_chain_ptr]
825
        mov     eax, [esi]
826
; -40h because the PreCache hits the boundary between lba28 and lba48
827
; 40h = 64  - the maximum number of sectors to be written for one command
828
        cmp     eax, 0x10000000-40h
829
        jae     .lba48
830
;--------------------------------------
831
.lba28:
832
        pushfd
833
        cli
160 diamond 834
        xor     eax, eax
835
        mov     edx, [hdbase]
836
        inc     edx
3725 Serge 837
        out     dx, al ; ATA Features регистр "особенностей"
160 diamond 838
        inc     edx
3725 Serge 839
        mov     al, [cache_chain_size] ; Sector Counter
840
        out     dx, al ; ATA Sector Counter счётчик секторов
160 diamond 841
        inc     edx
842
        mov     eax, [esi]
3725 Serge 843
        out     dx, al ; LBA Low LBA (7:0)
160 diamond 844
        shr     eax, 8
845
        inc     edx
3725 Serge 846
        out     dx, al ; LBA Mid LBA (15:8)
160 diamond 847
        shr     eax, 8
848
        inc     edx
3725 Serge 849
        out     dx, al ; LBA High LBA (23:16)
160 diamond 850
        shr     eax, 8
851
        inc     edx
3725 Serge 852
        and     al, 0xF ; LBA (27:24)
160 diamond 853
        add     al, byte [hdid]
854
        add     al, 11100000b
3725 Serge 855
        out     dx, al ; номер головки/номер диска
160 diamond 856
        inc     edx
3725 Serge 857
        mov     al, 0xCA ; WRITE DMA
858
        out     dx, al ; ATACommand регистр команд
859
        jmp     .continue
860
;--------------------------------------
861
.lba48:
862
        pushfd
863
        cli
864
        xor     eax, eax
865
        mov     edx, [hdbase]
866
        inc     edx
867
        out     dx, al ; Features Previous Reserved
868
        out     dx, al ; Features Current Reserved
869
        inc     edx
870
        out     dx, al ; Sector Count Previous Sector count (15:8)
871
        mov     al, [cache_chain_size] ; Sector Counter
872
        out     dx, al ; Sector Count Current Sector count (7:0)
873
        inc     edx
874
        mov     eax, [esi]
875
        rol     eax, 8
876
        out     dx, al ; LBA Low Previous LBA (31:24)
877
        xor     eax, eax ; because only 32 bit cache
878
        inc     edx
879
        out     dx, al ; LBA Mid Previous LBA (39:32)
880
        inc     edx
881
        out     dx, al ; LBA High Previous LBA (47:40)
882
        sub     edx, 2
883
        mov     eax, [esi]
884
        out     dx, al ; LBA Low Current LBA (7:0)
885
        shr     eax, 8
886
        inc     edx
887
        out     dx, al ; LBA Mid Current LBA (15:8)
888
        shr     eax, 8
889
        inc     edx
890
        out     dx, al ; LBA High Current LBA (23:16)
891
        inc     edx
892
        mov     al, byte [hdid]
893
        add     al, 128+64+32
894
        out     dx, al ; номер головки/номер диска
895
        inc     edx
896
        mov     al, 35h ; WRITE DMA EXT
897
        out     dx, al ; ATACommand регистр команд
898
;--------------------------------------
899
.continue:
160 diamond 900
        mov     dx, [IDEContrRegsBaseAddr]
3725 Serge 901
        mov     eax, [hd_address_table]
902
        cmp     [hdbase], eax ; 0x1F0
160 diamond 903
        jz      @f
904
        add     dx, 8
905
@@:
906
        mov     al, 1
907
        out     dx, al
389 serge 908
        mov     eax, [CURRENT_TASK]
160 diamond 909
        mov     [dma_process], eax
389 serge 910
        mov     eax, [TASK_BASE]
160 diamond 911
        mov     [dma_slot_ptr], eax
3725 Serge 912
        mov     eax, [hd_address_table]
913
        cmp     [hdbase], eax ; 0x1F0
160 diamond 914
        jnz     .ide1
915
        mov     [irq14_func], hdd_irq14
916
        jmp     @f
917
.ide1:
918
        mov     [irq15_func], hdd_irq15
919
@@:
3725 Serge 920
        popfd
160 diamond 921
        mov     [dma_cur_sector], not 0x40
3725 Serge 922
        mov     eax, [hd_address_table]
923
        cmp     [hdbase], eax ; 0x1F0
160 diamond 924
        jnz     .wait_ide1
925
        call    wait_for_sector_dma_ide0
926
        jmp     @f
927
.wait_ide1:
928
        call    wait_for_sector_dma_ide1
929
@@:
930
        cmp     [hd_error], 0
931
        jnz     hd_write_error_dma
932
        pop     esi
933
        ret
3725 Serge 934
;-----------------------------------------------------------------------------
160 diamond 935
uglobal
936
IDEContrRegsBaseAddr    dw      ?
3725 Serge 937
IDEContrProgrammingInterface dw ?
938
IDE_BAR0_val    dw ?
939
IDE_BAR1_val    dw ?
940
IDE_BAR2_val    dw ?
941
IDE_BAR3_val    dw ?
160 diamond 942
endg
3725 Serge 943
;-----------------------------------------------------------------------------
709 diamond 944
; \begin{diamond}
945
uglobal
946
bios_hdpos      dd      0       ; 0 is invalid value for [hdpos]
947
bios_cur_sector dd      ?
948
bios_read_len   dd      ?
949
endg
3725 Serge 950
;-----------------------------------------------------------------------------
951
align 4
709 diamond 952
bd_read:
953
        push    eax
954
        push    edx
955
        mov     edx, [bios_hdpos]
956
        cmp     edx, [hdpos]
957
        jne     .notread
958
        mov     edx, [bios_cur_sector]
959
        cmp     eax, edx
960
        jb      .notread
961
        add     edx, [bios_read_len]
962
        dec     edx
963
        cmp     eax, edx
964
        ja      .notread
965
        sub     eax, [bios_cur_sector]
966
        shl     eax, 9
820 diamond 967
        add     eax, (OS_BASE+0x9A000)
709 diamond 968
        push    ecx esi edi
969
        mov     esi, eax
970
        shl     edi, 9
3725 Serge 971
 
3555 Serge 972
        push    eax
973
        call    calculate_cache_2
2434 Serge 974
        add     edi, eax
3555 Serge 975
        pop     eax
709 diamond 976
 
977
        mov     ecx, 512/4
978
        cld
3555 Serge 979
        rep movsd
709 diamond 980
        pop     edi esi ecx
981
        pop     edx
982
        pop     eax
983
        ret
984
.notread:
985
        push    ecx
986
        mov     dl, 42h
987
        mov     ecx, 16
988
        call    int13_call
989
        pop     ecx
990
        test    eax, eax
991
        jnz     .v86err
992
        test    edx, edx
993
        jz      .readerr
994
        mov     [bios_read_len], edx
995
        mov     edx, [hdpos]
996
        mov     [bios_hdpos], edx
997
        pop     edx
998
        pop     eax
999
        mov     [bios_cur_sector], eax
1000
        jmp     bd_read
1001
.readerr:
1002
.v86err:
1003
        mov     [hd_error], 1
1004
        jmp     hd_read_error
3725 Serge 1005
;-----------------------------------------------------------------------------
1006
align 4
709 diamond 1007
bd_write_cache_chain:
1008
        pusha
1009
        mov     esi, [cache_chain_pos]
1010
        shl     esi, 9
1011
        call    calculate_cache_2
1012
        add     esi, eax
820 diamond 1013
        mov     edi, OS_BASE + 0x9A000
709 diamond 1014
        movzx   ecx, [cache_chain_size]
1015
        push    ecx
1016
        shl     ecx, 9-2
3555 Serge 1017
        rep movsd
709 diamond 1018
        pop     ecx
1019
        mov     dl, 43h
1020
        mov     eax, [cache_chain_ptr]
1021
        mov     eax, [eax]
1022
        call    int13_call
1023
        test    eax, eax
1024
        jnz     .v86err
1025
        cmp     edx, ecx
1026
        jnz     .writeerr
1027
        popa
1028
        ret
1029
.v86err:
1030
.writeerr:
1031
        popa
1032
        mov     [hd_error], 1
1033
        jmp     hd_write_error
3725 Serge 1034
;-----------------------------------------------------------------------------
709 diamond 1035
uglobal
2434 Serge 1036
int13_regs_in   rb      sizeof.v86_regs
1037
int13_regs_out  rb      sizeof.v86_regs
709 diamond 1038
endg
3725 Serge 1039
;-----------------------------------------------------------------------------
1040
align 4
709 diamond 1041
int13_call:
1042
; Because this code uses fixed addresses,
1043
; it can not be run simultaniously by many threads.
1044
; In current implementation it is protected by common mutex 'hd1_status'
1448 diamond 1045
        mov     word [OS_BASE + 510h], 10h             ; packet length
1046
        mov     word [OS_BASE + 512h], cx              ; number of sectors
1047
        mov     dword [OS_BASE + 514h], 9A000000h      ; buffer 9A00:0000
1048
        mov     dword [OS_BASE + 518h], eax
1049
        and     dword [OS_BASE + 51Ch], 0
709 diamond 1050
        push    ebx ecx esi edi
1051
        mov     ebx, int13_regs_in
1052
        mov     edi, ebx
2434 Serge 1053
        mov     ecx, sizeof.v86_regs/4
709 diamond 1054
        xor     eax, eax
3555 Serge 1055
        rep stosd
709 diamond 1056
        mov     byte [ebx+v86_regs.eax+1], dl
1057
        mov     eax, [hdpos]
1058
        lea     eax, [BiosDisksData+(eax-80h)*4]
1059
        mov     dl, [eax]
1060
        mov     byte [ebx+v86_regs.edx], dl
1061
        movzx   edx, byte [eax+1]
1062
;        mov     dl, 5
1063
        test    edx, edx
1064
        jnz     .hasirq
1065
        dec     edx
1066
        jmp     @f
1067
.hasirq:
1068
        pushad
1069
        stdcall enable_irq, edx
1070
        popad
1071
@@:
1072
        mov     word [ebx+v86_regs.esi], 510h
770 diamond 1073
        mov     word [ebx+v86_regs.ss], 9000h
820 diamond 1074
        mov     word [ebx+v86_regs.esp], 0A000h
709 diamond 1075
        mov     word [ebx+v86_regs.eip], 500h
1076
        mov     [ebx+v86_regs.eflags], 20200h
1077
        mov     esi, [sys_v86_machine]
1078
        mov     ecx, 0x502
3555 Serge 1079
        push    fs
709 diamond 1080
        call    v86_start
3555 Serge 1081
        pop     fs
709 diamond 1082
        and     [bios_hdpos], 0
1083
        pop     edi esi ecx ebx
1448 diamond 1084
        movzx   edx, byte [OS_BASE + 512h]
709 diamond 1085
        test    byte [int13_regs_out+v86_regs.eflags], 1
1086
        jnz     @f
1087
        mov     edx, ecx
1088
@@:
1089
        ret
1090
; \end{diamond}
3725 Serge 1091
;-----------------------------------------------------------------------------
1092
align 4
2987 Serge 1093
reserve_hd1:
1094
        cli
1095
        cmp     [hd1_status], 0
1096
        je      reserve_ok1
1097
 
1098
        sti
1099
        call    change_task
1100
        jmp     reserve_hd1
1101
 
3725 Serge 1102
reserve_ok1:
2987 Serge 1103
        push    eax
1104
        mov     eax, [CURRENT_TASK]
1105
        shl     eax, 5
1106
        mov     eax, [eax+CURRENT_TASK+TASKDATA.pid]
1107
        mov     [hd1_status], eax
1108
        pop     eax
1109
        sti
1110
        ret
3725 Serge 1111
;-----------------------------------------------------------------------------
2987 Serge 1112
uglobal
1113
hd_in_cache db ?
1114
endg
3725 Serge 1115
;-----------------------------------------------------------------------------
1116
align 4
2987 Serge 1117
reserve_hd_channel:
1118
; BIOS disk accesses are protected with common mutex hd1_status
1119
; This must be modified when hd1_status will not be valid!
1120
        cmp     [hdpos], 0x80
1121
        jae     .ret
1122
        cmp     [hdbase], 0x1F0
1123
        jne     .IDE_Channel_2
1124
.IDE_Channel_1:
1125
        cli
1126
        cmp     [IDE_Channel_1], 0
1127
        je      .reserve_ok_1
1128
        sti
1129
        call    change_task
1130
        jmp     .IDE_Channel_1
1131
.IDE_Channel_2:
1132
        cli
1133
        cmp     [IDE_Channel_2], 0
1134
        je      .reserve_ok_2
1135
        sti
1136
        call    change_task
1137
        jmp     .IDE_Channel_2
1138
.reserve_ok_1:
1139
        mov     [IDE_Channel_1], 1
1140
        push    eax
1141
        mov     al, 1
1142
        jmp     @f
1143
.reserve_ok_2:
1144
        mov     [IDE_Channel_2], 1
1145
        push    eax
1146
        mov     al, 3
1147
@@:
1148
        cmp     [hdid], 1
1149
        sbb     al, -1
1150
        mov     [hd_in_cache], al
1151
        pop     eax
1152
        sti
1153
.ret:
1154
        ret
3725 Serge 1155
;-----------------------------------------------------------------------------
2987 Serge 1156
free_hd_channel:
1157
; see comment at reserve_hd_channel
1158
        cmp     [hdpos], 0x80
1159
        jae     .ret
1160
        cmp     [hdbase], 0x1F0
1161
        jne     .IDE_Channel_2
1162
.IDE_Channel_1:
1163
        mov     [IDE_Channel_1], 0
1164
.ret:
1165
        ret
1166
.IDE_Channel_2:
1167
        mov     [IDE_Channel_2], 0
1168
        ret
3725 Serge 1169
;-----------------------------------------------------------------------------