Subversion Repositories Kolibri OS

Rev

Rev 6650 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2288 clevermous 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
5363 yogev_ezra 3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
2288 clevermous 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
$Revision: 6842 $
9
 
5569 Pathoswith 10
; HDD driver
2288 clevermous 11
 
3742 clevermous 12
struct HD_DATA
6842 pathoswith 13
hdpos   dw  ?
14
hdid    dw  ?
5852 pathoswith 15
hdbase  dw  ?
16
hd48    dw  ?
6842 pathoswith 17
sectors dq  ?
3742 clevermous 18
ends
5569 Pathoswith 19
;-----------------------------------------------------------------
3742 clevermous 20
iglobal
2288 clevermous 21
align 4
3742 clevermous 22
ide_callbacks:
5852 pathoswith 23
    dd  ide_callbacks.end - ide_callbacks
24
    dd  0   ; no close function
25
    dd  0   ; no closemedia function
26
    dd  ide_querymedia
27
    dd  ide_read
28
    dd  ide_write
29
    dd  0   ; no flush function
30
    dd  0   ; use default cache size
3742 clevermous 31
.end:
2288 clevermous 32
 
6842 pathoswith 33
hd0_data    HD_DATA     1,  0
34
hd1_data    HD_DATA     2,  16
35
hd2_data    HD_DATA     3,  0
36
hd3_data    HD_DATA     4,  16
37
hd4_data    HD_DATA     5,  0
38
hd5_data    HD_DATA     6,  16
39
hd6_data    HD_DATA     7,  0
40
hd7_data    HD_DATA     8,  16
41
hd8_data    HD_DATA     9,  0
42
hd9_data    HD_DATA     10, 16
43
hd10_data   HD_DATA     11, 0
44
hd11_data   HD_DATA     12, 16
4273 clevermous 45
 
4700 mario79 46
ide_mutex_table:
5852 pathoswith 47
    dd  ide_channel1_mutex
48
    dd  ide_channel2_mutex
49
    dd  ide_channel3_mutex
50
    dd  ide_channel4_mutex
51
    dd  ide_channel5_mutex
52
    dd  ide_channel6_mutex
3742 clevermous 53
endg
5569 Pathoswith 54
;-----------------------------------------------------------------
3742 clevermous 55
uglobal
56
ide_mutex               MUTEX
57
ide_channel1_mutex      MUTEX
58
ide_channel2_mutex      MUTEX
4700 mario79 59
ide_channel3_mutex      MUTEX
60
ide_channel4_mutex      MUTEX
61
ide_channel5_mutex      MUTEX
62
ide_channel6_mutex      MUTEX
5569 Pathoswith 63
blockSize:
64
rb 4
65
sector:
66
rb 6
67
allow_dma_access        db ?
68
IDE_common_irq_param    db ?
69
eventPointer            dd ?
70
eventID                 dd ?
3742 clevermous 71
endg
5569 Pathoswith 72
;-----------------------------------------------------------------
5570 clevermous 73
ide_read:
74
        mov     al, 25h     ; READ DMA EXT
75
        jmp     ide_read_write
76
 
77
ide_write:
78
        mov     al, 35h     ; WRITE DMA EXT
79
proc ide_read_write stdcall uses esi edi ebx, \
3742 clevermous 80
        hd_data, buffer, startsector:qword, numsectors
81
        ; hd_data = pointer to hd*_data
5570 clevermous 82
        ; buffer = pointer to buffer with/for data
3742 clevermous 83
        ; startsector = 64-bit start sector
84
        ; numsectors = pointer to number of sectors on input,
5570 clevermous 85
        ;  must be filled with number of sectors really read/written
3742 clevermous 86
locals
87
sectors_todo    dd      ?
88
channel_lock    dd      ?
89
endl
5852 pathoswith 90
        mov     bl, al
5569 Pathoswith 91
; get number of requested sectors and say that no sectors were read yet
3742 clevermous 92
        mov     ecx, [numsectors]
