6 IN PVOID HwDeviceExtension
,
7 IN ULONG lChannel
// logical channel
10 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
11 //ULONG Channel = deviceExtension->Channel + lChannel;
12 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
13 SATA_SSTATUS_REG SStatus
;
21 KdPrint2((PRINT_PREFIX
"UniataSataConnect:\n"));
23 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
24 KdPrint2((PRINT_PREFIX
" no I/O range\n"));
25 return IDE_STATUS_IDLE
;
28 /* clear SATA error register, some controllers need this */
29 AtapiWritePort4(chan
, IDX_SATA_SError
,
30 AtapiReadPort4(chan
, IDX_SATA_SError
));
31 /* wait up to 1 second for "connect well" */
32 for(i
=0; i
<100; i
++) {
33 SStatus
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SStatus
);
34 if(SStatus
.SPD
== SStatus_SPD_Gen1
||
35 SStatus
.SPD
== SStatus_SPD_Gen2
) {
36 deviceExtension
->lun
[lChannel
*2].TransferMode
= ATA_SA150
+ (UCHAR
)(SStatus
.SPD
- 1);
39 AtapiStallExecution(10000);
42 KdPrint2((PRINT_PREFIX
"UniataSataConnect: SStatus %8.8x\n", SStatus
.Reg
));
45 /* clear SATA error register */
46 AtapiWritePort4(chan
, IDX_SATA_SError
,
47 AtapiReadPort4(chan
, IDX_SATA_SError
));
49 Status
= WaitOnBaseBusyLong(chan
);
50 if(Status
& IDE_STATUS_BUSY
) {
54 signatureLow = AtapiReadPort1(chan, &deviceExtension->BaseIoAddress1[lChannel].i.CylinderLow);
55 signatureHigh = AtapiReadPort1(chan, &deviceExtension->baseIoAddress1[lChannel].i.CylinderHigh);
57 if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) {
60 KdPrint2((PRINT_PREFIX
"UniataSataConnect: OK, ATA status %x\n", Status
));
61 return IDE_STATUS_IDLE
;
62 } // end UniataSataConnect()
67 IN PVOID HwDeviceExtension
,
68 IN ULONG lChannel
// logical channel
71 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
72 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
73 SATA_SCONTROL_REG SControl
;
76 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable:\n"));
78 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
79 KdPrint2((PRINT_PREFIX
" no I/O range\n"));
80 return IDE_STATUS_IDLE
;
83 SControl
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SControl
);
84 KdPrint2((PRINT_PREFIX
"SControl %x\n", SControl
.Reg
));
85 if(SControl
.DET
== SControl_DET_Idle
) {
86 return UniataSataConnect(HwDeviceExtension
, lChannel
);
89 for (retry
= 0; retry
< 10; retry
++) {
90 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable: retry init %d\n", retry
));
91 for (loop
= 0; loop
< 10; loop
++) {
93 SControl
.DET
= SControl_DET_Init
;
94 AtapiWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
);
95 AtapiStallExecution(100);
96 SControl
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SControl
);
97 KdPrint2((PRINT_PREFIX
" SControl %8.8%x\n", SControl
.Reg
));
98 if(SControl
.DET
== SControl_DET_Init
) {
102 AtapiStallExecution(5000);
103 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable: retry idle %d\n", retry
));
104 for (loop
= 0; loop
< 10; loop
++) {
106 SControl
.DET
= SControl_DET_DoNothing
;
107 SControl
.IPM
= SControl_IPM_NoPartialSlumber
;
108 AtapiWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
);
109 AtapiStallExecution(100);
110 SControl
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SControl
);
111 KdPrint2((PRINT_PREFIX
" SControl %8.8%x\n", SControl
.Reg
));
112 if(SControl
.DET
== SControl_DET_Idle
) {
113 return UniataSataConnect(HwDeviceExtension
, lChannel
);
118 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable: failed\n"));
120 } // end UniataSataPhyEnable()
125 IN PVOID HwDeviceExtension
,
126 IN ULONG lChannel
, // logical channel
127 IN BOOLEAN do_connect
130 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
131 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
132 //ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
133 SATA_SSTATUS_REG SStatus
;
134 SATA_SERROR_REG SError
;
136 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
137 //if(ChipFlags & UNIATA_SATA) {
139 SStatus
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SStatus
);
140 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
143 KdPrint2((PRINT_PREFIX
" SStatus %x\n", SStatus
.Reg
));
146 KdPrint2((PRINT_PREFIX
" SError %x\n", SError
.Reg
));
147 /* clear error bits/interrupt */
148 AtapiWritePort4(chan
, IDX_SATA_SError
, SError
.Reg
);
151 /* if we have a connection event deal with it */
153 KdPrint2((PRINT_PREFIX
" catch SATA connect/disconnect\n"));
154 if(SStatus
.SPD
>= SStatus_SPD_Gen1
) {
155 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
);
157 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
);
165 } // end UniataSataClearErr()
170 IN PVOID HwDeviceExtension
,
171 IN ULONG lChannel
, // logical channel
175 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
177 ULONG ldev
= lChannel
*2;
179 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
184 case UNIATA_SATA_EVENT_ATTACH
:
185 KdPrint2((PRINT_PREFIX
" CONNECTED\n"));
186 Status
= UniataSataConnect(HwDeviceExtension
, lChannel
);
187 KdPrint2((PRINT_PREFIX
" Status %x\n", Status
));
188 if(Status
!= IDE_STATUS_IDLE
) {
191 CheckDevice(HwDeviceExtension
, lChannel
, 0 /*dev*/, FALSE
);
194 case UNIATA_SATA_EVENT_DETACH
:
195 KdPrint2((PRINT_PREFIX
" DISCONNECTED\n"));
196 UniataForgetDevice(&(deviceExtension
->lun
[ldev
]));
201 } // end UniataSataEvent()
206 IN PVOID HwDeviceExtension
209 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
214 ULONG BaseMemAddress
;
220 /* reset AHCI controller */
221 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_GHC
,
222 AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_GHC
) | AHCI_GHC_HR
);
223 AtapiStallExecution(1000000);
224 if(AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_GHC
) & AHCI_GHC_HR
) {
225 KdPrint2((PRINT_PREFIX
" AHCI reset failed\n"));
229 /* enable AHCI mode */
230 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_GHC
,
231 AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_GHC
) | AHCI_GHC_AE
);
233 CAP
= AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_CAP
);
234 PI
= AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_PI
);
235 /* get the number of HW channels */
236 for(i
=PI
, n
=0; i
; n
++, i
=i
>>1);
237 deviceExtension
->NumberChannels
=
238 max((CAP
& AHCI_CAP_NOP_MASK
)+1, n
);
239 if(CAP
& AHCI_CAP_S64A
) {
240 KdPrint2((PRINT_PREFIX
" AHCI 64bit\n"));
241 deviceExtension
->Host64
= TRUE
;
244 /* clear interrupts */
245 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_IS
,
246 AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_IS
));
248 /* enable AHCI interrupts */
249 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_GHC
,
250 AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_GHC
) | AHCI_GHC_IE
);
252 version
= AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_VS
);
253 KdPrint2((PRINT_PREFIX
" AHCI version %x%x.%x%x controller with %d ports (mask %x) detected\n",
254 (version
>> 24) & 0xff, (version
>> 16) & 0xff,
255 (version
>> 8) & 0xff, version
& 0xff, deviceExtension
->NumberChannels
, PI
));
258 deviceExtension
->HwFlags
|= UNIATA_SATA
;
259 deviceExtension
->HwFlags
|= UNIATA_AHCI
;
261 BaseMemAddress
= deviceExtension
->BaseIoAHCI_0
.Addr
;
262 MemIo
= deviceExtension
->BaseIoAHCI_0
.MemIo
;
264 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
265 chan
= &deviceExtension
->chan
[c
];
266 offs
= sizeof(IDE_AHCI_REGISTERS
) + c
*sizeof(IDE_AHCI_PORT_REGISTERS
);
268 chan
->RegTranslation
[IDX_IO1_i_Status
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.STS
);
269 chan
->RegTranslation
[IDX_IO1_i_Status
].MemIo
= MemIo
;
270 chan
->RegTranslation
[IDX_IO2_AltStatus
] = chan
->RegTranslation
[IDX_IO1_i_Status
];
271 chan
->RegTranslation
[IDX_IO1_i_Error
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.ERR
);
272 chan
->RegTranslation
[IDX_IO1_i_Error
].MemIo
= MemIo
;
273 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaLow
);
274 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].MemIo
= MemIo
;
275 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaHigh
);
276 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].MemIo
= MemIo
;
277 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.SectorCount
);
278 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].MemIo
= MemIo
;
280 UniataInitSyncBaseIO(chan
);
282 chan
->RegTranslation
[IDX_SATA_SStatus
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SSTS
);
283 chan
->RegTranslation
[IDX_SATA_SStatus
].MemIo
= MemIo
;
284 chan
->RegTranslation
[IDX_SATA_SError
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SERR
);
285 chan
->RegTranslation
[IDX_SATA_SError
].MemIo
= MemIo
;
286 chan
->RegTranslation
[IDX_SATA_SControl
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SCTL
);
287 chan
->RegTranslation
[IDX_SATA_SControl
].MemIo
= MemIo
;
288 chan
->RegTranslation
[IDX_SATA_SActive
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SACT
);
289 chan
->RegTranslation
[IDX_SATA_SActive
].MemIo
= MemIo
;
291 AtapiDmaAlloc(HwDeviceExtension
, NULL
, c
);
293 base
= chan
->AHCI_CL_PhAddr
;
295 KdPrint2((PRINT_PREFIX
" AHCI buffer allocation failed\n"));
298 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, offs
+ IDX_AHCI_P_CLB
,
299 (ULONG
)(base
& 0xffffffff));
300 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, offs
+ IDX_AHCI_P_CLB
+ 4,
301 (ULONG
)((base
>> 32) & 0xffffffff));
303 base
= chan
->AHCI_CL_PhAddr
+ ATA_AHCI_MAX_TAGS
;
304 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, offs
+ IDX_AHCI_P_FB
,
305 (ULONG
)(base
& 0xffffffff));
306 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, offs
+ IDX_AHCI_P_FB
+ 4,
307 (ULONG
)((base
>> 32) & 0xffffffff));
309 chan
->ChannelCtrlFlags
|= CTRFLAGS_NO_SLAVE
;
313 } // end UniataAhciInit()
318 IN PVOID HwDeviceExtension
,
322 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
323 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
324 ULONG Channel
= deviceExtension
->Channel
+ lChannel
;
328 SATA_SSTATUS_REG SStatus
;
329 SATA_SERROR_REG SError
;
330 ULONG offs
= sizeof(IDE_AHCI_REGISTERS
) + Channel
*sizeof(IDE_AHCI_PORT_REGISTERS
);
334 KdPrint(("UniataAhciStatus:\n"));
336 hIS
= AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_IS
);
337 KdPrint((" hIS %x\n", hIS
));
338 hIS
&= (1 << Channel
);
342 base
= (ULONG
)&deviceExtension
->BaseIoAHCI_0
+ offs
;
343 IS
.Reg
= AtapiReadPort4(chan
, base
+ IDX_AHCI_P_IS
);
344 CI
= AtapiReadPort4(chan
, base
+ IDX_AHCI_P_CI
);
345 SStatus
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SStatus
);
346 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
348 /* clear interrupt(s) */
349 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_IS
, hIS
);
350 AtapiWritePort4(chan
, base
+ IDX_AHCI_P_IS
, IS
.Reg
);
351 AtapiWritePort4(chan
, IDX_SATA_SError
, SError
.Reg
);
353 KdPrint((" AHCI: status=%08x sstatus=%08x error=%08x CI=%08x\n",
354 IS
.Reg
, SStatus
.Reg
, SError
.Reg
, CI
));
356 /* do we have cold connect surprise */
360 /* check for and handle connect events */
362 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
);
365 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
);
367 if(CI
& (1 << tag
)) {
370 KdPrint((" AHCI: unexpected\n"));
373 } // end UniataAhciStatus()
378 IN PHW_DEVICE_EXTENSION deviceExtension
,
379 IN ULONG DeviceNumber
,
389 ULONG ldev
= lChannel
*2 + DeviceNumber
;
393 KdPrint2((PRINT_PREFIX
" AHCI setup FIS\n" ));
397 if((AtaCommandFlags
[command
] & ATA_CMD_FLAG_LBAIOsupp
) &&
398 CheckIfBadBlock(&(deviceExtension
->lun
[ldev
]), lba
, count
)) {
399 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
400 return IDE_STATUS_ERROR
;
401 //return SRB_STATUS_ERROR;
404 /* translate command into 48bit version */
405 if ((lba
>= ATA_MAX_LBA28
|| count
> 256) &&
406 deviceExtension
->lun
[ldev
].IdentifyData
.FeaturesSupport
.Address48
) {
407 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
408 command
= AtaCommands48
[command
];
410 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
415 fis
[0] = 0x27; /* host to device */
416 fis
[1] = 0x80; /* command FIS (note PM goes here) */
418 fis
[3] = (UCHAR
)feature
;
423 fis
[7] = IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_2
: IDE_DRIVE_1
);
424 if ((lba
>= ATA_MAX_LBA28
|| count
> 256) &&
425 deviceExtension
->lun
[ldev
].IdentifyData
.FeaturesSupport
.Address48
) {
429 #pragma warning(push)
430 #pragma warning(disable:4333) // right shift by too large amount, data loss
432 fis
[7] |= (plba
[3] >> 24) & 0x0f;
441 fis
[11] = (UCHAR
)(feature
>>8) & 0xff;
443 fis
[12] = (UCHAR
)count
& 0xff;
444 fis
[13] = (UCHAR
)(count
>>8) & 0xff;
446 fis
[15] = IDE_DC_A_4BIT
;
453 } // end UniataAhciSetupFIS()