Subversion Repositories Kolibri OS

Rev

Rev 9138 | Rev 9140 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 9138 Rev 9139
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2021. All rights reserved. ;;
3
;; Copyright (C) KolibriOS team 2004-2021. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
7
 
8
$Revision$
8
$Revision$
9
 
9
 
10
PCI_REG_STATUS_COMMAND = 0x0004
10
PCI_REG_STATUS_COMMAND = 0x0004
11
PCI_REG_BAR5 = 0x0024
11
PCI_REG_BAR5 = 0x0024
12
 
12
 
13
; different SATA device signatures
13
; different SATA device signatures
14
SATA_SIG_ATA	= 0x00000101	; SATA drive
14
SATA_SIG_ATA	= 0x00000101	; SATA drive
15
SATA_SIG_ATAPI	= 0xEB140101	; SATAPI drive
15
SATA_SIG_ATAPI	= 0xEB140101	; SATAPI drive
16
SATA_SIG_SEMB	= 0xC33C0101	; Enclosure management bridge
16
SATA_SIG_SEMB	= 0xC33C0101	; Enclosure management bridge
17
SATA_SIG_PM	= 0x96690101	; Port multiplier
17
SATA_SIG_PM	= 0x96690101	; Port multiplier
18
 
18
 
19
; Device type constants
19
; Device type constants
20
AHCI_DEV_NULL   = 0
20
AHCI_DEV_NULL   = 0
21
AHCI_DEV_SATA   = 1
21
AHCI_DEV_SATA   = 1
22
AHCI_DEV_SEMB   = 2
22
AHCI_DEV_SEMB   = 2
23
AHCI_DEV_PM     = 3
23
AHCI_DEV_PM     = 3
24
AHCI_DEV_SATAPI = 4
24
AHCI_DEV_SATAPI = 4
25
 
25
 
26
; ATA commands
26
; ATA commands
27
ATA_IDENTIFY    = 0xEC
27
ATA_IDENTIFY    = 0xEC
-
 
28
 
-
 
29
; ATA constants
-
 
30
ATA_DEV_BUSY    = 0x80
-
 
31
ATA_DEV_DRQ     = 0x08
28
 
32
 
29
; ATAPI commands
33
; ATAPI commands
30
ATAPI_IDENTIFY  = 0xA1
34
ATAPI_IDENTIFY  = 0xA1
31
 
35
 
32
; bit_ prefix means that its index of bit
36
; bit_ prefix means that its index of bit
33
; format: bit_AHCI_STR_REG_BIT
37
; format: bit_AHCI_STR_REG_BIT
34
bit_AHCI_HBA_CAP2_BOH   = 0        ; Supports BIOS/OS Handoff
38
bit_AHCI_HBA_CAP2_BOH   = 0        ; Supports BIOS/OS Handoff
35
 
39
 