93
        mov     eax, [ecx]
94
        mov     dword [ecx], 0
95
        mov     [sectors_todo], eax
5569 Pathoswith 96
; acquire the global lock
3742 clevermous 97
        mov     ecx, ide_mutex
98
        call    mutex_lock
4700 mario79 99
        mov     ecx, [hd_data]
5852 pathoswith 100
        movzx   ecx, [ecx+HD_DATA.hdpos]
4700 mario79 101
        dec     ecx
102
        shr     ecx, 1
103
        shl     ecx, 2
104
        mov     ecx, [ecx + ide_mutex_table]
3742 clevermous 105
        mov     [channel_lock], ecx
106
        call    mutex_lock
5569 Pathoswith 107
; prepare worker procedures variables
5852 pathoswith 108
        mov     esi, [buffer]
109
        mov     edi, esi
3742 clevermous 110
        mov     ecx, [hd_data]
5852 pathoswith 111
        movzx   eax, [ecx+HD_DATA.hdbase]
3742 clevermous 112
        mov     [hdbase], eax
5852 pathoswith 113
        mov     ax, [ecx+HD_DATA.hdid]
3742 clevermous 114
        mov     [hdid], eax
115
        mov     eax, dword [startsector]
5569 Pathoswith 116
        mov     [sector], eax
5852 pathoswith 117
        cmp     [ecx+HD_DATA.hd48], 0
118
        jz      .LBA28
5569 Pathoswith 119
        mov     ax, word [startsector+4]
120
        mov     [sector+4], ax
5852 pathoswith 121
        movzx   ecx, [ecx+HD_DATA.hdpos]
122
        mov     [hdpos], ecx
4720 mario79 123
        dec     ecx
124
        shr     ecx, 2
125
        imul    ecx, sizeof.IDE_DATA
126
        add     ecx, IDE_controller_1
127
        mov     [IDE_controller_pointer], ecx
128
        mov     eax, [hdpos]
129
        dec     eax
130
        and     eax, 11b
131
        shr     eax, 1
132
        add     eax, ecx
133
        cmp     [eax+IDE_DATA.dma_hdd_channel_1], 1
5569 Pathoswith 134
        jz      .next
5570 clevermous 135
        dec     ebx     ; READ/WRITE SECTOR(S) EXT
5852 pathoswith 136
; LBA48 supports max 10000h sectors per time
5569 Pathoswith 137
; loop until all sectors will be processed
138
.next:
139
        mov     ecx, 8000h
140
        cmp     ecx, [sectors_todo]
141
        jbe     @f
142
        mov     ecx, [sectors_todo]
143
@@:
144
        mov     [blockSize], ecx
145
        push    ecx
146
        call    IDE_transfer
147
        pop     ecx
148
        jc      .out
3742 clevermous 149
        mov     eax, [numsectors]
150
        add     [eax], ecx
151
        sub     [sectors_todo], ecx
5569 Pathoswith 152
        jz      .out
153
        add     [sector], ecx
154
        adc     word [sector+4], 0
155
        jmp     .next
6650 pathoswith 156
 
5852 pathoswith 157
.LBA28:
158
        add     eax, [sectors_todo]
159
        add     eax, 0xF0000000
160
        jc      .out
161
        sub     bl, 5   ; READ/WRITE SECTOR(S)
162
; LBA28 supports max 256 sectors per time
163
; loop until all sectors will be processed
164
.next28:
165
        mov     ecx, 256
166
        cmp     ecx, [sectors_todo]
167
        jbe     @f
168
        mov     ecx, [sectors_todo]
169
@@:
170
        mov     [blockSize], ecx
171
        push    ecx
172
        call    IDE_transfer.LBA28
173
        pop     ecx
174
        jc      .out
175
        mov     eax, [numsectors]
176
        add     [eax], ecx
177
        sub     [sectors_todo], ecx
178
        jz      .out
179
        add     [sector], ecx
180
        jmp     .next28
6650 pathoswith 181
 
