Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
2288 clevermous 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3742 clevermous 3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
2288 clevermous 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 4578 $
9
 
10
 
11
; Low-level driver for HDD access
12
; DMA support by Mario79
3712 mario79 13
; LBA48 support by Mario79
14
;-----------------------------------------------------------------------------
3742 clevermous 15
struct HD_DATA
16
hdbase  dd      ?
17
hdid    dd      ?
18
hdpos   dd      ?
19
ends
20
 
21
iglobal
2288 clevermous 22
align 4
3742 clevermous 23
ide_callbacks:
24
        dd      ide_callbacks.end - ide_callbacks       ; strucsize
25
        dd      0       ; no close function
26
        dd      0       ; no closemedia function
27
        dd      ide_querymedia
28
        dd      ide_read
29
        dd      ide_write
30
        dd      0       ; no flush function
31
        dd      0       ; use default cache size
32
.end:
2288 clevermous 33
 
3742 clevermous 34
hd0_data        HD_DATA         ?,    0, 1
35
hd1_data        HD_DATA         ?, 0x10, 2
36
hd2_data        HD_DATA         ?,    0, 3
37
hd3_data        HD_DATA         ?, 0x10, 4
4273 clevermous 38
 
39
hd_address_table:
40
        dd      0x1f0, 0x00, 0x1f0, 0x10
41
        dd      0x170, 0x00, 0x170, 0x10
3742 clevermous 42
endg
2288 clevermous 43
 
3742 clevermous 44
uglobal
45
ide_mutex               MUTEX
46
ide_channel1_mutex      MUTEX
47
ide_channel2_mutex      MUTEX
48
endg
2288 clevermous 49
 
3742 clevermous 50
proc ide_read stdcall uses edi, \
51
        hd_data, buffer, startsector:qword, numsectors
52
        ; hd_data = pointer to hd*_data
53
        ; buffer = pointer to buffer for data
54
        ; startsector = 64-bit start sector
55
        ; numsectors = pointer to number of sectors on input,
56
        ;  must be filled with number of sectors really read
57
locals
58
sectors_todo    dd      ?
59
channel_lock    dd      ?
60
endl
61
; 1. Initialize number of sectors: get number of requested sectors
62
; and say that no sectors were read yet.
63
        mov     ecx, [numsectors]
64
        mov     eax, [ecx]
65
        mov     dword [ecx], 0
66
        mov     [sectors_todo], eax
67
; 2. Acquire the global lock.
68
        mov     ecx, ide_mutex
69
        call    mutex_lock
70
        mov     ecx, ide_channel2_mutex
71
        mov     eax, [hd_data]
3774 mario79 72
        push    ecx
73
        mov     ecx, [hd_address_table]
74
        cmp     [eax+HD_DATA.hdbase], ecx ; 0x1F0
75
        pop     ecx
3742 clevermous 76
        jne     .IDE_Channel_2
77
        mov     ecx, ide_channel1_mutex
78
.IDE_Channel_2:
79
        mov     [channel_lock], ecx
80
        call    mutex_lock
81
; 3. Convert parameters to the form suitable for worker procedures.
82
; Underlying procedures do not know about 64-bit sectors.
83
; Worker procedures use global variables and edi for [buffer].
84
        cmp     dword [startsector+4], 0
85
        jnz     .fail
86
        and     [hd_error], 0
87
        mov     ecx, [hd_data]
88
        mov     eax, [ecx+HD_DATA.hdbase]
89
        mov     [hdbase], eax
90
        mov     eax, [ecx+HD_DATA.hdid]
91
        mov     [hdid], eax
92
        mov     eax, [ecx+HD_DATA.hdpos]
93
        mov     [hdpos], eax
94
        mov     eax, dword [startsector]
95
        mov     edi, [buffer]
96
; 4. Worker procedures take one sectors per time, so loop over all sectors to read.
97
.sectors_loop:
2288 clevermous 98
; DMA read is permitted if [allow_dma_access]=1 or 2
99
        cmp     [allow_dma_access], 2
100
        ja      .nodma
101
        cmp     [dma_hdd], 1
102
        jnz     .nodma
4291 mario79 103
;--------------------------------------
104
        push    eax
105
        mov     eax, [hd_address_table]
106
        cmp     [hdbase], eax ; 0x1F0
107
        pop     eax
108
        jnz     @f
109
 
110
        test    [DRIVE_DATA+1], byte 10100000b
111
        jnz     .nodma
112
 
113
        jmp     .dma
114
@@:
115
        test    [DRIVE_DATA+1], byte 1010b
116
        jnz     .nodma
117
.dma:
118
;--------------------------------------
2288 clevermous 119
        call    hd_read_dma
120
        jmp     @f
121
.nodma:
122
        call    hd_read_pio
123
@@:
124
        cmp     [hd_error], 0
3742 clevermous 125
        jnz     .fail
126
        mov     ecx, [numsectors]
127
        inc     dword [ecx]     ; one more sector is read
128
        dec     [sectors_todo]
129
        jz      .done
130
        inc     eax
131
        jnz     .sectors_loop
132
; 5. Loop is done, either due to error or because everything is done.
133
; Release the global lock and return the corresponding status.
134
.fail:
135
        mov     ecx, [channel_lock]
136
        call    mutex_unlock
137
        mov     ecx, ide_mutex
138
        call    mutex_unlock
139
        or      eax, -1
140
        ret
141
.done:
142
        mov     ecx, [channel_lock]
143
        call    mutex_unlock
144
        mov     ecx, ide_mutex
145
        call    mutex_unlock
146
        xor     eax, eax
147
        ret
148
endp
3712 mario79 149
 
3742 clevermous 150
proc ide_write stdcall uses esi edi, \
151
        hd_data, buffer, startsector:qword, numsectors
152
        ; hd_data = pointer to hd*_data
153
        ; buffer = pointer to buffer with data
154
        ; startsector = 64-bit start sector
155
        ; numsectors = pointer to number of sectors on input,
156
        ;  must be filled with number of sectors really written
157
locals
158
sectors_todo    dd      ?
159
channel_lock    dd      ?
160
endl
161
; 1. Initialize number of sectors: get number of requested sectors
162
; and say that no sectors were read yet.
163
        mov     ecx, [numsectors]