36
bit_AHCI_HBA_BOHC_BOS  = 0         ; BIOS-Owned Semaphore (BIOS owns controller)
40
bit_AHCI_HBA_BOHC_BOS  = 0         ; BIOS-Owned Semaphore (BIOS owns controller)
37
bit_AHCI_HBA_BOHC_OOS  = 1         ; OS-Owned Semaphore (OS owns controller)
41
bit_AHCI_HBA_BOHC_OOS  = 1         ; OS-Owned Semaphore (OS owns controller)
38
bit_AHCI_HBA_BOHC_BB   = 4         ; BIOS Busy (polling bit while BIOS cleans up 
42
bit_AHCI_HBA_BOHC_BB   = 4         ; BIOS Busy (polling bit while BIOS cleans up 
39
 
43
 
40
bit_AHCI_HBA_GHC_AHCI_ENABLE      = 31  ; Enable AHCI mode
44
bit_AHCI_HBA_GHC_AHCI_ENABLE      = 31  ; Enable AHCI mode
41
bit_AHCI_HBA_GHC_RESET            = 0   ; Reset HBA
45
bit_AHCI_HBA_GHC_RESET            = 0   ; Reset HBA
42
bit_AHCI_HBA_GHC_INTERRUPT_ENABLE = 1   ; Enable interrupts from the HBA 
46
bit_AHCI_HBA_GHC_INTERRUPT_ENABLE = 1   ; Enable interrupts from the HBA 
43
 
47
 
44
bit_AHCI_HBA_PxCMD_ST    = 0
48
bit_AHCI_HBA_PxCMD_ST    = 0
45
bit_AHCI_HBA_PxCMD_FRE   = 4
49
bit_AHCI_HBA_PxCMD_FRE   = 4
46
bit_AHCI_HBA_PxCMD_FR    = 14
50
bit_AHCI_HBA_PxCMD_FR    = 14
47
bit_AHCI_HBA_PxCMD_CR    = 15
51
bit_AHCI_HBA_PxCMD_CR    = 15
-
 
52
bit_AHCI_HBA_PxIS_TFES   = 30
48
 
53
 
49
AHCI_HBA_PxCMD_ST    = 1 shl 0
54
AHCI_HBA_PxCMD_ST    = 1 shl 0
50
AHCI_HBA_PxCMD_FRE   = 1 shl 4
55
AHCI_HBA_PxCMD_FRE   = 1 shl 4
51
AHCI_HBA_PxCMD_FR    = 1 shl 14
56
AHCI_HBA_PxCMD_FR    = 1 shl 14
52
AHCI_HBA_PxCMD_CR    = 1 shl 15
57
AHCI_HBA_PxCMD_CR    = 1 shl 15
53
 
58
 
54
bit_AHCI_H2D_FLAG_CMD    = 7
59
bit_AHCI_H2D_FLAG_CMD    = 7
55
 
60
 
56
AHCI_HBA_PxSSTS_DET         = 0xF
61
AHCI_HBA_PxSSTS_DET         = 0xF
57
AHCI_HBA_PORT_IPM_ACTIVE    = 1
62
AHCI_HBA_PORT_IPM_ACTIVE    = 1
58
AHCI_HBA_PxSSTS_DET_PRESENT = 3
63
AHCI_HBA_PxSSTS_DET_PRESENT = 3
59
 
64
 
60
AHCI_MAX_PORTS = 32        ;
65
AHCI_MAX_PORTS = 32        ;
61
;HBA_MEMORY_SIZE = 0x1100
66
;HBA_MEMORY_SIZE = 0x1100
-
 
67
 
-
 
68
AHCI_PORT_TIMEOUT = 1000000
62
 
69
 
63
; Frame Information Structure Types
70
; Frame Information Structure Types
64
FIS_TYPE_REG_H2D    = 0x27 ; Register FIS - host to device
71
FIS_TYPE_REG_H2D    = 0x27 ; Register FIS - host to device
65
FIS_TYPE_REG_D2H    = 0x34 ; Register FIS - device to host
72
FIS_TYPE_REG_D2H    = 0x34 ; Register FIS - device to host
66
FIS_TYPE_DMA_ACT    = 0x39 ; DMA activate FIS - device to host
73
FIS_TYPE_DMA_ACT    = 0x39 ; DMA activate FIS - device to host
67
FIS_TYPE_DMA_SETUP  = 0x41 ; DMA setup FIS - bidirectional
74
FIS_TYPE_DMA_SETUP  = 0x41 ; DMA setup FIS - bidirectional
68
FIS_TYPE_DATA       = 0x46 ; Data FIS - bidirectional
75
FIS_TYPE_DATA       = 0x46 ; Data FIS - bidirectional
69
FIS_TYPE_BIST       = 0x58 ; BIST activate FIS - bidirectional
76
FIS_TYPE_BIST       = 0x58 ; BIST activate FIS - bidirectional
70
FIS_TYPE_PIO_SETUP  = 0x5F ; PIO setup FIS - device to host
77
FIS_TYPE_PIO_SETUP  = 0x5F ; PIO setup FIS - device to host
71
FIS_TYPE_DEV_BITS   = 0xA1 ; Set device bits FIS - device to host
78
FIS_TYPE_DEV_BITS   = 0xA1 ; Set device bits FIS - device to host
72
 
79
 
73
struct AHCI_DATA
80
struct AHCI_DATA
74
        abar    dd ?       ; pointer to HBA Memory (BAR5) mapped to virtual kernelspace memory
81
        abar    dd ?       ; pointer to HBA Memory (BAR5) mapped to virtual kernelspace memory
75
        pcidev  dd ?       ; pointer to corresponding PCIDEV structure
82
        pcidev  dd ?       ; pointer to corresponding PCIDEV structure
76
ends
83
ends
77
 
84
 
78
; Generic Host Control registers
85
; Generic Host Control registers
79
struct HBA_MEM
86
struct HBA_MEM
80
        cap                   dd ?                    ; 0x00, Host capabilities
87
        cap                   dd ?                    ; 0x00, Host capabilities
81
        ghc                   dd ?                    ; 0x04, Global host control
88
        ghc                   dd ?                    ; 0x04, Global host control
82
        is                    dd ?                    ; 0x08, Interrupt status
89
        is                    dd ?                    ; 0x08, Interrupt status
83
        pi                    dd ?                    ; 0x0C, Port implemented
90
        pi                    dd ?                    ; 0x0C, Port implemented
84
        version               dd ?                    ; 0x10, Version
91
        version               dd ?                    ; 0x10, Version
85
        ccc_ctl               dd ?                    ; 0x14, Command completion coalescing control
92
        ccc_ctl               dd ?                    ; 0x14, Command completion coalescing control
86
        ccc_pts               dd ?                    ; 0x18, Command completion coalescing ports
93
        ccc_pts               dd ?                    ; 0x18, Command completion coalescing ports
87
        em_loc                dd ?                    ; 0x1C, Enclosure management location
94
        em_loc                dd ?                    ; 0x1C, Enclosure management location
88
        em_ctl                dd ?                    ; 0x20, Enclosure management control
95
        em_ctl                dd ?                    ; 0x20, Enclosure management control
89
        cap2                  dd ?                    ; 0x24, Host capabilities extended
96
        cap2                  dd ?                    ; 0x24, Host capabilities extended
90
        bohc                  dd ?                    ; 0x28, BIOS/OS handoff control and status
97
        bohc                  dd ?                    ; 0x28, BIOS/OS handoff control and status
91
        reserved              rb (0xA0-HBA_MEM.reserved)        ; 0x2C - 0x9F, Reserved
98
        reserved              rb (0xA0-HBA_MEM.reserved)        ; 0x2C - 0x9F, Reserved
92
        vendor                rb (0x100-HBA_MEM.vendor)         ; 0xA0 - 0xFF, Vendor specific 
99
        vendor                rb (0x100-HBA_MEM.vendor)         ; 0xA0 - 0xFF, Vendor specific 
93
        ports                 rb (sizeof.HBA_PORT*AHCI_MAX_PORTS) ; 0x100 - 0x10FF, Port control registers, max AHCI_MAX_PORTS
100
        ports                 rb (sizeof.HBA_PORT*AHCI_MAX_PORTS) ; 0x100 - 0x10FF, Port control registers, max AHCI_MAX_PORTS
94
ends
101
ends
95
 
102
 
96
; Port Control registers
103
; Port Control registers
97
struct HBA_PORT
104
struct HBA_PORT
98
        command_list_base_l      dd ?                 ; 0x00, command list base address, 1K-byte aligned
105
        command_list_base_l      dd ?                 ; 0x00, command list base address, 1K-byte aligned
99
        command_list_base_h      dd ?                 ; 0x04, command list base address upper 32 bits, used on 64 bit systems
106
        command_list_base_h      dd ?                 ; 0x04, command list base address upper 32 bits, used on 64 bit systems
100
        fis_base_l               dd ?                 ; 0x08, FIS base address, 256-byte aligned
107
        fis_base_l               dd ?                 ; 0x08, FIS base address, 256-byte aligned
101
        fis_base_h               dd ?                 ; 0x0C, FIS base address upper 32 bits, used on 64 bit systems
108
        fis_base_h               dd ?                 ; 0x0C, FIS base address upper 32 bits, used on 64 bit systems
102
        interrupt_status         dd ?                 ; 0x10
109
        interrupt_status         dd ?                 ; 0x10
103
        interrupt_enable         dd ?                 ; 0x14
110
        interrupt_enable         dd ?                 ; 0x14
104
        command                  dd ?                 ; 0x18, command and status
111
        command                  dd ?                 ; 0x18, command and status
105
        reserved0                dd ?                 ; 0x1C
112
        reserved0                dd ?                 ; 0x1C
106
        task_file_data           dd ?                 ; 0x20
113
        task_file_data           dd ?                 ; 0x20
107
        signature                dd ?                 ; 0x24
114
        signature                dd ?                 ; 0x24
108
        sata_status              dd ?                 ; 0x28, SATA status (SCR0:SStatus)
115
        sata_status              dd ?                 ; 0x28, SATA status (SCR0:SStatus)
109
        sata_control             dd ?                 ; 0x2C, SATA control (SCR2:SControl)
116
        sata_control             dd ?                 ; 0x2C, SATA control (SCR2:SControl)
110
        sata_error               dd ?                 ; 0x30, SATA error (SCR1:SError)
117
        sata_error               dd ?                 ; 0x30, SATA error (SCR1:SError)
111
        sata_active              dd ?                 ; 0x34, SATA active (SCR3:SActive)
118
        sata_active              dd ?                 ; 0x34, SATA active (SCR3:SActive)
112
        command_issue            dd ?                 ; 0x38
119
        command_issue            dd ?                 ; 0x38
113
        sata_notification        dd ?                 ; 0x3C, SATA notification (SCR4:SNotification)
120
        sata_notification        dd ?                 ; 0x3C, SATA notification (SCR4:SNotification)
114
        fis_based_switch_control dd ?                 ; 0x40
121
        fis_based_switch_control dd ?                 ; 0x40
115
        reserved1                rd 11                ; 0x44 - 0x6F
122
        reserved1                rd 11                ; 0x44 - 0x6F
116
        vendor                   rd 4                 ; 0x70 - 0x7F, vendor specific
123
        vendor                   rd 4                 ; 0x70 - 0x7F, vendor specific
117
ends
124
ends
118
 
125
 
119
; Command header structure, size = 32 bytes
126
; Command header structure, size = 32 bytes
120
struct HBA_CMD_HDR
127
struct HBA_CMD_HDR
121
    flags1       db ? ; 0bPWACCCCC, P - Prefetchable, W - Write (1: H2D, 0: D2H)
128
    flags1       db ? ; 0bPWACCCCC, P - Prefetchable, W - Write (1: H2D, 0: D2H)
122
                       ; A - ATAPI, C - Command FIS length in DWORDS, 2 ~ 16
129
                       ; A - ATAPI, C - Command FIS length in DWORDS, 2 ~ 16
123
    
130
    
124
    flags2       db ? ; 0bPPPPRCB(Re), P - Port multiplier port, R - Reserved,
131
    flags2       db ? ; 0bPPPPRCB(Re), P - Port multiplier port, R - Reserved,
125
                       ; C - Clear busy upon R_OK, B - BIST, Re - Reset
132
                       ; C - Clear busy upon R_OK, B - BIST, Re - Reset
126
    
133
    
127
    prdtl         dw ? ; Physical region descriptor table length in entries
134
    prdtl         dw ? ; Physical region descriptor table length in entries
128
    prdbc         dd ? ; Physical region descriptor byte count transferred
135
    prdbc         dd ? ; Physical region descriptor byte count transferred
129
    ctba          dd ? ; Command table descriptor base address
136
    ctba          dd ? ; Command table descriptor base address
130
    ctbau         dd ? ; Command table descriptor base address upper 32 bits
137
    ctbau         dd ? ; Command table descriptor base address upper 32 bits
131
                  rd 4 ; Reserved
138
                  rd 4 ; Reserved
132
ends
139
ends
133
 
140
 
134
; Physical region descriptor table entry, size = 16 bytes
141
; Physical region descriptor table entry, size = 16 bytes
135
struct HBA_PRDT_ENTRY
142
struct HBA_PRDT_ENTRY
136
    dba           dd ?  ; Data base address
143
    dba           dd ?  ; Data base address
137
    dbau          dd ?  ; Data base address upper 32 bits
144
    dbau          dd ?  ; Data base address upper 32 bits
138
                  dd ?  ; Reserved
145
                  dd ?  ; Reserved
139
    flags        dd ?  ; 0bIR..RD..D, I (1 bit) - Interrupt on completion,
146
    flags        dd ?  ; 0bIR..RD..D, I (1 bit) - Interrupt on completion,
140
                        ; R (9 bits) - Reserved, D (22 bits) - Byte count, 4M max
147
                        ; R (9 bits) - Reserved, D (22 bits) - Byte count, 4M max
141
ends
148
ends
142
 
149
 
143
struct HBA_CMD_TBL
150
struct HBA_CMD_TBL
144
    cfis          rb 64 ; 0x00, Command FIS
151
    cfis          rb 64 ; 0x00, Command FIS
145
    acmd          rb 16 ; 0x40, ATAPI command, 12 or 16 bytes
152
    acmd          rb 16 ; 0x40, ATAPI command, 12 or 16 bytes
146
                  rb 48 ; 0x50, Reserved
153
                  rb 48 ; 0x50, Reserved
147
    prdt_entry    HBA_PRDT_ENTRY  ; 0x80, Physical region descriptor table entries, 0 ~ 65535
154
    prdt_entry    HBA_PRDT_ENTRY  ; 0x80, Physical region descriptor table entries, 0 ~ 65535
148
                        ; so, this structure is variable-length
155
                        ; so, this structure is variable-length
149
ends
156
ends
150
 
157
 
151
; Contains virtual mappings for port phys memory regions
158
; Contains virtual mappings for port phys memory regions
152
struct PORT_DATA
159
struct PORT_DATA
153
    clb           dd ? ; Command list base
160
    clb           dd ? ; Command list base
154
    fb            dd ? ; FIS base
161
    fb            dd ? ; FIS base
155
    ctba_arr      rd 32 ; ctba_arr[0] = clb[0].ctba, ... and so on.
162
    ctba_arr      rd 32 ; ctba_arr[0] = clb[0].ctba, ... and so on.
156
    port          dd ? ; address of correspoding HBA_PORT structure
163
    port          dd ? ; address of correspoding HBA_PORT structure
157
    portno        dd ? ; port index, 0..31
164
    portno        dd ? ; port index, 0..31
158
    drive_type    db ? ; drive type
165
    drive_type    db ? ; drive type
159
ends
166
ends
160
 
167
 
161
; Register FIS – Host to Device
168
; Register FIS – Host to Device
162
struct FIS_REG_H2D
169
struct FIS_REG_H2D
163
        fis_type      db ?       ; FIS_TYPE_REG_H2D
170
        fis_type      db ?       ; FIS_TYPE_REG_H2D
164
        flags        db ?       ; 0bCRRRPPPP, C - 1: Command, 0: Control
171
        flags        db ?       ; 0bCRRRPPPP, C - 1: Command, 0: Control
165
                                 ; R - Reserved, P - Port multiplier
172
                                 ; R - Reserved, P - Port multiplier
166
 
173
 
167
        command       db ?       ; Command register
174
        command       db ?       ; Command register
168
        featurel      db ?       ; Feature register, 7:0
175
        featurel      db ?       ; Feature register, 7:0
169
 
176
 
170
        lba0          db ?       ; LBA low register, 7:0
177
        lba0          db ?       ; LBA low register, 7:0
171
        lba1          db ?       ; LBA mid register, 15:8
178
        lba1          db ?       ; LBA mid register, 15:8
172
        lba2          db ?       ; LBA high register, 23:16
179
        lba2          db ?       ; LBA high register, 23:16
173
        device        db ?       ; Device register
180
        device        db ?       ; Device register
174
 
181
 
175
        lba3          db ?       ; LBA register, 31:24
182
        lba3          db ?       ; LBA register, 31:24
176
        lba4          db ?       ; LBA register, 39:32
183
        lba4          db ?       ; LBA register, 39:32
177
        lba5          db ?       ; LBA register, 47:40
184
        lba5          db ?       ; LBA register, 47:40
178
        featureh      db ?       ; Feature register, 15:8
185
        featureh      db ?       ; Feature register, 15:8
179
 
186
 
180
        countl        db ?       ; Count register, 7:0
187
        countl        db ?       ; Count register, 7:0
181
        counth        db ?       ; Count register, 15:8
188
        counth        db ?       ; Count register, 15:8
182
        icc           db ?       ; Isochronous command completion
189
        icc           db ?       ; Isochronous command completion
183
        control       db ?       ; Control register
190
        control       db ?       ; Control register
184
 
191
 
185
                      rb 4       ; Reserved
192
                      rb 4       ; Reserved
186
ends
193
ends
187
 
194
 
188
; Register FIS – Device to Host
195
; Register FIS – Device to Host
189
struct FIS_REG_D2H
196
struct FIS_REG_D2H
190
    fis_type      db ?           ; FIS_TYPE_REG_D2H
197
    fis_type      db ?           ; FIS_TYPE_REG_D2H
191
 
198
 
192
    flags        db ?           ; 0bRIRPPPP, P - Port multiplier, R - Reserved
199
    flags        db ?           ; 0bRIRPPPP, P - Port multiplier, R - Reserved
193
                                 ; I - Interrupt bit
200
                                 ; I - Interrupt bit
194
 
201
 
195
    status        db ?           ; Status register
202
    status        db ?           ; Status register
196
    error         db ?           ; Error register
203
    error         db ?           ; Error register
197
 
204
 
198
    lba0          db ?           ; LBA low register, 7:0
205
    lba0          db ?           ; LBA low register, 7:0
199
    lba1          db ?           ; LBA mid register, 15:8
206
    lba1          db ?           ; LBA mid register, 15:8
200
    lba2          db ?           ; LBA high register, 23:16
207
    lba2          db ?           ; LBA high register, 23:16
201
    device        db ?           ; Device register
208
    device        db ?           ; Device register
202
 
209
 
203
    lba3          db ?           ; LBA register, 31:24
210
    lba3          db ?           ; LBA register, 31:24
204
    lba4          db ?           ; LBA register, 39:32
211
    lba4          db ?           ; LBA register, 39:32
205
    lba5          db ?           ; LBA register, 47:40
212
    lba5          db ?           ; LBA register, 47:40
206
                  db ?           ; Reserved
213
                  db ?           ; Reserved
207
 
214
 
208
    countl        db ?           ; Count register, 7:0
215
    countl        db ?           ; Count register, 7:0
209
    counth        db ?           ; Count register, 15:8
216
    counth        db ?           ; Count register, 15:8
210
                  rb 2           ; Reserved
217
                  rb 2           ; Reserved
211
 
218
 
212
                  rb 4           ; Reserved
219
                  rb 4           ; Reserved
213
ends
220
ends
214
 
221
 
215
; Data FIS – Bidirectional
222
; Data FIS – Bidirectional
216
struct FIS_DATA
223
struct FIS_DATA
217
    fis_type      db ?           ; FIS_TYPE_DATA
224
    fis_type      db ?           ; FIS_TYPE_DATA
218
    flags        db ?           ; 0bRRRRPPPP, R - Reserved, P - Port multiplier
225
    flags        db ?           ; 0bRRRRPPPP, R - Reserved, P - Port multiplier
219
                  rb 2           ; Reserved
226
                  rb 2           ; Reserved
220
    ; DWORD 1 ~ N (?)
227
    ; DWORD 1 ~ N (?)
221
    data          rd 1           ; Payload
228
    data          rd 1           ; Payload
222
ends
229
ends
223
 
230
 
224
; PIO Setup – Device to Host
231
; PIO Setup – Device to Host
225
struct FIS_PIO_SETUP
232
struct FIS_PIO_SETUP
226
    fis_type      db ?           ; FIS_TYPE_PIO_SETUP
233
    fis_type      db ?           ; FIS_TYPE_PIO_SETUP
227
 
234
 
228
    flags        db ?           ; 0bRIDRPPPP, P - Port multiplier, R - Reserved
235
    flags        db ?           ; 0bRIDRPPPP, P - Port multiplier, R - Reserved
229
                                 ; I - Interrupt bit, D - Data transfer direction, 1 - device to host
236
                                 ; I - Interrupt bit, D - Data transfer direction, 1 - device to host
230
 
237
 
231
    status        db ?           ; Status register
238
    status        db ?           ; Status register
232
    error         db ?           ; Error register
239
    error         db ?           ; Error register
233
 
240
 
234
    lba0          db ?           ; LBA low register, 7:0
241
    lba0          db ?           ; LBA low register, 7:0
235
    lba1          db ?           ; LBA mid register, 15:8
242
    lba1          db ?           ; LBA mid register, 15:8
236
    lba2          db ?           ; LBA high register, 23:16
243
    lba2          db ?           ; LBA high register, 23:16
237
    device        db ?           ; Device register
244
    device        db ?           ; Device register
238
 
245
 
239
    lba3          db ?           ; LBA register, 31:24
246
    lba3          db ?           ; LBA register, 31:24
240
    lba4          db ?           ; LBA register, 39:32
247
    lba4          db ?           ; LBA register, 39:32
241
    lba5          db ?           ; LBA register, 47:40
248
    lba5          db ?           ; LBA register, 47:40
242
                  db ?           ; Reserved
249
                  db ?           ; Reserved
243
 
250
 
244
    countl        db ?           ; Count register, 7:0
251
    countl        db ?           ; Count register, 7:0
245
    counth        db ?           ; Count register, 15:8
252
    counth        db ?           ; Count register, 15:8
246
                  db ?           ; Reserved
253
                  db ?           ; Reserved
247
    e_status      db ?           ; New value of status register
254
    e_status      db ?           ; New value of status register
248
 
255
 
249
    tc            dw ?           ; Transfer count
256
    tc            dw ?           ; Transfer count
250
                  rb 2           ; Reserved
257
                  rb 2           ; Reserved
251
ends
258
ends
252
 
259
 
253
; DMA Setup – Device to Host
260
; DMA Setup – Device to Host
254
struct FIS_DMA_SETUP
261
struct FIS_DMA_SETUP
255
    fis_type      db ?           ; FIS_TYPE_DMA_SETUP
262
    fis_type      db ?           ; FIS_TYPE_DMA_SETUP
256
    flags        db ?           ; 0bAIDRPPPP, A - Auto-activate. Specifies if DMA Activate FIS is needed,
263
    flags        db ?           ; 0bAIDRPPPP, A - Auto-activate. Specifies if DMA Activate FIS is needed,
257
                                 ; I - Interrupt bit, D - Data transfer direction, 1 - device to host,
264
                                 ; I - Interrupt bit, D - Data transfer direction, 1 - device to host,
258
                                 ; R - Reserved, P - Port multiplier
265
                                 ; R - Reserved, P - Port multiplier
259
 
266
 
260
                  rb 2           ; Reserved
267
                  rb 2           ; Reserved
261
    DMAbufferID   dq ?           ; DMA Buffer Identifier.
268
    DMAbufferID   dq ?           ; DMA Buffer Identifier.
262
                                 ; Used to Identify DMA buffer in host memory.
269
                                 ; Used to Identify DMA buffer in host memory.
263
                                 ; SATA Spec says host specific and not in Spec.
270
                                 ; SATA Spec says host specific and not in Spec.
264
                                 ; Trying AHCI spec might work.
271
                                 ; Trying AHCI spec might work.
265
 
272
 
266
                  dd ?           ; Reserved
273
                  dd ?           ; Reserved
267
    DMAbufOffset  dd ?           ; Byte offset into buffer. First 2 bits must be 0
274
    DMAbufOffset  dd ?           ; Byte offset into buffer. First 2 bits must be 0
268
    TransferCount dd ?           ; Number of bytes to transfer. Bit 0 must be 0
275
    TransferCount dd ?           ; Number of bytes to transfer. Bit 0 must be 0
269
                  dd ?           ; Reserved
276
                  dd ?           ; Reserved
270
ends
277
ends
271
 
278
 
272
; Set device bits FIS - device to host
279
; Set device bits FIS - device to host
273
struct FIS_DEV_BITS
280
struct FIS_DEV_BITS
274
    fis_type      db ?           ; FIS_TYPE_DEV_BITS
281
    fis_type      db ?           ; FIS_TYPE_DEV_BITS
275
    flags        db ?           ; 0bNIRRPPPP, N - Notification, I - Interrupt,
282
    flags        db ?           ; 0bNIRRPPPP, N - Notification, I - Interrupt,
276
                                 ; R - Reserved, P - Port multiplier
283
                                 ; R - Reserved, P - Port multiplier
277
    
284
    
278
    status        db ?           ; Status register
285
    status        db ?           ; Status register
279
    error         db ?           ; Error register
286
    error         db ?           ; Error register
280
    
287
    
281
    protocol      dd ?           ; Protocol
288
    protocol      dd ?           ; Protocol
282
ends
289
ends
283
 
290
 
284
struct HBA_FIS
291
struct HBA_FIS
285
    dsfis         FIS_DMA_SETUP  ; 0x00, DMA Setup FIS
292
    dsfis         FIS_DMA_SETUP  ; 0x00, DMA Setup FIS
286
                  rb 4           ; padding
293
                  rb 4           ; padding
287
 
294
 
288
    psfis         FIS_PIO_SETUP  ; 0x20, PIO Setup FIS
295
    psfis         FIS_PIO_SETUP  ; 0x20, PIO Setup FIS
289
                  rb 12          ; padding
296
                  rb 12          ; padding
290
 
297
 
291
    rfis          FIS_REG_D2H    ; 0x40, Register - Device to Host FIS
298
    rfis          FIS_REG_D2H    ; 0x40, Register - Device to Host FIS
292
                  rb 4           ; padding
299
                  rb 4           ; padding
293
 
300
 
294
    sdbfis        FIS_DEV_BITS   ; 0x58, Set Device Bit FIS
301
    sdbfis        FIS_DEV_BITS   ; 0x58, Set Device Bit FIS
295
 
302
 
296
    ufis          rb 64          ; 0x60
303
    ufis          rb 64          ; 0x60
297
 
304
 
298
                  rb (0x100 - 0xA0) ; 0xA0, Reserved
305
                  rb (0x100 - 0xA0) ; 0xA0, Reserved
299
ends
306
ends
300
 
307
 
301
; --------------------------------------------------
308
; --------------------------------------------------
302
uglobal
309
uglobal
303
align 4
310
align 4
304
        ahci_controller AHCI_DATA
311
        ahci_controller AHCI_DATA
305
        port_data_arr   rb (sizeof.PORT_DATA*AHCI_MAX_PORTS)
312
        port_data_arr   rb (sizeof.PORT_DATA*AHCI_MAX_PORTS)
306
endg
313
endg
307
 
314
 
308
; -----------------------------------------------------------------------
315
; -----------------------------------------------------------------------
309
; detect ahci controller and initialize
316
; detect ahci controller and initialize
310
align 4
317
align 4
311
ahci_init:
318
ahci_init:
312
        mov     ecx, ahci_controller
319
        mov     ecx, ahci_controller
313
        mov     esi, pcidev_list
320
        mov     esi, pcidev_list
314
.find_ahci_ctr:
321
.find_ahci_ctr:
315
        mov     esi, [esi + PCIDEV.fd]
322
        mov     esi, [esi + PCIDEV.fd]
316
        cmp     esi, pcidev_list
323
        cmp     esi, pcidev_list
317
        jz      .ahci_ctr_not_found
324
        jz      .ahci_ctr_not_found
318
        mov     eax, [esi + PCIDEV.class]
325
        mov     eax, [esi + PCIDEV.class]
319
        ;DEBUGF  1, "K: device class = %x\n", eax
326
        ;DEBUGF  1, "K: device class = %x\n", eax
320
        shr     eax, 8 ; shift right because lowest 8 bits if ProgIf field
327
        shr     eax, 8 ; shift right because lowest 8 bits if ProgIf field
321
        cmp     eax, 0x0106 ; 0x01 - Mass Storage Controller class,  0x06 - Serial ATA Controller subclass
328
        cmp     eax, 0x0106 ; 0x01 - Mass Storage Controller class,  0x06 - Serial ATA Controller subclass
322
        jz      .ahci_ctr_found
329
        jz      .ahci_ctr_found
323
        jmp     .find_ahci_ctr
330
        jmp     .find_ahci_ctr
324
 
331
 
325
.ahci_ctr_not_found:
332
.ahci_ctr_not_found:
326
        DEBUGF  1, "K: AHCI controller not found\n"
333
        DEBUGF  1, "K: AHCI controller not found\n"
327
        ret
334
        ret
328
 
335
 
329
.ahci_ctr_found:
336
.ahci_ctr_found:
330
        mov     [ahci_controller + AHCI_DATA.pcidev], esi
337
        mov     [ahci_controller + AHCI_DATA.pcidev], esi
331
 
338
 
332
        mov     eax, [esi+PCIDEV.class]
339
        mov     eax, [esi+PCIDEV.class]
333
        movzx   ebx, byte [esi+PCIDEV.bus]
340
        movzx   ebx, byte [esi+PCIDEV.bus]
334
        movzx   ecx, byte [esi+PCIDEV.devfn]
341
        movzx   ecx, byte [esi+PCIDEV.devfn]
335
        shr     ecx, 3 ; get rid of 3 lowest bits (function code), the rest bits is device code
342
        shr     ecx, 3 ; get rid of 3 lowest bits (function code), the rest bits is device code
336
        movzx   edx, byte [esi+PCIDEV.devfn]
343
        movzx   edx, byte [esi+PCIDEV.devfn]
337
        and     edx, 00000111b ; get only 3 lowest bits (function code)
344
        and     edx, 00000111b ; get only 3 lowest bits (function code)
338
        DEBUGF  1, "K: found AHCI controller, (class, subcl, progif) = %x, bus = %x, device = %x, function = %x\n", eax, ebx, ecx, edx
345
        DEBUGF  1, "K: found AHCI controller, (class, subcl, progif) = %x, bus = %x, device = %x, function = %x\n", eax, ebx, ecx, edx
339
        
346
        
340
        ; get BAR5 value, it is physical address 
347
        ; get BAR5 value, it is physical address 
341
        movzx   ebx, [esi + PCIDEV.bus]
348
        movzx   ebx, [esi + PCIDEV.bus]
342
        movzx   ebp, [esi + PCIDEV.devfn]
349
        movzx   ebp, [esi + PCIDEV.devfn]
343
        stdcall pci_read32, ebx, ebp, PCI_REG_BAR5
350
        stdcall pci_read32, ebx, ebp, PCI_REG_BAR5
344
        DEBUGF  1, "K: AHCI controller MMIO = %x\n", eax
351
        DEBUGF  1, "K: AHCI controller MMIO = %x\n", eax
345
        mov     edi, eax
352
        mov     edi, eax
346
 
353
 
347
        ; get the size of MMIO region
354
        ; get the size of MMIO region
348
        stdcall pci_write32, ebx, ebp, PCI_REG_BAR5, 0xFFFFFFFF
355
        stdcall pci_write32, ebx, ebp, PCI_REG_BAR5, 0xFFFFFFFF
349
        stdcall pci_read32, ebx, ebp, PCI_REG_BAR5
356
        stdcall pci_read32, ebx, ebp, PCI_REG_BAR5
350
        not     eax
357
        not     eax
351
        inc     eax
358
        inc     eax
352
        DEBUGF  1, "K: AHCI: MMIO region size = 0x%x bytes\n", eax
359
        DEBUGF  1, "K: AHCI: MMIO region size = 0x%x bytes\n", eax
353
 
360
 
354
        ; Map MMIO region to virtual memory
361
        ; Map MMIO region to virtual memory
355
        stdcall map_io_mem, edi, eax, PG_SWR + PG_NOCACHE
362
        stdcall map_io_mem, edi, eax, PG_SWR + PG_NOCACHE
356
        mov     [ahci_controller + AHCI_DATA.abar], eax
363
        mov     [ahci_controller + AHCI_DATA.abar], eax
357
        DEBUGF  1, "K: AHCI controller BAR5 mapped to virtual addr %x\n", eax
364
        DEBUGF  1, "K: AHCI controller BAR5 mapped to virtual addr %x\n", eax
358
 
365
 
359
        ; Restore the original BAR5 value
366
        ; Restore the original BAR5 value
360
        stdcall pci_write32, ebx, ebp, PCI_REG_BAR5, edi
367
        stdcall pci_write32, ebx, ebp, PCI_REG_BAR5, edi
361
 
368
 
362
        ; Enable dma bus mastering, memory space access, clear the "disable interrupts" bit
369
        ; Enable dma bus mastering, memory space access, clear the "disable interrupts" bit
363
        ; Usually, it is already done before us
370
        ; Usually, it is already done before us
364
        movzx   ebx, [esi + PCIDEV.bus]
371
        movzx   ebx, [esi + PCIDEV.bus]
365
        movzx   ebp, [esi + PCIDEV.devfn]
372
        movzx   ebp, [esi + PCIDEV.devfn]
366
        stdcall pci_read32, ebx, ebp, PCI_REG_STATUS_COMMAND
373
        stdcall pci_read32, ebx, ebp, PCI_REG_STATUS_COMMAND
367
        DEBUGF  1, "K: AHCI: pci_status_command = %x\nEnabling interrupts, DMA bus mastering and memory space access\n", eax
374
        DEBUGF  1, "K: AHCI: pci_status_command = %x\nEnabling interrupts, DMA bus mastering and memory space access\n", eax
368
        or      eax, 0x06 ; pci.command |= 0x06 (dma bus mastering + memory space access)
375
        or      eax, 0x06 ; pci.command |= 0x06 (dma bus mastering + memory space access)
369
        btr     eax, 10 ; clear the "disable interrupts" bit
376
        btr     eax, 10 ; clear the "disable interrupts" bit
370
        DEBUGF  1, "K: AHCI: pci_status_command = %x\n", eax
377
        DEBUGF  1, "K: AHCI: pci_status_command = %x\n", eax
371
        stdcall pci_write32, ebx, ebp, PCI_REG_STATUS_COMMAND, eax
378
        stdcall pci_write32, ebx, ebp, PCI_REG_STATUS_COMMAND, eax
372
 
379
 
373
        ; ; Print some register values to debug board
380
        ; ; Print some register values to debug board
374
        ; mov     esi, [ahci_controller + AHCI_DATA.abar]
381
        ; mov     esi, [ahci_controller + AHCI_DATA.abar]
375
        ; 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]
382
        ; 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]
