5 IN PVOID HwDeviceExtension
,
6 IN ULONG lChannel
// logical channel
9 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
10 ULONG Channel
= deviceExtension
->Channel
+ lChannel
;
11 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
12 SATA_SSTATUS_REG SStatus
;
20 KdPrint2((PRINT_PREFIX
"UniataSataConnect:\n"));
22 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
23 KdPrint2((PRINT_PREFIX
" no I/O range\n"));
24 return IDE_STATUS_IDLE
;
27 /* clear SATA error register, some controllers need this */
28 AtapiWritePort4(chan
, IDX_SATA_SError
,
29 AtapiReadPort4(chan
, IDX_SATA_SError
));
30 /* wait up to 1 second for "connect well" */
31 for(i
=0; i
<100; i
++) {
32 SStatus
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SStatus
);
33 if(SStatus
.SPD
== SStatus_SPD_Gen1
||
34 SStatus
.SPD
== SStatus_SPD_Gen2
) {
35 deviceExtension
->lun
[lChannel
*2].TransferMode
= ATA_SA150
+ (UCHAR
)(SStatus
.SPD
- 1);
38 AtapiStallExecution(10000);
41 KdPrint2((PRINT_PREFIX
"UniataSataConnect: SStatus %8.8x\n", SStatus
.Reg
));
44 /* clear SATA error register */
45 AtapiWritePort4(chan
, IDX_SATA_SError
,
46 AtapiReadPort4(chan
, IDX_SATA_SError
));
48 Status
= WaitOnBaseBusyLong(chan
);
49 if(Status
& IDE_STATUS_BUSY
) {
53 signatureLow = AtapiReadPort1(chan, &deviceExtension->BaseIoAddress1[lChannel].i.CylinderLow);
54 signatureHigh = AtapiReadPort1(chan, &deviceExtension->baseIoAddress1[lChannel].i.CylinderHigh);
56 if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) {
59 KdPrint2((PRINT_PREFIX
"UniataSataConnect: OK, ATA status %x\n", Status
));
60 return IDE_STATUS_IDLE
;
61 } // end UniataSataConnect()
65 IN PVOID HwDeviceExtension
,
66 IN ULONG lChannel
// logical channel
69 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
70 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
71 SATA_SCONTROL_REG SControl
;
74 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable:\n"));
76 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
77 KdPrint2((PRINT_PREFIX
" no I/O range\n"));
78 return IDE_STATUS_IDLE
;
81 SControl
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SControl
);
82 KdPrint2((PRINT_PREFIX
"SControl %x\n", SControl
.Reg
));
83 if(SControl
.DET
== SControl_DET_Idle
) {
84 return UniataSataConnect(HwDeviceExtension
, lChannel
);
87 for (retry
= 0; retry
< 10; retry
++) {
88 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable: retry init %d\n", retry
));
89 for (loop
= 0; loop
< 10; loop
++) {
91 SControl
.DET
= SControl_DET_Init
;
92 AtapiWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
);
93 AtapiStallExecution(100);
94 SControl
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SControl
);
95 KdPrint2((PRINT_PREFIX
" SControl %8.8%x\n", SControl
.Reg
));
96 if(SControl
.DET
== SControl_DET_Init
) {
100 AtapiStallExecution(5000);
101 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable: retry idle %d\n", retry
));
102 for (loop
= 0; loop
< 10; loop
++) {
104 SControl
.DET
= SControl_DET_DoNothing
;
105 SControl
.IPM
= SControl_IPM_NoPartialSlumber
;
106 AtapiWritePort4(chan
, IDX_SATA_SControl
, SControl
.Reg
);
107 AtapiStallExecution(100);
108 SControl
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SControl
);
109 KdPrint2((PRINT_PREFIX
" SControl %8.8%x\n", SControl
.Reg
));
110 if(SControl
.DET
== SControl_DET_Idle
) {
111 return UniataSataConnect(HwDeviceExtension
, lChannel
);
116 KdPrint2((PRINT_PREFIX
"UniataSataPhyEnable: failed\n"));
118 } // end UniataSataPhyEnable()
122 IN PVOID HwDeviceExtension
,
123 IN ULONG lChannel
, // logical channel
124 IN BOOLEAN do_connect
127 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
128 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
129 ULONG ChipFlags
= deviceExtension
->HwFlags
& CHIPFLAG_MASK
;
130 SATA_SSTATUS_REG SStatus
;
131 SATA_SERROR_REG SError
;
133 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
134 //if(ChipFlags & UNIATA_SATA) {
136 SStatus
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SStatus
);
137 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
140 KdPrint2((PRINT_PREFIX
" SStatus %x\n", SStatus
.Reg
));
143 KdPrint2((PRINT_PREFIX
" SError %x\n", SError
.Reg
));
144 /* clear error bits/interrupt */
145 AtapiWritePort4(chan
, IDX_SATA_SError
, SError
.Reg
);
148 /* if we have a connection event deal with it */
150 KdPrint2((PRINT_PREFIX
" catch SATA connect/disconnect\n"));
151 if(SStatus
.SPD
>= SStatus_SPD_Gen1
) {
152 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
);
154 UniataSataEvent(deviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
);
162 } // end UniataSataClearErr()
166 IN PVOID HwDeviceExtension
,
167 IN ULONG lChannel
, // logical channel
171 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
173 ULONG ldev
= lChannel
*2;
175 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
180 case UNIATA_SATA_EVENT_ATTACH
:
181 KdPrint2((PRINT_PREFIX
" CONNECTED\n"));
182 Status
= UniataSataConnect(HwDeviceExtension
, lChannel
);
183 KdPrint2((PRINT_PREFIX
" Status %x\n", Status
));
184 if(Status
!= IDE_STATUS_IDLE
) {
187 CheckDevice(HwDeviceExtension
, lChannel
, 0 /*dev*/, FALSE
);
190 case UNIATA_SATA_EVENT_DETACH
:
191 KdPrint2((PRINT_PREFIX
" DISCONNECTED\n"));
192 UniataForgetDevice(&(deviceExtension
->lun
[ldev
]));
197 } // end UniataSataEvent()
201 IN PVOID HwDeviceExtension
204 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
209 ULONG BaseMemAddress
;
215 /* reset AHCI controller */
216 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_GHC
,
217 AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_GHC
) | AHCI_GHC_HR
);
218 AtapiStallExecution(1000000);
219 if(AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_GHC
) & AHCI_GHC_HR
) {
220 KdPrint2((PRINT_PREFIX
" AHCI reset failed\n"));
224 /* enable AHCI mode */
225 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_GHC
,
226 AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_GHC
) | AHCI_GHC_AE
);
228 CAP
= AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_CAP
);
229 PI
= AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_PI
);
230 /* get the number of HW channels */
231 for(i
=PI
, n
=0; i
; n
++, i
=i
>>1);
232 deviceExtension
->NumberChannels
=
233 max((CAP
& AHCI_CAP_NOP_MASK
)+1, n
);
234 if(CAP
& AHCI_CAP_S64A
) {
235 KdPrint2((PRINT_PREFIX
" AHCI 64bit\n"));
236 deviceExtension
->Host64
= TRUE
;
239 /* clear interrupts */
240 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_IS
,
241 AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_IS
));
243 /* enable AHCI interrupts */
244 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_GHC
,
245 AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_GHC
) | AHCI_GHC_IE
);
247 version
= AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_VS
);
248 KdPrint2((PRINT_PREFIX
" AHCI version %x%x.%x%x controller with %d ports (mask %x) detected\n",
249 (version
>> 24) & 0xff, (version
>> 16) & 0xff,
250 (version
>> 8) & 0xff, version
& 0xff, deviceExtension
->NumberChannels
, PI
));
253 deviceExtension
->HwFlags
|= UNIATA_SATA
;
254 deviceExtension
->HwFlags
|= UNIATA_AHCI
;
256 BaseMemAddress
= deviceExtension
->BaseIoAHCI_0
.Addr
;
257 MemIo
= deviceExtension
->BaseIoAHCI_0
.MemIo
;
259 for(c
=0; c
<deviceExtension
->NumberChannels
; c
++) {
260 chan
= &deviceExtension
->chan
[c
];
261 offs
= sizeof(IDE_AHCI_REGISTERS
) + c
*sizeof(IDE_AHCI_PORT_REGISTERS
);
263 chan
->RegTranslation
[IDX_IO1_i_Status
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.STS
);
264 chan
->RegTranslation
[IDX_IO1_i_Status
].MemIo
= MemIo
;
265 chan
->RegTranslation
[IDX_IO2_AltStatus
] = chan
->RegTranslation
[IDX_IO1_i_Status
];
266 chan
->RegTranslation
[IDX_IO1_i_Error
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, TFD
.ERR
);
267 chan
->RegTranslation
[IDX_IO1_i_Error
].MemIo
= MemIo
;
268 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaLow
);
269 chan
->RegTranslation
[IDX_IO1_i_CylinderLow
].MemIo
= MemIo
;
270 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.LbaHigh
);
271 chan
->RegTranslation
[IDX_IO1_i_CylinderHigh
].MemIo
= MemIo
;
272 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SIG
.SectorCount
);
273 chan
->RegTranslation
[IDX_IO1_i_BlockCount
].MemIo
= MemIo
;
275 UniataInitSyncBaseIO(chan
);
277 chan
->RegTranslation
[IDX_SATA_SStatus
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SSTS
);
278 chan
->RegTranslation
[IDX_SATA_SStatus
].MemIo
= MemIo
;
279 chan
->RegTranslation
[IDX_SATA_SError
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SERR
);
280 chan
->RegTranslation
[IDX_SATA_SError
].MemIo
= MemIo
;
281 chan
->RegTranslation
[IDX_SATA_SControl
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SCTL
);
282 chan
->RegTranslation
[IDX_SATA_SControl
].MemIo
= MemIo
;
283 chan
->RegTranslation
[IDX_SATA_SActive
].Addr
= BaseMemAddress
+ offs
+ FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS
, SACT
);
284 chan
->RegTranslation
[IDX_SATA_SActive
].MemIo
= MemIo
;
286 AtapiDmaAlloc(HwDeviceExtension
, NULL
, c
);
288 base
= chan
->AHCI_CL_PhAddr
;
290 KdPrint2((PRINT_PREFIX
" AHCI buffer allocation failed\n"));
293 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, offs
+ IDX_AHCI_P_CLB
,
294 (ULONG
)(base
& 0xffffffff));
295 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, offs
+ IDX_AHCI_P_CLB
+ 4,
296 (ULONG
)((base
>> 32) & 0xffffffff));
298 base
= chan
->AHCI_CL_PhAddr
+ ATA_AHCI_MAX_TAGS
;
299 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, offs
+ IDX_AHCI_P_FB
,
300 (ULONG
)(base
& 0xffffffff));
301 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, offs
+ IDX_AHCI_P_FB
+ 4,
302 (ULONG
)((base
>> 32) & 0xffffffff));
304 chan
->ChannelCtrlFlags
|= CTRFLAGS_NO_SLAVE
;
308 } // end UniataAhciInit()
312 IN PVOID HwDeviceExtension
,
316 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
317 PHW_CHANNEL chan
= &deviceExtension
->chan
[lChannel
];
318 ULONG Channel
= deviceExtension
->Channel
+ lChannel
;
322 SATA_SSTATUS_REG SStatus
;
323 SATA_SERROR_REG SError
;
324 ULONG offs
= sizeof(IDE_AHCI_REGISTERS
) + Channel
*sizeof(IDE_AHCI_PORT_REGISTERS
);
328 KdPrint(("UniataAhciStatus:\n"));
330 hIS
= AtapiReadPortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_IS
);
331 KdPrint((" hIS %x\n", hIS
));
332 hIS
&= (1 << Channel
);
336 base
= (ULONG
)&deviceExtension
->BaseIoAHCI_0
+ offs
;
337 IS
.Reg
= AtapiReadPort4(chan
, base
+ IDX_AHCI_P_IS
);
338 CI
= AtapiReadPort4(chan
, base
+ IDX_AHCI_P_CI
);
339 SStatus
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SStatus
);
340 SError
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SError
);
342 /* clear interrupt(s) */
343 AtapiWritePortEx4(NULL
, (ULONG
)&deviceExtension
->BaseIoAHCI_0
, IDX_AHCI_IS
, hIS
);
344 AtapiWritePort4(chan
, base
+ IDX_AHCI_P_IS
, IS
.Reg
);
345 AtapiWritePort4(chan
, IDX_SATA_SError
, SError
.Reg
);
347 KdPrint((" AHCI: status=%08x sstatus=%08x error=%08x CI=%08x\n",
348 IS
.Reg
, SStatus
.Reg
, SError
.Reg
, CI
));
350 /* do we have cold connect surprise */
354 /* check for and handle connect events */
356 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_ATTACH
);
359 UniataSataEvent(HwDeviceExtension
, lChannel
, UNIATA_SATA_EVENT_DETACH
);
361 if(CI
& (1 << tag
)) {
364 KdPrint((" AHCI: unexpected\n"));
367 } // end UniataAhciStatus()
371 IN PHW_DEVICE_EXTENSION deviceExtension
,
372 IN ULONG DeviceNumber
,
382 ULONG ldev
= lChannel
*2 + DeviceNumber
;
386 KdPrint2((PRINT_PREFIX
" AHCI setup FIS\n" ));
390 if((AtaCommandFlags
[command
] & ATA_CMD_FLAG_LBAIOsupp
) &&
391 CheckIfBadBlock(&(deviceExtension
->lun
[ldev
]), lba
, count
)) {
392 KdPrint3((PRINT_PREFIX
": artificial bad block, lba %#I64x count %#x\n", lba
, count
));
393 return IDE_STATUS_ERROR
;
394 //return SRB_STATUS_ERROR;
397 /* translate command into 48bit version */
398 if ((lba
>= ATA_MAX_LBA28
|| count
> 256) &&
399 deviceExtension
->lun
[ldev
].IdentifyData
.FeaturesSupport
.Address48
) {
400 if(AtaCommandFlags
[command
] & ATA_CMD_FLAG_48supp
) {
401 command
= AtaCommands48
[command
];
403 KdPrint2((PRINT_PREFIX
" unhandled LBA48 command\n"));
408 fis
[0] = 0x27; /* host to device */
409 fis
[1] = 0x80; /* command FIS (note PM goes here) */
411 fis
[3] = (UCHAR
)feature
;
416 fis
[7] = IDE_USE_LBA
| (DeviceNumber
? IDE_DRIVE_2
: IDE_DRIVE_1
);
417 if ((lba
>= ATA_MAX_LBA28
|| count
> 256) &&
418 deviceExtension
->lun
[ldev
].IdentifyData
.FeaturesSupport
.Address48
) {
421 fis
[7] |= (plba
[3] >> 24) & 0x0f;
427 fis
[11] = (UCHAR
)(feature
>>8) & 0xff;
429 fis
[12] = (UCHAR
)count
& 0xff;
430 fis
[13] = (UCHAR
)(count
>>8) & 0xff;
432 fis
[15] = IDE_DC_A_4BIT
;
439 } // end UniataAhciSetupFIS()