164
        mov     eax, [ecx]
165
        mov     dword [ecx], 0
166
        mov     [sectors_todo], eax
167
; 2. Acquire the global lock.
168
        mov     ecx, ide_mutex
169
        call    mutex_lock
170
        mov     ecx, ide_channel2_mutex
171
        mov     eax, [hd_data]
3774 mario79 172
        push    ecx
173
        mov     ecx, [hd_address_table]
174
        cmp     [eax+HD_DATA.hdbase], ecx ; 0x1F0
175
        pop     ecx
3742 clevermous 176
        jne     .IDE_Channel_2
177
        mov     ecx, ide_channel1_mutex
178
.IDE_Channel_2:
179
        mov     [channel_lock], ecx
180
        call    mutex_lock
181
; 3. Convert parameters to the form suitable for worker procedures.
182
; Underlying procedures do not know about 64-bit sectors.
183
; Worker procedures use global variables and esi for [buffer].
184
        cmp     dword [startsector+4], 0
185
        jnz     .fail
186
        and     [hd_error], 0
187
        mov     ecx, [hd_data]
188
        mov     eax, [ecx+HD_DATA.hdbase]
189
        mov     [hdbase], eax
190
        mov     eax, [ecx+HD_DATA.hdid]
191
        mov     [hdid], eax
192
        mov     eax, [ecx+HD_DATA.hdpos]
193
        mov     [hdpos], eax
194
        mov     esi, [buffer]
195
        lea     edi, [startsector]
196
        mov     [cache_chain_ptr], edi
197
; 4. Worker procedures take max 16 sectors per time,
198
; loop until all sectors will be processed.
199
.sectors_loop:
200
        mov     ecx, 16
201
        cmp     ecx, [sectors_todo]
202
        jbe     @f
203
        mov     ecx, [sectors_todo]
204
@@:
205
        mov     [cache_chain_size], cl
206
; DMA write is permitted only if [allow_dma_access]=1
207
        cmp     [allow_dma_access], 2
208
        jae     .nodma
209
        cmp     [dma_hdd], 1
210
        jnz     .nodma
4291 mario79 211
;--------------------------------------
212
        push    eax
213
        mov     eax, [hd_address_table]
214
        cmp     [hdbase], eax ; 0x1F0
215
        pop     eax
216
        jnz     @f
217
 
218
        test    [DRIVE_DATA+1], byte 10100000b
219
        jnz     .nodma
220
 
221
        jmp     .dma
222
@@:
223
        test    [DRIVE_DATA+1], byte 1010b
224
        jnz     .nodma
225
.dma:
226
;--------------------------------------
3742 clevermous 227
        call    cache_write_dma
228
        jmp     .common
229
.nodma:
230
        mov     [cache_chain_size], 1
231
        call    cache_write_pio
232
.common:
233
        cmp     [hd_error], 0
234
        jnz     .fail
235
        movzx   ecx, [cache_chain_size]
236
        mov     eax, [numsectors]
237
        add     [eax], ecx
238
        sub     [sectors_todo], ecx
239
        jz      .done
240
        add     [edi], ecx
241
        jc      .fail
242
        shl     ecx, 9
243
        add     esi, ecx
244
        jmp     .sectors_loop
245
; 5. Loop is done, either due to error or because everything is done.
246
; Release the global lock and return the corresponding status.
247
.fail:
248
        mov     ecx, [channel_lock]
249
        call    mutex_unlock
250
        mov     ecx, ide_mutex
251
        call    mutex_unlock
252
        or      eax, -1
253
        ret
254
.done:
255
        mov     ecx, [channel_lock]
256
        call    mutex_unlock
257
        mov     ecx, ide_mutex
258
        call    mutex_unlock
259
        xor     eax, eax
260
        ret
261
endp
2288 clevermous 262
 
3742 clevermous 263
; This is a stub.
264
proc ide_querymedia stdcall, hd_data, mediainfo
265
        mov     eax, [mediainfo]
266
        mov     [eax+DISKMEDIAINFO.Flags], 0
267
        mov     [eax+DISKMEDIAINFO.SectorSize], 512
268
        or      dword [eax+DISKMEDIAINFO.Capacity], 0xFFFFFFFF
269
        or      dword [eax+DISKMEDIAINFO.Capacity+4], 0xFFFFFFFF
270
        xor     eax, eax
271
        ret
272
endp
2288 clevermous 273
 
3712 mario79 274
;-----------------------------------------------------------------------------
2288 clevermous 275
align 4
3742 clevermous 276
; input: eax = sector, edi -> buffer
277
; output: edi = edi + 512
2288 clevermous 278
hd_read_pio:
279
        push    eax edx
280
 
3712 mario79 281
; Select the desired drive
3702 mario79 282
        mov     edx, [hdbase]
283
        add     edx, 6   ;адрес регистра головок
284
        mov     al, byte [hdid]
285
        add     al, 128+64+32
286
        out     dx, al; номер головки/номер диска
3711 clevermous 287
 
2288 clevermous 288
        call    wait_for_hd_idle
289
        cmp     [hd_error], 0
290
        jne     hd_read_error
3711 clevermous 291
 
3702 mario79 292
; ATA with 28 or 48 bit for sector number?
293
        mov     eax, [esp+4]
294
        cmp     eax, 0x10000000
3711 clevermous 295
        jae     .lba48
3712 mario79 296
;--------------------------------------
3702 mario79 297
.lba28:
3706 mario79 298
        pushfd
2288 clevermous 299
        cli
300
        xor     eax, eax
301
        mov     edx, [hdbase]
302
        inc     edx
3706 mario79 303
        out     dx, al ; ATA Features регистр "особенностей"
2288 clevermous 304
        inc     edx
305
        inc     eax
3706 mario79 306
        out     dx, al ; ATA Sector Counter счётчик секторов
2288 clevermous 307
        inc     edx
3706 mario79 308
        mov     eax, [esp+4+4]
309
        out     dx, al ; LBA Low LBA (7:0)
2288 clevermous 310
        shr     eax, 8
311
        inc     edx
