Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2021. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision$
  9.  
  10. PCI_REG_STATUS_COMMAND = 0x0004
  11. PCI_REG_BAR5 = 0x0024
  12.  
  13. ; bit_ prefix means that its index of bit
  14. ; format: bit_AHCI_STR_REG_BIT
  15. bit_AHCI_HBA_CAP2_BOH   = 0        ; Supports BIOS/OS Handoff
  16.  
  17. bit_AHCI_HBA_BOHC_BOS  = 0         ; BIOS-Owned Semaphore (BIOS owns controller)
  18. bit_AHCI_HBA_BOHC_OOS  = 1         ; OS-Owned Semaphore (OS owns controller)
  19. bit_AHCI_HBA_BOHC_BB   = 4         ; BIOS Busy (polling bit while BIOS cleans up
  20.  
  21. bit_AHCI_HBA_GHC_AHCI_ENABLE      = 31  ; Enable AHCI mode
  22. bit_AHCI_HBA_GHC_RESET            = 0   ; Reset HBA
  23. bit_AHCI_HBA_GHC_INTERRUPT_ENABLE = 1   ; Enable interrupts from the HBA
  24.  
  25. AHCI_HBA_PxSSTS_DET         = 0xF
  26. AHCI_HBA_PORT_IPM_ACTIVE    = 1
  27. AHCI_HBA_PxSSTS_DET_PRESENT = 3
  28.  
  29. AHCI_MAX_PORTS = 32        ;
  30. ;HBA_MEMORY_SIZE = 0x1100
  31.  
  32. ; Frame Information Structure Types
  33. FIS_TYPE_REG_H2D    = 0x27 ; Register FIS - host to device
  34. FIS_TYPE_REG_D2H    = 0x34 ; Register FIS - device to host
  35. FIS_TYPE_DMA_ACT    = 0x39 ; DMA activate FIS - device to host
  36. FIS_TYPE_DMA_SETUP  = 0x41 ; DMA setup FIS - bidirectional
  37. FIS_TYPE_DATA       = 0x46 ; Data FIS - bidirectional
  38. FIS_TYPE_BIST       = 0x58 ; BIST activate FIS - bidirectional
  39. FIS_TYPE_PIO_SETUP  = 0x5F ; PIO setup FIS - device to host
  40. FIS_TYPE_DEV_BITS   = 0xA1 ; Set device bits FIS - device to host
  41.  
  42. struct AHCI_DATA
  43.         abar    dd ?       ; pointer to HBA Memory (BAR5) mapped to virtual kernelspace memory
  44.         pcidev  dd ?       ; pointer to corresponding PCIDEV structure
  45. ends
  46.  
  47. ; Generic Host Control registers
  48. struct HBA_MEM
  49.         cap                   dd ?                    ; 0x00, Host capabilities
  50.         ghc                   dd ?                    ; 0x04, Global host control
  51.         is                    dd ?                    ; 0x08, Interrupt status
  52.         pi                    dd ?                    ; 0x0C, Port implemented
  53.         version               dd ?                    ; 0x10, Version
  54.         ccc_ctl               dd ?                    ; 0x14, Command completion coalescing control
  55.         ccc_pts               dd ?                    ; 0x18, Command completion coalescing ports
  56.         em_loc                dd ?                    ; 0x1C, Enclosure management location
  57.         em_ctl                dd ?                    ; 0x20, Enclosure management control
  58.         cap2                  dd ?                    ; 0x24, Host capabilities extended
  59.         bohc                  dd ?                    ; 0x28, BIOS/OS handoff control and status
  60.         reserved              rb (0xA0-0x2C)          ; 0x2C - 0x9F, Reserved
  61.         vendor                rb (0x100-0xA0)         ; 0xA0 - 0xFF, Vendor specific
  62.         ports                 rb (sizeof.HBA_PORT*AHCI_MAX_PORTS) ; 0x100 - 0x10FF, Port control registers, max AHCI_MAX_PORTS
  63. ends
  64.  
  65. ; Port Control registers
  66. struct HBA_PORT
  67.         command_list_base_l      dd ?                 ; 0x00, command list base address, 1K-byte aligned
  68.         command_list_base_h      dd ?                 ; 0x04, command list base address upper 32 bits, used on 64 bit systems
  69.         fis_base_l               dd ?                 ; 0x08, FIS base address, 256-byte aligned
  70.         fis_base_h               dd ?                 ; 0x0C, FIS base address upper 32 bits, used on 64 bit systems
  71.         interrupt_status         dd ?                 ; 0x10
  72.         interrupt_enable         dd ?                 ; 0x14
  73.         command                  dd ?                 ; 0x18, command and status
  74.         reserved0                dd ?                 ; 0x1C
  75.         task_file_data           dd ?                 ; 0x20
  76.         signature                dd ?                 ; 0x24
  77.         sata_status              dd ?                 ; 0x28, SATA status (SCR0:SStatus)
  78.         sata_control             dd ?                 ; 0x2C, SATA control (SCR2:SControl)
  79.         sata_error               dd ?                 ; 0x30, SATA error (SCR1:SError)
  80.         sata_active              dd ?                 ; 0x34, SATA active (SCR3:SActive)
  81.         command_issue            dd ?                 ; 0x38
  82.         sata_notification        dd ?                 ; 0x3C, SATA notification (SCR4:SNotification)
  83.         fis_based_switch_control dd ?                 ; 0x40
  84.         reserved1                rd 11                ; 0x44 - 0x6F
  85.         vendor                   rd 4                 ; 0x70 - 0x7F, vendor specific
  86. ends
  87.  
  88. ; Register FIS – Host to Device
  89. struct FIS_REG_H2D
  90.         fis_type      db ?       ; FIS_TYPE_REG_H2D
  91.         _flags        db ?       ; 0bCRRRPPPP, C - 1: Command, 0: Control
  92.                                  ; R - Reserved, P - Port multiplier
  93.  
  94.         command       db ?       ; Command register
  95.         featurel      db ?       ; Feature register, 7:0
  96.  
  97.         lba0          db ?       ; LBA low register, 7:0
  98.         lba1          db ?       ; LBA mid register, 15:8
  99.         lba2          db ?       ; LBA high register, 23:16
  100.         device        db ?       ; Device register
  101.  
  102.         lba3          db ?       ; LBA register, 31:24
  103.         lba4          db ?       ; LBA register, 39:32
  104.         lba5          db ?       ; LBA register, 47:40
  105.         featureh      db ?       ; Feature register, 15:8
  106.  
  107.         countl        db ?       ; Count register, 7:0
  108.         counth        db ?       ; Count register, 15:8
  109.         icc           db ?       ; Isochronous command completion
  110.         control       db ?       ; Control register
  111.  
  112.         rsv1          rb 4       ; Reserved
  113. ends
  114.  
  115. ; Register FIS – Device to Host
  116. struct FIS_REG_D2H
  117.     fis_type      db ?           ; FIS_TYPE_REG_D2H
  118.  
  119.     _flags        db ?           ; 0bRIRPPPP, P - Port multiplier, R - Reserved
  120.                                  ; I - Interrupt bit
  121.  
  122.     status        db ?           ; Status register
  123.     error         db ?           ; Error register
  124.  
  125.     lba0          db ?           ; LBA low register, 7:0
  126.     lba1          db ?           ; LBA mid register, 15:8
  127.     lba2          db ?           ; LBA high register, 23:16
  128.     device        db ?           ; Device register
  129.  
  130.     lba3          db ?           ; LBA register, 31:24
  131.     lba4          db ?           ; LBA register, 39:32
  132.     lba5          db ?           ; LBA register, 47:40
  133.     rsv2          db ?           ; Reserved
  134.  
  135.     countl        db ?           ; Count register, 7:0
  136.     counth        db ?           ; Count register, 15:8
  137.     rsv3          rb 2           ; Reserved
  138.  
  139.     rsv4          rb 4           ; Reserved
  140. ends
  141.  
  142. ; Data FIS – Bidirectional
  143. struct FIS_DATA
  144.     fis_type      db ?           ; FIS_TYPE_DATA
  145.     _flags        db ?           ; 0bRRRRPPPP, R - Reserved, P - Port multiplier
  146.     rsv1          rb 2           ; Reserved
  147.     ; DWORD 1 ~ N (?)
  148.     data          rd 1           ; Payload
  149. ends
  150.  
  151. ; PIO Setup – Device to Host
  152. struct FIS_PIO_SETUP
  153.     fis_type      db ?           ; FIS_TYPE_PIO_SETUP
  154.  
  155.     _flags        db ?           ; 0bRIDRPPPP, P - Port multiplier, R - Reserved
  156.                                  ; I - Interrupt bit, D - Data transfer direction, 1 - device to host
  157.  
  158.     status        db ?           ; Status register
  159.     error         db ?           ; Error register
  160.  
  161.     lba0          db ?           ; LBA low register, 7:0
  162.     lba1          db ?           ; LBA mid register, 15:8
  163.     lba2          db ?           ; LBA high register, 23:16
  164.     device        db ?           ; Device register
  165.  
  166.     lba3          db ?           ; LBA register, 31:24
  167.     lba4          db ?           ; LBA register, 39:32
  168.     lba5          db ?           ; LBA register, 47:40
  169.     rsv2          db ?           ; Reserved
  170.  
  171.     countl        db ?           ; Count register, 7:0
  172.     counth        db ?           ; Count register, 15:8
  173.     rsv3          db ?           ; Reserved
  174.     e_status      db ?           ; New value of status register
  175.  
  176.     tc            dw ?           ; Transfer count
  177.     rsv4          rb 2           ; Reserved
  178. ends
  179.  
  180. ; DMA Setup – Device to Host
  181. struct FIS_DMA_SETUP
  182.     fis_type      db ?           ; FIS_TYPE_DMA_SETUP
  183.     _flags        db ?           ; 0bAIDRPPPP, A - Auto-activate. Specifies if DMA Activate FIS is needed,
  184.                                  ; I - Interrupt bit, D - Data transfer direction, 1 - device to host,
  185.                                  ; R - Reserved, P - Port multiplier
  186.  
  187.     rsved         rb 2           ; Reserved
  188.     DMAbufferID   dq ?           ; DMA Buffer Identifier.
  189.                                  ; Used to Identify DMA buffer in host memory.
  190.                                  ; SATA Spec says host specific and not in Spec.
  191.                                  ; Trying AHCI spec might work.
  192.  
  193.     TransferCount dd ?           ; Number of bytes to transfer. Bit 0 must be 0
  194.     resvd         dd ?           ; Reserved
  195. ends
  196.  
  197. ; Set device bits FIS - device to host
  198. struct FIS_DEV_BITS
  199.     fis_type      db ?           ; FIS_TYPE_DEV_BITS
  200.     _flags        db ?           ; 0bNIRRPPPP, N - Notification, I - Interrupt,
  201.                                  ; R - Reserved, P - Port multiplier
  202.    
  203.     status        db ?           ; Status register
  204.     error         db ?           ; Error register
  205.    
  206.     protocol      dd ?           ; Protocol
  207. ends
  208.  
  209. ; --------------------------------------------------
  210. uglobal
  211. align 4
  212.         ahci_controller AHCI_DATA
  213. endg
  214.  
  215. ; -----------------------------------------------------------------------
  216. ; detect ahci controller and initialize
  217. align 4
  218. init_ahci:
  219.         mov     ecx, ahci_controller
  220.         mov     esi, pcidev_list
  221. .find_ahci_ctr:
  222.         mov     esi, [esi + PCIDEV.fd]
  223.         cmp     esi, pcidev_list
  224.         jz      .ahci_ctr_not_found
  225.         mov     eax, [esi + PCIDEV.class]
  226.         ;DEBUGF  1, "K: device class = %x\n", eax
  227.         shr     eax, 8 ; shift right because lowest 8 bits if ProgIf field
  228.         cmp     eax, 0x0106 ; 0x01 - Mass Storage Controller class,  0x06 - Serial ATA Controller subclass
  229.         jz      .ahci_ctr_found
  230.         jmp     .find_ahci_ctr
  231.  
  232. .ahci_ctr_not_found:
  233.         DEBUGF  1, "K: AHCI controller not found\n"
  234.         ret
  235.  
  236. .ahci_ctr_found:
  237.         mov     [ahci_controller + AHCI_DATA.pcidev], esi
  238.  
  239.         mov     eax, [esi+PCIDEV.class]
  240.         movzx   ebx, byte [esi+PCIDEV.bus]
  241.         movzx   ecx, byte [esi+PCIDEV.devfn]
  242.         shr     ecx, 3 ; get rid of 3 lowest bits (function code), the rest bits is device code
  243.         movzx   edx, byte [esi+PCIDEV.devfn]
  244.         and     edx, 00000111b ; get only 3 lowest bits (function code)
  245.         DEBUGF  1, "K: found AHCI controller, (class, subcl, progif) = %x, bus = %x, device = %x, function = %x\n", eax, ebx, ecx, edx
  246.        
  247.         ; get BAR5 value, it is physical address
  248.         movzx   ebx, [esi + PCIDEV.bus]
  249.         movzx   ebp, [esi + PCIDEV.devfn]
  250.         stdcall pci_read32, ebx, ebp, PCI_REG_BAR5
  251.         DEBUGF  1, "K: AHCI controller MMIO = %x\n", eax
  252.         mov     edi, eax
  253.  
  254.         ; get the size of MMIO region
  255.         stdcall pci_write32, ebx, ebp, PCI_REG_BAR5, 0xFFFFFFFF
  256.         stdcall pci_read32, ebx, ebp, PCI_REG_BAR5
  257.         not     eax
  258.         inc     eax
  259.         DEBUGF  1, "K: AHCI: MMIO region size = 0x%x bytes\n", eax
  260.  
  261.         ; Map MMIO region to virtual memory
  262.         stdcall map_io_mem, edi, eax, PG_SWR + PG_NOCACHE
  263.         mov     [ahci_controller + AHCI_DATA.abar], eax
  264.         DEBUGF  1, "K: AHCI controller BAR5 mapped to virtual addr %x\n", eax
  265.  
  266.         ; Restore the original BAR5 value
  267.         stdcall pci_write32, ebx, ebp, PCI_REG_BAR5, edi
  268.  
  269.         ; Enable dma bus mastering, memory space access, clear the "disable interrupts" bit
  270.         ; Usually, it is already done before us
  271.         movzx   ebx, [esi + PCIDEV.bus]
  272.         movzx   ebp, [esi + PCIDEV.devfn]
  273.         stdcall pci_read32, ebx, ebp, PCI_REG_STATUS_COMMAND
  274.         DEBUGF  1, "K: AHCI: pci_status_command = %x\nEnabling interrupts, DMA bus mastering and memory space access\n", eax
  275.         or      eax, 0x06 ; pci.command |= 0x06 (dma bus mastering + memory space access)
  276.         btr     eax, 10 ; clear the "disable interrupts" bit
  277.         DEBUGF  1, "K: AHCI: pci_status_command = %x\n", eax
  278.         stdcall pci_write32, ebx, ebp, PCI_REG_STATUS_COMMAND, eax
  279.  
  280.         ; ; Print some register values to debug board
  281.         ; mov     esi, [ahci_controller + AHCI_DATA.abar]
  282.         ; DEBUGF  1, "K: AHCI: HBA.cap = %x, HBA.ghc = %x, HBA_MEM.version = %x\n", [esi + HBA_MEM.cap], [esi + HBA_MEM.ghc], [esi + HBA_MEM.version]
  283.  
  284.         ;-------------------------------------------------------
  285.         ; Request BIOS/OS ownership handoff, if supported. (TODO check correctness)
  286.         mov     esi, [ahci_controller + AHCI_DATA.abar]
  287.         ;mov     ebx, [esi + HBA_MEM.cap2]
  288.         ;DEBUGF  1, "K: AHCI: HBA_MEM.cap2 = %x\n", ebx
  289.         bt      [esi + HBA_MEM.cap2], bit_AHCI_HBA_CAP2_BOH
  290.         jnc     .end_handoff
  291.         DEBUGF  1, "K: AHCI: requesting AHCI ownership change...\n"
  292.         bts     [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_OOS
  293.  
  294. .wait_not_bos:
  295.         bt      [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_BOS
  296.         jc      .wait_not_bos
  297.  
  298.         mov     ebx, 3
  299.         call    delay_hs
  300.  
  301.         ; if Bios Busy is still set after 30 mS, wait 2 seconds.
  302.         bt      [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_BB
  303.         jnc     @f
  304.  
  305.         mov     ebx, 200
  306.         call    delay_hs
  307. @@:
  308.         DEBUGF  1, "K: AHCI: ownership change completed.\n"
  309.  
  310. .end_handoff:
  311.         ;-------------------------------------------------------
  312.  
  313.         ; enable the AHCI and reset it
  314.         bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_AHCI_ENABLE
  315.         bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_RESET
  316.  
  317.         ; wait for reset to complete
  318. .wait_reset:
  319.         bt      [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_RESET
  320.         jc      .wait_reset
  321.  
  322.         ; enable the AHCI and interrupts
  323.         bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_AHCI_ENABLE
  324.         bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_INTERRUPT_ENABLE
  325.         mov     ebx, 2
  326.         call    delay_hs
  327.        
  328.         DEBUGF  1, "K: AHCI: caps: %x %x, ver: %x, ghc: %x, pi: %x\n", [esi + HBA_MEM.cap], [esi + HBA_MEM.cap2], [esi + HBA_MEM.version], [esi + HBA_MEM.ghc], [esi + HBA_MEM.pi]
  329.  
  330.         ; TODO:
  331.         ; calculate irq line
  332.         ; ahciHBA->ghc |= AHCI_GHC_IE;
  333.         ; IDT::RegisterInterruptHandler(irq, InterruptHandler);
  334.         ; ahciHBA->is = 0xffffffff;
  335.  
  336.         xor     ebx, ebx
  337. .detect_drives:
  338.         cmp     ebx, AHCI_MAX_PORTS
  339.         jae     .end_detect_drives
  340.  
  341.         ; if port with index ebx is not implemented then go to next
  342.         mov     ecx, [esi + HBA_MEM.pi]
  343.         bt      ecx, ebx
  344.         jnc     .continue_detect_drives
  345.  
  346.         mov     edi, ebx
  347.         shl     edi, BSF sizeof.HBA_PORT
  348.         add     edi, HBA_MEM.ports
  349.         add     edi, esi
  350.         ; now edi - base of HBA_MEM.ports[ebx]
  351.  
  352.         DEBUGF  1, "K: AHCI: port %d, ssts = %x\n", ebx, [edi + HBA_PORT.sata_status]
  353.  
  354.         mov     ecx, [edi + HBA_PORT.sata_status]
  355.         shr     ecx, 8
  356.         and     ecx, 0x0F
  357.         cmp     ecx, AHCI_HBA_PORT_IPM_ACTIVE
  358.         jne     .continue_detect_drives
  359.  
  360.         mov     ecx, [edi + HBA_PORT.sata_status]
  361.         and     ecx, AHCI_HBA_PxSSTS_DET
  362.         cmp     ecx, AHCI_HBA_PxSSTS_DET_PRESENT
  363.         jne    .continue_detect_drives
  364.  
  365.         DEBUGF 1, "K: AHCI: found drive at port %d, signature = %x\n", ebx, [edi + HBA_PORT.signature]    
  366.  
  367. .continue_detect_drives:
  368.         inc     ebx
  369.         jmp     .detect_drives
  370.  
  371.        
  372.  
  373. .end_detect_drives:
  374.        
  375.  
  376.         ret
  377.  
  378.