Subversion Repositories Kolibri OS

Rev

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