3706 mario79 312
        out     dx, al ; LBA Mid LBA (15:8)
2288 clevermous 313
        shr     eax, 8
314
        inc     edx
3706 mario79 315
        out     dx, al ; LBA High LBA (23:16)
2288 clevermous 316
        shr     eax, 8
317
        inc     edx
3706 mario79 318
        and     al, 1+2+4+8 ; LBA (27:24)
2288 clevermous 319
        add     al, byte [hdid]
320
        add     al, 128+64+32
3706 mario79 321
        out     dx, al ; номер головки/номер диска
2288 clevermous 322
        inc     edx
3711 clevermous 323
        mov     al, 20h ; READ SECTOR(S)
3706 mario79 324
        out     dx, al ; ATACommand регистр команд
325
        popfd
3711 clevermous 326
        jmp     .continue
3712 mario79 327
;--------------------------------------
3702 mario79 328
.lba48:
3706 mario79 329
        pushfd
3702 mario79 330
        cli
331
        xor     eax, eax
332
        mov     edx, [hdbase]
333
        inc     edx
334
        out     dx, al ; Features Previous Reserved
335
        out     dx, al ; Features Current Reserved
336
        inc     edx
337
        out     dx, al ; Sector Count Previous Sector count (15:8)
338
        inc     eax
339
        out     dx, al ; Sector Count Current Sector count (7:0)
340
        inc     edx
3706 mario79 341
        mov     eax, [esp+4+4]
3711 clevermous 342
        rol     eax, 8
3702 mario79 343
        out     dx, al ; LBA Low Previous LBA (31:24)
3712 mario79 344
        xor     eax, eax ; because only 32 bit cache
3702 mario79 345
        inc     edx
346
        out     dx, al ; LBA Mid Previous LBA (39:32)
347
        inc     edx
348
        out     dx, al ; LBA High Previous LBA (47:40)
3711 clevermous 349
        sub     edx, 2
3706 mario79 350
        mov     eax, [esp+4+4]
3702 mario79 351
        out     dx, al ; LBA Low Current LBA (7:0)
352
        shr     eax, 8
353
        inc     edx
354
        out     dx, al ; LBA Mid Current LBA (15:8)
355
        shr     eax, 8
356
        inc     edx
357
        out     dx, al ; LBA High Current LBA (23:16)
358
        inc     edx
359
        mov     al, byte [hdid]
360
        add     al, 128+64+32
3712 mario79 361
        out     dx, al ; номер головки/номер диска
3702 mario79 362
        inc     edx
3711 clevermous 363
        mov     al, 24h ; READ SECTOR(S) EXT
3712 mario79 364
        out     dx, al ; ATACommand регистр команд
3706 mario79 365
        popfd
3712 mario79 366
;--------------------------------------
3702 mario79 367
.continue:
2288 clevermous 368
        call    wait_for_sector_buffer
369
 
370
        cmp     [hd_error], 0
371
        jne     hd_read_error
372
 
3712 mario79 373
        pushfd
2288 clevermous 374
        cli
3712 mario79 375
 
2288 clevermous 376
        mov     ecx, 256
377
        mov     edx, [hdbase]
378
        cld
379
        rep insw
3712 mario79 380
        popfd
2288 clevermous 381
 
382
        pop     edx eax
383
        ret
3712 mario79 384
;-----------------------------------------------------------------------------
2288 clevermous 385
align 4
3742 clevermous 386
; edi -> sector, esi -> data
2288 clevermous 387
cache_write_pio:
3712 mario79 388
; Select the desired drive
3702 mario79 389
        mov     edx, [hdbase]
390
        add     edx, 6   ;адрес регистра головок
391
        mov     al, byte [hdid]
392
        add     al, 128+64+32
3712 mario79 393
        out     dx, al ; номер головки/номер диска
3702 mario79 394
 
2288 clevermous 395
        call    wait_for_hd_idle
396
        cmp     [hd_error], 0
397
        jne     hd_write_error
398
 
3706 mario79 399
; ATA with 28 or 48 bit for sector number?
3742 clevermous 400
        mov     eax, [edi]
3706 mario79 401
        cmp     eax, 0x10000000
402
        jae     .lba48
3712 mario79 403
;--------------------------------------
3706 mario79 404
.lba28:
405
        pushfd
2288 clevermous 406
        cli
407
        xor     eax, eax
408
        mov     edx, [hdbase]
409
        inc     edx
3706 mario79 410
        out     dx, al ; ATA Features регистр "особенностей"
2288 clevermous 411
        inc     edx
412
        inc     eax
3706 mario79 413
        out     dx, al ; ATA Sector Counter счётчик секторов
2288 clevermous 414
        inc     edx
3742 clevermous 415
        mov     eax, [edi]      ; eax = sector to write
3706 mario79 416
        out     dx, al ; LBA Low LBA (7:0)
2288 clevermous 417
        shr     eax, 8
418
        inc     edx
3706 mario79 419
        out     dx, al ; LBA Mid LBA (15:8)
2288 clevermous 420
        shr     eax, 8
421
        inc     edx
3706 mario79 422
        out     dx, al ; LBA High LBA (23:16)
2288 clevermous 423
        shr     eax, 8
424
        inc     edx
3706 mario79 425
        and     al, 1+2+4+8 ; LBA (27:24)
2288 clevermous 426
        add     al, byte [hdid]
427
        add     al, 128+64+32
3706 mario79 428
        out     dx, al ; номер головки/номер диска
2288 clevermous 429
        inc     edx
3706 mario79 430
        mov     al, 30h ; WRITE SECTOR(S)
431
        out     dx, al ; ATACommand регистр команд
3711 clevermous 432
        jmp     .continue
3712 mario79 433
;--------------------------------------
3706 mario79 434
.lba48:
435
        pushfd
436
        cli
437
        xor     eax, eax
438
        mov     edx, [hdbase]
439
        inc     edx
440
        out     dx, al ; Features Previous Reserved
441
        out     dx, al ; Features Current Reserved
442
        inc     edx
443
        out     dx, al ; Sector Count Previous Sector count (15:8)
444
        inc     eax
445
        out     dx, al ; Sector Count Current Sector count (7:0)
446
        inc     edx
