Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4429 Serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 4420 $
9
 
10
 
11
; Low-level driver for HDD access
12
; DMA support by Mario79
13
; LBA48 support by Mario79
14
;-----------------------------------------------------------------------------
15
struct HD_DATA
16
hdbase  dd      ?
17
hdid    dd      ?
18
hdpos   dd      ?
19
ends
20
 
21
iglobal
22
align 4
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:
33
 
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
38
 
39
hd_address_table:
40
        dd      0x1f0, 0x00, 0x1f0, 0x10
41
        dd      0x170, 0x00, 0x170, 0x10
42
endg
43
 
44
uglobal
45
ide_mutex               MUTEX
46
ide_channel1_mutex      MUTEX
47
ide_channel2_mutex      MUTEX
48
endg
49
 
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]
72
        push    ecx
73
        mov     ecx, [hd_address_table]
74
        cmp     [eax+HD_DATA.hdbase], ecx ; 0x1F0
75
        pop     ecx
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:
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
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
;--------------------------------------
119
        call    hd_read_dma
120
        jmp     @f
121
.nodma:
122
        call    hd_read_pio
123
@@:
124
        cmp     [hd_error], 0
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
149
 
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]
172
        push    ecx
173
        mov     ecx, [hd_address_table]
174
        cmp     [eax+HD_DATA.hdbase], ecx ; 0x1F0
175
        pop     ecx
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
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
;--------------------------------------
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
262
 
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
273
 
274
;-----------------------------------------------------------------------------
275
align 4
276
; input: eax = sector, edi -> buffer
277
; output: edi = edi + 512
278
hd_read_pio:
279
        push    eax edx
280
 
281
; Select the desired drive
282
        mov     edx, [hdbase]
283
        add     edx, 6   ;адрес регистра головок
284
        mov     al, byte [hdid]
285
        add     al, 128+64+32
286
        out     dx, al; номер головки/номер диска
287
 
288
        call    wait_for_hd_idle
289
        cmp     [hd_error], 0
290
        jne     hd_read_error
291
 
292
; ATA with 28 or 48 bit for sector number?
293
        mov     eax, [esp+4]
294
        cmp     eax, 0x10000000
295
        jae     .lba48
296
;--------------------------------------
297
.lba28:
298
        pushfd
299
        cli
300
        xor     eax, eax
301
        mov     edx, [hdbase]
302
        inc     edx
303
        out     dx, al ; ATA Features регистр "особенностей"
304
        inc     edx
305
        inc     eax
306
        out     dx, al ; ATA Sector Counter счётчик секторов
307
        inc     edx
308
        mov     eax, [esp+4+4]
309
        out     dx, al ; LBA Low LBA (7:0)
310
        shr     eax, 8
311
        inc     edx
312
        out     dx, al ; LBA Mid LBA (15:8)
313
        shr     eax, 8
314
        inc     edx
315
        out     dx, al ; LBA High LBA (23:16)
316
        shr     eax, 8
317
        inc     edx
318
        and     al, 1+2+4+8 ; LBA (27:24)
319
        add     al, byte [hdid]
320
        add     al, 128+64+32
321
        out     dx, al ; номер головки/номер диска
322
        inc     edx
323
        mov     al, 20h ; READ SECTOR(S)
324
        out     dx, al ; ATACommand регистр команд
325
        popfd
326
        jmp     .continue
327
;--------------------------------------
328
.lba48:
329
        pushfd
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
341
        mov     eax, [esp+4+4]
342
        rol     eax, 8
343
        out     dx, al ; LBA Low Previous LBA (31:24)
344
        xor     eax, eax ; because only 32 bit cache
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)
349
        sub     edx, 2
350
        mov     eax, [esp+4+4]
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
361
        out     dx, al ; номер головки/номер диска
362
        inc     edx
363
        mov     al, 24h ; READ SECTOR(S) EXT
364
        out     dx, al ; ATACommand регистр команд
365
        popfd