376
 
383
 
377
        ;-------------------------------------------------------
384
        ;-------------------------------------------------------
378
        ; Request BIOS/OS ownership handoff, if supported. (TODO check correctness)
385
        ; Request BIOS/OS ownership handoff, if supported. (TODO check correctness)
379
        mov     esi, [ahci_controller + AHCI_DATA.abar]
386
        mov     esi, [ahci_controller + AHCI_DATA.abar]
380
        ;mov     ebx, [esi + HBA_MEM.cap2]
387
        ;mov     ebx, [esi + HBA_MEM.cap2]
381
        ;DEBUGF  1, "K: AHCI: HBA_MEM.cap2 = %x\n", ebx
388
        ;DEBUGF  1, "K: AHCI: HBA_MEM.cap2 = %x\n", ebx
382
        bt      [esi + HBA_MEM.cap2], bit_AHCI_HBA_CAP2_BOH
389
        bt      [esi + HBA_MEM.cap2], bit_AHCI_HBA_CAP2_BOH
383
        jnc     .end_handoff
390
        jnc     .end_handoff
384
        DEBUGF  1, "K: AHCI: requesting AHCI ownership change...\n"
391
        DEBUGF  1, "K: AHCI: requesting AHCI ownership change...\n"
385
        bts     [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_OOS
392
        bts     [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_OOS
386
 
393
 
387
.wait_not_bos:
394
.wait_not_bos:
388
        bt      [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_BOS
395
        bt      [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_BOS
389
        jc      .wait_not_bos
396
        jc      .wait_not_bos
390
 
397
 
391
        mov     ebx, 3
398
        mov     ebx, 3
392
        call    delay_hs
399
        call    delay_hs
393
 
400
 
394
        ; if Bios Busy is still set after 30 mS, wait 2 seconds.
401
        ; if Bios Busy is still set after 30 mS, wait 2 seconds.
395
        bt      [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_BB
402
        bt      [esi + HBA_MEM.bohc], bit_AHCI_HBA_BOHC_BB
396
        jnc     @f
403
        jnc     @f
397
 
404
 
398
        mov     ebx, 200
405
        mov     ebx, 200
399
        call    delay_hs
406
        call    delay_hs
400
@@:
407
@@:
401
        DEBUGF  1, "K: AHCI: ownership change completed.\n"
408
        DEBUGF  1, "K: AHCI: ownership change completed.\n"
402
 
409
 
403
.end_handoff:
410
.end_handoff:
404
        ;-------------------------------------------------------
411
        ;-------------------------------------------------------
405
 
412
 
406
        ; enable the AHCI and reset it
413
        ; enable the AHCI and reset it
407
        bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_AHCI_ENABLE
414
        bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_AHCI_ENABLE
408
        bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_RESET
415
        bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_RESET
409
 
416
 
410
        ; wait for reset to complete
417
        ; wait for reset to complete
411
.wait_reset:
418
.wait_reset:
412
        bt      [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_RESET
419
        bt      [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_RESET
413
        jc      .wait_reset
420
        jc      .wait_reset
414
 
421
 
415
        ; enable the AHCI and interrupts
422
        ; enable the AHCI and interrupts
416
        bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_AHCI_ENABLE
423
        bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_AHCI_ENABLE
417
        bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_INTERRUPT_ENABLE
424
        bts     [esi + HBA_MEM.ghc], bit_AHCI_HBA_GHC_INTERRUPT_ENABLE
418
        mov     ebx, 2
425
        mov     ebx, 2
419
        call    delay_hs
426
        call    delay_hs
420
        
427
        
421
        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]
428
        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]
422
 
429
 
423
        ; TODO:
430
        ; TODO:
424
        ; calculate irq line
431
        ; calculate irq line
425
        ; ahciHBA->ghc |= AHCI_GHC_IE;
432
        ; ahciHBA->ghc |= AHCI_GHC_IE;
426
        ; IDT::RegisterInterruptHandler(irq, InterruptHandler);
433
        ; IDT::RegisterInterruptHandler(irq, InterruptHandler);
427
        ; ahciHBA->is = 0xffffffff;
434
        ; ahciHBA->is = 0xffffffff;
428
 
435
 
429
        xor     ebx, ebx
436
        xor     ebx, ebx
430
.detect_drives:
437
.detect_drives:
431
        cmp     ebx, AHCI_MAX_PORTS
438
        cmp     ebx, AHCI_MAX_PORTS
432
        jae     .end_detect_drives
439
        jae     .end_detect_drives
433
 
440
 
434
        ; if port with index ebx is not implemented then go to next
441
        ; if port with index ebx is not implemented then go to next
435
        mov     ecx, [esi + HBA_MEM.pi]
442
        mov     ecx, [esi + HBA_MEM.pi]
436
        bt      ecx, ebx
443
        bt      ecx, ebx
437
        jnc     .continue_detect_drives
444
        jnc     .continue_detect_drives
438
 
445
 
439
        mov     edi, ebx
446
        mov     edi, ebx
440
        imul    edi, sizeof.HBA_PORT
447
        imul    edi, sizeof.HBA_PORT
441
        add     edi, HBA_MEM.ports
448
        add     edi, HBA_MEM.ports
442
        add     edi, esi
449
        add     edi, esi
443
        ; now edi - base of HBA_MEM.ports[ebx]
450
        ; now edi - base of HBA_MEM.ports[ebx]
444
 
451
 
445
        DEBUGF  1, "K: AHCI: port %d, cmd = %x, ssts = %x\n", ebx, [edi + HBA_PORT.command], [edi + HBA_PORT.sata_status]
452
        DEBUGF  1, "K: AHCI: port %d, cmd = %x, ssts = %x\n", ebx, [edi + HBA_PORT.command], [edi + HBA_PORT.sata_status]
446
 
453
 
447
        ; If port is not idle force it to be idle
454
        ; If port is not idle force it to be idle
448
        mov     eax, [edi + HBA_PORT.command]
455
        mov     eax, [edi + HBA_PORT.command]
449
        and     eax, (AHCI_HBA_PxCMD_ST or AHCI_HBA_PxCMD_CR or AHCI_HBA_PxCMD_FRE or AHCI_HBA_PxCMD_FR)
456
        and     eax, (AHCI_HBA_PxCMD_ST or AHCI_HBA_PxCMD_CR or AHCI_HBA_PxCMD_FRE or AHCI_HBA_PxCMD_FR)
450
        test    eax, eax
457
        test    eax, eax
451
        jz      @f
458
        jz      @f
452
 
459
 
453
        mov     eax, edi
460
        mov     eax, edi
454
        DEBUGF  1, "ahci_stop_cmd..\n"
461
        DEBUGF  1, "ahci_stop_cmd..\n"
455
        call    ahci_stop_cmd
462
        call    ahci_stop_cmd
456
@@:
463
@@:
457
        ; TODO: what is purpose of this block of code ?
464
        ; TODO: what is purpose of this block of code ?
458
        ; Reset port, disable slumber and partial state
465
        ; Reset port, disable slumber and partial state
459
        ; mov     [edi + HBA_PORT.sata_control], 0x301
466
        ; mov     [edi + HBA_PORT.sata_control], 0x301
460
        ; push    ebx
467
        ; push    ebx
461
        ; mov     ebx, 5 ; wait 50 ms
468
        ; mov     ebx, 5 ; wait 50 ms
462
        ; call    delay_hs
469
        ; call    delay_hs
463
        ; pop     ebx
470
        ; pop     ebx
464
        ; mov     [edi + HBA_PORT.sata_control], 0x300
471
        ; mov     [edi + HBA_PORT.sata_control], 0x300
465
 
472
 
466
        ; if(abar->cap & HBA_MEM_CAP_SSS)
473
        ; if(abar->cap & HBA_MEM_CAP_SSS)
467
        ; {
474
        ; {
468
        ; abar->ports[i].cmd |= (HBA_PxCMD_SUD | HBA_PxCMD_POD | HBA_PxCMD_ICC);
475
        ; abar->ports[i].cmd |= (HBA_PxCMD_SUD | HBA_PxCMD_POD | HBA_PxCMD_ICC);
469
        ; Sleep(10);
476
        ; Sleep(10);
470
        ; }
477
        ; }
471
        ; rewritten to:
478
        ; rewritten to:
472
        bt      [esi + HBA_MEM.cap], 27 ; check Supports Staggered Spin-up bit in capabilities
479
        bt      [esi + HBA_MEM.cap], 27 ; check Supports Staggered Spin-up bit in capabilities
473
        jnc     @f
480
        jnc     @f
474
        DEBUGF  1, "Supports Staggered Spin-up, spinning up the port..\n"
481
        DEBUGF  1, "Supports Staggered Spin-up, spinning up the port..\n"
475
        or      [edi + HBA_PORT.command], (0x0002 or 0x0004 or 0x10000000)
482
        or      [edi + HBA_PORT.command], (0x0002 or 0x0004 or 0x10000000)
476
        push    ebx
483
        push    ebx
477
        mov     ebx, 1 ; wait 10 ms
484
        mov     ebx, 1 ; wait 10 ms
478
        call    delay_hs
485
        call    delay_hs
479
        pop     ebx
486
        pop     ebx
480
@@:
487
@@:
481
        ; Clear interrupt status and error status
488
        ; Clear interrupt status and error status
482
        mov     [edi + HBA_PORT.sata_error], 0xFFFFFFFF
489
        mov     [edi + HBA_PORT.sata_error], 0xFFFFFFFF
483
        mov     [edi + HBA_PORT.interrupt_status], 0xFFFFFFFF
490
        mov     [edi + HBA_PORT.interrupt_status], 0xFFFFFFFF
484
 
491
 
485
        ; ------------------------------------------
492
        ; ------------------------------------------
486
 
493
 
487
        mov     ecx, [edi + HBA_PORT.sata_status]
494
        mov     ecx, [edi + HBA_PORT.sata_status]
488
        shr     ecx, 8
495
        shr     ecx, 8
489
        and     ecx, 0x0F
496
        and     ecx, 0x0F
490
        cmp     ecx, AHCI_HBA_PORT_IPM_ACTIVE
497
        cmp     ecx, AHCI_HBA_PORT_IPM_ACTIVE
491
        jne     .continue_detect_drives
498
        jne     .continue_detect_drives
492
 
499
 
493
        mov     ecx, [edi + HBA_PORT.sata_status]
500
        mov     ecx, [edi + HBA_PORT.sata_status]
494
        and     ecx, AHCI_HBA_PxSSTS_DET
501
        and     ecx, AHCI_HBA_PxSSTS_DET
495
        cmp     ecx, AHCI_HBA_PxSSTS_DET_PRESENT
502
        cmp     ecx, AHCI_HBA_PxSSTS_DET_PRESENT
496
        jne     .continue_detect_drives
503
        jne     .continue_detect_drives
497
 
504
 
498
        ; DEBUGF  1, "K: AHCI: found drive at port %d, cmd = 0x%x, ssts = 0x%x, signature = 0x%x\n", ebx, [edi + HBA_PORT.command], [edi + HBA_PORT.sata_status], [edi + HBA_PORT.signature]  
505
        ; DEBUGF  1, "K: AHCI: found drive at port %d, cmd = 0x%x, ssts = 0x%x, signature = 0x%x\n", ebx, [edi + HBA_PORT.command], [edi + HBA_PORT.sata_status], [edi + HBA_PORT.signature]  
499
 
506
 
500
        mov     ecx, ebx
507
        mov     ecx, ebx
501
        imul    ecx, sizeof.PORT_DATA
508
        imul    ecx, sizeof.PORT_DATA
502
        add     ecx, port_data_arr
509
        add     ecx, port_data_arr
503
        stdcall ahci_port_rebase, edi, ebx, ecx
510
        stdcall ahci_port_rebase, edi, ebx, ecx
504
 
511
 
505
        ; DEBUGF  1, "K: AHCI: After REBASING, signature = 0x%x\n", [edi + HBA_PORT.signature]
512
        ; DEBUGF  1, "K: AHCI: After REBASING, signature = 0x%x\n", [edi + HBA_PORT.signature]
506
 
513
 
507
        ; Determine drive type by checking port signature
514
        ; Determine drive type by checking port signature
508
.switch_sig:
515
.switch_sig:
509
        cmp     [edi + HBA_PORT.signature], SATA_SIG_ATA
516
        cmp     [edi + HBA_PORT.signature], SATA_SIG_ATA
510
        mov     eax, AHCI_DEV_SATA
517
        mov     eax, AHCI_DEV_SATA
511
        jz      .end_switch_sig
518
        jz      .end_switch_sig
512
 
519
 
513
        cmp     [edi + HBA_PORT.signature], SATA_SIG_ATAPI
520
        cmp     [edi + HBA_PORT.signature], SATA_SIG_ATAPI
514
        mov     eax, AHCI_DEV_SATAPI
521
        mov     eax, AHCI_DEV_SATAPI
515
        jz      .end_switch_sig
522
        jz      .end_switch_sig
516
 
523
 
517
        cmp     [edi + HBA_PORT.signature], SATA_SIG_SEMB
524
        cmp     [edi + HBA_PORT.signature], SATA_SIG_SEMB
518
        mov     eax, AHCI_DEV_SEMB
525
        mov     eax, AHCI_DEV_SEMB
519
        jz      .end_switch_sig
526
        jz      .end_switch_sig
520
 
527
 
521
        cmp     [edi + HBA_PORT.signature], SATA_SIG_PM
528
        cmp     [edi + HBA_PORT.signature], SATA_SIG_PM
522
        mov     eax, AHCI_DEV_PM
529
        mov     eax, AHCI_DEV_PM
523
        jz      .end_switch_sig
530
        jz      .end_switch_sig
524
 
531
 
525
        DEBUGF  1, "Unknown device signature\n"
532
        DEBUGF  1, "Unknown device signature\n"
526
        mov     eax, AHCI_DEV_NULL
533
        mov     eax, AHCI_DEV_NULL
527
.end_switch_sig:
534
.end_switch_sig:
528
        mov     [ecx + PORT_DATA.drive_type], al
535
        mov     [ecx + PORT_DATA.drive_type], al
529
 
536
 
530
        DEBUGF  1, "K: AHCI: found drive on port %u: TYPE = %u\n", ebx, [ecx + PORT_DATA.drive_type]
537
        DEBUGF  1, "K: AHCI: found drive on port %u: TYPE = %u\n", ebx, [ecx + PORT_DATA.drive_type]
531
 
538
 
532
        stdcall ahci_port_identify, ecx
539
        stdcall ahci_port_identify, ecx
533
 
540
 
534
.continue_detect_drives:
541
.continue_detect_drives:
535
        inc     ebx
542
        inc     ebx
536
        jmp     .detect_drives
543
        jmp     .detect_drives
537
 
544
 
538
        
545
        
539
 
546
 
540
.end_detect_drives:
547
.end_detect_drives:
541
        
548
        
542
 
549
 
543
        ret
550
        ret
544
; -------------------------------------------------
551
; -------------------------------------------------
545
 
552
 
546
modelstr  rb 42
553
modelstr  rb 42
547
; Identify drive on port ; TODO check
554
; Identify drive on port ; TODO check
548
; in: pdata - address of PORT_DATA structure
555
; in: pdata - address of PORT_DATA structure
549
proc ahci_port_identify stdcall, pdata: dword
556
proc ahci_port_identify stdcall, pdata: dword
550
        locals
557
        locals
551
            cmdslot dd ?
558
            cmdslot dd ?
552
            cmdheader dd ?
559
            cmdheader dd ?
553
            cmdtable  dd ?
560
            cmdtable  dd ?
554
            buf_phys  dd ?
561
            buf_phys  dd ?
555
            buf_virt  dd ?
562
            buf_virt  dd ?
556
        endl
563
        endl
557
 
564
 
558
        pushad
565
        pushad
559
        
566
        
560
        mov     esi, [pdata] ; esi - address of PORT_DATA struct of port
567
        mov     esi, [pdata] ; esi - address of PORT_DATA struct of port
561
        mov     edi, [esi + PORT_DATA.port] ; edi - address of HBA_PORT struct of port
568
        mov     edi, [esi + PORT_DATA.port] ; edi - address of HBA_PORT struct of port
562
 
569
 
563
        mov     eax, edi
570
        mov     eax, edi
564
        call    ahci_find_cmdslot
571
        call    ahci_find_cmdslot
565
 
572
 
566
        cmp     eax, -1
573
        cmp     eax, -1
567
        jne      .cmdslot_found
574
        jne      .cmdslot_found
568
 
575
 
569
        DEBUGF  1, "No free cmdslot on port %u\n", [esi + PORT_DATA.portno]
576
        DEBUGF  1, "No free cmdslot on port %u\n", [esi + PORT_DATA.portno]
570
 
577
 
571
.cmdslot_found:
578
.cmdslot_found:
572
        mov     [cmdslot], eax
579
        mov     [cmdslot], eax
573
        ; DEBUGF  1, "Found free cmdslot %u on port %u\n", [cmdslot], [esi + PORT_DATA.portno]
580
        ; DEBUGF  1, "Found free cmdslot %u on port %u\n", [cmdslot], [esi + PORT_DATA.portno]
574
 
581
 
575
        shl     eax, BSF sizeof.HBA_CMD_HDR
582
        shl     eax, BSF sizeof.HBA_CMD_HDR
576
        add     eax, [esi + PORT_DATA.clb]
583
        add     eax, [esi + PORT_DATA.clb]
577
        mov     [cmdheader], eax ; address of virtual mapping of command header
584
        mov     [cmdheader], eax ; address of virtual mapping of command header
578
        mov     eax, [cmdslot]
585
        mov     eax, [cmdslot]
579
        mov     eax, [esi + eax*4 + PORT_DATA.ctba_arr]
586
        mov     eax, [esi + eax*4 + PORT_DATA.ctba_arr]
580
        mov     [cmdtable], eax ; address of virtual mapping of command table of command header
587
        mov     [cmdtable], eax ; address of virtual mapping of command table of command header
581
 
588
 
582
        stdcall _memset, eax, 0, sizeof.HBA_CMD_TBL
589
        stdcall _memset, eax, 0, sizeof.HBA_CMD_TBL
583
 
590
 
584
        call    alloc_page
591
        call    alloc_page
585
        mov     [buf_phys], eax
592
        mov     [buf_phys], eax
586
 
593
 
587
        stdcall map_io_mem, eax, 4096, PG_NOCACHE + PG_SWR  ; map to virt memory so we can work with it
594
        stdcall map_io_mem, eax, 4096, PG_NOCACHE + PG_SWR  ; map to virt memory so we can work with it
588
        mov     [buf_virt], eax
595
        mov     [buf_virt], eax
589
 
596
 
590
        mov     eax, [cmdtable]
597
        mov     eax, [cmdtable]
591
        mov     ebx, [buf_phys]
598
        mov     ebx, [buf_phys]
592
        mov     dword [eax + HBA_CMD_TBL.prdt_entry + HBA_PRDT_ENTRY.dba], ebx
599
        mov     dword [eax + HBA_CMD_TBL.prdt_entry + HBA_PRDT_ENTRY.dba], ebx
593
        mov     dword [eax + HBA_CMD_TBL.prdt_entry + HBA_PRDT_ENTRY.dbau], 0
600
        mov     dword [eax + HBA_CMD_TBL.prdt_entry + HBA_PRDT_ENTRY.dbau], 0
594
        and     [eax + HBA_CMD_TBL.prdt_entry + HBA_PRDT_ENTRY.flags], not 0x3FFFFF ; zero out lower 22 bits, they used for byte count
601
        and     [eax + HBA_CMD_TBL.prdt_entry + HBA_PRDT_ENTRY.flags], not 0x3FFFFF ; zero out lower 22 bits, they used for byte count
595
        or      [eax + HBA_CMD_TBL.prdt_entry + HBA_PRDT_ENTRY.flags], 512 - 1 ; reason why -1 see in spec on this field
602
        or      [eax + HBA_CMD_TBL.prdt_entry + HBA_PRDT_ENTRY.flags], 512 - 1 ; reason why -1 see in spec on this field
596
        ; or      [eax + HBA_CMD_TBL.prdt_entry + HBA_PRDT_ENTRY.flags], 1 shl 31 ; enable interrupt on completion
603
        ; or      [eax + HBA_CMD_TBL.prdt_entry + HBA_PRDT_ENTRY.flags], 1 shl 31 ; enable interrupt on completion
597
 
604
 
598
        mov     eax, [cmdheader]
605
        mov     eax, [cmdheader]
599
        and     [eax + HBA_CMD_HDR.flags1], not 0x1F ; zero out lower 5 bits, they will be used for cfl
606
        and     [eax + HBA_CMD_HDR.flags1], not 0x1F ; zero out lower 5 bits, they will be used for cfl
600
        or      [eax + HBA_CMD_HDR.flags1], (sizeof.FIS_REG_H2D / 4) ; set command fis length in dwords
607
        or      [eax + HBA_CMD_HDR.flags1], (sizeof.FIS_REG_H2D / 4) ; set command fis length in dwords
601
        movzx   bx, [eax + HBA_CMD_HDR.flags1]
608
        movzx   bx, [eax + HBA_CMD_HDR.flags1]
602
        btr     bx, 6 ; flag W = 0
609
        btr     bx, 6 ; flag W = 0
603
        mov     [eax + HBA_CMD_HDR.flags1], bl
610
        mov     [eax + HBA_CMD_HDR.flags1], bl
604
        movzx   bx, [eax + HBA_CMD_HDR.flags2]
611
        movzx   bx, [eax + HBA_CMD_HDR.flags2]
605
        btr     bx, 2 ; flag C = 0
612
        btr     bx, 2 ; flag C = 0
606
        mov     [eax + HBA_CMD_HDR.flags2], bl
613
        mov     [eax + HBA_CMD_HDR.flags2], bl
607
        mov     [eax + HBA_CMD_HDR.prdtl], 1
614
        mov     [eax + HBA_CMD_HDR.prdtl], 1
608
 
615
 
609
        mov     eax, [cmdtable]
616
        mov     eax, [cmdtable]
610
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.fis_type], FIS_TYPE_REG_H2D
617
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.fis_type], FIS_TYPE_REG_H2D
611
        movzx   ebx, byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.flags]
618
        movzx   ebx, byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.flags]
612
        bts     ebx, bit_AHCI_H2D_FLAG_CMD ; Set Command bit in H2D FIS.
619
        bts     ebx, bit_AHCI_H2D_FLAG_CMD ; Set Command bit in H2D FIS.
613
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.flags], bl
620
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.flags], bl
614
 