3742 clevermous 447
        mov     eax, [edi]
3711 clevermous 448
        rol     eax, 8
3706 mario79 449
        out     dx, al ; LBA Low Previous LBA (31:24)
3712 mario79 450
        xor     eax, eax ; because only 32 bit cache
3706 mario79 451
        inc     edx
452
        out     dx, al ; LBA Mid Previous LBA (39:32)
453
        inc     edx
454
        out     dx, al ; LBA High Previous LBA (47:40)
3711 clevermous 455
        sub     edx, 2
3742 clevermous 456
        mov     eax, [edi]
3706 mario79 457
        out     dx, al ; LBA Low Current LBA (7:0)
458
        shr     eax, 8
459
        inc     edx
460
        out     dx, al ; LBA Mid Current LBA (15:8)
461
        shr     eax, 8
462
        inc     edx
463
        out     dx, al ; LBA High Current LBA (23:16)
464
        inc     edx
465
        mov     al, byte [hdid]
466
        add     al, 128+64+32
3712 mario79 467
        out     dx, al ; номер головки/номер диска
3706 mario79 468
        inc     edx
3711 clevermous 469
        mov     al, 34h ; WRITE SECTOR(S) EXT
3712 mario79 470
        out     dx, al ; ATACommand регистр команд
471
;--------------------------------------
3706 mario79 472
.continue:
3881 mario79 473
        popfd
2288 clevermous 474
        call    wait_for_sector_buffer
475
 
476
        cmp     [hd_error], 0
477
        jne     hd_write_error
478
 
479
        push    ecx esi
480
 
3712 mario79 481
        pushfd
2288 clevermous 482
        cli
483
        mov     ecx, 256
484
        mov     edx, [hdbase]
485
        cld
486
        rep outsw
3712 mario79 487
        popfd
2288 clevermous 488
 
489
        pop     esi ecx
490
        ret
3712 mario79 491
;-----------------------------------------------------------------------------
492
align 4
2288 clevermous 493
save_hd_wait_timeout:
494
        push    eax
495
        mov     eax, [timer_ticks]
496
        add     eax, 300        ; 3 sec timeout
497
        mov     [hd_wait_timeout], eax
498
        pop     eax
499
        ret
3712 mario79 500
;-----------------------------------------------------------------------------
2288 clevermous 501
align 4
502
check_hd_wait_timeout:
503
        push    eax
504
        mov     eax, [hd_wait_timeout]
505
        cmp     [timer_ticks], eax
506
        jg      hd_timeout_error
3712 mario79 507
 
2288 clevermous 508
        pop     eax
509
        mov     [hd_error], 0
510
        ret
3712 mario79 511
;-----------------------------------------------------------------------------
2288 clevermous 512
hd_timeout_error:
3712 mario79 513
        if lang eq sp
514
        DEBUGF 1,"K : FS - HD tiempo de espera agotado\n"
515
        else
516
        DEBUGF 1,"K : FS - HD timeout\n"
517
        end if
2288 clevermous 518
        mov     [hd_error], 1
519
        pop     eax
520
        ret
3712 mario79 521
;-----------------------------------------------------------------------------
2288 clevermous 522
hd_read_error:
3712 mario79 523
        if lang eq sp
524
        DEBUGF 1,"K : FS - HD error de lectura\n"
525
        else
526
        DEBUGF 1,"K : FS - HD read error\n"
527
        end if
2288 clevermous 528
        pop     edx eax
529
        ret
3712 mario79 530
;-----------------------------------------------------------------------------
531
hd_write_error_dma:
532
        pop     esi
2288 clevermous 533
hd_write_error:
3309 esevece 534
        if lang eq sp
535
        DEBUGF 1,"K : FS - HD error de escritura\n"
536
        else
537
        DEBUGF 1,"K : FS - HD write error\n"
538
        end if
2288 clevermous 539
        ret
3712 mario79 540
;-----------------------------------------------------------------------------
2288 clevermous 541
align 4
542
wait_for_hd_idle:
543
        push    eax edx
544
 
545
        call    save_hd_wait_timeout
546
 
547
        mov     edx, [hdbase]
548
        add     edx, 0x7
3712 mario79 549
;--------------------------------------
550
align 4
551
wfhil1:
2288 clevermous 552
        call    check_hd_wait_timeout
553
        cmp     [hd_error], 0
554
        jne     @f
555
 
556
        in      al, dx
557
        test    al, 128
558
        jnz     wfhil1
559
 
3712 mario79 560
@@:
2288 clevermous 561
        pop     edx eax
562
        ret
3712 mario79 563
;-----------------------------------------------------------------------------
2288 clevermous 564
align 4
565
wait_for_sector_buffer:
566
        push    eax edx
567
 
568
        mov     edx, [hdbase]
569
        add     edx, 0x7
570
 
571
        call    save_hd_wait_timeout
3712 mario79 572
;--------------------------------------
573
align 4
574
hdwait_sbuf:                  ; wait for sector buffer to be ready
2288 clevermous 575
        call    check_hd_wait_timeout
576
        cmp     [hd_error], 0
577
        jne     @f
578
 
579
        in      al, dx
580
        test    al, 8
581
        jz      hdwait_sbuf
582
 
583
        mov     [hd_error], 0
584
 
585
        cmp     [hd_setup], 1   ; do not mark error for setup request
586
        je      buf_wait_ok
587
 
588
        test    al, 1           ; previous command ended up with an error
589
        jz      buf_wait_ok
3712 mario79 590
@@:
2288 clevermous 591
        mov     [hd_error], 1
592
 
3712 mario79 593
buf_wait_ok:
2288 clevermous 594
        pop     edx eax
595
        ret
3712 mario79 596
;-----------------------------------------------------------------------------
3762 mario79 597
irq14_num equ byte 14
598
irq15_num equ byte 15
599
;-----------------------------------------------------------------------------
2288 clevermous 600
align 4
601
wait_for_sector_dma_ide0:
602
        push    eax
603
        push    edx
604
        call    save_hd_wait_timeout
3712 mario79 605
;--------------------------------------
606
align 4
2288 clevermous 607
.wait:
608
        call    change_task
3870 mario79 609
        cmp     [IDE_common_irq_param], 0
