Subversion Repositories Kolibri OS

Rev

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