366
;--------------------------------------
367
.continue:
368
        call    wait_for_sector_buffer
369
 
370
        cmp     [hd_error], 0
371
        jne     hd_read_error
372
 
373
        pushfd
374
        cli
375
 
376
        mov     ecx, 256
377
        mov     edx, [hdbase]
378
        cld
379
        rep insw
380
        popfd
381
 
382
        pop     edx eax
383
        ret
384
;-----------------------------------------------------------------------------
385
align 4
386
; edi -> sector, esi -> data
387
cache_write_pio:
388
; Select the desired drive
389
        mov     edx, [hdbase]
390
        add     edx, 6   ;адрес регистра головок
391
        mov     al, byte [hdid]
392
        add     al, 128+64+32
393
        out     dx, al ; номер головки/номер диска
394
 
395
        call    wait_for_hd_idle
396
        cmp     [hd_error], 0
397
        jne     hd_write_error
398
 
399
; ATA with 28 or 48 bit for sector number?
400
        mov     eax, [edi]
401
        cmp     eax, 0x10000000
402
        jae     .lba48
403
;--------------------------------------
404
.lba28:
405
        pushfd
406
        cli
407
        xor     eax, eax
408
        mov     edx, [hdbase]
409
        inc     edx
410
        out     dx, al ; ATA Features регистр "особенностей"
411
        inc     edx
412
        inc     eax
413
        out     dx, al ; ATA Sector Counter счётчик секторов
414
        inc     edx
415
        mov     eax, [edi]      ; eax = sector to write
416
        out     dx, al ; LBA Low LBA (7:0)
417
        shr     eax, 8
418
        inc     edx
419
        out     dx, al ; LBA Mid LBA (15:8)
420
        shr     eax, 8
421
        inc     edx
422
        out     dx, al ; LBA High LBA (23:16)
423
        shr     eax, 8
424
        inc     edx
425
        and     al, 1+2+4+8 ; LBA (27:24)
426
        add     al, byte [hdid]
427
        add     al, 128+64+32
428
        out     dx, al ; номер головки/номер диска
429
        inc     edx
430
        mov     al, 30h ; WRITE SECTOR(S)
431
        out     dx, al ; ATACommand регистр команд
432
        jmp     .continue
433
;--------------------------------------
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
447
        mov     eax, [edi]
448
        rol     eax, 8
449
        out     dx, al ; LBA Low Previous LBA (31:24)
450
        xor     eax, eax ; because only 32 bit cache
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)
455
        sub     edx, 2
456
        mov     eax, [edi]
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
467
        out     dx, al ; номер головки/номер диска
468
        inc     edx
469
        mov     al, 34h ; WRITE SECTOR(S) EXT
470
        out     dx, al ; ATACommand регистр команд
471
;--------------------------------------
472
.continue:
473
        popfd
474
        call    wait_for_sector_buffer
475
 
476
        cmp     [hd_error], 0
477
        jne     hd_write_error
478
 
479
        push    ecx esi
480
 
481
        pushfd
482
        cli
483
        mov     ecx, 256
484
        mov     edx, [hdbase]
485
        cld
486
        rep outsw
487
        popfd
488
 
489
        pop     esi ecx
490
        ret
491
;-----------------------------------------------------------------------------
492
align 4
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
500
;-----------------------------------------------------------------------------
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
507
 
508
        pop     eax
509
        mov     [hd_error], 0
510
        ret
511
;-----------------------------------------------------------------------------
512
hd_timeout_error:
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
518
        mov     [hd_error], 1
519
        pop     eax
520
        ret
521
;-----------------------------------------------------------------------------
522
hd_read_error:
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
528
        pop     edx eax
529
        ret
530
;-----------------------------------------------------------------------------
531
hd_write_error_dma:
532
        pop     esi
533
hd_write_error:
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
539
        ret
540
;-----------------------------------------------------------------------------
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
549
;--------------------------------------
550
align 4
551
wfhil1:
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
 