610
        jz      .done
3762 mario79 611
 
2288 clevermous 612
        call    check_hd_wait_timeout
613
        cmp     [hd_error], 0
614
        jz      .wait
3881 mario79 615
; clear Bus Master IDE Command register
3870 mario79 616
        pushfd
617
        cli
3762 mario79 618
        mov     [IDE_common_irq_param], 0
2288 clevermous 619
        mov     dx, [IDEContrRegsBaseAddr]
620
        mov     al, 0
621
        out     dx, al
3870 mario79 622
        popfd
3881 mario79 623
;--------------------------------------
624
align 4
2288 clevermous 625
.done:
626
        pop     edx
627
        pop     eax
628
        ret
3712 mario79 629
;-----------------------------------------------------------------------------
2288 clevermous 630
align 4
631
wait_for_sector_dma_ide1:
632
        push    eax
633
        push    edx
634
        call    save_hd_wait_timeout
3712 mario79 635
;--------------------------------------
636
align 4
2288 clevermous 637
.wait:
638
        call    change_task
3870 mario79 639
        cmp     [IDE_common_irq_param], 0
640
        jz      .done
3762 mario79 641
 
2288 clevermous 642
        call    check_hd_wait_timeout
643
        cmp     [hd_error], 0
644
        jz      .wait
3881 mario79 645
; clear Bus Master IDE Command register
3870 mario79 646
        pushfd
647
        cli
3762 mario79 648
        mov     [IDE_common_irq_param], 0
2288 clevermous 649
        mov     dx, [IDEContrRegsBaseAddr]
650
        add     dx, 8
651
        mov     al, 0
652
        out     dx, al
3870 mario79 653
        popfd
3881 mario79 654
;--------------------------------------
655
align 4
2288 clevermous 656
.done:
657
        pop     edx
658
        pop     eax
659
        ret
3712 mario79 660
;-----------------------------------------------------------------------------
2288 clevermous 661
iglobal
662
align 4
663
; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary
664
IDE_descriptor_table:
3712 mario79 665
        dd IDE_DMA
666
        dw 0x2000
667
        dw 0x8000
2288 clevermous 668
 
3712 mario79 669
dma_cur_sector  dd not 40h
670
dma_hdpos       dd 0
3762 mario79 671
IDE_common_irq_param db 0
2288 clevermous 672
endg
3712 mario79 673
;-----------------------------------------------------------------------------
2288 clevermous 674
uglobal
675
; all uglobals are zeroed at boot
3712 mario79 676
dma_process         dd 0
677
dma_slot_ptr        dd 0
678
cache_chain_pos     dd 0
679
cache_chain_ptr     dd 0
680
cache_chain_size    db 0
681
cache_chain_started db 0
682
dma_task_switched   db 0
683
dma_hdd             db 0
684
allow_dma_access    db 0
2288 clevermous 685
endg
3712 mario79 686
;-----------------------------------------------------------------------------
2288 clevermous 687
align 4
3870 mario79 688
IDE_irq_14_handler:
689
        cmp     [IDE_common_irq_param], irq14_num
690
        jne     .exit
691
 
2288 clevermous 692
        pushfd
693
        cli
694
        pushad
3870 mario79 695
        mov     [IDE_common_irq_param], 0
2288 clevermous 696
        mov     dx, [IDEContrRegsBaseAddr]
4291 mario79 697
; test whether it is our interrupt?
698
        add     edx, 2
699
        in      al, dx
700
        test    al, 100b
701
        jz      @f
3881 mario79 702
; clear Bus Master IDE Status register
703
; clear Interrupt bit
704
        out     dx, al
4291 mario79 705
; clear Bus Master IDE Command register
706
        sub     edx, 2
707
        xor     eax, eax
708
        out     dx, al
709
; read status register and remove the interrupt request
710
        mov     edx, [hdbase]
711
        add     edx, 0x7
712
        in      al, dx
3870 mario79 713
        popad
714
        popfd
4291 mario79 715
        mov     al, 1
716
        ret
3881 mario79 717
;--------------------------------------
718
align 4
4291 mario79 719
@@:
720
        popad
721
        popfd
722
;--------------------------------------
723
align 4
3870 mario79 724
.exit:
4291 mario79 725
        mov     al, 0
3870 mario79 726
        ret
727
;-----------------------------------------------------------------------------
2288 clevermous 728
align 4
3870 mario79 729
IDE_irq_15_handler:
730
        cmp     [IDE_common_irq_param], irq15_num
731
        jne     .exit
732
 
733
        pushfd
734
        cli
735
        pushad
736
        mov     [IDE_common_irq_param], 0
2288 clevermous 737
        mov     dx, [IDEContrRegsBaseAddr]
738
        add     dx, 8
4291 mario79 739
; test whether it is our interrupt?
740
        add     edx, 2
741
        in      al, dx
742
        test    al, 100b
743
        jz      @f
3881 mario79 744
; clear Bus Master IDE Status register
745
; clear Interrupt bit
746
        out     dx, al
4291 mario79 747
; clear Bus Master IDE Command register
748
        sub     edx, 2
749
        mov     al, 0
750
        out     dx, al
751
; read status register and remove the interrupt request
752
        mov     edx, [hdbase]
753
        add     edx, 0x7
754
        in      al, dx
3870 mario79 755
        popad
756
        popfd
4291 mario79 757
        mov     al, 1
758
        ret
3881 mario79 759
;--------------------------------------
760
align 4
4291 mario79 761
@@:
762
        popad
763
        popfd
764
;--------------------------------------
765
align 4
3870 mario79 766
.exit:
4291 mario79 767
        mov     al, 0
3870 mario79 768
        ret
769
;-----------------------------------------------------------------------------
770
align 4
771
IDE_common_irq_handler:
772
        cmp     [IDE_common_irq_param], 0
773
        je      .exit
774
 
775
        pushfd
776
        cli
777
        pushad
778
        xor     ebx, ebx
779
        mov     dx, [IDEContrRegsBaseAddr]
780
        mov     eax, IDE_common_irq_param
781
        cmp     [eax], irq14_num
782
        mov     [eax], bl
783
        je      @f
784
 