5569 Pathoswith 182
; loop is done, either due to error or because everything is done
183
; release the global lock and return the corresponding status
184
.out:
185
        sbb     eax, eax
186
        push    eax
3742 clevermous 187
        mov     ecx, [channel_lock]
188
        call    mutex_unlock
189
        mov     ecx, ide_mutex
190
        call    mutex_unlock
5569 Pathoswith 191
        pop     eax
3742 clevermous 192
        ret
193
endp
5569 Pathoswith 194
;-----------------------------------------------------------------
3742 clevermous 195
proc ide_querymedia stdcall, hd_data, mediainfo
196
        mov     eax, [mediainfo]
6842 pathoswith 197
        mov     edx, [hd_data]
3742 clevermous 198
        mov     [eax+DISKMEDIAINFO.Flags], 0
199
        mov     [eax+DISKMEDIAINFO.SectorSize], 512
6842 pathoswith 200
        mov     ecx, dword[edx+HD_DATA.sectors]
201
        mov     dword[eax+DISKMEDIAINFO.Capacity], ecx
202
        mov     ecx, dword[edx+HD_DATA.sectors+4]
203
        mov     dword[eax+DISKMEDIAINFO.Capacity+4], ecx
3742 clevermous 204
        xor     eax, eax
205
        ret
206
endp
5569 Pathoswith 207
;-----------------------------------------------------------------
208
; input: esi -> buffer, bl = command, [sector], [blockSize]
209
; output: esi -> next block in buffer
210
; for pio read esi equal edi
211
IDE_transfer:
3702 mario79 212
        mov     edx, [hdbase]
5569 Pathoswith 213
        add     edx, 6
3702 mario79 214
        mov     al, byte [hdid]
5569 Pathoswith 215
        add     al, 224
216
        out     dx, al  ; select the desired drive
217
        call    save_hd_wait_timeout
218
        inc     edx
219
@@:
220
        call    check_hd_wait_timeout
221
        jc      .hd_error
222
        in      al, dx
223
        test    al, 128 ; ready for command?
224
        jnz     @b
225
        pushfd          ; fill the ports
2288 clevermous 226
        cli
227
        mov     edx, [hdbase]
228
        inc     edx
229
        inc     edx
5569 Pathoswith 230
        mov     al, [blockSize+1]
231
        out     dx, al  ; Sector count (15:8)
2288 clevermous 232
        inc     edx
5569 Pathoswith 233
        mov     eax, [sector+3]
234
        out     dx, al  ; LBA (31:24)
2288 clevermous 235
        inc     edx
236
        shr     eax, 8
5569 Pathoswith 237
        out     dx, al  ; LBA (39:32)
2288 clevermous 238
        inc     edx
239
        shr     eax, 8
5569 Pathoswith 240
        out     dx, al  ; LBA (47:40)
241
        sub     edx, 3
242
        mov     al, [blockSize]
243
        out     dx, al  ; Sector count (7:0)
2288 clevermous 244
        inc     edx
5569 Pathoswith 245
        mov     eax, [sector]
246
        out     dx, al  ; LBA (7:0)
2288 clevermous 247
        inc     edx
3702 mario79 248
        shr     eax, 8
5569 Pathoswith 249
        out     dx, al  ; LBA (15:8)
3702 mario79 250
        inc     edx
251
        shr     eax, 8
5569 Pathoswith 252
        out     dx, al  ; LBA (23:16)
3702 mario79 253
        inc     edx
254
        mov     al, byte [hdid]
5569 Pathoswith 255
        add     al, 224
256
        out     dx, al
257
        test    bl, 1
258
        jz      .PIO
259
; DMA
260
        mov     dword [esp], 0x1000
261
        call    kernel_alloc
262
        mov     edi, eax
263
        push    eax
264
        shl     dword [blockSize], 9
265
        mov     eax, esi
266
        add     eax, [blockSize]
267
        push    eax