621
 
615
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.command], ATA_IDENTIFY
622
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.command], ATA_IDENTIFY
616
        cmp     [esi + PORT_DATA.drive_type], AHCI_DEV_SATAPI
623
        cmp     [esi + PORT_DATA.drive_type], AHCI_DEV_SATAPI
617
        jne     @f
624
        jne     @f
618
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.command], ATAPI_IDENTIFY
625
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.command], ATAPI_IDENTIFY
619
@@:
626
@@:
620
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.device], 0
627
        mov     byte [eax + HBA_CMD_TBL.cfis + FIS_REG_H2D.device], 0
621
 
628
 
-
 
629
        ; Wait on previous command to complete, before issuing new command.
622
        ; TODO Wait on previous command to complete. AHCIPortWait(bd->port_num, tS + 2);
630
        stdcall ahci_port_wait, edi, AHCI_PORT_TIMEOUT
623
        mov     ebx, 20 ;;;
631
        ; DEBUGF  1, "eax = %x\n", eax
624
        call    delay_hs ;;;
632
        ; TODO check eax error value
625
 
633
 
626
        mov     eax, [cmdslot]
634
        mov     eax, [cmdslot]
627
        bts     [edi + HBA_PORT.command_issue], eax ; Issue the command
635
        bts     [edi + HBA_PORT.command_issue], eax ; Issue the command