785
        add     dx, 8
3762 mario79 786
;--------------------------------------
787
align 4
3870 mario79 788
@@:
4291 mario79 789
; test whether it is our interrupt?
790
        add     edx, 2
791
        in      al, dx
792
        test    al, 100b
793
        jz      @f
3881 mario79 794
; clear Bus Master IDE Status register
795
; clear Interrupt bit
796
        out     dx, al
4291 mario79 797
; clear Bus Master IDE Command register
798
        sub     edx, 2
799
        xor     eax, eax
800
        out     dx, al
801
; read status register and remove the interrupt request
802
        mov     edx, [hdbase]
803
        add     edx, 0x7
804
        in      al, dx
2288 clevermous 805
        popad
806
        popfd
4291 mario79 807
        mov     al, 1
808
        ret
3881 mario79 809
;--------------------------------------
810
align 4
4291 mario79 811
@@:
812
        popad
813
        popfd
814
;--------------------------------------
815
align 4
3870 mario79 816
.exit:
4291 mario79 817
        mov     al, 0
2288 clevermous 818
        ret
3712 mario79 819
;-----------------------------------------------------------------------------
2288 clevermous 820
align 4
821
hd_read_dma:
822
        push    eax
823
        push    edx
824
        mov     edx, [dma_hdpos]
825
        cmp     edx, [hdpos]
826
        jne     .notread
827
        mov     edx, [dma_cur_sector]
828
        cmp     eax, edx
829
        jb      .notread
830
        add     edx, 15
831
        cmp     [esp+4], edx
832
        ja      .notread
833
        mov     eax, [esp+4]
834
        sub     eax, [dma_cur_sector]
835
        shl     eax, 9
836
        add     eax, (OS_BASE+IDE_DMA)
3742 clevermous 837
        push    ecx esi
2288 clevermous 838
        mov     esi, eax
3712 mario79 839
 
2288 clevermous 840
        mov     ecx, 512/4
841
        cld
842
        rep movsd
3742 clevermous 843
        pop     esi ecx
2288 clevermous 844
        pop     edx
845
        pop     eax
846
        ret
847
.notread:
3870 mario79 848
; set data for PRD Table
2288 clevermous 849
        mov     eax, IDE_descriptor_table
850
        mov     dword [eax], IDE_DMA
851
        mov     word [eax+4], 0x2000
852
        sub     eax, OS_BASE
3870 mario79 853
; select controller Primary or Secondary
2288 clevermous 854
        mov     dx, [IDEContrRegsBaseAddr]
3774 mario79 855
        push    eax
856
        mov     eax, [hd_address_table]
857
        cmp     [hdbase], eax ; 0x1F0
858
        pop     eax
2288 clevermous 859
        jz      @f
860
        add     edx, 8
861
@@:
862
        push    edx
3870 mario79 863
; Bus Master IDE PRD Table Address
2288 clevermous 864
        add     edx, 4
3870 mario79 865
; save IDE_descriptor_table
2288 clevermous 866
        out     dx, eax
867
        pop     edx
3870 mario79 868
; clear Bus Master IDE Command register
2288 clevermous 869
        mov     al, 0
870
        out     dx, al
3870 mario79 871
; clear Bus Master IDE Status register
872
; clear Error bit and Interrupt bit
2288 clevermous 873
        add     edx, 2
3870 mario79 874
        mov     al, 6 ; 110b
2288 clevermous 875
        out     dx, al
3712 mario79 876
; Select the desired drive
877
        mov     edx, [hdbase]
878
        add     edx, 6   ; адрес регистра головок
879
        mov     al, byte [hdid]
880
        add     al, 128+64+32
881
        out     dx, al ; номер головки/номер диска
882
 
2288 clevermous 883
        call    wait_for_hd_idle
884
        cmp     [hd_error], 0
885
        jnz     hd_read_error
3712 mario79 886
 
887
; ATA with 28 or 48 bit for sector number?
888
        mov     eax, [esp+4]
889
; -10h because the PreCache hits the boundary between lba28 and lba48
890
; 10h = 16  - size of PreCache
891
        cmp     eax, 0x10000000-10h
892
        jae     .lba48
893
;--------------------------------------
894
.lba28:
895
        pushfd
896
        cli
2288 clevermous 897
        xor     eax, eax
898
        mov     edx, [hdbase]
899
        inc     edx
3712 mario79 900
        out     dx, al ; ATA Features регистр "особенностей"
2288 clevermous 901
        inc     edx
3712 mario79 902
        mov     eax, 10h ; Sector Counter = 16 ; PreCache
903
        out     dx, al ; ATA Sector Counter счётчик секторов
2288 clevermous 904
        inc     edx
3712 mario79 905
        mov     eax, [esp+4+4]
906
        out     dx, al ; LBA Low LBA (7:0)
2288 clevermous 907
        shr     eax, 8
908
        inc     edx
3712 mario79 909
        out     dx, al ; LBA Mid LBA (15:8)
2288 clevermous 910
        shr     eax, 8
911
        inc     edx
3712 mario79 912
        out     dx, al ; LBA High LBA (23:16)
2288 clevermous 913
        shr     eax, 8
914
        inc     edx
3712 mario79 915
        and     al, 0xF ; LBA (27:24)
2288 clevermous 916
        add     al, byte [hdid]
917
        add     al, 11100000b
3712 mario79 918
        out     dx, al ; номер головки/номер диска
2288 clevermous 919
        inc     edx
3712 mario79 920
        mov     al, 0xC8 ; READ DMA
921
        out     dx, al ; ATACommand регистр команд
922
        jmp     .continue
923
;--------------------------------------
924
.lba48:
925
        pushfd
926
        cli
927
        xor     eax, eax
928
        mov     edx, [hdbase]
929
        inc     edx
930
        out     dx, al ; Features Previous Reserved
931
        out     dx, al ; Features Current Reserved
932
        inc     edx
933
        out     dx, al ; Sector Count Previous Sector count (15:8)
934
        mov     eax, 10h ; Sector Counter = 16 PreCache
935
        out     dx, al ; Sector Count Current Sector count (7:0)
936
        inc     edx
937
        mov     eax, [esp+4+4]