268
; check buffer pages physical addresses and fill the scatter-gather list
269
; buffer may be not aligned and may have size not divisible by page size
270
; [edi] = block physical address, [edi+4] = block size in bytes
271
; block addresses can not cross 10000h borders
272
        mov     ecx, esi
273
        and     ecx, 0xFFF
274
        jz      .aligned
275
        mov     eax, esi
276
        call    get_pg_addr
277
        add     eax, ecx
278
        neg     ecx
279
        add     ecx, 0x1000
280
        mov     [edi], eax
281
        cmp     ecx, [blockSize]
282
        jnc     .end
283
        mov     [edi+4], ecx
284
        add     esi, 0x1000
285
        add     edi, 8
286
        sub     [blockSize], ecx
287
.aligned:
288
        mov     eax, esi
289
        call    get_pg_addr
290
        mov     ecx, eax
291
        mov     [edi], eax
292
        and     ecx, 0xFFFF
293
        neg     ecx
294
        add     ecx, 0x10000
295
        cmp     [blockSize], ecx
296
        jnc     @f
297
        mov     ecx, [blockSize]
298
        and     ecx, 0xF000
299
        jz      .end
300
@@:
301
        push    ecx
302
@@:
303
        add     esi, 0x1000
304
        add     eax, 0x1000
305
        sub     ecx, 0x1000
306
        jz      @f
307
        mov     edx, eax
308
        mov     eax, esi
309
        call    get_pg_addr
310
        cmp     eax, edx
311
        jz      @b
312
@@:
313
        pop     edx
314
        sub     edx, ecx
315
        mov     [edi+4], edx
316
        add     edi, 8
317
        sub     [blockSize], edx
318
        jnz     .aligned
319
        sub     edi, 8
320
        jmp     @f
6650 pathoswith 321
 
5569 Pathoswith 322
.end:
323
        mov     ecx, [blockSize]
324
        mov     [edi+4], ecx
325
@@:
326
        mov     byte [edi+7], 80h   ; list end
327
        pop     esi
328
        pop     edi
329
; select controller Primary or Secondary
330
        mov     ecx, [IDE_controller_pointer]
331
        mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
332
        mov     eax, [hdpos]
333
        dec     eax
334
        test    eax, 10b
335
        jz      @f
336
        add     edx, 8
337
@@:
338
        add     edx, 2      ; Bus Master IDE Status register
339
        mov     al, 6
340
        out     dx, al      ; clear Error bit and Interrupt bit
2288 clevermous 341
 
5569 Pathoswith 342
        add     edx, 2      ; Bus Master IDE PRD Table Address
343
        mov     eax, edi
344
        call    get_pg_addr
345
        out     dx, eax     ; send scatter-gather list physical address
2288 clevermous 346
 
5569 Pathoswith 347
        push    edx
2288 clevermous 348
        mov     edx, [hdbase]
5569 Pathoswith 349
        add     edx, 7      ; ATACommand
350
        mov     al, bl
351
        out     dx, al      ; Start hard drive
352
        pop     edx
2288 clevermous 353
 
5569 Pathoswith 354
        sub     edx, 4      ; Bus Master IDE Command register
355
        mov     al, 1       ; set direction
356
        cmp     bl, 35h     ; write
357
        jz      @f
358
        add     al, 8       ; read
359
@@:
360
        out     dx, al      ; Start Bus Master
361
        mov     [IDE_common_irq_param], 14
362
        mov     eax, [hdpos]
363
        dec     eax
364
        test    eax, 10b
365
        jz      @f
366
        inc     [IDE_common_irq_param]
367
@@:
368
        push    edi esi ebx
369
        xor     ecx, ecx
370
        xor     esi, esi
371
        call    create_event
372
        mov     [eventPointer], eax
373
        mov     [eventID], edx
374
        sti
375
        mov     ebx, edx
376
        mov     ecx, 300
377
        call    wait_event_timeout
378
        test    eax, eax
379
        jnz     @f
6650 pathoswith 380
        dbgstr 'IDE DMA IRQ timeout'