560
@@:
561
        pop     edx eax
562
        ret
563
;-----------------------------------------------------------------------------
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
572
;--------------------------------------
573
align 4
574
hdwait_sbuf:                  ; wait for sector buffer to be ready
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
590
@@:
591
        mov     [hd_error], 1
592
 
593
buf_wait_ok:
594
        pop     edx eax
595
        ret
596
;-----------------------------------------------------------------------------
597
irq14_num equ byte 14
598
irq15_num equ byte 15
599
;-----------------------------------------------------------------------------
600
align 4
601
wait_for_sector_dma_ide0:
602
        push    eax
603
        push    edx
604
        call    save_hd_wait_timeout
605
;--------------------------------------
606
align 4
607
.wait:
608
        call    change_task
609
        cmp     [IDE_common_irq_param], 0
610
        jz      .done
611
 
612
        call    check_hd_wait_timeout
613
        cmp     [hd_error], 0
614
        jz      .wait
615
; clear Bus Master IDE Command register
616
        pushfd
617
        cli
618
        mov     [IDE_common_irq_param], 0
619
        mov     dx, [IDEContrRegsBaseAddr]
620
        mov     al, 0
621
        out     dx, al
622
        popfd
623
;--------------------------------------
624
align 4
625
.done:
626
        pop     edx
627
        pop     eax
628
        ret
629
;-----------------------------------------------------------------------------
630
align 4
631
wait_for_sector_dma_ide1:
632
        push    eax
633
        push    edx
634
        call    save_hd_wait_timeout
635
;--------------------------------------
636
align 4
637
.wait:
638
        call    change_task
639
        cmp     [IDE_common_irq_param], 0
640
        jz      .done
641
 
642
        call    check_hd_wait_timeout
643
        cmp     [hd_error], 0
644
        jz      .wait
645
; clear Bus Master IDE Command register
646
        pushfd
647
        cli
648
        mov     [IDE_common_irq_param], 0
649
        mov     dx, [IDEContrRegsBaseAddr]
650
        add     dx, 8
651
        mov     al, 0
652
        out     dx, al
653
        popfd
654
;--------------------------------------
655
align 4
656
.done:
657
        pop     edx
658
        pop     eax
659
        ret
660
;-----------------------------------------------------------------------------
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:
665
        dd IDE_DMA
666
        dw 0x2000
667
        dw 0x8000
668
 
669
dma_cur_sector  dd not 40h
670
dma_hdpos       dd 0
671
IDE_common_irq_param db 0
672
endg
673
;-----------------------------------------------------------------------------
674
uglobal
675
; all uglobals are zeroed at boot
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
685
endg
686
;-----------------------------------------------------------------------------
687
align 4
688
IDE_irq_14_handler:
689
        cmp     [IDE_common_irq_param], irq14_num
690
        jne     .exit
691
 
692
        pushfd
693
        cli
694
        pushad
695
        mov     [IDE_common_irq_param], 0
696
        mov     dx, [IDEContrRegsBaseAddr]
697
; test whether it is our interrupt?
698
        add     edx, 2
699
        in      al, dx
700
        test    al, 100b
701
        jz      @f
702
; clear Bus Master IDE Status register
703
; clear Interrupt bit
704
        out     dx, al
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
713
        popad
714
        popfd
715
        mov     al, 1
716
        ret
717
;--------------------------------------
718
align 4
719
@@:
720
        popad
721
        popfd
722
;--------------------------------------
723
align 4
724
.exit:
725
        mov     al, 0
726
        ret
727
;-----------------------------------------------------------------------------
728
align 4
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
737
        mov     dx, [IDEContrRegsBaseAddr]
738
        add     dx, 8
739
; test whether it is our interrupt?
740
        add     edx, 2
741
        in      al, dx
742
        test    al, 100b
743
        jz      @f
744
; clear Bus Master IDE Status register
745
; clear Interrupt bit
746
        out     dx, al
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
755
        popad