628
 
636
 
-
 
637
        ; Wait for command completion
629
        ; TODO AHCIPortCmdWait(bd->port_num, cmd_slot);
638
        stdcall ahci_port_cmd_wait, edi, eax;, AHCI_PORT_CMD_TIMEOUT
630
        mov     ebx, 20 ;;;
639
        ; DEBUGF  1, " eax = %x\n", eax
631
        call    delay_hs ;;;
640
        ; TODO check eax error value
632
 
641
 
633
        ; DEBUGF  1, "sata_error register = 0x%x\n", [edi + HBA_PORT.sata_error]
642
        ; DEBUGF  1, "sata_error register = 0x%x\n", [edi + HBA_PORT.sata_error]
634
 
-
 
635
;         mov     ecx, ecx
-
 
636
;         mov     esi, [buf_virt]
-
 
637
; .print_ident:
-
 
638
;         cmp     ecx, 512 - 1 ; why -1 ?
-
 
639
;         jae     .end_print_ident
-
 
640
 
-
 
641
;         mov     al, byte [esi + ecx]
-
 
642
;         mov     byte [modelstr], al
-
 
643
;         mov     byte [modelstr + 1], 0
-
 
644
;         DEBUGF  1, "(%s) ", modelstr
-
 
645
 
-
 