5569 Pathoswith 381
        mov     [IDE_common_irq_param], 0
382
        mov     eax, [eventPointer]
383
        mov     ebx, [eventID]
384
        call    destroy_event
385
        mov     [eventPointer], 0
386
@@:
387
        pop     ebx esi
388
        call    kernel_free
389
        cmp     [eventPointer], 0
390
        jz      .hd_error
2288 clevermous 391
        ret
5852 pathoswith 392
 
393
.LBA28:
394
        mov     edx, [hdbase]
395
        add     edx, 6
396
        mov     al, byte [hdid]
397
        add     al, 224
398
        out     dx, al  ; select the desired drive
399
        call    save_hd_wait_timeout
400
        inc     edx
401
@@:
402
        call    check_hd_wait_timeout
403
        jc      .hd_error
404
        in      al, dx
405
        test    al, 128 ; ready for command?
406
        jnz     @b
407
        pushfd          ; fill the ports
408
        cli
409
        mov     edx, [hdbase]
410
        inc     edx
411
        inc     edx
412
        mov     al, [blockSize]
413
        out     dx, al  ; Sector count (7:0)
414
        inc     edx
415
        mov     eax, [sector]
416
        out     dx, al  ; LBA (7:0)
417
        inc     edx
418
        shr     eax, 8
419
        out     dx, al  ; LBA (15:8)
420
        inc     edx
421
        shr     eax, 8
422
        out     dx, al  ; LBA (23:16)
423
        inc     edx
424
        shr     eax, 8
425
        add     al, byte [hdid]
426
        add     al, 224
427
        out     dx, al  ; LBA (27:24)
5569 Pathoswith 428
.PIO:
429
        inc     edx     ; ATACommand
430
        mov     al, bl
431
        out     dx, al  ; Start hard drive
3881 mario79 432
        popfd
5569 Pathoswith 433
.sectorTransfer:
434
        call    save_hd_wait_timeout
435
        in      al, dx
436
        in      al, dx
437
        in      al, dx
438
        in      al, dx
439
@@:
440
        call    check_hd_wait_timeout
441
        jc      .hd_error
442
        in      al, dx
443
        test    al, 8   ; ready for transfer?
444
        jz      @b
445
        cmp     [hd_setup], 1   ; do not mark error for setup request
446
        jz      @f
447
        test    al, 1   ; previous command ended up with an error
6650 pathoswith 448
        jnz     .pio_error
5569 Pathoswith 449
@@:
3712 mario79 450
        pushfd
2288 clevermous 451
        cli
5569 Pathoswith 452
        cld
2288 clevermous 453
        mov     ecx, 256
454
        mov     edx, [hdbase]
5852 pathoswith 455
        cmp     bl, 30h
456
        jnc     .write
5569 Pathoswith 457
        rep insw
458
        jmp     @f
6650 pathoswith 459
 
5569 Pathoswith 460
.write:
2288 clevermous 461
        rep outsw
5569 Pathoswith 462
@@:
3712 mario79 463
        popfd
5569 Pathoswith 464
        add     edx, 7
465
        dec     dword [blockSize]
466
        jnz     .sectorTransfer
2288 clevermous 467
        ret
6650 pathoswith 468
 
469
.pio_error:
470
        dbgstr 'IDE PIO transfer error'
5569 Pathoswith 471
.hd_error:
472
        cmp     bl, 30h
473
        jnc     hd_write_error
474
;-----------------------------------------------------------------
2288 clevermous 475
hd_read_error:
6650 pathoswith 476
        dbgstr 'HD read error'
5569 Pathoswith 477
        stc
2288 clevermous 478
        ret
5569 Pathoswith 479
;-----------------------------------------------------------------
2288 clevermous 480
hd_write_error:
6650 pathoswith 481
        dbgstr 'HD write error'
5569 Pathoswith 482
        stc
2288 clevermous 483
        ret
5569 Pathoswith 484
;-----------------------------------------------------------------
485
save_hd_wait_timeout:
486
        mov     eax, [timer_ticks]
