Subversion Repositories Kolibri OS

Rev

Rev 6015 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 6650 $
  9.  
  10. ; HDD driver
  11.  
  12. struct HD_DATA
  13. hdbase  dw  ?
  14. hdid    dw  ?
  15. hdpos   dw  ?
  16. hd48    dw  ?
  17. ends
  18. ;-----------------------------------------------------------------
  19. iglobal
  20. align 4
  21. ide_callbacks:
  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
  30. .end:
  31.  
  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
  44.  
  45. ide_mutex_table:
  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
  52. endg
  53. ;-----------------------------------------------------------------
  54. uglobal
  55. ide_mutex               MUTEX
  56. ide_channel1_mutex      MUTEX
  57. ide_channel2_mutex      MUTEX
  58. ide_channel3_mutex      MUTEX
  59. ide_channel4_mutex      MUTEX
  60. ide_channel5_mutex      MUTEX
  61. ide_channel6_mutex      MUTEX
  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 ?
  70. endg
  71. ;-----------------------------------------------------------------
  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, \
  79.         hd_data, buffer, startsector:qword, numsectors
  80.         ; hd_data = pointer to hd*_data
  81.         ; buffer = pointer to buffer with/for data
  82.         ; startsector = 64-bit start sector
  83.         ; numsectors = pointer to number of sectors on input,
  84.         ;  must be filled with number of sectors really read/written
  85. locals
  86. sectors_todo    dd      ?
  87. channel_lock    dd      ?
  88. endl
  89.         mov     bl, al
  90. ; get number of requested sectors and say that no sectors were read yet
  91.         mov     ecx, [numsectors]
  92.         mov     eax, [ecx]
  93.         mov     dword [ecx], 0
  94.         mov     [sectors_todo], eax
  95. ; acquire the global lock
  96.         mov     ecx, ide_mutex
  97.         call    mutex_lock
  98.         mov     ecx, [hd_data]
  99.         movzx   ecx, [ecx+HD_DATA.hdpos]
  100.         dec     ecx
  101.         shr     ecx, 1
  102.         shl     ecx, 2
  103.         mov     ecx, [ecx + ide_mutex_table]
  104.         mov     [channel_lock], ecx
  105.         call    mutex_lock
  106. ; prepare worker procedures variables
  107.         mov     esi, [buffer]
  108.         mov     edi, esi
  109.         mov     ecx, [hd_data]
  110.         movzx   eax, [ecx+HD_DATA.hdbase]
  111.         mov     [hdbase], eax
  112.         mov     ax, [ecx+HD_DATA.hdid]
  113.         mov     [hdid], eax
  114.         mov     eax, dword [startsector]
  115.         mov     [sector], eax
  116.         cmp     [ecx+HD_DATA.hd48], 0
  117.         jz      .LBA28
  118.         mov     ax, word [startsector+4]
  119.         mov     [sector+4], ax
  120.         movzx   ecx, [ecx+HD_DATA.hdpos]
  121.         mov     [hdpos], ecx
  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
  133.         jz      .next
  134.         dec     ebx     ; READ/WRITE SECTOR(S) EXT
  135. ; LBA48 supports max 10000h sectors per time
  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
  148.         mov     eax, [numsectors]
  149.         add     [eax], ecx
  150.         sub     [sectors_todo], ecx
  151.         jz      .out
  152.         add     [sector], ecx
  153.         adc     word [sector+4], 0
  154.         jmp     .next
  155.  
  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
  180.  
  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
  186.         mov     ecx, [channel_lock]
  187.         call    mutex_unlock
  188.         mov     ecx, ide_mutex
  189.         call    mutex_unlock
  190.         pop     eax
  191.         ret
  192. endp
  193. ;-----------------------------------------------------------------
  194. ; this is a stub
  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
  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:
  209.         mov     edx, [hdbase]
  210.         add     edx, 6
  211.         mov     al, byte [hdid]
  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
  223.         cli
  224.         mov     edx, [hdbase]
  225.         inc     edx
  226.         inc     edx
  227.         mov     al, [blockSize+1]
  228.         out     dx, al  ; Sector count (15:8)
  229.         inc     edx
  230.         mov     eax, [sector+3]
  231.         out     dx, al  ; LBA (31:24)
  232.         inc     edx
  233.         shr     eax, 8
  234.         out     dx, al  ; LBA (39:32)
  235.         inc     edx
  236.         shr     eax, 8
  237.         out     dx, al  ; LBA (47:40)
  238.         sub     edx, 3
  239.         mov     al, [blockSize]
  240.         out     dx, al  ; Sector count (7:0)
  241.         inc     edx
  242.         mov     eax, [sector]
  243.         out     dx, al  ; LBA (7:0)
  244.         inc     edx
  245.         shr     eax, 8
  246.         out     dx, al  ; LBA (15:8)
  247.         inc     edx
  248.         shr     eax, 8
  249.         out     dx, al  ; LBA (23:16)
  250.         inc     edx
  251.         mov     al, byte [hdid]
  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
  318.  
  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
  338.  
  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
  343.  
  344.         push    edx
  345.         mov     edx, [hdbase]
  346.         add     edx, 7      ; ATACommand
  347.         mov     al, bl
  348.         out     dx, al      ; Start hard drive
  349.         pop     edx
  350.  
  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
  377.         dbgstr 'IDE DMA IRQ timeout'
  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
  388.         ret
  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)
  425. .PIO:
  426.         inc     edx     ; ATACommand
  427.         mov     al, bl
  428.         out     dx, al  ; Start hard drive
  429.         popfd
  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
  445.         jnz     .pio_error
  446. @@:
  447.         pushfd
  448.         cli
  449.         cld
  450.         mov     ecx, 256
  451.         mov     edx, [hdbase]
  452.         cmp     bl, 30h
  453.         jnc     .write
  454.         rep insw
  455.         jmp     @f
  456.  
  457. .write:
  458.         rep outsw
  459. @@:
  460.         popfd
  461.         add     edx, 7
  462.         dec     dword [blockSize]
  463.         jnz     .sectorTransfer
  464.         ret
  465.  
  466. .pio_error:
  467.         dbgstr 'IDE PIO transfer error'
  468. .hd_error:
  469.         cmp     bl, 30h
  470.         jnc     hd_write_error
  471. ;-----------------------------------------------------------------
  472. hd_read_error:
  473.         dbgstr 'HD read error'
  474.         stc
  475.         ret
  476. ;-----------------------------------------------------------------
  477. hd_write_error:
  478.         dbgstr 'HD write error'
  479.         stc
  480.         ret
  481. ;-----------------------------------------------------------------
  482. save_hd_wait_timeout:
  483.         mov     eax, [timer_ticks]
  484.         add     eax, 300        ; 3 sec timeout
  485.         mov     [hd_wait_timeout], eax
  486.         ret
  487. ;-----------------------------------------------------------------
  488. check_hd_wait_timeout:
  489.         mov     eax, [timer_ticks]
  490.         cmp     [hd_wait_timeout], eax
  491.         jc      @f
  492.         ret
  493.  
  494. @@:
  495.         dbgstr 'IDE device timeout'
  496.         stc
  497.         ret
  498. ;-----------------------------------------------------------------
  499. align 4
  500. IDE_irq_14_handler:
  501. IDE_irq_15_handler:
  502. IDE_common_irq_handler:
  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.
  516. ; DEBUGF 1, 'K : IDE_irq_handler %x\n', [IDE_common_irq_param]:2
  517.         mov     ecx, [esp+4]
  518.         mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
  519.         add     edx, 2  ; Bus Master IDE Status register
  520.         in      al, dx
  521.         test    al, 4
  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
  529.  
  530. .interrupt_from_primary:
  531.         out     dx, al  ; clear Interrupt bit
  532.         sub     edx, 2
  533.         xor     eax, eax
  534.         out     dx, al  ; clear Bus Master IDE Command register
  535.         mov     dx, [ecx+IDE_DATA.BAR0_val]
  536.         add     edx, 7
  537.         in      al, dx  ; read status register
  538.         cmp     [IDE_common_irq_param], 14
  539.         jz      .raise
  540. .exit_our:
  541.         mov     al, 1
  542.         ret
  543.  
  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
  551.         in      al, dx  ; read status register
  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
  558.         mov     eax, [eventPointer]
  559.         mov     ebx, [eventID]
  560.         xor     edx, edx
  561.         xor     esi, esi
  562.         call    raise_event
  563.         popad
  564.         mov     al, 1   ; remove the interrupt request
  565.         ret
  566.