646
;         inc     ecx
-
 
647
;         jmp     .print_ident
-
 
648
; .end_print_ident:
-
 
649
        ; DEBUGF  1, "\n"
-
 
650
 
-
 
651
        ; DEBUGF  1, "after identification: signature = 0x%x\n", [edi + HBA_PORT.signature]
-
 
652
 
643
 
653
        mov     esi, [buf_virt]
644
        mov     esi, [buf_virt]
654
        add     esi, 27*2
645
        add     esi, 27*2
655
        mov     edi, modelstr
646
        mov     edi, modelstr
656
        mov     ecx, ((46-27)+1)*2
647
        mov     ecx, ((46-27)+1)*2
657
        cld
648
        cld
658
        rep movsb
649
        rep movsb
659
        mov     byte [edi], 0
650
        mov     byte [edi], 0
660
        
651
        
661
        stdcall swap_bytes_in_words, modelstr, (46-27)+1
652
        stdcall swap_bytes_in_words, modelstr, (46-27)+1
662
        DEBUGF  1, "IDENTIFICATION RESULT: MODEL = %s\n", modelstr
653
        DEBUGF  1, "IDENTIFICATION RESULT: MODEL = %s\n", modelstr
663
 
654
 
664
        mov     esi, [buf_virt]
655
        mov     esi, [buf_virt]
665
        mov     eax, [esi + 200]
656
        mov     eax, [esi + 200]
666
        mov     edx, [esi + 200 + 4]
657
        mov     edx, [esi + 200 + 4]
