Subversion Repositories Kolibri OS

Rev

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