938
        rol     eax, 8
939
        out     dx, al ; LBA Low Previous LBA (31:24)
940
        xor     eax, eax ; because only 32 bit cache
941
        inc     edx
942
        out     dx, al ; LBA Mid Previous LBA (39:32)
943
        inc     edx
944
        out     dx, al ; LBA High Previous LBA (47:40)
945
        sub     edx, 2
946
        mov     eax, [esp+4+4]
947
        out     dx, al ; LBA Low Current LBA (7:0)
948
        shr     eax, 8
949
        inc     edx
950
        out     dx, al ; LBA Mid Current LBA (15:8)
951
        shr     eax, 8
952
        inc     edx
953
        out     dx, al ; LBA High Current LBA (23:16)
954
        inc     edx
955
        mov     al, byte [hdid]
956
        add     al, 128+64+32
957
        out     dx, al ; номер головки/номер диска
958
        inc     edx
959
        mov     al, 25h ; READ DMA EXT
960
        out     dx, al ; ATACommand регистр команд
961
;--------------------------------------
962
.continue:
3870 mario79 963
; select controller Primary or Secondary
2288 clevermous 964
        mov     dx, [IDEContrRegsBaseAddr]
3712 mario79 965
        mov     eax, [hd_address_table]
966
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 967
        jz      @f
968
        add     dx, 8
969
@@:
3870 mario79 970
; set write to memory and Start Bus Master
2288 clevermous 971
        mov     al, 9
972
        out     dx, al
3870 mario79 973
 
2288 clevermous 974
        mov     eax, [CURRENT_TASK]
975
        mov     [dma_process], eax
3870 mario79 976
 
2288 clevermous 977
        mov     eax, [TASK_BASE]
978
        mov     [dma_slot_ptr], eax
3870 mario79 979
 
3712 mario79 980
        mov     eax, [hd_address_table]
981
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 982
        jnz     .ide1
3762 mario79 983
 
984
        mov     [IDE_common_irq_param], irq14_num
2288 clevermous 985
        jmp     @f
986
.ide1:
3762 mario79 987
        mov     [IDE_common_irq_param], irq15_num
2288 clevermous 988
@@:
3712 mario79 989
        popfd
3870 mario79 990
; wait for interrupt
3712 mario79 991
        mov     eax, [hd_address_table]
992
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 993
        jnz     .wait_ide1
994
        call    wait_for_sector_dma_ide0
995
        jmp     @f
996
.wait_ide1:
997
        call    wait_for_sector_dma_ide1
998
@@:
999
        cmp     [hd_error], 0
1000
        jnz     hd_read_error
1001
        mov     eax, [hdpos]
1002
        mov     [dma_hdpos], eax
1003
        pop     edx
1004
        pop     eax
1005
        mov     [dma_cur_sector], eax
1006
        jmp     hd_read_dma
3712 mario79 1007
;-----------------------------------------------------------------------------
3742 clevermous 1008
cache_write_dma:
3881 mario79 1009
        mov     eax, [cache_chain_ptr] ; for what?
2288 clevermous 1010
        push    esi
3881 mario79 1011
; set data for PRD Table
2288 clevermous 1012
        mov     eax, IDE_descriptor_table
1013
        mov     edx, eax
1014
        pusha
1015
        mov     edi, (OS_BASE+IDE_DMA)
1016
        mov     dword [edx], IDE_DMA
1017
        movzx   ecx, [cache_chain_size]
1018
        shl     ecx, 9
1019
        mov     word [edx+4], cx
1020
        shr     ecx, 2
1021
        cld
1022
        rep movsd
1023
        popa
1024
        sub     eax, OS_BASE
3881 mario79 1025
; select controller Primary or Secondary
2288 clevermous 1026
        mov     dx, [IDEContrRegsBaseAddr]
3774 mario79 1027
        push    eax
1028
        mov     eax, [hd_address_table]
1029
        cmp     [hdbase], eax ; 0x1F0
1030
        pop     eax
2288 clevermous 1031
        jz      @f
1032
        add     edx, 8
1033
@@:
1034
        push    edx
3881 mario79 1035
; Bus Master IDE PRD Table Address
2288 clevermous 1036
        add     edx, 4
3881 mario79 1037
; save IDE_descriptor_table
2288 clevermous 1038
        out     dx, eax
1039
        pop     edx
3881 mario79 1040
; clear Bus Master IDE Command register
2288 clevermous 1041
        mov     al, 0
1042
        out     dx, al
3881 mario79 1043
; clear Bus Master IDE Status register
1044
; clear Error bit and Interrupt bit
2288 clevermous 1045
        add     edx, 2
1046
        mov     al, 6
1047
        out     dx, al
3712 mario79 1048
; Select the desired drive
1049
        mov     edx, [hdbase]
1050
        add     edx, 6   ; адрес регистра головок
1051
        mov     al, byte [hdid]
1052
        add     al, 128+64+32
1053
        out     dx, al ; номер головки/номер диска
1054
 
2288 clevermous 1055
        call    wait_for_hd_idle
1056
        cmp     [hd_error], 0
1057
        jnz     hd_write_error_dma
3712 mario79 1058
 
1059
; ATA with 28 or 48 bit for sector number?
1060
        mov     esi, [cache_chain_ptr]
1061
        mov     eax, [esi]
1062
; -40h because the PreCache hits the boundary between lba28 and lba48
1063
; 40h = 64  - the maximum number of sectors to be written for one command
1064
        cmp     eax, 0x10000000-40h
1065
        jae     .lba48
1066
;--------------------------------------
1067
.lba28:
1068
        pushfd
1069
        cli
2288 clevermous 1070
        xor     eax, eax
1071
        mov     edx, [hdbase]
1072
        inc     edx
3712 mario79 1073
        out     dx, al ; ATA Features регистр "особенностей"
2288 clevermous 1074
        inc     edx
3712 mario79 1075
        mov     al, [cache_chain_size] ; Sector Counter
1076
        out     dx, al ; ATA Sector Counter счётчик секторов
2288 clevermous 1077
        inc     edx
1078
        mov     eax, [esi]
3712 mario79 1079
        out     dx, al ; LBA Low LBA (7:0)