487
        add     eax, 300        ; 3 sec timeout
488
        mov     [hd_wait_timeout], eax
2288 clevermous 489
        ret
5569 Pathoswith 490
;-----------------------------------------------------------------
491
check_hd_wait_timeout:
492
        mov     eax, [timer_ticks]
493
        cmp     [hd_wait_timeout], eax
494
        jc      @f
495
        ret
6650 pathoswith 496
 
3712 mario79 497
@@:
6650 pathoswith 498
        dbgstr 'IDE device timeout'
5569 Pathoswith 499
        stc
2288 clevermous 500
        ret
5569 Pathoswith 501
;-----------------------------------------------------------------
2288 clevermous 502
align 4
3870 mario79 503
IDE_irq_14_handler:
504
IDE_irq_15_handler:
5569 Pathoswith 505
IDE_common_irq_handler:
6015 clevermous 506
; Most of the time, we are here because we have requested
507
; a DMA transfer for the corresponding drive.
508
; However,
509
; a) we can be here because IDE IRQ is shared with some other device,
510
;    that device has actually raised IRQ,
511
;    it has nothing to do with IDE;
512
; b) we can be here because IDE controller just does not want
513
;    to be silent and reacts to something even though
514
;    we have, in theory, disabled IRQs.
515
; If the interrupt corresponds to our current request,
516
; remove the interrupt request and raise the event for the waiting code.
517
; In the case a), just return zero - not our interrupt.
518
; In the case b), remove the interrupt request and hope for the best.
6650 pathoswith 519
; DEBUGF 1, 'K : IDE_irq_handler %x\n', [IDE_common_irq_param]:2
6015 clevermous 520
        mov     ecx, [esp+4]
4700 mario79 521
        mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
5569 Pathoswith 522
        add     edx, 2  ; Bus Master IDE Status register
4291 mario79 523
        in      al, dx
5569 Pathoswith 524
        test    al, 4
6015 clevermous 525
        jnz     .interrupt_from_primary
526
        add     edx, 8
527
        in      al, dx
528
        test    al, 4
529
        jnz     .interrupt_from_secondary
530
        xor     eax, eax ; not our interrupt
531
        ret
6650 pathoswith 532
 
6015 clevermous 533
.interrupt_from_primary:
5569 Pathoswith 534
        out     dx, al  ; clear Interrupt bit
4291 mario79 535
        sub     edx, 2
536
        xor     eax, eax
5569 Pathoswith 537
        out     dx, al  ; clear Bus Master IDE Command register
6015 clevermous 538
        mov     dx, [ecx+IDE_DATA.BAR0_val]
5569 Pathoswith 539
        add     edx, 7
6650 pathoswith 540
        in      al, dx  ; read status register
6015 clevermous 541
        cmp     [IDE_common_irq_param], 14
542
        jz      .raise
543
.exit_our:
544
        mov     al, 1
545
        ret
6650 pathoswith 546
 
6015 clevermous 547
.interrupt_from_secondary:
548
        out     dx, al  ; clear Interrupt bit
549
        sub     edx, 2
550
        xor     eax, eax
551
        out     dx, al  ; clear Bus Master IDE Command register
552
        mov     dx, [ecx+IDE_DATA.BAR2_val]
553
        add     edx, 7
6650 pathoswith 554
        in      al, dx  ; read status register
6015 clevermous 555
        cmp     [IDE_common_irq_param], 15
556
        jnz     .exit_our
557
.raise:
558
        cmp     ecx, [IDE_controller_pointer]
559
        jnz     .exit_our
560
        pushad
5569 Pathoswith 561
        mov     eax, [eventPointer]
562
        mov     ebx, [eventID]
563
        xor     edx, edx
564
        xor     esi, esi
565
        call    raise_event
2288 clevermous 566
        popad
5569 Pathoswith 567
        mov     al, 1   ; remove the interrupt request
4291 mario79 568
        ret