Subversion Repositories Kolibri OS

Rev

Rev 5852 | Rev 6650 | 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: 6015 $
  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.  
  79. proc ide_read_write stdcall uses esi edi ebx, \
  80.         hd_data, buffer, startsector:qword, numsectors
  81.         ; hd_data = pointer to hd*_data
  82.         ; buffer = pointer to buffer with/for data
  83.         ; startsector = 64-bit start sector
  84.         ; numsectors = pointer to number of sectors on input,
  85.         ;  must be filled with number of sectors really read/written
  86. locals
  87. sectors_todo    dd      ?
  88. channel_lock    dd      ?
  89. endl
  90.         mov     bl, al
  91. ; get number of requested sectors and say that no sectors were read yet
  92.         mov     ecx, [numsectors]
  93.         mov     eax, [ecx]
  94.         mov     dword [ecx], 0
  95.         mov     [sectors_todo], eax
  96. ; acquire the global lock
  97.         mov     ecx, ide_mutex
  98.         call    mutex_lock
  99.         mov     ecx, [hd_data]
  100.         movzx   ecx, [ecx+HD_DATA.hdpos]
  101.         dec     ecx
  102.         shr     ecx, 1
  103.         shl     ecx, 2
  104.         mov     ecx, [ecx + ide_mutex_table]
  105.         mov     [channel_lock], ecx
  106.         call    mutex_lock
  107. ; prepare worker procedures variables
  108.         mov     esi, [buffer]
  109.         mov     edi, esi
  110.         mov     ecx, [hd_data]
  111.         movzx   eax, [ecx+HD_DATA.hdbase]
  112.         mov     [hdbase], eax
  113.         mov     ax, [ecx+HD_DATA.hdid]
  114.         mov     [hdid], eax
  115.         mov     eax, dword [startsector]
  116.         mov     [sector], eax
  117.         cmp     [ecx+HD_DATA.hd48], 0
  118.         jz      .LBA28
  119.         mov     ax, word [startsector+4]
  120.         mov     [sector+4], ax
  121.         movzx   ecx, [ecx+HD_DATA.hdpos]
  122.         mov     [hdpos], ecx
  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
  134.         jz      .next
  135.         dec     ebx     ; READ/WRITE SECTOR(S) EXT
  136. ; LBA48 supports max 10000h sectors per time
  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
  149.         mov     eax, [numsectors]
  150.         add     [eax], ecx
  151.         sub     [sectors_todo], ecx
  152.         jz      .out
  153.         add     [sector], ecx
  154.         adc     word [sector+4], 0
  155.         jmp     .next
  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. ; 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
  185.         mov     ecx, [channel_lock]
  186.         call    mutex_unlock
  187.         mov     ecx, ide_mutex
  188.         call    mutex_unlock
  189.         pop     eax
  190.         ret
  191. endp
  192. ;-----------------------------------------------------------------
  193. ; this is a stub
  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
  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:
  208.         mov     edx, [hdbase]
  209.         add     edx, 6
  210.         mov     al, byte [hdid]
  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
  222.         cli
  223.         mov     edx, [hdbase]
  224.         inc     edx
  225.         inc     edx
  226.         mov     al, [blockSize+1]
  227.         out     dx, al  ; Sector count (15:8)
  228.         inc     edx
  229.         mov     eax, [sector+3]
  230.         out     dx, al  ; LBA (31:24)
  231.         inc     edx
  232.         shr     eax, 8
  233.         out     dx, al  ; LBA (39:32)
  234.         inc     edx
  235.         shr     eax, 8
  236.         out     dx, al  ; LBA (47:40)
  237.         sub     edx, 3
  238.         mov     al, [blockSize]
  239.         out     dx, al  ; Sector count (7:0)
  240.         inc     edx
  241.         mov     eax, [sector]
  242.         out     dx, al  ; LBA (7:0)
  243.         inc     edx
  244.         shr     eax, 8
  245.         out     dx, al  ; LBA (15:8)
  246.         inc     edx
  247.         shr     eax, 8
  248.         out     dx, al  ; LBA (23:16)
  249.         inc     edx
  250.         mov     al, byte [hdid]
  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
  336.  
  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
  341.  
  342.         push    edx
  343.         mov     edx, [hdbase]
  344.         add     edx, 7      ; ATACommand
  345.         mov     al, bl
  346.         out     dx, al      ; Start hard drive
  347.         pop     edx
  348.  
  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
  385.         ret
  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)
  422. .PIO:
  423.         inc     edx     ; ATACommand
  424.         mov     al, bl
  425.         out     dx, al  ; Start hard drive
  426.         popfd
  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. @@:
  444.         pushfd
  445.         cli
  446.         cld
  447.         mov     ecx, 256
  448.         mov     edx, [hdbase]
  449.         cmp     bl, 30h
  450.         jnc     .write
  451.         rep insw
  452.         jmp     @f
  453. .write:
  454.         rep outsw
  455. @@:
  456.         popfd
  457.         add     edx, 7
  458.         dec     dword [blockSize]
  459.         jnz     .sectorTransfer
  460.         ret
  461. .hd_error:
  462.         cmp     bl, 30h
  463.         jnc     hd_write_error
  464. ;-----------------------------------------------------------------
  465. hd_read_error:
  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
  471.         stc
  472.         ret
  473. ;-----------------------------------------------------------------
  474. hd_write_error:
  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
  480.         stc
  481.         ret
  482. ;-----------------------------------------------------------------
  483. save_hd_wait_timeout:
  484.         mov     eax, [timer_ticks]
  485.         add     eax, 300        ; 3 sec timeout
  486.         mov     [hd_wait_timeout], eax
  487.         ret
  488. ;-----------------------------------------------------------------
  489. check_hd_wait_timeout:
  490.         mov     eax, [timer_ticks]
  491.         cmp     [hd_wait_timeout], eax
  492.         jc      @f
  493.         ret
  494. @@:
  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
  501.         ret
  502. ;-----------------------------------------------------------------
  503. align 4
  504. IDE_irq_14_handler:
  505. IDE_irq_15_handler:
  506. IDE_common_irq_handler:
  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.
  520. ; DEBUGF  1, 'K : IDE_irq_handler %x\n', [IDE_common_irq_param]:2
  521.         mov     ecx, [esp+4]
  522.         mov     dx, [ecx+IDE_DATA.RegsBaseAddres]
  523.         add     edx, 2  ; Bus Master IDE Status register
  524.         in      al, dx
  525.         test    al, 4
  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:
  535.         out     dx, al  ; clear Interrupt bit
  536.         sub     edx, 2
  537.         xor     eax, eax
  538.         out     dx, al  ; clear Bus Master IDE Command register
  539.         mov     dx, [ecx+IDE_DATA.BAR0_val]
  540.         add     edx, 7
  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
  561.         mov     eax, [eventPointer]
  562.         mov     ebx, [eventID]
  563.         xor     edx, edx
  564.         xor     esi, esi
  565.         call    raise_event
  566.         popad
  567.         mov     al, 1   ; remove the interrupt request
  568.         ret
  569. ;-----------------------------------------------------------------
  570.