Subversion Repositories Kolibri OS

Rev

Rev 9020 | Rev 9024 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
9020 rgimad 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
 
9023 rgimad 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
9020 rgimad 16
 
9023 rgimad 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
9020 rgimad 20
 
9023 rgimad 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_MAX_PORTS = 32        ;
9020 rgimad 26
HBA_MEMORY_SIZE = 0x1100
27
 
28
struct AHCI_DATA
29
        ;;
30
        abar    dd ?       ; pointer to HBA Memory (BAR5) mapped to virtual kernelspace memory
31
        pcidev  dd ?       ; pointer to corresponding PCIDEV structure
32
ends
33
 
34
; Generic Host Control registers
35
struct HBA_MEM
36
        capability            dd ?                    ; 0x00
37
        global_host_control   dd ?                    ; 0x04
38
        interrupt_status      dd ?                    ; 0x08
39
        port_implemented      dd ?                    ; 0x0C
40
        version               dd ?                    ; 0x10
41
        ccc_ctl               dd ?                    ; 0x14, Command completion coalescing control
42
        ccc_pts               dd ?                    ; 0x18, Command completion coalescing ports
43
        em_loc                dd ?                    ; 0x1C, Enclosure management location
44
        em_ctl                dd ?                    ; 0x20, Enclosure management control
45
        capability2           dd ?                    ; 0x24, Host capabilities extended
46
        bohc                  dd ?                    ; 0x28, BIOS/OS handoff control and status
47
        reserved              rb (0xA0-0x2C)          ; 0x2C - 0x9F, Reserved
48
        vendor                rb (0x100-0xA0)         ; 0xA0 - 0xFF, Vendor specific
9023 rgimad 49
        ports                 rb (sizeof.HBA_PORT*AHCI_MAX_PORTS) ; 0x100 - 0x10FF, Port control registers, max AHCI_MAX_PORTS
9020 rgimad 50
ends
51
 
52
; Port Control registers
53
struct HBA_PORT
54
	command_list_base_l      dd ?                 ; 0x00, command list base address, 1K-byte aligned
55
	command_list_base_h      dd ?                 ; 0x04, command list base address upper 32 bits, used on 64 bit systems
56
	fis_base_l               dd ?                 ; 0x08, FIS base address, 256-byte aligned
57
	fis_base_h               dd ?                 ; 0x0C, FIS base address upper 32 bits, used on 64 bit systems
58
	interrupt_status         dd ?                 ; 0x10
59
	interrupt_enable         dd ?                 ; 0x14
60
	command                  dd ?                 ; 0x18, command and status
61
	reserved0                dd ?                 ; 0x1C
62
	task_file_data           dd ?                 ; 0x20
63
	signature                dd ?                 ; 0x24
64
	sata_status              dd ?                 ; 0x28, SATA status (SCR0:SStatus)
65
	sata_control             dd ?                 ; 0x2C, SATA control (SCR2:SControl)
66
	sata_error               dd ?                 ; 0x30, SATA error (SCR1:SError)
67
	sata_active              dd ?                 ; 0x34, SATA active (SCR3:SActive)
68
	command_issue            dd ?                 ; 0x38
69
	sata_notification        dd ?                 ; 0x3C, SATA notification (SCR4:SNotification)
70
	fis_based_switch_control dd ?                 ; 0x40
71
	reserved1                rd 11                ; 0x44 - 0x6F
72
	vendor                   rd 4                 ; 0x70 - 0x7F, vendor specific
73
ends
74
 
75
uglobal
76
align 4
77
        ahci_controller AHCI_DATA
78
endg
79
 
80
 
81
; detect ahci controller and initialize
82
align 4
83
init_ahci:
84
        mov     ecx, ahci_controller
85
        mov     esi, pcidev_list
86
.find_ahci_ctr:
87
        mov     esi, [esi + PCIDEV.fd]
88
        cmp     esi, pcidev_list
89
        jz      .ahci_ctr_not_found
90
        mov     eax, [esi + PCIDEV.class]
91
        ;DEBUGF  1, "K: device class = %x\n", eax
92
        shr     eax, 8 ; shift right because lowest 8 bits if ProgIf field
93
        cmp     eax, 0x0106 ; 0x01 - Mass Storage Controller class,  0x06 - Serial ATA Controller subclass
94
        jz      .ahci_ctr_found
95
        jmp     .find_ahci_ctr
96
 
97
.ahci_ctr_not_found:
98
        DEBUGF  1, "K: AHCI controller not found\n"
99
        ret
100
 
101
.ahci_ctr_found:
102
        mov     [ahci_controller + AHCI_DATA.pcidev], esi
103
 
104
        mov     eax, [esi+PCIDEV.class]
105
        movzx   ebx, byte [esi+PCIDEV.bus]
106
        movzx   ecx, byte [esi+PCIDEV.devfn]
107
        shr     ecx, 3 ; get rid of 3 lowest bits (function code), the rest bits is device code
108
        movzx   edx, byte [esi+PCIDEV.devfn]
109
        and     edx, 00000111b ; get only 3 lowest bits (function code)
110
        DEBUGF  1, "K: found AHCI controller, (class, subcl, progif) = %x, bus = %x, device = %x, function = %x\n", eax, ebx, ecx, edx
111
 
9023 rgimad 112
        ; get BAR5 value, it is physical address
9020 rgimad 113
        mov     ah, [esi + PCIDEV.bus]