756
        popfd
757
        mov     al, 1
758
        ret
759
;--------------------------------------
760
align 4
761
@@:
762
        popad
763
        popfd
764
;--------------------------------------
765
align 4
766
.exit:
767
        mov     al, 0
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
786
;--------------------------------------
787
align 4
788
@@:
789
; test whether it is our interrupt?
790
        add     edx, 2
791
        in      al, dx
792
        test    al, 100b
793
        jz      @f
794
; clear Bus Master IDE Status register
795
; clear Interrupt bit
796
        out     dx, al
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
805
        popad
806
        popfd
807
        mov     al, 1
808
        ret
809
;--------------------------------------
810
align 4
811
@@:
812
        popad
813
        popfd
814
;--------------------------------------
815
align 4
816
.exit:
817
        mov     al, 0
818
        ret
819
;-----------------------------------------------------------------------------
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)
837
        push    ecx esi
838
        mov     esi, eax
839
 
840
        mov     ecx, 512/4
841
        cld
842
        rep movsd
843
        pop     esi ecx
844
        pop     edx
845
        pop     eax
846
        ret
847
.notread:
848
; set data for PRD Table
849
        mov     eax, IDE_descriptor_table
850
        mov     dword [eax], IDE_DMA
851
        mov     word [eax+4], 0x2000
852
        sub     eax, OS_BASE
853
; select controller Primary or Secondary
854
        mov     dx, [IDEContrRegsBaseAddr]
855
        push    eax
856
        mov     eax, [hd_address_table]
857
        cmp     [hdbase], eax ; 0x1F0
858
        pop     eax
859
        jz      @f
860
        add     edx, 8
861
@@:
862
        push    edx
863
; Bus Master IDE PRD Table Address
864
        add     edx, 4
865
; save IDE_descriptor_table
866
        out     dx, eax
867
        pop     edx
868
; clear Bus Master IDE Command register
869
        mov     al, 0
870
        out     dx, al
871
; clear Bus Master IDE Status register
872
; clear Error bit and Interrupt bit
873
        add     edx, 2
874
        mov     al, 6 ; 110b
875
        out     dx, al
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
 
883
        call    wait_for_hd_idle
884
        cmp     [hd_error], 0
885
        jnz     hd_read_error
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
897
        xor     eax, eax
898
        mov     edx, [hdbase]
899
        inc     edx
900
        out     dx, al ; ATA Features регистр "особенностей"
901
        inc     edx
902
        mov     eax, 10h ; Sector Counter = 16 ; PreCache
903
        out     dx, al ; ATA Sector Counter счётчик секторов
904
        inc     edx
905
        mov     eax, [esp+4+4]
906
        out     dx, al ; LBA Low LBA (7:0)
907
        shr     eax, 8
908
        inc     edx
909
        out     dx, al ; LBA Mid LBA (15:8)
910
        shr     eax, 8
911
        inc     edx
912
        out     dx, al ; LBA High LBA (23:16)
913
        shr     eax, 8
914
        inc     edx
915
        and     al, 0xF ; LBA (27:24)
916
        add     al, byte [hdid]
917
        add     al, 11100000b
918
        out     dx, al ; номер головки/номер диска
919
        inc     edx
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:
963
; select controller Primary or Secondary
964
        mov     dx, [IDEContrRegsBaseAddr]
965
        mov     eax, [hd_address_table]
966
        cmp     [hdbase], eax ; 0x1F0
967
        jz      @f
968
        add     dx, 8
969
@@:
970
; set write to memory and Start Bus Master
971
        mov     al, 9
972
        out     dx, al
973
 
974
        mov     eax, [CURRENT_TASK]
975
        mov     [dma_process], eax
976
 
977
        mov     eax, [TASK_BASE]
978
        mov     [dma_slot_ptr], eax
979
 
980
        mov     eax, [hd_address_table]
981
        cmp     [hdbase], eax ; 0x1F0
982
        jnz     .ide1
983
 