2288 clevermous 1080
        shr     eax, 8
1081
        inc     edx
3712 mario79 1082
        out     dx, al ; LBA Mid LBA (15:8)
2288 clevermous 1083
        shr     eax, 8
1084
        inc     edx
3712 mario79 1085
        out     dx, al ; LBA High LBA (23:16)
2288 clevermous 1086
        shr     eax, 8
1087
        inc     edx
3712 mario79 1088
        and     al, 0xF ; LBA (27:24)
2288 clevermous 1089
        add     al, byte [hdid]
1090
        add     al, 11100000b
3712 mario79 1091
        out     dx, al ; номер головки/номер диска
2288 clevermous 1092
        inc     edx
3712 mario79 1093
        mov     al, 0xCA ; WRITE DMA
1094
        out     dx, al ; ATACommand регистр команд
1095
        jmp     .continue
1096
;--------------------------------------
1097
.lba48:
1098
        pushfd
1099
        cli
1100
        xor     eax, eax
1101
        mov     edx, [hdbase]
1102
        inc     edx
1103
        out     dx, al ; Features Previous Reserved
1104
        out     dx, al ; Features Current Reserved
1105
        inc     edx
1106
        out     dx, al ; Sector Count Previous Sector count (15:8)
1107
        mov     al, [cache_chain_size] ; Sector Counter
1108
        out     dx, al ; Sector Count Current Sector count (7:0)
1109
        inc     edx
1110
        mov     eax, [esi]
1111
        rol     eax, 8
1112
        out     dx, al ; LBA Low Previous LBA (31:24)
1113
        xor     eax, eax ; because only 32 bit cache
1114
        inc     edx
1115
        out     dx, al ; LBA Mid Previous LBA (39:32)
1116
        inc     edx
1117
        out     dx, al ; LBA High Previous LBA (47:40)
1118
        sub     edx, 2
1119
        mov     eax, [esi]
1120
        out     dx, al ; LBA Low Current LBA (7:0)
1121
        shr     eax, 8
1122
        inc     edx
1123
        out     dx, al ; LBA Mid Current LBA (15:8)
1124
        shr     eax, 8
1125
        inc     edx
1126
        out     dx, al ; LBA High Current LBA (23:16)
1127
        inc     edx
1128
        mov     al, byte [hdid]
1129
        add     al, 128+64+32
1130
        out     dx, al ; номер головки/номер диска
1131
        inc     edx
1132
        mov     al, 35h ; WRITE DMA EXT
1133
        out     dx, al ; ATACommand регистр команд
1134
;--------------------------------------
1135
.continue:
3881 mario79 1136
; select controller Primary or Secondary
2288 clevermous 1137
        mov     dx, [IDEContrRegsBaseAddr]
3712 mario79 1138
        mov     eax, [hd_address_table]
1139
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 1140
        jz      @f
1141
        add     dx, 8
1142
@@:
3881 mario79 1143
; set write to device and Start Bus Master
2288 clevermous 1144
        mov     al, 1
1145
        out     dx, al
1146
        mov     eax, [CURRENT_TASK]
1147
        mov     [dma_process], eax
1148
        mov     eax, [TASK_BASE]
1149
        mov     [dma_slot_ptr], eax
3712 mario79 1150
        mov     eax, [hd_address_table]
1151
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 1152
        jnz     .ide1
3762 mario79 1153
 
1154
        mov     [IDE_common_irq_param], irq14_num
2288 clevermous 1155
        jmp     @f
1156
.ide1:
3762 mario79 1157
        mov     [IDE_common_irq_param], irq15_num
2288 clevermous 1158
@@:
3712 mario79 1159
        popfd
3881 mario79 1160
; wait for interrupt
2288 clevermous 1161
        mov     [dma_cur_sector], not 0x40
3712 mario79 1162
        mov     eax, [hd_address_table]
1163
        cmp     [hdbase], eax ; 0x1F0
2288 clevermous 1164
        jnz     .wait_ide1
1165
        call    wait_for_sector_dma_ide0
1166
        jmp     @f
1167
.wait_ide1:
1168
        call    wait_for_sector_dma_ide1
1169
@@:
1170
        cmp     [hd_error], 0
1171
        jnz     hd_write_error_dma
1172
        pop     esi
1173
        ret
3712 mario79 1174
;-----------------------------------------------------------------------------
2288 clevermous 1175
uglobal
3881 mario79 1176
align 4
3762 mario79 1177
IDE_Interrupt   dw ?
3712 mario79 1178
IDEContrRegsBaseAddr         dw ?
1179
IDEContrProgrammingInterface dw ?
3711 clevermous 1180
IDE_BAR0_val    dw ?
1181
IDE_BAR1_val    dw ?
1182
IDE_BAR2_val    dw ?
1183
IDE_BAR3_val    dw ?
2288 clevermous 1184
endg
3712 mario79 1185
;-----------------------------------------------------------------------------
4578 clevermous 1186
 
1187
proc clear_pci_ide_interrupts
1188
        mov     esi, pcidev_list
1189
.loop:
1190
        mov     esi, [esi+PCIDEV.fd]
1191
        cmp     esi, pcidev_list
1192
        jz      .done
1193
        cmp     [esi+PCIDEV.class], 0x01018F
1194
        jnz     .loop
1195
        mov     ah, [esi+PCIDEV.bus]
1196
        mov     al, 2
1197
        mov     bh, [esi+PCIDEV.devfn]
1198
        mov     bl, 0x20
1199
        call    pci_read_reg
1200
        and     eax, 0FFFCh
1201
        mov     edx, eax
1202
        add     edx, 2
1203
        in      al, dx
1204
        DEBUGF 1,'K : clear_pci_ide_interrupts: port[%x] = %x ',dx,al
1205
        out     dx, al
1206
        in      al, dx
1207
        DEBUGF 1,'-> %x; ',al
1208
        add     edx, 8
1209
        in      al, dx
1210
        DEBUGF 1,'port[%x] = %x ',dx,al
1211
        out     dx, al
1212
        in      al, dx
1213
        DEBUGF 1,'-> %x\n',al
1214
        jmp     .loop
1215
.done:
1216
        ret
1217
endp