667
        DEBUGF 1, "lba48 mode sector count = 0x%x:%x\n", edx, eax
658
        DEBUGF 1, "lba48 mode sector count = 0x%x:%x\n", edx, eax
668
 
659
 
669
        shrd    eax, edx, 11 ; i.e *512 / 1024 / 1024, 512 - sector size
660
        shrd    eax, edx, 11 ; i.e *512 / 1024 / 1024, 512 - sector size
670
        DEBUGF  1, "disk capacity = %u MiB ", eax
661
        DEBUGF  1, "disk capacity = %u MiB ", eax
671
        shrd    eax, edx, 10 ; / 1024
662
        shrd    eax, edx, 10 ; / 1024
672
        DEBUGF  1, "= %u GiB\n", eax
663
        DEBUGF  1, "= %u GiB\n", eax
673
.ret:
664
.ret:
674
        popad
665
        popad
675
        ret
666
        ret
676
endp
667
endp
677
 
668
 
678
 
669
 
679
; Start command engine
670
; Start command engine
680
; in: eax - address of HBA_PORT structure
671
; in: eax - address of HBA_PORT structure
681
ahci_start_cmd:
672
ahci_start_cmd:
682
.wait_cr: ; Wait until CR (bit15) is cleared
673
.wait_cr: ; Wait until CR (bit15) is cleared
683
        bt      [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_CR
674
        bt      [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_CR
684
        jc      .wait_cr
675
        jc      .wait_cr
685
 
676
 
686
        ; Set FRE (bit4) and ST (bit0)
677
        ; Set FRE (bit4) and ST (bit0)
687
        bts     [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_FRE
678
        bts     [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_FRE
688
        bts     [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_ST
679
        bts     [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_ST
689
        ; maybe here call ahci flush cmd ? TODO (see seakernel)
680
        ; maybe here call ahci flush cmd ? TODO (see seakernel)
690
        ret
681
        ret
691
 
682
 
692
; Stop command engine
683
; Stop command engine
693
; in: eax - address of HBA_PORT structure
684
; in: eax - address of HBA_PORT structure
694
ahci_stop_cmd:
685
ahci_stop_cmd:
695
        btr     [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_ST ; Clear ST (bit0)
686
        btr     [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_ST ; Clear ST (bit0)
696
        btr     [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_FRE ; Clear FRE (bit4)
687
        btr     [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_FRE ; Clear FRE (bit4)
697
.wait_fr_cr: ; Wait until FR (bit14), CR (bit15) are cleared
688
.wait_fr_cr: ; Wait until FR (bit14), CR (bit15) are cleared
698
        bt      [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_FR
689
        bt      [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_FR
699
        jc      .wait_fr_cr
690
        jc      .wait_fr_cr
700
        bt      [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_CR
691
        bt      [eax + HBA_PORT.command], bit_AHCI_HBA_PxCMD_CR
701
        jc      .wait_fr_cr
692
        jc      .wait_fr_cr
702
 
693
 
703
        ret
694
        ret
704
 
695
 
705
; The commands may not take effect until the command
696
; waits until the port is no longer busy before issuing a new command
706
; register is read again by software, because reasons.
697
; in: [port] - address of HBA_PORT structure
707
; in: eax - address of HBA_PORT structure
698
; [timeout] - timeout (in iterations)
-
 
699
; out: eax = 0 if success, 1 if timeout expired
708
; out: eax - command register value
700
proc ahci_port_wait stdcall, port: dword, timeout: dword
-
 
701
        push    ebx ecx
-
 
702
        mov     ebx, [port]
-
 
703
        xor     ecx, ecx
-
 
704
.wait:
-
 
705
        cmp     ecx, [timeout]
709
ahci_flush_cmd:
706
        jae     .wait_end
-
 
707
        mov     eax, [ebx + HBA_PORT.task_file_data]
-
 
708
        and     eax, ATA_DEV_BUSY or ATA_DEV_DRQ
-
 
709
        test    eax, eax
-
 
710
        jz      .wait_end
-
 
711
        inc     ecx
-
 
712
        jmp     .wait
-
 
713
.wait_end:
-
 
714
        xor     eax, eax
-
 
715
        DEBUGF  1, "port wait counter = %u\n", ecx
-
 
716
        cmp     ecx, [timeout] ; if they equal it means port is hung
-
 
717
        setz    al
710
        mov     eax, [eax + HBA_PORT.command]
718
        pop     ecx ebx
-
 
719
        ret
711
        ret
-
 
712
 
-
 
713
; Send command to port
-
 
714
; in: eax - address of HBA_PORT structure
-
 
715
;     ebx - index of command slot
-
 
716
ahci_send_cmd:
-
 
717
        push    ecx
-
 
718
        mov     [eax + HBA_PORT.interrupt_status], 0xFFFFFFFF
-
 
719
        
-
 
720
        mov     cl, bl
-
 
-
 
720
endp
-
 
721
 
-
 
722
 
-
 
723
; Wait for command completion
-
 
724
; in: [port] - address of HBA_PORT structure
-
 
725
;     [cmdslot] - number of command slot
-
 
726
; out: eax = 0 if success, 1 if error
-
 
727
proc ahci_port_cmd_wait stdcall, port: dword, cmdslot: dword ;, timeout: dword
-
 
728
        push    ebx ecx edx
-
 
729
        mov     ebx, [port]
-
 
730
        mov     edx, [cmdslot]
-
 
731
        xor     eax, eax
721
        mov     [eax + HBA_PORT.command_issue], 1
732
        xor     ecx, ecx
-
 
733
.wait:
-
 
734
        bt      [ebx + HBA_PORT.command_issue], edx
722
        shl     [eax + HBA_PORT.command_issue], cl
735
        jnc     .wait_end
-
 
736
        bt      [ebx + HBA_PORT.interrupt_status], bit_AHCI_HBA_PxIS_TFES ; check for Task File Error
-
 
737
        jc      .error
-
 
738
        inc     ecx
-
 
739
        jmp     .wait
-
 
740
.wait_end:
-
 
741
        DEBUGF  1, "port cmd wait counter = %u\n", ecx
-
 
742
        bt      [ebx + HBA_PORT.interrupt_status], bit_AHCI_HBA_PxIS_TFES ; check for Task File Error
-
 
743
        jc      .error
-
 
744
        jmp     .ret
-
 
745
.error:
723
 
746
        mov     eax, 1
-
 
747
.ret:
-
 
748
        pop     edx ecx ebx
-
 
749
        ret
-
 
750
endp
-
 
751
 
-
 
752
; ; The commands may not take effect until the command
-
 
753
; ; register is read again by software, because reasons.
-
 
754
; ; in: eax - address of HBA_PORT structure
-
 
755
; ; out: eax - command register value
-
 
756
; ahci_flush_cmd:
-
 
757
;         mov     eax, [eax + HBA_PORT.command]
-
 
758
;         ret
-
 
759
 
-
 
760
; ; Send command to port
-
 
761
; ; in: eax - address of HBA_PORT structure
-
 
762
; ;     ebx - index of command slot
-
 
763
; ahci_send_cmd:
-
 
764
;         push    ecx
-
 
765
;         mov     [eax + HBA_PORT.interrupt_status], 0xFFFFFFFF
-
 
766
        
-
 
767
;         mov     cl, bl
-
 
768
;         mov     [eax + HBA_PORT.command_issue], 1
-
 
769
;         shl     [eax + HBA_PORT.command_issue], cl
-
 
770
 
724
        call    ahci_flush_cmd
771
;         call    ahci_flush_cmd
725
        pop     ecx
772
;         pop     ecx
726
        ret
773
;         ret
727
 
774
 
728
; ---------------------------------------------------------------------------
775
; ---------------------------------------------------------------------------
729
; in: port - address of HBA_PORT structure
776
; in: port - address of HBA_PORT structure
730
;     portno - port index (0..31)
777
;     portno - port index (0..31)
731
;     pdata - address of PORT_DATA structure
778
;     pdata - address of PORT_DATA structure
732
proc ahci_port_rebase stdcall, port: dword, portno: dword, pdata: dword
779
proc ahci_port_rebase stdcall, port: dword, portno: dword, pdata: dword
733
        locals
780
        locals
734
            phys_page1  dd ?
781
            phys_page1  dd ?
735
            virt_page1  dd ?
782
            virt_page1  dd ?
736
            phys_page23 dd ?
783
            phys_page23 dd ?
737
            virt_page23 dd ?
784
            virt_page23 dd ?
738
            tmp         dd ?
785
            tmp         dd ?
739
        endl
786
        endl
740
 
787
 
741
        pushad
788
        pushad
742
 
789
 
743
        DEBUGF  1, "Rebasing port %u\n", [portno]
790
        DEBUGF  1, "Rebasing port %u\n", [portno]
744
 
791
 
745
        mov     eax, [port]
792
        mov     eax, [port]
746
        call    ahci_stop_cmd
793
        call    ahci_stop_cmd
747
 
794
 
748
        ; Command list entry size = 32
795
        ; Command list entry size = 32
749
        ; Command list entry maxim count = 32
796
        ; Command list entry maxim count = 32
750
        ; Command list maxim size = 32*32 = 1K per port
797
        ; Command list maxim size = 32*32 = 1K per port
751
        call    alloc_page
798
        call    alloc_page
752
        mov     [phys_page1], eax
799
        mov     [phys_page1], eax
753
 
800
 
754
        stdcall map_io_mem, eax, 4096, PG_NOCACHE + PG_SWR  ; map to virt memory so we can work with it
801
        stdcall map_io_mem, eax, 4096, PG_NOCACHE + PG_SWR  ; map to virt memory so we can work with it
755
        mov     [virt_page1], eax
802
        mov     [virt_page1], eax
756
 
803
 
757
        mov     esi, [port]
804
        mov     esi, [port]
758
        mov     ebx, [phys_page1]
805
        mov     ebx, [phys_page1]
759
        mov     [esi + HBA_PORT.command_list_base_l], ebx ; set the command list base
806
        mov     [esi + HBA_PORT.command_list_base_l], ebx ; set the command list base
760
        mov     [esi + HBA_PORT.command_list_base_h], 0  ; zero upper 32 bits of addr cause we are 32 bit os 
807
        mov     [esi + HBA_PORT.command_list_base_h], 0  ; zero upper 32 bits of addr cause we are 32 bit os 
761
 
808
 
762
        mov     edi, [pdata]
809
        mov     edi, [pdata]
763
        mov     ebx, [virt_page1]
810
        mov     ebx, [virt_page1]
764
        mov     [edi + PORT_DATA.clb], ebx ; set pdata->clb
811
        mov     [edi + PORT_DATA.clb], ebx ; set pdata->clb
765
 
812
 
766
        mov     eax, [port]
813
        mov     eax, [port]
767
        mov     [edi + PORT_DATA.port], eax ; set pdata->port
814
        mov     [edi + PORT_DATA.port], eax ; set pdata->port
768
        mov     eax, [portno]               ; set pdata->portno
815
        mov     eax, [portno]               ; set pdata->portno
769
        mov     [edi + PORT_DATA.portno], eax
816
        mov     [edi + PORT_DATA.portno], eax
770
 
817
 
771
        stdcall _memset, ebx, 0, 1024 ; zero out the command list
818
        stdcall _memset, ebx, 0, 1024 ; zero out the command list
772
        
819
        
773
        ; FIS entry size = 256 bytes per port
820
        ; FIS entry size = 256 bytes per port
774
        mov     eax, [phys_page1]
821
        mov     eax, [phys_page1]
775
        add     eax, 1024
822
        add     eax, 1024
776
        mov     [esi + HBA_PORT.fis_base_l], eax
823
        mov     [esi + HBA_PORT.fis_base_l], eax
777
        mov     [esi + HBA_PORT.fis_base_h], 0
824
        mov     [esi + HBA_PORT.fis_base_h], 0
778
 
825
 
779
        mov     eax, [virt_page1]
826
        mov     eax, [virt_page1]
780
        add     eax, 1024
827
        add     eax, 1024
781
        mov     [edi + PORT_DATA.fb], eax ; set pdata->fb 
828
        mov     [edi + PORT_DATA.fb], eax ; set pdata->fb 
782
        stdcall _memset, eax, 0, 256 ; zero out
829
        stdcall _memset, eax, 0, 256 ; zero out
783
        
830
        
784
        stdcall alloc_pages, 2
831
        stdcall alloc_pages, 2
785
        mov     [phys_page23], eax
832
        mov     [phys_page23], eax
786
        stdcall map_io_mem, eax, 2*4096, PG_NOCACHE + PG_SWR
833
        stdcall map_io_mem, eax, 2*4096, PG_NOCACHE + PG_SWR
787
        mov     [virt_page23], eax
834
        mov     [virt_page23], eax
788
 
835
 
789
        ; Command table size = 256*32 = 8K per port
836
        ; Command table size = 256*32 = 8K per port
790
        mov     edx, [edi + PORT_DATA.clb] ; cmdheader array base
837
        mov     edx, [edi + PORT_DATA.clb] ; cmdheader array base
791
        xor     ecx, ecx
838
        xor     ecx, ecx
792
 
839
 
793
.for1:
840
.for1:
794
        cmp     ecx, 32
841
        cmp     ecx, 32
795
        jae     .for1_end
842
        jae     .for1_end
796
 
843
 
797
        mov     ebx, ecx
844
        mov     ebx, ecx
798
        shl     ebx, BSF sizeof.HBA_CMD_HDR
845
        shl     ebx, BSF sizeof.HBA_CMD_HDR
799
        add     ebx, edx ; ebx = cmdheader[ecx]
846
        add     ebx, edx ; ebx = cmdheader[ecx]
800
 
847
 
801
        mov     [ebx + HBA_CMD_HDR.prdtl], 8 ; 8 prdt entries per command table
848
        mov     [ebx + HBA_CMD_HDR.prdtl], 8 ; 8 prdt entries per command table
802
 
849
 
803
        ; 256 bytes per command table, 64+16+48+16*8
850
        ; 256 bytes per command table, 64+16+48+16*8
804
 
851
 
805
        push    edx
852
        push    edx
806
        
853
        
807
        ; cmdheader[ecx].ctba = phys_page23 + ecx*256
854
        ; cmdheader[ecx].ctba = phys_page23 + ecx*256
808
        mov     [ebx + HBA_CMD_HDR.ctba], ecx
855
        mov     [ebx + HBA_CMD_HDR.ctba], ecx
809
        shl     [ebx + HBA_CMD_HDR.ctba], BSF 256 ; *= 256
856
        shl     [ebx + HBA_CMD_HDR.ctba], BSF 256 ; *= 256
810
        mov     eax, [ebx + HBA_CMD_HDR.ctba]
857
        mov     eax, [ebx + HBA_CMD_HDR.ctba]
811
        mov     edx, [phys_page23]
858
        mov     edx, [phys_page23]
812
        add     [ebx + HBA_CMD_HDR.ctba], edx
859
        add     [ebx + HBA_CMD_HDR.ctba], edx
813
 
860
 
814
        add     eax, [virt_page23]
861
        add     eax, [virt_page23]
815
        mov     [tmp], eax  ; tmp = virt_page23 + ecx*256
862
        mov     [tmp], eax  ; tmp = virt_page23 + ecx*256
816
        lea     eax, [ecx*4 + edi + PORT_DATA.ctba_arr] ; eax = pdata->ctba_arr[ecx]
863
        lea     eax, [ecx*4 + edi + PORT_DATA.ctba_arr] ; eax = pdata->ctba_arr[ecx]
817
        mov     edx, [tmp]
864
        mov     edx, [tmp]
818
        mov     [eax], edx  ; pdata->ctba_arr[ecx] = virt_page23 + ecx*256
865
        mov     [eax], edx  ; pdata->ctba_arr[ecx] = virt_page23 + ecx*256
819
 
866
 
820
        pop     edx
867
        pop     edx
821
 
868
 
822
        mov     [ebx + HBA_CMD_HDR.ctbau], 0
869
        mov     [ebx + HBA_CMD_HDR.ctbau], 0
823
        stdcall _memset, [eax], 0, 256 ; zero out
870
        stdcall _memset, [eax], 0, 256 ; zero out
824
 
871
 
825
        inc     ecx
872
        inc     ecx
826
        jmp     .for1
873
        jmp     .for1
827
.for1_end:
874
.for1_end:
828
        
875
        
829
        mov     eax, [port]
876
        mov     eax, [port]
830
        call    ahci_start_cmd
877
        call    ahci_start_cmd
831
 
878
 
832
        DEBUGF  1, "End rebasing port %u\n", [portno]
879
        DEBUGF  1, "End rebasing port %u\n", [portno]
833
        popad
880
        popad
834
        ret    
881
        ret    
835
endp
882
endp
836
 
883
 
837
; ----------------------------------------------------------- ; TODO check
884
; ----------------------------------------------------------- ; TODO check
838
; Find a free command list slot
885
; Find a free command list slot
839
; in: eax - address of HBA_PORT structure
886
; in: eax - address of HBA_PORT structure
840
; out: eax - if not found -1, else slot index
887
; out: eax - if not found -1, else slot index
841
ahci_find_cmdslot:
888
ahci_find_cmdslot:
842
        push    ebx ecx edx esi
889
        push    ebx ecx edx esi
843
        ; If not set in SACT and CI, the slot is free
890
        ; If not set in SACT and CI, the slot is free
844
        mov     ebx, [eax + HBA_PORT.sata_active]
891
        mov     ebx, [eax + HBA_PORT.sata_active]
845
        or      ebx, [eax + HBA_PORT.command_issue] ; ebx = slots
892
        or      ebx, [eax + HBA_PORT.command_issue] ; ebx = slots
846
 
893
 
847
        mov     esi, [ahci_controller + AHCI_DATA.abar]
894
        mov     esi, [ahci_controller + AHCI_DATA.abar]
848
        mov     edx, [esi + HBA_MEM.cap]
895
        mov     edx, [esi + HBA_MEM.cap]
849
        shr     edx, 8
896
        shr     edx, 8
850
        and     edx, 0xf
897
        and     edx, 0xf
851
        ; DEBUGF  1, "Number of Command Slots on each port = %u\n", edx
898
        ; DEBUGF  1, "Number of Command Slots on each port = %u\n", edx
852
        xor     ecx, ecx
899
        xor     ecx, ecx
853
.for1:
900
.for1:
854
        cmp     ecx, edx
901
        cmp     ecx, edx
855
        jae     .for1_end
902
        jae     .for1_end
856
 
903
 
857
        ; if ((slots&1) == 0) return i;
904
        ; if ((slots&1) == 0) return i;
858
        bt      ebx, 0
905
        bt      ebx, 0
859
        jc      .cont1
906
        jc      .cont1
860
 
907
 
861
        mov     eax, ecx
908
        mov     eax, ecx
862
        jmp     .ret
909
        jmp     .ret
863
 
910
 
864
.cont1:
911
.cont1:
865
        shr     ebx, 1
912
        shr     ebx, 1
866
        inc     ecx
913
        inc     ecx
867
        jmp     .for1
914
        jmp     .for1
868
.for1_end:
915
.for1_end:
869
        DEBUGF  1, "Cannot find free command list entry\n"
916
        DEBUGF  1, "Cannot find free command list entry\n"
870
        mov     eax, -1
917
        mov     eax, -1
871
.ret:
918
.ret:
872
        pop     esi edx ecx ebx
919
        pop     esi edx ecx ebx
873
        ret
920
        ret
874
 
921
 
875
 
922
 
876
proc _memset stdcall, dest:dword, val:byte, cnt:dword ; doesnt clobber any registers
923
proc _memset stdcall, dest:dword, val:byte, cnt:dword ; doesnt clobber any registers
877
        ;DEBUGF  DBG_INFO, "memset(%x, %u, %u)\n", [dest], [val], [cnt]
924
        ;DEBUGF  DBG_INFO, "memset(%x, %u, %u)\n", [dest], [val], [cnt]
878
        push    eax ecx edi
925
        push    eax ecx edi
879
        mov     edi, dword [dest]
926
        mov     edi, dword [dest]
880
        mov     al,  byte [val]
927
        mov     al,  byte [val]
881
        mov     ecx, dword [cnt]
928
        mov     ecx, dword [cnt]
882
        rep stosb   
929
        rep stosb   
883
        pop     edi ecx eax
930
        pop     edi ecx eax
884
        ret 
931
        ret 
885
endp
932
endp
886
 
933
 
887
; Swaps byte order in words
934
; Swaps byte order in words
888
; base - address of first word
935
; base - address of first word
889
; len - how many words to swap bytes in
936
; len - how many words to swap bytes in
890
; doesnt clobber any registers
937
; doesnt clobber any registers
891
proc swap_bytes_in_words stdcall, base: dword, len: dword
938
proc swap_bytes_in_words stdcall, base: dword, len: dword
892
        push    eax ebx ecx
939
        push    eax ebx ecx
893
        xor     ecx, ecx
940
        xor     ecx, ecx
894
        mov     ebx, [base]
941
        mov     ebx, [base]
895
.loop:
942
.loop:
896
        cmp     ecx, [len]
943
        cmp     ecx, [len]
897
        jae     .loop_end
944
        jae     .loop_end
898
        mov     ax, word [ebx + ecx*2]
945
        mov     ax, word [ebx + ecx*2]
899
        xchg    ah, al
946
        xchg    ah, al
900
        mov     word [ebx + ecx*2], ax
947
        mov     word [ebx + ecx*2], ax
901
        inc     ecx
948
        inc     ecx
902
        jmp     .loop
949
        jmp     .loop
903
.loop_end:
950
.loop_end:
904
        pop     ecx ebx eax
951
        pop     ecx ebx eax
905
        ret
952
        ret
906
endp
953
endp