114
        mov     al, 2 ; read dword
115
        mov     bh, [esi + PCIDEV.devfn]
116
        mov     bl, PCI_REG_BAR5
117
        call    pci_read_reg
118
        DEBUGF  1, "K: AHCI controller BAR5 = %x\n", eax
119
 
9023 rgimad 120
        ; Map BAR5 to virtual memory
9020 rgimad 121
        stdcall map_io_mem, eax, HBA_MEMORY_SIZE, PG_SWR + PG_NOCACHE
122
        mov     [ahci_controller + AHCI_DATA.abar], eax
123
        DEBUGF  1, "K: AHCI controller BAR5 mapped to virtual addr %x\n", eax
124
 
9023 rgimad 125
        ; Enable dma bus mastering, memory space access, clear the "disable interrupts" bit
126
        ; Usually, it is already done before us
9020 rgimad 127
        mov     ah, [esi + PCIDEV.bus]
128
        mov     al, 2 ; read dword
129
        mov     bh, [esi + PCIDEV.devfn]
130
        mov     bl, PCI_REG_STATUS_COMMAND
131
        call    pci_read_reg
132
        DEBUGF  1, "K: AHCI: pci_status_command = %x\nEnabling interrupts, DMA bus mastering and memory space access\n", eax
133
        or      eax, 0x06 ; pci.command |= 0x06 (dma bus mastering + memory space access)
134
        btr     eax, 10 ; clear the "disable interrupts" bit
135
        DEBUGF  1, "K: AHCI: pci_status_command = %x\n", eax
136
        mov     ecx, eax
137
        mov     ah, [esi + PCIDEV.bus]
138
        mov     al, 2 ; write dword
139
        mov     bh, [esi + PCIDEV.devfn]
140
        mov     bl, PCI_REG_STATUS_COMMAND
141
        call    pci_write_reg
142
 
9023 rgimad 143
        ; ; Print some register values to debug board
144
        ; mov     esi, [ahci_controller + AHCI_DATA.abar]
145
        ; mov     ebx, [esi + HBA_MEM.capability]
146
        ; mov     ecx, [esi + HBA_MEM.global_host_control]
147
        ; mov     edx, [esi + HBA_MEM.version]
148
        ; DEBUGF  1, "K: AHCI: HBA.cap = %x, HBA.ghc = %x, HBA_MEM.version = %x\n", ebx, ecx, edx
9020 rgimad 149
 
9023 rgimad 150
        ;-------------------------------------------------------
151
        ; Request BIOS/OS ownership handoff, if supported. (TODO check correctness)
152
        mov     esi, [ahci_controller + AHCI_DATA.abar]
153
        ;mov     ebx, [esi + HBA_MEM.capability2]
154
        ;DEBUGF  1, "K: AHCI: HBA_MEM.cap2 = %x\n", ebx
155
        bt      dword [esi + HBA_MEM.capability2], bit_AHCI_HBA_CAP2_BOH
9020 rgimad 156
        jnc     .end_handoff
9023 rgimad 157
        DEBUGF  1, "K: AHCI: requesting AHCI ownership change...\n"
158
        bts     dword [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_OOS
9020 rgimad 159
 
160
.wait_not_bos:
9023 rgimad 161
        bt      dword [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_BOS
9020 rgimad 162
        jc      .wait_not_bos
163
 
164
        mov     ebx, 3
165
        call    delay_hs
166
 
9023 rgimad 167
        ; if Bios Busy is still set after 30 mS, wait 2 seconds.
168
        bt      dword [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_BB
9020 rgimad 169
        jnc     @f
170
 
171
        mov     ebx, 200
172
        call    delay_hs
173
@@:
9023 rgimad 174
        DEBUGF  1, "K: AHCI: ownership change completed.\n"
9020 rgimad 175
 
176
.end_handoff:
9023 rgimad 177
        ;-------------------------------------------------------
9020 rgimad 178
 
9023 rgimad 179
        ; enable the AHCI and reset it
180
        bts     dword [esi + HBA_MEM.global_host_control], bit_AHCI_HBA_GHC_AHCI_ENABLE
181
        bts     dword [esi + HBA_MEM.global_host_control], bit_AHCI_HBA_GHC_RESET
9020 rgimad 182
 
9023 rgimad 183
        ; wait for reset to complete
184
.wait_reset:
185
        bt      dword [esi + HBA_MEM.global_host_control], bit_AHCI_HBA_GHC_RESET
186
        jc      .wait_reset
9020 rgimad 187
 
9023 rgimad 188
        ; enable the AHCI and interrupts
189
        bts     dword [esi + HBA_MEM.global_host_control], bit_AHCI_HBA_GHC_AHCI_ENABLE
190
        bts     dword [esi + HBA_MEM.global_host_control], bit_AHCI_HBA_GHC_INTERRUPT_ENABLE
191
        mov     ebx, 2
192
        call    delay_hs
193
        mov     ebx, [esi + HBA_MEM.capability]
194
        mov     ecx, [esi + HBA_MEM.capability2]
195
        mov     edx, [esi + HBA_MEM.version]
196
        mov     edi, [esi + HBA_MEM.global_host_control]
197
 
198
        DEBUGF  1, "K: AHCI: caps: %x %x, ver: %x, ghc: %x\n", ebx, ecx, edx, edi
9020 rgimad 199
 
200
        ret
201