984
        mov     [IDE_common_irq_param], irq14_num
985
        jmp     @f
986
.ide1:
987
        mov     [IDE_common_irq_param], irq15_num
988
@@:
989
        popfd
990
; wait for interrupt
991
        mov     eax, [hd_address_table]
992
        cmp     [hdbase], eax ; 0x1F0
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
1007
;-----------------------------------------------------------------------------
1008
cache_write_dma:
1009
        mov     eax, [cache_chain_ptr] ; for what?
1010
        push    esi
1011
; set data for PRD Table
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
1025
; select controller Primary or Secondary
1026
        mov     dx, [IDEContrRegsBaseAddr]
1027
        push    eax
1028
        mov     eax, [hd_address_table]
1029
        cmp     [hdbase], eax ; 0x1F0
1030
        pop     eax
1031
        jz      @f
1032
        add     edx, 8
1033
@@:
1034
        push    edx
1035
; Bus Master IDE PRD Table Address
1036
        add     edx, 4
1037
; save IDE_descriptor_table
1038
        out     dx, eax
1039
        pop     edx
1040
; clear Bus Master IDE Command register
1041
        mov     al, 0
1042
        out     dx, al
1043
; clear Bus Master IDE Status register
1044
; clear Error bit and Interrupt bit
1045
        add     edx, 2
1046
        mov     al, 6
1047
        out     dx, al
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
 
1055
        call    wait_for_hd_idle
1056
        cmp     [hd_error], 0
1057
        jnz     hd_write_error_dma
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
1070
        xor     eax, eax
1071
        mov     edx, [hdbase]
1072
        inc     edx
1073
        out     dx, al ; ATA Features регистр "особенностей"
1074
        inc     edx
1075
        mov     al, [cache_chain_size] ; Sector Counter
1076
        out     dx, al ; ATA Sector Counter счётчик секторов
1077
        inc     edx
1078
        mov     eax, [esi]
1079
        out     dx, al ; LBA Low LBA (7:0)
1080
        shr     eax, 8
1081
        inc     edx
1082
        out     dx, al ; LBA Mid LBA (15:8)
1083
        shr     eax, 8
1084
        inc     edx
1085
        out     dx, al ; LBA High LBA (23:16)
1086
        shr     eax, 8
1087
        inc     edx
1088
        and     al, 0xF ; LBA (27:24)
1089
        add     al, byte [hdid]
1090
        add     al, 11100000b
1091
        out     dx, al ; номер головки/номер диска
1092
        inc     edx
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:
1136
; select controller Primary or Secondary
1137
        mov     dx, [IDEContrRegsBaseAddr]
1138
        mov     eax, [hd_address_table]
1139
        cmp     [hdbase], eax ; 0x1F0
1140
        jz      @f
1141
        add     dx, 8
1142
@@:
1143
; set write to device and Start Bus Master
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
1150
        mov     eax, [hd_address_table]
1151
        cmp     [hdbase], eax ; 0x1F0
1152
        jnz     .ide1
1153
 
1154
        mov     [IDE_common_irq_param], irq14_num
1155
        jmp     @f
1156
.ide1:
1157
        mov     [IDE_common_irq_param], irq15_num
1158
@@:
1159
        popfd
1160
; wait for interrupt
1161
        mov     [dma_cur_sector], not 0x40
1162
        mov     eax, [hd_address_table]
1163
        cmp     [hdbase], eax ; 0x1F0
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
1174
;-----------------------------------------------------------------------------
1175
uglobal
1176
align 4
1177
IDE_Interrupt   dw ?
1178
IDEContrRegsBaseAddr         dw ?
1179
IDEContrProgrammingInterface dw ?
1180
IDE_BAR0_val    dw ?
1181
IDE_BAR1_val    dw ?
1182
IDE_BAR2_val    dw ?
1183
IDE_BAR3_val    dw ?
1184
endg
1185
;-----------------------------------------------------------------------------
4587 Serge 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