Sync to trunk revision 61757.
[reactos.git] / drivers / storage / ide / uniata / id_sata.cpp
1 /*++
2
3 Copyright (c) 2008-2012 Alexandr A. Telyatnikov (Alter)
4
5 Module Name:
6 id_probe.cpp
7
8 Abstract:
9 This module handles SATA-related staff
10
11 Author:
12 Alexander A. Telyatnikov (Alter)
13
14 Environment:
15 kernel mode only
16
17 Notes:
18
19 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 Revision History:
31
32 --*/
33
34 #include "stdafx.h"
35
36 UCHAR
37 NTAPI
38 UniataSataConnect(
39 IN PVOID HwDeviceExtension,
40 IN ULONG lChannel, // logical channel
41 IN ULONG pm_port /* for port multipliers */
42 )
43 {
44 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
45 //ULONG Channel = deviceExtension->Channel + lChannel;
46 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
47 SATA_SSTATUS_REG SStatus;
48 ULONG i;
49 /*
50 UCHAR signatureLow,
51 signatureHigh;
52 */
53 UCHAR Status;
54
55 KdPrint2((PRINT_PREFIX "UniataSataConnect:\n"));
56
57 if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
58 KdPrint2((PRINT_PREFIX " no I/O range\n"));
59 return IDE_STATUS_IDLE;
60 }
61
62 /* clear SATA error register, some controllers need this */
63 UniataSataWritePort4(chan, IDX_SATA_SError,
64 UniataSataReadPort4(chan, IDX_SATA_SError, pm_port), pm_port);
65 /* wait up to 1 second for "connect well" */
66 for(i=0; i<100; i++) {
67 SStatus.Reg = UniataSataReadPort4(chan, IDX_SATA_SStatus, pm_port);
68 if(SStatus.SPD == SStatus_SPD_Gen1 ||
69 SStatus.SPD == SStatus_SPD_Gen2 ||
70 SStatus.SPD == SStatus_SPD_Gen3) {
71 // SATA sets actual transfer rate in LunExt on init.
72 // There is no run-time SATA rate adjustment yet.
73 // On the other hand, we may turn SATA device in PIO mode
74 // TODO: make separate states for interface speed and transfer mode (DMA vs PIO)
75 chan->lun[0]->LimitedTransferMode =
76 chan->lun[0]->PhyTransferMode =
77 chan->lun[0]->TransferMode = ATA_SA150 + (UCHAR)(SStatus.SPD - 1);
78
79 KdPrint2((PRINT_PREFIX "SATA TransferMode %#x\n", chan->lun[0]->TransferMode));
80 if(chan->MaxTransferMode < chan->lun[0]->TransferMode) {
81 KdPrint2((PRINT_PREFIX "SATA upd chan TransferMode\n"));
82 chan->MaxTransferMode = chan->lun[0]->TransferMode;
83 }
84 if(deviceExtension->MaxTransferMode < chan->lun[0]->TransferMode) {
85 KdPrint2((PRINT_PREFIX "SATA upd controller TransferMode\n"));
86 deviceExtension->MaxTransferMode = chan->lun[0]->TransferMode;
87 }
88
89 break;
90 }
91 AtapiStallExecution(10000);
92 }
93 if(i >= 100) {
94 KdPrint2((PRINT_PREFIX "UniataSataConnect: SStatus %8.8x\n", SStatus.Reg));
95 return IDE_STATUS_WRONG;
96 }
97 /* clear SATA error register */
98 UniataSataWritePort4(chan, IDX_SATA_SError,
99 UniataSataReadPort4(chan, IDX_SATA_SError, pm_port), pm_port);
100
101 Status = WaitOnBaseBusyLong(chan);
102 if(Status & IDE_STATUS_BUSY) {
103 return Status;
104 }
105 /*
106 signatureLow = AtapiReadPort1(chan, &deviceExtension->BaseIoAddress1[lChannel].i.CylinderLow);
107 signatureHigh = AtapiReadPort1(chan, &deviceExtension->baseIoAddress1[lChannel].i.CylinderHigh);
108
109 if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) {
110 }
111 */
112 KdPrint2((PRINT_PREFIX "UniataSataConnect: OK, ATA status %#x\n", Status));
113 return IDE_STATUS_IDLE;
114 } // end UniataSataConnect()
115
116 UCHAR
117 NTAPI
118 UniataSataPhyEnable(
119 IN PVOID HwDeviceExtension,
120 IN ULONG lChannel, // logical channel
121 IN ULONG pm_port, /* for port multipliers */
122 IN BOOLEAN doReset
123 )
124 {
125 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
126 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
127 SATA_SCONTROL_REG SControl;
128 int loop, retry;
129
130 KdPrint2((PRINT_PREFIX "UniataSataPhyEnable:\n"));
131
132 if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
133 KdPrint2((PRINT_PREFIX " no I/O range\n"));
134 return IDE_STATUS_IDLE;
135 }
136
137 SControl.Reg = UniataSataReadPort4(chan, IDX_SATA_SControl, pm_port);
138 KdPrint2((PRINT_PREFIX "SControl %#x\n", SControl.Reg));
139 if(SControl.DET == SControl_DET_Idle) {
140 if(!doReset) {
141 return UniataSataConnect(HwDeviceExtension, lChannel, pm_port);
142 }
143 }
144
145 for (retry = 0; retry < 10; retry++) {
146 KdPrint2((PRINT_PREFIX "UniataSataPhyEnable: retry init %d\n", retry));
147 for (loop = 0; loop < 10; loop++) {
148 SControl.Reg = 0;
149 SControl.DET = SControl_DET_Init;
150 UniataSataWritePort4(chan, IDX_SATA_SControl, SControl.Reg, pm_port);
151 AtapiStallExecution(100);
152 SControl.Reg = UniataSataReadPort4(chan, IDX_SATA_SControl, pm_port);
153 KdPrint2((PRINT_PREFIX " SControl %8.8x\n", SControl.Reg));
154 if(SControl.DET == SControl_DET_Init) {
155 break;
156 }
157 }
158 AtapiStallExecution(5000);
159 KdPrint2((PRINT_PREFIX "UniataSataPhyEnable: retry idle %d\n", retry));
160 for (loop = 0; loop < 10; loop++) {
161 SControl.Reg = 0;
162 SControl.DET = SControl_DET_DoNothing;
163 SControl.IPM = SControl_IPM_NoPartialSlumber;
164 UniataSataWritePort4(chan, IDX_SATA_SControl, SControl.Reg, pm_port);
165 AtapiStallExecution(100);
166 SControl.Reg = UniataSataReadPort4(chan, IDX_SATA_SControl, pm_port);
167 KdPrint2((PRINT_PREFIX " SControl %8.8x\n", SControl.Reg));
168 if(SControl.DET == SControl_DET_Idle) {
169 return UniataSataConnect(HwDeviceExtension, lChannel, pm_port);
170 }
171 }
172 }
173
174 KdPrint2((PRINT_PREFIX "UniataSataPhyEnable: failed\n"));
175 return IDE_STATUS_WRONG;
176 } // end UniataSataPhyEnable()
177
178 BOOLEAN
179 NTAPI
180 UniataSataClearErr(
181 IN PVOID HwDeviceExtension,
182 IN ULONG lChannel, // logical channel
183 IN BOOLEAN do_connect,
184 IN ULONG pm_port /* for port multipliers */
185 )
186 {
187 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
188 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
189 //ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
190 SATA_SSTATUS_REG SStatus;
191 SATA_SERROR_REG SError;
192
193 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
194 //if(ChipFlags & UNIATA_SATA) {
195
196 SStatus.Reg = UniataSataReadPort4(chan, IDX_SATA_SStatus, pm_port);
197 SError.Reg = UniataSataReadPort4(chan, IDX_SATA_SError, pm_port);
198
199 if(SStatus.Reg) {
200 KdPrint2((PRINT_PREFIX " SStatus %#x\n", SStatus.Reg));
201 }
202 if(SError.Reg) {
203 KdPrint2((PRINT_PREFIX " SError %#x\n", SError.Reg));
204 /* clear error bits/interrupt */
205 UniataSataWritePort4(chan, IDX_SATA_SError, SError.Reg, pm_port);
206
207 if(do_connect) {
208 /* if we have a connection event deal with it */
209 if(SError.DIAG.N) {
210 KdPrint2((PRINT_PREFIX " catch SATA connect/disconnect\n"));
211 if(SStatus.SPD >= SStatus_SPD_Gen1) {
212 UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH, pm_port);
213 } else {
214 UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH, pm_port);
215 }
216 return TRUE;
217 }
218 }
219 //return TRUE;
220 }
221 }
222 return FALSE;
223 } // end UniataSataClearErr()
224
225 BOOLEAN
226 NTAPI
227 UniataSataEvent(
228 IN PVOID HwDeviceExtension,
229 IN ULONG lChannel, // logical channel
230 IN ULONG Action,
231 IN ULONG pm_port /* for port multipliers */
232 )
233 {
234 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
235 UCHAR Status;
236 ULONG DeviceNumber = (pm_port ? 1 : 0);
237
238 if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
239 return FALSE;
240 }
241
242 switch(Action) {
243 case UNIATA_SATA_EVENT_ATTACH:
244 KdPrint2((PRINT_PREFIX " CONNECTED\n"));
245 Status = UniataSataConnect(HwDeviceExtension, lChannel, pm_port);
246 KdPrint2((PRINT_PREFIX " Status %#x\n", Status));
247 if(Status != IDE_STATUS_IDLE) {
248 return FALSE;
249 }
250 CheckDevice(HwDeviceExtension, lChannel, DeviceNumber /*dev*/, FALSE);
251 return TRUE;
252 break;
253 case UNIATA_SATA_EVENT_DETACH:
254 KdPrint2((PRINT_PREFIX " DISCONNECTED\n"));
255 UniataForgetDevice(deviceExtension->chan[lChannel].lun[DeviceNumber]);
256 return TRUE;
257 break;
258 }
259 return FALSE;
260 } // end UniataSataEvent()
261
262 ULONG
263 NTAPI
264 UniataSataReadPort4(
265 IN PHW_CHANNEL chan,
266 IN ULONG io_port_ndx,
267 IN ULONG pm_port /* for port multipliers */
268 )
269 {
270 if(chan && (io_port_ndx < IDX_MAX_REG) &&
271 chan->RegTranslation[io_port_ndx].Proc) {
272
273 KdPrint3((PRINT_PREFIX " UniataSataReadPort4 %#x[%d]\n", io_port_ndx, pm_port));
274
275 PHW_DEVICE_EXTENSION deviceExtension = chan->DeviceExtension;
276 PVOID HwDeviceExtension = (PVOID)deviceExtension;
277 ULONG slotNumber = deviceExtension->slotNumber;
278 ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
279 ULONG VendorID = deviceExtension->DevID & 0xffff;
280 ULONG offs;
281 ULONG p;
282
283 switch(VendorID) {
284 case ATA_INTEL_ID: {
285 p = pm_port ? 1 : 0;
286 if(deviceExtension->HwFlags & ICH5) {
287 offs = 0x50+chan->lun[p]->SATA_lun_map*0x10;
288 KdPrint3((PRINT_PREFIX " ICH5 way, offs %#x\n", offs));
289 switch(io_port_ndx) {
290 case IDX_SATA_SStatus:
291 offs += 0;
292 break;
293 case IDX_SATA_SError:
294 offs += 1*4;
295 break;
296 case IDX_SATA_SControl:
297 offs += 2*4;
298 break;
299 default:
300 return -1;
301 }
302 SetPciConfig4(0xa0, offs);
303 GetPciConfig4(0xa4, offs);
304 return offs;
305 } else
306 if(deviceExtension->HwFlags & ICH7) {
307 offs = 0x100+chan->lun[p]->SATA_lun_map*0x80;
308 KdPrint3((PRINT_PREFIX " ICH7 way, offs %#x\n", offs));
309 switch(io_port_ndx) {
310 case IDX_SATA_SStatus:
311 offs += IDX_AHCI_P_SStatus;
312 break;
313 case IDX_SATA_SError:
314 offs += IDX_AHCI_P_SError;
315 break;
316 case IDX_SATA_SControl:
317 offs += IDX_AHCI_P_SControl;
318 break;
319 default:
320 return -1;
321 }
322 return AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), offs);
323 } else {
324 offs = ((deviceExtension->Channel+chan->lChannel)*2+p) * 0x100;
325 KdPrint3((PRINT_PREFIX " def way, offs %#x\n", offs));
326 switch(io_port_ndx) {
327 case IDX_SATA_SStatus:
328 offs += 0;
329 break;
330 case IDX_SATA_SControl:
331 offs += 1;
332 break;
333 case IDX_SATA_SError:
334 offs += 2;
335 break;
336 default:
337 return -1;
338 }
339 AtapiWritePort4(chan, IDX_INDEXED_ADDR, offs);
340 return AtapiReadPort4(chan, IDX_INDEXED_DATA);
341 }
342 } // ATA_INTEL_ID
343 } // end switch(VendorID)
344 return -1;
345 }
346 return AtapiReadPort4(chan, io_port_ndx);
347 } // end UniataSataReadPort4()
348
349 VOID
350 NTAPI
351 UniataSataWritePort4(
352 IN PHW_CHANNEL chan,
353 IN ULONG io_port_ndx,
354 IN ULONG data,
355 IN ULONG pm_port /* for port multipliers */
356 )
357 {
358 if(chan && (io_port_ndx < IDX_MAX_REG) &&
359 chan->RegTranslation[io_port_ndx].Proc) {
360
361 KdPrint3((PRINT_PREFIX " UniataSataWritePort4 %#x[%d]\n", io_port_ndx, pm_port));
362
363 PHW_DEVICE_EXTENSION deviceExtension = chan->DeviceExtension;
364 PVOID HwDeviceExtension = (PVOID)deviceExtension;
365 ULONG slotNumber = deviceExtension->slotNumber;
366 ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
367 ULONG VendorID = deviceExtension->DevID & 0xffff;
368 ULONG offs;
369 ULONG p;
370
371 switch(VendorID) {
372 case ATA_INTEL_ID: {
373 p = pm_port ? 1 : 0;
374 if(deviceExtension->HwFlags & ICH5) {
375 offs = 0x50+chan->lun[p]->SATA_lun_map*0x10;
376 KdPrint3((PRINT_PREFIX " ICH5 way, offs %#x\n", offs));
377 switch(io_port_ndx) {
378 case IDX_SATA_SStatus:
379 offs += 0;
380 break;
381 case IDX_SATA_SError:
382 offs += 1*4;
383 break;
384 case IDX_SATA_SControl:
385 offs += 2*4;
386 break;
387 default:
388 return;
389 }
390 SetPciConfig4(0xa0, offs);
391 SetPciConfig4(0xa4, data);
392 return;
393 } else
394 if(deviceExtension->HwFlags & ICH7) {
395 offs = 0x100+chan->lun[p]->SATA_lun_map*0x80;
396 KdPrint3((PRINT_PREFIX " ICH7 way, offs %#x\n", offs));
397 switch(io_port_ndx) {
398 case IDX_SATA_SStatus:
399 offs += IDX_AHCI_P_SStatus;
400 break;
401 case IDX_SATA_SError:
402 offs += IDX_AHCI_P_SError;
403 break;
404 case IDX_SATA_SControl:
405 offs += IDX_AHCI_P_SControl;
406 break;
407 default:
408 return;
409 }
410 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), offs, data);
411 return;
412 } else {
413 offs = ((deviceExtension->Channel+chan->lChannel)*2+p) * 0x100;
414 KdPrint3((PRINT_PREFIX " def way, offs %#x\n", offs));
415 switch(io_port_ndx) {
416 case IDX_SATA_SStatus:
417 offs += 0;
418 break;
419 case IDX_SATA_SControl:
420 offs += 1;
421 break;
422 case IDX_SATA_SError:
423 offs += 2;
424 break;
425 default:
426 return;
427 }
428 AtapiWritePort4(chan, IDX_INDEXED_ADDR, offs);
429 AtapiWritePort4(chan, IDX_INDEXED_DATA, data);
430 }
431 } // ATA_INTEL_ID
432 } // end switch(VendorID)
433 return;
434 }
435 AtapiWritePort4(chan, io_port_ndx, data);
436 } // end UniataSataWritePort4()
437
438 BOOLEAN
439 NTAPI
440 UniataSataReadPM(
441 IN PHW_CHANNEL chan,
442 IN ULONG DeviceNumber,
443 IN ULONG Reg,
444 OUT PULONG result
445 )
446 {
447 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
448 return UniataAhciReadPM(chan, DeviceNumber, Reg, result);
449 }
450 return FALSE;
451 } // end UniataSataReadPM()
452
453 UCHAR
454 NTAPI
455 UniataSataWritePM(
456 IN PHW_CHANNEL chan,
457 IN ULONG DeviceNumber,
458 IN ULONG Reg,
459 IN ULONG value
460 )
461 {
462 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
463 return UniataAhciWritePM(chan, DeviceNumber, Reg, value);
464 }
465 return IDE_STATUS_WRONG;
466 } // end UniataSataWritePM()
467
468 ULONG
469 NTAPI
470 UniataSataSoftReset(
471 IN PVOID HwDeviceExtension,
472 IN ULONG lChannel,
473 IN ULONG DeviceNumber
474 )
475 {
476 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
477
478 if(deviceExtension->HwFlags & UNIATA_AHCI) {
479 return UniataAhciSoftReset(HwDeviceExtension, lChannel, DeviceNumber);
480 }
481 return 0xffffffff;
482 } // end UniataSataSoftReset()
483
484 VOID
485 UniataSataIdentifyPM(
486 IN PHW_CHANNEL chan
487 )
488 {
489 ULONG PM_DeviceId;
490 ULONG PM_RevId;
491 ULONG PM_Ports;
492 UCHAR i;
493 ULONG signature;
494 PHW_LU_EXTENSION LunExt;
495
496 KdPrint((PRINT_PREFIX "UniataSataIdentifyPM:\n"));
497
498 chan->PmLunMap = 0;
499
500 /* get PM vendor & product data */
501 if(!UniataSataReadPM(chan, AHCI_DEV_SEL_PM, 0, &PM_DeviceId)) {
502 KdPrint2((PRINT_PREFIX " error getting PM vendor data\n"));
503 return;
504 }
505 /* get PM revision data */
506 if(!UniataSataReadPM(chan, AHCI_DEV_SEL_PM, 1, &PM_RevId)) {
507 KdPrint2((PRINT_PREFIX " error getting PM revison data\n"));
508 return;
509 }
510 /* get number of HW ports on the PM */
511 if(!UniataSataReadPM(chan, AHCI_DEV_SEL_PM, 2, &PM_Ports)) {
512 KdPrint2((PRINT_PREFIX " error getting PM port info\n"));
513 return;
514 }
515
516 PM_Ports &= 0x0000000f;
517
518 switch(PM_DeviceId) {
519 case 0x37261095:
520 /* This PM declares 6 ports, while only 5 of them are real.
521 * Port 5 is enclosure management bridge port, which has implementation
522 * problems, causing probe faults. Hide it for now. */
523 KdPrint2((PRINT_PREFIX " SiI 3726 (rev=%#x) Port Multiplier with %d (5) ports\n",
524 PM_RevId, PM_Ports));
525 PM_Ports = 5;
526 break;
527 case 0x47261095:
528 /* This PM declares 7 ports, while only 5 of them are real.
529 * Port 5 is some fake "Config Disk" with 640 sectors size,
530 * port 6 is enclosure management bridge port.
531 * Both fake ports has implementation problems, causing
532 * probe faults. Hide them for now. */
533 KdPrint2((PRINT_PREFIX " SiI 4726 (rev=%#x) Port Multiplier with %d (5) ports\n",
534 PM_RevId, PM_Ports));
535 PM_Ports = 5;
536 break;
537 default:
538 KdPrint2((PRINT_PREFIX " Port Multiplier (id=%08x rev=%#x) with %d ports\n",
539 PM_DeviceId, PM_RevId, PM_Ports));
540 break;
541 }
542
543 // reset
544 for(i=0; i<PM_Ports; i++) {
545
546 LunExt = chan->lun[i];
547
548 KdPrint2((PRINT_PREFIX " Port %d\n", i));
549 if(UniataSataPhyEnable(chan->DeviceExtension, chan->lChannel, i, UNIATA_SATA_RESET_ENABLE) != IDE_STATUS_IDLE) {
550 LunExt->DeviceFlags &= ~DFLAGS_DEVICE_PRESENT;
551 continue;
552 }
553 /*
554 * XXX: I have no idea how to properly wait for PMP port hardreset
555 * completion. Without this delay soft reset does not completes
556 * successfully.
557 */
558 AtapiStallExecution(1000000);
559
560 signature = UniataSataSoftReset(chan->DeviceExtension, chan->lChannel, i);
561 KdPrint2((PRINT_PREFIX " signature %#x\n", signature));
562
563 LunExt->DeviceFlags |= DFLAGS_DEVICE_PRESENT;
564 chan->PmLunMap |= (1 << i);
565 /* figure out whats there */
566 switch (signature >> 16) {
567 case 0x0000:
568 LunExt->DeviceFlags &= ~DFLAGS_ATAPI_DEVICE;
569 continue;
570 case 0xeb14:
571 LunExt->DeviceFlags |= DFLAGS_ATAPI_DEVICE;
572 continue;
573 }
574
575 }
576
577 } // end UniataSataIdentifyPM()
578
579 #ifdef DBG
580 VOID
581 NTAPI
582 UniataDumpAhciRegs(
583 IN PHW_DEVICE_EXTENSION deviceExtension
584 )
585 {
586 ULONG j;
587 ULONG xReg;
588
589 KdPrint2((PRINT_PREFIX
590 " AHCI Base: %#x MemIo %d Proc %d\n",
591 deviceExtension->BaseIoAHCI_0.Addr,
592 deviceExtension->BaseIoAHCI_0.MemIo,
593 deviceExtension->BaseIoAHCI_0.Proc));
594
595 for(j=0; j<=IDX_AHCI_VS; j+=sizeof(ULONG)) {
596 xReg = AtapiReadPortEx4(NULL, (ULONGIO_PTR)&deviceExtension->BaseIoAHCI_0, j);
597 KdPrint2((PRINT_PREFIX
598 " AHCI_%#x (%#x) = %#x\n",
599 j,
600 (deviceExtension->BaseIoAHCI_0.Addr+j),
601 xReg));
602 }
603 return;
604 } // end UniataDumpAhciRegs()
605
606
607 VOID
608 NTAPI
609 UniataDumpAhciPortRegs(
610 IN PHW_CHANNEL chan
611 )
612 {
613 ULONG j;
614 ULONG xReg;
615
616 KdPrint2((PRINT_PREFIX
617 " AHCI port %d Base: %#x MemIo %d Proc %d\n",
618 chan->lChannel,
619 chan->BaseIoAHCI_Port.Addr,
620 chan->BaseIoAHCI_Port.MemIo,
621 chan->BaseIoAHCI_Port.Proc));
622
623 for(j=0; j<=IDX_AHCI_P_SNTF; j+=sizeof(ULONG)) {
624 xReg = AtapiReadPortEx4(NULL, (ULONGIO_PTR)&chan->BaseIoAHCI_Port, j);
625 KdPrint2((PRINT_PREFIX
626 " AHCI%d_%#x (%#x) = %#x\n",
627 chan->lChannel,
628 j,
629 (chan->BaseIoAHCI_Port.Addr+j),
630 xReg));
631 }
632 return;
633 } // end UniataDumpAhciPortRegs()
634 #endif //DBG
635
636
637 BOOLEAN
638 NTAPI
639 UniataAhciInit(
640 IN PVOID HwDeviceExtension
641 )
642 {
643 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
644 ULONG c, i;
645 PHW_CHANNEL chan;
646 ULONG offs;
647 ULONG BaseMemAddress;
648 #ifdef DBG
649 ULONG PI;
650 #endif //DBG
651 ULONG CAP;
652 ULONG GHC;
653 BOOLEAN MemIo = FALSE;
654
655 KdPrint2((PRINT_PREFIX " UniataAhciInit:\n"));
656
657 #ifdef DBG
658 UniataDumpAhciRegs(deviceExtension);
659 #endif //DBG
660
661 /* disable AHCI interrupts, for MSI compatibility issue
662 see http://www.intel.com/Assets/PDF/specupdate/307014.pdf
663 26. AHCI Reset and MSI Request
664 */
665
666 KdPrint2((PRINT_PREFIX " get GHC\n"));
667 /* enable AHCI mode */
668 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
669 if(!(GHC & AHCI_GHC_AE)) {
670 KdPrint2((PRINT_PREFIX " enable AHCI mode, disable intr, GHC %#x\n", GHC));
671 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC,
672 (GHC | AHCI_GHC_AE) & ~AHCI_GHC_IE);
673 } else {
674 KdPrint2((PRINT_PREFIX " disable intr, GHC %#x\n", GHC));
675 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC,
676 GHC & ~AHCI_GHC_IE);
677 }
678 AtapiStallExecution(100);
679
680 /* read GHC again and reset AHCI controller */
681 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
682 KdPrint2((PRINT_PREFIX " reset AHCI controller, GHC %#x\n", GHC));
683 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC,
684 GHC | AHCI_GHC_HR);
685
686 for(i=0; i<1000; i++) {
687 AtapiStallExecution(1000);
688 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
689 KdPrint2((PRINT_PREFIX " AHCI GHC %#x\n", GHC));
690 if(!(GHC & AHCI_GHC_HR)) {
691 break;
692 }
693 }
694 if(GHC & AHCI_GHC_HR) {
695 KdPrint2((PRINT_PREFIX " AHCI reset failed\n"));
696 return FALSE;
697 }
698
699 /* re-enable AHCI mode */
700 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
701 if(!(GHC & AHCI_GHC_AE)) {
702 KdPrint2((PRINT_PREFIX " re-enable AHCI mode, GHC %#x\n", GHC));
703 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC,
704 GHC | AHCI_GHC_AE);
705 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
706 }
707 KdPrint2((PRINT_PREFIX " AHCI GHC %#x\n", GHC));
708 if(!(GHC & AHCI_GHC_AE)) {
709 KdPrint2((PRINT_PREFIX " Can't enable AHCI mode\n"));
710 return FALSE;
711 }
712
713 deviceExtension->AHCI_CAP =
714 CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
715 KdPrint2((PRINT_PREFIX " AHCI CAP %#x\n", CAP));
716 if(CAP & AHCI_CAP_S64A) {
717 KdPrint2((PRINT_PREFIX " AHCI 64bit\n"));
718 deviceExtension->Host64 = TRUE;
719 }
720 KdPrint2((PRINT_PREFIX " AHCI %d CMD slots\n", (CAP & AHCI_CAP_NCS_MASK) >> 8 ));
721 if(CAP & AHCI_CAP_PMD) {
722 KdPrint2((PRINT_PREFIX " AHCI multi-block PIO\n"));
723 }
724 if(CAP & AHCI_CAP_SAM) {
725 KdPrint2((PRINT_PREFIX " AHCI legasy SATA\n"));
726 }
727 #ifdef DBG
728 /* get the number of HW channels */
729 PI = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_PI);
730 KdPrint2((PRINT_PREFIX " AHCI PI %#x\n", PI));
731 #endif //DBG
732
733 /* clear interrupts */
734 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_IS,
735 UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS));
736
737 /* enable AHCI interrupts */
738 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC,
739 UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC) | AHCI_GHC_IE);
740
741 BaseMemAddress = deviceExtension->BaseIoAHCI_0.Addr;
742 MemIo = deviceExtension->BaseIoAHCI_0.MemIo;
743
744 deviceExtension->MaxTransferMode = ATA_SA150+(((CAP & AHCI_CAP_ISS_MASK) >> 20)-1);
745 KdPrint2((PRINT_PREFIX " SATA Gen %d\n", ((CAP & AHCI_CAP_ISS_MASK) >> 20) ));
746
747 for(c=0; c<deviceExtension->NumberChannels; c++) {
748 chan = &deviceExtension->chan[c];
749 offs = sizeof(IDE_AHCI_REGISTERS) + c*sizeof(IDE_AHCI_PORT_REGISTERS);
750
751 KdPrint2((PRINT_PREFIX " chan %d, offs %#x\n", c, offs));
752
753 chan->MaxTransferMode = deviceExtension->MaxTransferMode;
754
755 AtapiSetupLunPtrs(chan, deviceExtension, c);
756
757 chan->BaseIoAHCI_Port = deviceExtension->BaseIoAHCI_0;
758 chan->BaseIoAHCI_Port.Addr = BaseMemAddress + offs;
759
760 chan->RegTranslation[IDX_IO1_i_Status ].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, TFD.STS);
761 chan->RegTranslation[IDX_IO1_i_Status ].MemIo = MemIo;
762 chan->RegTranslation[IDX_IO2_AltStatus] = chan->RegTranslation[IDX_IO1_i_Status];
763 chan->RegTranslation[IDX_IO1_i_Error ].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, TFD.ERR);
764 chan->RegTranslation[IDX_IO1_i_Error ].MemIo = MemIo;
765 chan->RegTranslation[IDX_IO1_i_CylinderLow ].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SIG.LbaLow);
766 chan->RegTranslation[IDX_IO1_i_CylinderLow ].MemIo = MemIo;
767 chan->RegTranslation[IDX_IO1_i_CylinderHigh].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SIG.LbaHigh);
768 chan->RegTranslation[IDX_IO1_i_CylinderHigh].MemIo = MemIo;
769 chan->RegTranslation[IDX_IO1_i_BlockCount ].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SIG.SectorCount);
770 chan->RegTranslation[IDX_IO1_i_BlockCount ].MemIo = MemIo;
771
772 UniataInitSyncBaseIO(chan);
773
774 chan->RegTranslation[IDX_SATA_SStatus].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SSTS);
775 chan->RegTranslation[IDX_SATA_SStatus].MemIo = MemIo;
776 chan->RegTranslation[IDX_SATA_SError].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SERR);
777 chan->RegTranslation[IDX_SATA_SError].MemIo = MemIo;
778 chan->RegTranslation[IDX_SATA_SControl].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SCTL);
779 chan->RegTranslation[IDX_SATA_SControl].MemIo = MemIo;
780 chan->RegTranslation[IDX_SATA_SActive].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SACT);
781 chan->RegTranslation[IDX_SATA_SActive].MemIo = MemIo;
782
783 AtapiDmaAlloc(HwDeviceExtension, NULL, c);
784
785 if(!UniataAhciChanImplemented(deviceExtension, c)) {
786 KdPrint2((PRINT_PREFIX " chan %d not implemented\n", c));
787 continue;
788 }
789
790 UniataAhciResume(chan);
791
792 chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
793 }
794
795 return TRUE;
796 } // end UniataAhciInit()
797
798 BOOLEAN
799 NTAPI
800 UniAtaAhciValidateVersion(
801 IN PHW_DEVICE_EXTENSION deviceExtension,
802 IN ULONG version,
803 IN BOOLEAN Strict
804 )
805 {
806 switch(version) {
807 case 0x00000000:
808 case 0xffffffff:
809 KdPrint((" wrong AHCI revision %#x\n", version));
810 return FALSE;
811 case 0x00000905:
812 case 0x00010000:
813 case 0x00010100:
814 case 0x00010200:
815 case 0x00010300:
816 break;
817 default:
818 KdPrint2((PRINT_PREFIX " Unknown AHCI revision\n"));
819 if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"CheckAhciRevision", Strict)) {
820 KdPrint((" AHCI revision excluded\n"));
821 return FALSE;
822 }
823 }
824 return TRUE;
825 } // end UniAtaAhciValidateVersion()
826
827 BOOLEAN
828 NTAPI
829 UniataAhciDetect(
830 IN PVOID HwDeviceExtension,
831 IN PPCI_COMMON_CONFIG pciData, // optional
832 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
833 )
834 {
835 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
836 //ULONG slotNumber = deviceExtension->slotNumber;
837 ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
838 ULONG version;
839 ULONG i, n;
840 ULONG PI;
841 ULONG CAP;
842 ULONG CAP2;
843 ULONG GHC, GHC0;
844 #ifdef DBG
845 ULONG BOHC;
846 ULONG v_Mn, v_Mj;
847 #endif //DBG
848 ULONG NumberChannels;
849 ULONG BaseMemAddress;
850 BOOLEAN MemIo = FALSE;
851 BOOLEAN found = FALSE;
852
853 KdPrint2((PRINT_PREFIX " UniataAhciDetect:\n"));
854
855 if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreAhci", 0)) {
856 KdPrint((" AHCI excluded\n"));
857 return FALSE;
858 }
859 BaseMemAddress = AtapiGetIoRange(HwDeviceExtension, ConfigInfo, pciData, SystemIoBusNumber,
860 5, 0, 0x10);
861 if(!BaseMemAddress) {
862 KdPrint2((PRINT_PREFIX " AHCI init failed - no IoRange\n"));
863 return FALSE;
864 }
865 if((*ConfigInfo->AccessRanges)[5].RangeInMemory) {
866 KdPrint2((PRINT_PREFIX "MemIo\n"));
867 MemIo = TRUE;
868 }
869 deviceExtension->BaseIoAHCI_0.Addr = BaseMemAddress;
870 deviceExtension->BaseIoAHCI_0.MemIo = MemIo;
871
872 #ifdef DBG
873 UniataDumpAhciRegs(deviceExtension);
874 #endif //DBG
875
876 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
877 if(GHC & AHCI_GHC_HR) {
878 KdPrint2((PRINT_PREFIX " AHCI in reset state\n"));
879 return FALSE;
880 }
881
882 /* check AHCI mode. Save state and try enable */
883 GHC0 =
884 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
885 KdPrint2((PRINT_PREFIX " check AHCI mode, GHC %#x\n", GHC));
886
887 version = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_VS);
888
889 if(!(GHC & AHCI_GHC_AE)) {
890 KdPrint2((PRINT_PREFIX " Non-AHCI GHC (!AE), check revision %#x\n", version));
891 if(!UniAtaAhciValidateVersion(deviceExtension, version, FALSE)) {
892 KdPrint2((PRINT_PREFIX " Non-AHCI\n"));
893 goto exit_detect;
894 }
895 KdPrint2((PRINT_PREFIX " try enable\n"));
896 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC,
897 (GHC | AHCI_GHC_AE) & ~AHCI_GHC_IE);
898 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
899
900 KdPrint2((PRINT_PREFIX " re-check AHCI mode, GHC %#x\n", GHC));
901 if(!(GHC & AHCI_GHC_AE)) {
902 KdPrint2((PRINT_PREFIX " Non-AHCI GHC (!AE)\n"));
903 goto exit_detect;
904 }
905 }
906
907 CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
908 CAP2 = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP2);
909 KdPrint2((PRINT_PREFIX " AHCI CAP %#x, CAP2 %#x\n", CAP, CAP2));
910 if(CAP & AHCI_CAP_S64A) {
911 KdPrint2((PRINT_PREFIX " 64bit"));
912 //deviceExtension->Host64 = TRUE; // this is just DETECT, do not update anything
913 }
914 #ifdef DBG
915 if(CAP2 & AHCI_CAP2_BOH) {
916 BOHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_BOHC);
917 KdPrint2((PRINT_PREFIX " BOHC %#x", BOHC));
918 }
919 #endif //DBG
920 if(CAP & AHCI_CAP_NCQ) {
921 KdPrint2((PRINT_PREFIX " NCQ"));
922 }
923 if(CAP & AHCI_CAP_SNTF) {
924 KdPrint2((PRINT_PREFIX " SNTF"));
925 }
926 if(CAP & AHCI_CAP_CCC) {
927 KdPrint2((PRINT_PREFIX " CCC"));
928 }
929 KdPrint2((PRINT_PREFIX "\n"));
930
931 /* get the number of HW channels */
932 PI = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_PI);
933 deviceExtension->AHCI_PI = PI;
934 KdPrint2((PRINT_PREFIX " AHCI PI %#x\n", PI));
935 for(i=PI, n=0; i; n++, i=i>>1);
936 NumberChannels =
937 max((CAP & AHCI_CAP_NOP_MASK)+1, n);
938
939 KdPrint2((PRINT_PREFIX " CommandSlots %d\n", (CAP & AHCI_CAP_NCS_MASK)>>8 ));
940 KdPrint2((PRINT_PREFIX " Channels %d\n", n));
941
942 switch(deviceExtension->DevID) {
943 case ATA_M88SX6111:
944 NumberChannels = 1;
945 break;
946 case ATA_M88SX6121:
947 NumberChannels = 2;
948 break;
949 case ATA_M88SX6141:
950 case ATA_M88SX6145:
951 NumberChannels = 4;
952 break;
953 } // switch()
954
955 if(!NumberChannels) {
956 KdPrint2((PRINT_PREFIX " Non-AHCI - NumberChannels=0\n"));
957 found = FALSE;
958 goto exit_detect;
959 }
960
961 #ifdef DBG
962 v_Mj = ((version >> 20) & 0xf0) + ((version >> 16) & 0x0f);
963 v_Mn = ((version >> 4) & 0xf0) + (version & 0x0f);
964
965 KdPrint2((PRINT_PREFIX " AHCI version %#x.%02x controller with %d ports (mask %#x) detected\n",
966 v_Mj, v_Mn,
967 NumberChannels, PI));
968 KdPrint((" AHCI SATA Gen %d\n", (((CAP & AHCI_CAP_ISS_MASK) >> 20)) ));
969 #endif //DBG
970
971 if(CAP & AHCI_CAP_SPM) {
972 KdPrint2((PRINT_PREFIX " PM supported\n"));
973 if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreAhciPM", 1 /* DEBUG */)) {
974 KdPrint2((PRINT_PREFIX "SATA/AHCI w/o PM, max luns 1\n"));
975 deviceExtension->NumberLuns = 1;
976 //chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
977 } else {
978 KdPrint2((PRINT_PREFIX "SATA/AHCI -> possible PM, max luns %d\n", SATA_MAX_PM_UNITS));
979 deviceExtension->NumberLuns = SATA_MAX_PM_UNITS;
980 //deviceExtension->NumberLuns = 1;
981 }
982 } else {
983 KdPrint2((PRINT_PREFIX " PM not supported -> 1 lun/chan\n"));
984 deviceExtension->NumberLuns = 1;
985 }
986
987 if(!UniAtaAhciValidateVersion(deviceExtension, version, TRUE)) {
988 goto exit_detect;
989 }
990
991 deviceExtension->HwFlags |= UNIATA_SATA | UNIATA_AHCI;
992 if(deviceExtension->NumberChannels < NumberChannels) {
993 deviceExtension->NumberChannels = NumberChannels;
994 }
995 deviceExtension->DmaSegmentLength = 0x3fffff+1; // 4MB
996 deviceExtension->DmaSegmentAlignmentMask = -1; // no restrictions
997
998 deviceExtension->BusMaster = DMA_MODE_AHCI;
999 deviceExtension->MaxTransferMode = max(deviceExtension->MaxTransferMode, ATA_SA150+(((CAP & AHCI_CAP_ISS_MASK) >> 20)-1) );
1000
1001 found = TRUE;
1002
1003 exit_detect:
1004 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, GHC0);
1005 KdPrint((" AHCI detect status %d\n", found));
1006
1007 return found;
1008 } // end UniataAhciDetect()
1009
1010 UCHAR
1011 NTAPI
1012 UniataAhciStatus(
1013 IN PVOID HwDeviceExtension,
1014 IN ULONG lChannel,
1015 IN ULONG DeviceNumber
1016 )
1017 {
1018 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1019 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1020 ULONG Channel = deviceExtension->Channel + lChannel;
1021 ULONG hIS;
1022 ULONG CI, ACT;
1023 AHCI_IS_REG IS;
1024 SATA_SSTATUS_REG SStatus;
1025 SATA_SERROR_REG SError;
1026 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1027 ULONG tag=0;
1028
1029 KdPrint(("UniataAhciStatus(%d-%d):\n", lChannel, Channel));
1030
1031 hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
1032 KdPrint((" hIS %#x\n", hIS));
1033 hIS &= (1 << Channel);
1034 if(!hIS) {
1035 return INTERRUPT_REASON_IGNORE;
1036 }
1037 IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS);
1038 CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI);
1039 ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT);
1040 SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus);
1041 SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError);
1042
1043 /* clear interrupt(s) */
1044 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_IS, hIS);
1045 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS.Reg);
1046 AtapiWritePort4(chan, IDX_SATA_SError, SError.Reg);
1047
1048 KdPrint((" AHCI: is=%08x ss=%08x serror=%08x CI=%08x, ACT=%08x\n",
1049 IS.Reg, SStatus.Reg, SError.Reg, CI, ACT));
1050
1051 /* do we have cold connect surprise */
1052 if(IS.CPDS) {
1053 }
1054
1055 /* check for and handle connect events */
1056 if(IS.PCS) {
1057 UniataSataEvent(HwDeviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH);
1058 }
1059 if(IS.PRCS) {
1060 UniataSataEvent(HwDeviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH);
1061 }
1062 chan->AhciCompleteCI = (chan->AhciPrevCI ^ CI) & chan->AhciPrevCI; // only 1->0 states
1063 chan->AhciPrevCI = CI;
1064 KdPrint((" AHCI: complete mask %#x\n", chan->AhciCompleteCI));
1065 chan->AhciLastIS = IS.Reg;
1066 if(CI & (1 << tag)) {
1067 #ifdef DBG
1068 UniataDumpAhciPortRegs(chan);
1069 #endif //DBG
1070 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
1071 if(IS.Reg &
1072 (ATA_AHCI_P_IX_OF | ATA_AHCI_P_IX_INF | ATA_AHCI_P_IX_IF |
1073 ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_HBF | ATA_AHCI_P_IX_TFE)) {
1074 KdPrint((" AHCI: unexpected, error\n"));
1075 } else {
1076 KdPrint((" AHCI: unexpected, incomplete command or error ?\n"));
1077 /*
1078 ULONG TFD;
1079
1080 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
1081 KdPrint2((" TFD %#x\n", TFD));
1082 if(TFD & IDE_STATUS_BUSY) {
1083 KdPrint2((" Seems to be interrupt on error\n"));
1084 return INTERRUPT_REASON_OUR;
1085 }
1086 */
1087 return INTERRUPT_REASON_UNEXPECTED;
1088 }
1089 }
1090 return INTERRUPT_REASON_OUR;
1091
1092 } // end UniataAhciStatus()
1093
1094 VOID
1095 NTAPI
1096 UniataAhciSnapAtaRegs(
1097 IN PHW_CHANNEL chan,
1098 IN ULONG DeviceNumber,
1099 IN OUT PIDEREGS_EX regs
1100 )
1101 {
1102 ULONG TFD, SIG;
1103
1104 regs->bDriveHeadReg = IDE_DRIVE_SELECT_1;
1105 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
1106 regs->bCommandReg = (UCHAR)(TFD & 0xff);
1107 regs->bFeaturesReg = (UCHAR)((TFD >> 8) & 0xff);
1108
1109 SIG = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_SIG);
1110 regs->bSectorCountReg = (UCHAR)(SIG & 0xff);
1111 regs->bSectorNumberReg = (UCHAR)((SIG >> 8) & 0xff);
1112 regs->bCylLowReg = (UCHAR)((SIG >> 16) & 0xff);
1113 regs->bCylHighReg = (UCHAR)((SIG >> 24) & 0xff);
1114 regs->bOpFlags = 0;
1115
1116 return;
1117 } // end UniataAhciSnapAtaRegs()
1118
1119 ULONG
1120 NTAPI
1121 UniataAhciSetupFIS_H2D(
1122 IN PHW_DEVICE_EXTENSION deviceExtension,
1123 IN ULONG DeviceNumber,
1124 IN ULONG lChannel,
1125 OUT PUCHAR fis,
1126 IN UCHAR command,
1127 IN ULONGLONG lba,
1128 IN USHORT count,
1129 IN USHORT feature
1130 )
1131 {
1132 //ULONG i;
1133 PUCHAR plba;
1134 BOOLEAN need48;
1135 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1136
1137 KdPrint2((PRINT_PREFIX " AHCI setup FIS %x, ch %d, dev %d\n", fis, lChannel, DeviceNumber));
1138 //i = 0;
1139 plba = (PUCHAR)&lba;
1140
1141 RtlZeroMemory(fis, 20);
1142
1143 fis[0] = AHCI_FIS_TYPE_ATA_H2D; /* host to device */
1144 fis[1] = 0x80 | ((UCHAR)DeviceNumber & 0x0f); /* command FIS (note PM goes here) */
1145 fis[IDX_AHCI_o_DriveSelect] = IDE_DRIVE_SELECT_1 |
1146 ((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_48)) ? IDE_USE_LBA : 0);
1147 fis[IDX_AHCI_o_Control] = IDE_DC_A_4BIT;
1148
1149 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1150 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1151 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1152 */
1153 command == IDE_COMMAND_ATAPI_PACKET) {
1154 fis[IDX_AHCI_o_Command] = IDE_COMMAND_ATAPI_PACKET;
1155 if(feature & ATA_F_DMA) {
1156 fis[IDX_AHCI_o_Feature] = (UCHAR)(feature & 0xff);
1157 } else {
1158 fis[IDX_AHCI_o_CylinderLow] = (UCHAR)(count & 0xff);
1159 fis[IDX_AHCI_o_CylinderHigh] = (UCHAR)(count>>8) & 0xff;
1160 }
1161 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1162 } else {
1163
1164 if(((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp|ATA_CMD_FLAG_FUA)) == ATA_CMD_FLAG_LBAIOsupp) &&
1165 CheckIfBadBlock(chan->lun[DeviceNumber], lba, count)) {
1166 KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count));
1167 //return IDE_STATUS_ERROR;
1168 //return SRB_STATUS_ERROR;
1169 return 0;
1170 }
1171
1172 need48 = UniAta_need_lba48(command, lba, count,
1173 chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48);
1174
1175 /* translate command into 48bit version */
1176 if(need48) {
1177 if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) {
1178 command = AtaCommands48[command];
1179 } else {
1180 KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n"));
1181 return 0;
1182 }
1183 }
1184
1185 fis[IDX_AHCI_o_Command] = command;
1186 fis[IDX_AHCI_o_Feature] = (UCHAR)feature;
1187
1188 fis[IDX_AHCI_o_BlockNumber] = plba[0];
1189 fis[IDX_AHCI_o_CylinderLow] = plba[1];
1190 fis[IDX_AHCI_o_CylinderHigh] = plba[2];
1191
1192 fis[IDX_AHCI_o_BlockCount] = (UCHAR)count & 0xff;
1193
1194 if(need48) {
1195 //i++;
1196 fis[IDX_AHCI_o_Control] |= IDE_DC_USE_HOB;
1197
1198 fis[IDX_AHCI_o_BlockNumberExp] = plba[3];
1199 fis[IDX_AHCI_o_CylinderLowExp] = plba[4];
1200 fis[IDX_AHCI_o_CylinderHighExp] = plba[5];
1201
1202 fis[IDX_AHCI_o_BlockCountExp] = (UCHAR)(count>>8) & 0xff;
1203
1204 fis[IDX_AHCI_o_FeatureExp] = (UCHAR)(feature>>8) & 0xff;
1205
1206 chan->ChannelCtrlFlags |= CTRFLAGS_LBA48;
1207 } else {
1208 //#ifdef _MSC_VER
1209 //#pragma warning(push)
1210 //#pragma warning(disable:4333) // right shift by too large amount, data loss
1211 //#endif
1212 fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f);
1213 chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48;
1214 //#ifdef _MSC_VER
1215 //#pragma warning(pop)
1216 //#endif
1217 }
1218
1219 //fis[14] = 0x00;
1220
1221 }
1222
1223 KdDump(fis, 20);
1224
1225 return 20;
1226 } // end UniataAhciSetupFIS_H2D()
1227
1228 ULONG
1229 NTAPI
1230 UniataAhciSetupFIS_H2D_Direct(
1231 IN PHW_DEVICE_EXTENSION deviceExtension,
1232 IN ULONG DeviceNumber,
1233 IN ULONG lChannel,
1234 OUT PUCHAR fis,
1235 IN PIDEREGS_EX regs
1236 )
1237 {
1238 //ULONG i;
1239 //PUCHAR plba;
1240 BOOLEAN need48;
1241 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1242 UCHAR command;
1243
1244 command = regs->bCommandReg;
1245
1246 KdPrint2((PRINT_PREFIX " AHCI setup FIS Direct %x, ch %d, dev %d\n", fis, lChannel, DeviceNumber));
1247 //i = 0;
1248 //plba = (PUCHAR)&lba;
1249
1250 RtlZeroMemory(fis, 20);
1251
1252 fis[0] = AHCI_FIS_TYPE_ATA_H2D; /* host to device */
1253 fis[1] = 0x80 | ((UCHAR)DeviceNumber & 0x0f); /* command FIS (note PM goes here) */
1254 fis[IDX_AHCI_o_DriveSelect] = IDE_DRIVE_SELECT_1 |
1255 ((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_48)) ? IDE_USE_LBA : 0);
1256 fis[IDX_AHCI_o_Control] = IDE_DC_A_4BIT;
1257
1258 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1259 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1260 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1261 */
1262 command == IDE_COMMAND_ATAPI_PACKET) {
1263 /* fis[IDX_AHCI_o_Command] = IDE_COMMAND_ATAPI_PACKET;
1264 if(feature & ATA_F_DMA) {
1265 fis[IDX_AHCI_o_Feature] = (UCHAR)(feature & 0xff);
1266 } else {
1267 fis[IDX_AHCI_o_CylinderLow] = (UCHAR)(count & 0xff);
1268 fis[IDX_AHCI_o_CylinderHigh] = (UCHAR)(count>>8) & 0xff;
1269 }*/
1270 return 0;
1271 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1272 } else {
1273
1274 need48 = (regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) &&
1275 chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48;
1276
1277 /* translate command into 48bit version */
1278 if(need48) {
1279 if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) {
1280 command = AtaCommands48[command];
1281 } else {
1282 KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n"));
1283 return 0;
1284 }
1285 }
1286
1287 fis[IDX_AHCI_o_Command] = command;
1288 fis[IDX_AHCI_o_Feature] = regs->bFeaturesReg;
1289
1290 fis[IDX_AHCI_o_BlockNumber] = regs->bSectorNumberReg;
1291 fis[IDX_AHCI_o_CylinderLow] = regs->bCylLowReg;
1292 fis[IDX_AHCI_o_CylinderHigh] = regs->bCylHighReg;
1293
1294 fis[IDX_AHCI_o_BlockCount] = regs->bSectorCountReg;
1295
1296 if(need48) {
1297 //i++;
1298 fis[IDX_AHCI_o_Control] |= IDE_DC_USE_HOB;
1299
1300 fis[IDX_AHCI_o_BlockNumberExp] = regs->bSectorNumberRegH;
1301 fis[IDX_AHCI_o_CylinderLowExp] = regs->bCylLowRegH;
1302 fis[IDX_AHCI_o_CylinderHighExp] = regs->bCylHighRegH;
1303
1304 fis[IDX_AHCI_o_BlockCountExp] = regs->bSectorCountRegH;
1305
1306 fis[IDX_AHCI_o_FeatureExp] = regs->bFeaturesRegH;
1307
1308 chan->ChannelCtrlFlags |= CTRFLAGS_LBA48;
1309 } else {
1310 //fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f);
1311 chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48;
1312 }
1313 fis[IDX_AHCI_o_DriveSelect] |= regs->bDriveHeadReg & 0x0f;
1314 }
1315
1316 KdDump(fis, 20);
1317
1318 return 20;
1319 } // end UniataAhciSetupFIS_H2D_Direct()
1320
1321 UCHAR
1322 NTAPI
1323 UniataAhciWaitCommandReady(
1324 IN PHW_CHANNEL chan,
1325 IN ULONG timeout
1326 )
1327 {
1328 AHCI_IS_REG IS;
1329 //ULONG ACT;
1330 ULONG CI=0;
1331 ULONG i;
1332 ULONG SError;
1333 ULONG tag=0;
1334
1335 timeout *= 5;
1336
1337 for (i=0; i<timeout; i++) {
1338 CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI);
1339 //ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT);
1340 if (!(( CI >> tag) & 0x01)) {
1341 break;
1342 }
1343 IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS);
1344 //KdPrint((" IS %#x\n", IS.Reg));
1345 if(IS.Reg) {
1346 break;
1347 }
1348 SError = AtapiReadPort4(chan, IDX_SATA_SError);
1349 if(SError) {
1350 KdPrint((" AHCI: error %#x\n", SError));
1351 i = timeout;
1352 break;
1353 }
1354 AtapiStallExecution(200);
1355 }
1356 KdPrint((" CI %#x\n", CI));
1357
1358 //SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus);
1359 //SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError);
1360
1361 /* clear interrupt(s) */
1362 IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS);
1363 KdPrint((" IS %#x\n", IS.Reg));
1364 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS.Reg);
1365
1366 if (timeout && (i >= timeout)) {
1367 #ifdef DBG
1368 ULONG TFD;
1369
1370 SError = AtapiReadPort4(chan, IDX_SATA_SError);
1371 KdPrint((" AHCI: timeout, SError %#x\n", SError));
1372
1373 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
1374 KdPrint2((" TFD %#x\n", TFD));
1375 #endif //DBG
1376
1377 return IDE_STATUS_WRONG;
1378 }
1379
1380 return IDE_STATUS_IDLE;
1381 } // end UniataAhciWaitCommandReady()
1382
1383 UCHAR
1384 NTAPI
1385 UniataAhciSendCommand(
1386 IN PVOID HwDeviceExtension,
1387 IN ULONG lChannel,
1388 IN ULONG DeviceNumber,
1389 IN USHORT ahci_flags,
1390 IN ULONG timeout
1391 )
1392 {
1393 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1394 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1395 //ULONG Channel = deviceExtension->Channel + lChannel;
1396 //ULONG hIS;
1397 //ULONG SError;
1398 //SATA_SSTATUS_REG SStatus;
1399 //SATA_SERROR_REG SError;
1400 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1401 //ULONGIO_PTR base;
1402 ULONG tag=0;
1403
1404 PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1405
1406 KdPrint(("UniataAhciSendCommand: lChan %d\n", chan->lChannel));
1407
1408 AHCI_CL->prd_length = 0;
1409 //AHCI_CL->cmd_flags = (20 / sizeof(ULONG)) | ahci_flags | (DeviceNumber << 12);
1410 AHCI_CL->cmd_flags = UniAtaAhciAdjustIoFlags(0, ahci_flags, 20, DeviceNumber);
1411
1412 AHCI_CL->bytecount = 0;
1413 AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
1414 if(AHCI_CL->cmd_table_phys & AHCI_CMD_ALIGNEMENT_MASK) {
1415 KdPrint2((PRINT_PREFIX " AHCI CMD address is not aligned (mask %#x)\n", (ULONG)AHCI_CMD_ALIGNEMENT_MASK));
1416 }
1417
1418 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
1419 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, 1 << tag);
1420
1421 return UniataAhciWaitCommandReady(chan, timeout);
1422
1423 } // end UniataAhciSendCommand()
1424
1425 UCHAR
1426 NTAPI
1427 UniataAhciSendPIOCommand(
1428 IN PVOID HwDeviceExtension,
1429 IN ULONG lChannel,
1430 IN ULONG DeviceNumber,
1431 IN PSCSI_REQUEST_BLOCK Srb,
1432 IN PUCHAR data,
1433 IN ULONG length, /* bytes */
1434 IN UCHAR command,
1435 IN ULONGLONG lba,
1436 IN USHORT bcount, /* block count, just ATA register */
1437 IN USHORT feature,
1438 IN USHORT ahci_flags,
1439 IN ULONG wait_flags,
1440 IN ULONG timeout
1441 )
1442 {
1443 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1444 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1445 UCHAR statusByte;
1446 PATA_REQ AtaReq;
1447 ULONG fis_size;
1448 //ULONG tag=0;
1449 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1450 PIDE_AHCI_CMD AHCI_CMD = NULL;
1451
1452 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1453
1454 KdPrint2((PRINT_PREFIX "UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x bcount %#x feature %#x, buff %#x, len %#x, WF %#x \n",
1455 deviceExtension->DevIndex, lChannel, DeviceNumber, command, lba, bcount, feature, data, length, wait_flags ));
1456
1457 if(length/DEV_BSIZE != bcount) {
1458 KdPrint((" length/DEV_BSIZE != bcount\n"));
1459 }
1460
1461 #ifdef DBG
1462 //UniataDumpAhciPortRegs(chan);
1463 #endif // DBG
1464
1465 if(!Srb) {
1466 Srb = BuildAhciInternalSrb(HwDeviceExtension, DeviceNumber, lChannel, data, length);
1467 if(!Srb) {
1468 KdPrint((" !Srb\n"));
1469 return IDE_STATUS_WRONG;
1470 }
1471 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1472 //should be already called on init
1473 }
1474 AtaReq = (PATA_REQ)(Srb->SrbExtension);
1475 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1476
1477 AHCI_CMD = AtaReq->ahci.ahci_cmd_ptr;
1478
1479 fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
1480 &(AHCI_CMD->cfis[0]),
1481 command,
1482 lba,
1483 bcount,
1484 feature
1485 );
1486
1487 if(!fis_size) {
1488 KdPrint2(("!fis_size\n"));
1489 return IDE_STATUS_WRONG;
1490 }
1491
1492 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1493 ahci_flags = UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber);
1494 KdPrint2(("ahci_flags %#x\n", ahci_flags));
1495
1496 if(data) {
1497 if(ahci_flags & ATA_AHCI_CMD_WRITE) {
1498 AtaReq->Flags &= ~REQ_FLAG_READ;
1499 Srb->SrbFlags |= SRB_FLAGS_DATA_OUT;
1500 KdPrint((" assume OUT\n"));
1501 } else {
1502 AtaReq->Flags |= REQ_FLAG_READ;
1503 Srb->SrbFlags |= SRB_FLAGS_DATA_IN;
1504 KdPrint((" assume IN\n"));
1505 }
1506 if(!AtapiDmaSetup(HwDeviceExtension,
1507 DeviceNumber,
1508 lChannel, // logical channel,
1509 Srb,
1510 data,
1511 length)) {
1512 KdPrint2((" can't setup buffer\n"));
1513 return IDE_STATUS_WRONG;
1514 }
1515 }
1516
1517 AtaReq->ahci.io_cmd_flags = ahci_flags;
1518
1519 #ifdef DBG
1520 //UniataDumpAhciPortRegs(chan);
1521 #endif // DBG
1522
1523 UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
1524
1525 #ifdef DBG
1526 //UniataDumpAhciPortRegs(chan);
1527 #endif // DBG
1528
1529 if(wait_flags == ATA_IMMEDIATE) {
1530 statusByte = 0;
1531 KdPrint2((" return imemdiately\n"));
1532 } else {
1533 statusByte = UniataAhciWaitCommandReady(chan, timeout);
1534 UniataAhciStatus(HwDeviceExtension, lChannel, DeviceNumber);
1535 UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
1536 }
1537
1538 return statusByte;
1539
1540 } // end UniataAhciSendPIOCommand()
1541
1542 UCHAR
1543 NTAPI
1544 UniataAhciSendPIOCommandDirect(
1545 IN PVOID HwDeviceExtension,
1546 IN ULONG lChannel,
1547 IN ULONG DeviceNumber,
1548 IN PSCSI_REQUEST_BLOCK Srb,
1549 IN PIDEREGS_EX regs,
1550 IN ULONG wait_flags,
1551 IN ULONG timeout
1552 )
1553 {
1554 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1555 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1556 UCHAR statusByte;
1557 PATA_REQ AtaReq;
1558 ULONG fis_size;
1559 //ULONG tag=0;
1560 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1561 PIDE_AHCI_CMD AHCI_CMD = NULL;
1562 USHORT ahci_flags=0;
1563 // USHORT bcount=0;
1564
1565 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1566
1567 KdPrint2((PRINT_PREFIX "UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, buff %#x, len %#x, WF %#x \n",
1568 deviceExtension->DevIndex, lChannel, DeviceNumber, Srb->DataBuffer, Srb->DataTransferLength, wait_flags ));
1569
1570 // if(Srb->DataTransferLength/DEV_BSIZE != bcount) {
1571 // KdPrint((" length/DEV_BSIZE != bcount\n"));
1572 // }
1573
1574 #ifdef DBG
1575 //UniataDumpAhciPortRegs(chan);
1576 #endif // DBG
1577
1578 if(!Srb) {
1579 KdPrint((" !Srb\n"));
1580 return IDE_STATUS_WRONG;
1581 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1582 //should be already called on init
1583 }
1584 AtaReq = (PATA_REQ)(Srb->SrbExtension);
1585 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1586
1587 AHCI_CMD = AtaReq->ahci.ahci_cmd_ptr;
1588 if(!AHCI_CMD) {
1589 KdPrint((" !AHCI_CMD\n"));
1590 return IDE_STATUS_WRONG;
1591 }
1592
1593 if(Srb->DataTransferLength) {
1594 if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
1595 ahci_flags |= ATA_AHCI_CMD_WRITE;
1596 AtaReq->Flags &= ~REQ_FLAG_READ;
1597 } else {
1598 AtaReq->Flags |= REQ_FLAG_READ;
1599 }
1600 }
1601
1602 fis_size = UniataAhciSetupFIS_H2D_Direct(deviceExtension, DeviceNumber, lChannel,
1603 &(AHCI_CMD->cfis[0]),
1604 regs);
1605
1606 if(!fis_size) {
1607 KdPrint2(("!fis_size\n"));
1608 return IDE_STATUS_WRONG;
1609 }
1610
1611 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1612 ahci_flags = UniAtaAhciAdjustIoFlags(regs->bCommandReg, ahci_flags, fis_size, DeviceNumber);
1613 KdPrint2(("ahci_flags %#x\n", ahci_flags));
1614
1615 if(Srb->DataTransferLength) {
1616 if(!AtapiDmaSetup(HwDeviceExtension,
1617 DeviceNumber,
1618 lChannel, // logical channel,
1619 Srb,
1620 (PUCHAR)(Srb->DataBuffer),
1621 Srb->DataTransferLength)) {
1622 KdPrint2((" can't setup buffer\n"));
1623 return IDE_STATUS_WRONG;
1624 }
1625 }
1626
1627 AtaReq->ahci.io_cmd_flags = ahci_flags;
1628
1629 #ifdef DBG
1630 //UniataDumpAhciPortRegs(chan);
1631 #endif // DBG
1632
1633 UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
1634
1635 #ifdef DBG
1636 //UniataDumpAhciPortRegs(chan);
1637 #endif // DBG
1638
1639 if(wait_flags == ATA_IMMEDIATE) {
1640 statusByte = 0;
1641 KdPrint2((" return imemdiately\n"));
1642 } else {
1643 statusByte = UniataAhciWaitCommandReady(chan, timeout);
1644 UniataAhciStatus(HwDeviceExtension, lChannel, DeviceNumber);
1645 UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
1646 }
1647
1648 return statusByte;
1649
1650 } // end UniataAhciSendPIOCommandDirect()
1651
1652 BOOLEAN
1653 NTAPI
1654 UniataAhciAbortOperation(
1655 IN PHW_CHANNEL chan
1656 )
1657 {
1658 /* kick controller into sane state */
1659 if(!UniataAhciStop(chan)) {
1660 return FALSE;
1661 }
1662 if(!UniataAhciStopFR(chan)) {
1663 return FALSE;
1664 }
1665 if(!UniataAhciCLO(chan)) {
1666 return FALSE;
1667 }
1668 UniataAhciStartFR(chan);
1669 UniataAhciStart(chan);
1670
1671 return TRUE;
1672 } // end UniataAhciAbortOperation()
1673
1674 ULONG
1675 NTAPI
1676 UniataAhciSoftReset(
1677 IN PVOID HwDeviceExtension,
1678 IN ULONG lChannel,
1679 IN ULONG DeviceNumber
1680 )
1681 {
1682 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1683 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1684 //ULONG Channel = deviceExtension->Channel + lChannel;
1685 //ULONG hIS;
1686 //ULONG CI;
1687 //AHCI_IS_REG IS;
1688 //ULONG tag=0;
1689
1690 KdPrint(("UniataAhciSoftReset: lChan %d\n", chan->lChannel));
1691
1692 PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1693 PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
1694
1695 /* kick controller into sane state */
1696 if(!UniataAhciAbortOperation(chan)) {
1697 KdPrint2((" abort failed\n"));
1698 return (ULONG)(-1);
1699 }
1700
1701 /* pull reset active */
1702 RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis));
1703 AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D;
1704 AHCI_CMD->cfis[1] = (UCHAR)DeviceNumber & 0x0f;
1705 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1706 AHCI_CMD->cfis[15] = (IDE_DC_A_4BIT | IDE_DC_RESET_CONTROLLER);
1707
1708 if(UniataAhciSendCommand(HwDeviceExtension, lChannel, DeviceNumber, ATA_AHCI_CMD_RESET | ATA_AHCI_CMD_CLR_BUSY, 100) == IDE_STATUS_WRONG) {
1709 KdPrint2((" timeout\n"));
1710 return (ULONG)(-1);
1711 }
1712 AtapiStallExecution(50);
1713
1714 /* pull reset inactive */
1715 RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis));
1716 AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D;
1717 AHCI_CMD->cfis[1] = (UCHAR)DeviceNumber & 0x0f;
1718 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1719 AHCI_CMD->cfis[15] = (IDE_DC_A_4BIT);
1720 if(UniataAhciSendCommand(HwDeviceExtension, lChannel, DeviceNumber, 0, 3000) == IDE_STATUS_WRONG) {
1721 KdPrint2((" timeout (2)\n"));
1722 return (ULONG)(-1);
1723 }
1724
1725 UniataAhciWaitReady(chan, 1);
1726
1727 KdDump(RCV_FIS, sizeof(chan->AhciCtlBlock->rcv_fis.rfis));
1728
1729 return UniataAhciUlongFromRFIS(RCV_FIS);
1730
1731 } // end UniataAhciSoftReset()
1732
1733 ULONG
1734 NTAPI
1735 UniataAhciWaitReady(
1736 IN PHW_CHANNEL chan,
1737 IN ULONG timeout
1738 )
1739 {
1740 ULONG TFD;
1741 ULONG i;
1742
1743 KdPrint2(("UniataAhciWaitReady: lChan %d\n", chan->lChannel));
1744
1745 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1746
1747 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
1748 for(i=0; i<timeout && (TFD &
1749 (IDE_STATUS_DRQ | IDE_STATUS_BUSY)); i++) {
1750 AtapiStallExecution(1000);
1751 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
1752 }
1753
1754 KdPrint2((" TFD %#x\n", TFD));
1755
1756 return TFD;
1757
1758 } // end UniataAhciWaitReady()
1759
1760 ULONG
1761 NTAPI
1762 UniataAhciHardReset(
1763 IN PVOID HwDeviceExtension,
1764 IN ULONG lChannel,
1765 OUT PULONG signature
1766 )
1767 {
1768 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1769 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1770 //ULONG Channel = deviceExtension->Channel + lChannel;
1771 ULONG TFD;
1772
1773
1774 KdPrint(("UniataAhciHardReset: lChan %d\n", chan->lChannel));
1775
1776 (*signature) = 0xffffffff;
1777
1778 UniataAhciStop(chan);
1779 if(UniataSataPhyEnable(HwDeviceExtension, lChannel, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE) == IDE_STATUS_WRONG) {
1780 KdPrint((" no PHY\n"));
1781 return IDE_STATUS_WRONG;
1782 }
1783
1784 /* Wait for clearing busy status. */
1785 TFD = UniataAhciWaitReady(chan, 15000);
1786 if(TFD & (IDE_STATUS_DRQ | IDE_STATUS_BUSY)) {
1787 KdPrint((" busy: TFD %#x\n", TFD));
1788 return TFD;
1789 }
1790 KdPrint((" TFD %#x\n", TFD));
1791
1792 #ifdef DBG
1793 UniataDumpAhciPortRegs(chan);
1794 #endif // DBG
1795
1796 (*signature) = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_SIG);
1797 KdPrint((" sig: %#x\n", *signature));
1798
1799 UniataAhciStart(chan);
1800
1801 return 0;
1802
1803 } // end UniataAhciHardReset()
1804
1805 VOID
1806 NTAPI
1807 UniataAhciReset(
1808 IN PVOID HwDeviceExtension,
1809 IN ULONG lChannel
1810 )
1811 {
1812 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1813 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1814 //ULONG Channel = deviceExtension->Channel + lChannel;
1815 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1816 ULONG CAP;
1817 //ULONGIO_PTR base;
1818 ULONG signature;
1819 ULONG i;
1820 ULONG VendorID = deviceExtension->DevID & 0xffff;
1821
1822 KdPrint(("UniataAhciReset: lChan %d\n", chan->lChannel));
1823
1824 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1825
1826 /* Disable port interrupts */
1827 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
1828
1829 if(UniataAhciHardReset(HwDeviceExtension, lChannel, &signature)) {
1830
1831 KdPrint((" No devices in all LUNs\n"));
1832 for (i=0; i<deviceExtension->NumberLuns; i++) {
1833 // Zero device fields to ensure that if earlier devices were found,
1834 // but not claimed, the fields are cleared.
1835 UniataForgetDevice(chan->lun[i]);
1836 }
1837
1838 /* enable wanted port interrupts */
1839 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE,
1840 ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC);
1841 return;
1842 }
1843
1844 /* enable wanted port interrupts */
1845 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE,
1846 (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF |
1847 ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF |
1848 ((/*ch->pm_level == */0) ? (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC) : 0) |
1849 ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB |
1850 ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR) );
1851
1852 /*
1853 * Only probe for PortMultiplier if HW has support.
1854 * Ignore Marvell, which is not working,
1855 */
1856 CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
1857 if ((CAP & AHCI_CAP_SPM) &&
1858 (VendorID != ATA_MARVELL_ID)) {
1859 KdPrint((" check PM\n"));
1860 signature = UniataAhciSoftReset(HwDeviceExtension, lChannel, AHCI_DEV_SEL_PM);
1861 /* Workaround for some ATI chips, failing to soft-reset
1862 * when port multiplicator supported, but absent.
1863 * XXX: We can also check PxIS.IPMS==1 here to be sure. */
1864 if (signature == 0xffffffff) {
1865 KdPrint((" re-check PM\n"));
1866 signature = UniataAhciSoftReset(HwDeviceExtension, lChannel, 0);
1867 }
1868 } else {
1869 signature = UniataAhciSoftReset(HwDeviceExtension, lChannel, 0);
1870 }
1871
1872 KdPrint((" signature %#x\n", signature));
1873 chan->lun[0]->DeviceFlags &= ~(DFLAGS_ATAPI_DEVICE | DFLAGS_DEVICE_PRESENT | CTRFLAGS_AHCI_PM);
1874 switch (signature >> 16) {
1875 case 0x0000:
1876 KdPrint((" ATA dev\n"));
1877 chan->lun[0]->DeviceFlags |= DFLAGS_DEVICE_PRESENT;
1878 chan->PmLunMap = 0;
1879 break;
1880 case 0x9669:
1881 KdPrint((" PM\n"));
1882 if(deviceExtension->NumberLuns > 1) {
1883 chan->ChannelCtrlFlags |= CTRFLAGS_AHCI_PM;
1884 UniataSataIdentifyPM(chan);
1885 } else {
1886 KdPrint((" no PM supported (1 lun/chan)\n"));
1887 }
1888 break;
1889 case 0xeb14:
1890 KdPrint((" ATAPI dev\n"));
1891 chan->lun[0]->DeviceFlags |= (DFLAGS_ATAPI_DEVICE | DFLAGS_DEVICE_PRESENT);
1892 chan->PmLunMap = 0;
1893 break;
1894 default: /* SOS XXX */
1895 KdPrint((" default to ATA ???\n"));
1896 chan->lun[0]->DeviceFlags |= DFLAGS_DEVICE_PRESENT;
1897 chan->PmLunMap = 0;
1898 }
1899
1900 return;
1901
1902 } // end UniataAhciReset()
1903
1904 VOID
1905 NTAPI
1906 UniataAhciStartFR(
1907 IN PHW_CHANNEL chan
1908 )
1909 {
1910 ULONG CMD;
1911
1912 KdPrint2(("UniataAhciStartFR: lChan %d\n", chan->lChannel));
1913
1914 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
1915 KdPrint2((" CMD %#x\n", CMD));
1916 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD | ATA_AHCI_P_CMD_FRE);
1917
1918 return;
1919 } // end UniataAhciStartFR()
1920
1921 BOOLEAN
1922 NTAPI
1923 UniataAhciStopFR(
1924 IN PHW_CHANNEL chan
1925 )
1926 {
1927 ULONG CMD;
1928 ULONG i;
1929
1930 KdPrint2(("UniataAhciStopFR: lChan %d\n", chan->lChannel));
1931
1932 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
1933 KdPrint2((" CMD %#x\n", CMD));
1934 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD & ~ATA_AHCI_P_CMD_FRE);
1935
1936 for(i=0; i<1000; i++) {
1937 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
1938 if(!(CMD & ATA_AHCI_P_CMD_FR)) {
1939 KdPrint2((" final CMD %#x\n", CMD));
1940 return TRUE;
1941 }
1942 AtapiStallExecution(1000);
1943 }
1944 KdPrint2((" CMD %#x\n", CMD));
1945 KdPrint((" SError %#x\n", AtapiReadPort4(chan, IDX_SATA_SError)));
1946 KdPrint2(("UniataAhciStopFR: timeout\n"));
1947 return FALSE;
1948 } // end UniataAhciStopFR()
1949
1950 VOID
1951 NTAPI
1952 UniataAhciStart(
1953 IN PHW_CHANNEL chan
1954 )
1955 {
1956 ULONG IS, CMD;
1957 SATA_SERROR_REG SError;
1958
1959 KdPrint2(("UniataAhciStart: lChan %d\n", chan->lChannel));
1960
1961 /* clear SATA error register */
1962 SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError);
1963
1964 /* clear any interrupts pending on this channel */
1965 IS = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS);
1966 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS);
1967
1968 KdPrint2((" SError %#x, IS %#x\n", SError.Reg, IS));
1969
1970 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
1971 KdPrint2((" CMD %#x\n", CMD));
1972 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD,
1973 CMD |
1974 ATA_AHCI_P_CMD_ST |
1975 ((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) ? ATA_AHCI_P_CMD_PMA : 0));
1976
1977 return;
1978 } // end UniataAhciStart()
1979
1980 BOOLEAN
1981 NTAPI
1982 UniataAhciCLO(
1983 IN PHW_CHANNEL chan
1984 )
1985 {
1986 //PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1987 //PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1988 ULONG CAP, CMD;
1989 //SATA_SERROR_REG SError;
1990 ULONG i;
1991
1992 KdPrint2(("UniataAhciCLO: lChan %d\n", chan->lChannel));
1993
1994 /* issue Command List Override if supported */
1995 //CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
1996 CAP = chan->DeviceExtension->AHCI_CAP;
1997 if(!(CAP & AHCI_CAP_SCLO)) {
1998 return TRUE;
1999 }
2000 KdPrint2((" send CLO\n"));
2001 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
2002 CMD |= ATA_AHCI_P_CMD_CLO;
2003 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD);
2004
2005 for(i=0; i<1000; i++) {
2006 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
2007 if(!(CMD & ATA_AHCI_P_CMD_CLO)) {
2008 KdPrint2((" final CMD %#x\n", CMD));
2009 return TRUE;
2010 }
2011 AtapiStallExecution(1000);
2012 }
2013 KdPrint2((" CMD %#x\n", CMD));
2014 KdPrint2(("UniataAhciCLO: timeout\n"));
2015 return FALSE;
2016 } // end UniataAhciCLO()
2017
2018 BOOLEAN
2019 NTAPI
2020 UniataAhciStop(
2021 IN PHW_CHANNEL chan
2022 )
2023 {
2024 ULONG CMD;
2025 //SATA_SERROR_REG SError;
2026 ULONG i;
2027
2028 KdPrint2(("UniataAhciStop: lChan %d\n", chan->lChannel));
2029
2030 /* issue Command List Override if supported */
2031 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
2032 CMD &= ~ATA_AHCI_P_CMD_ST;
2033 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD);
2034
2035 for(i=0; i<1000; i++) {
2036 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
2037 if(!(CMD & ATA_AHCI_P_CMD_CR)) {
2038 KdPrint2((" final CMD %#x\n", CMD));
2039 return TRUE;
2040 }
2041 AtapiStallExecution(1000);
2042 }
2043 KdPrint2((" CMD %#x\n", CMD));
2044 KdPrint((" SError %#x\n", AtapiReadPort4(chan, IDX_SATA_SError)));
2045 KdPrint2(("UniataAhciStop: timeout\n"));
2046 return FALSE;
2047 } // end UniataAhciStop()
2048
2049 UCHAR
2050 NTAPI
2051 UniataAhciBeginTransaction(
2052 IN PVOID HwDeviceExtension,
2053 IN ULONG lChannel,
2054 IN ULONG DeviceNumber,
2055 IN PSCSI_REQUEST_BLOCK Srb
2056 )
2057 {
2058 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2059 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
2060 //ULONG Channel = deviceExtension->Channel + lChannel;
2061 //ULONG hIS;
2062 ULONG CMD, CMD0;
2063 //AHCI_IS_REG IS;
2064 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
2065 //SATA_SSTATUS_REG SStatus;
2066 //SATA_SERROR_REG SError;
2067 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
2068 //ULONGIO_PTR base;
2069 ULONG tag=0;
2070 //ULONG i;
2071
2072 PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
2073
2074 KdPrint2(("UniataAhciBeginTransaction: lChan %d, AtaReq %#x\n", chan->lChannel, AtaReq));
2075
2076 if(Srb->DataTransferLength && (!AtaReq->dma_entries || AtaReq->dma_entries >= (USHORT)0xffff)) {
2077 KdPrint2(("UniataAhciBeginTransaction wrong DMA tab len %x\n", AtaReq->dma_entries));
2078 return 0;
2079 }
2080
2081 AHCI_CL->prd_length = (USHORT)(AtaReq->dma_entries);
2082 AHCI_CL->cmd_flags = AtaReq->ahci.io_cmd_flags;
2083 AHCI_CL->bytecount = 0;
2084 if(AtaReq->ahci.ahci_base64) {
2085 KdPrint2((PRINT_PREFIX " AHCI AtaReq CMD %#x (ph %#x)\n", AtaReq->ahci.ahci_cmd_ptr, (ULONG)(AtaReq->ahci.ahci_base64)));
2086 AHCI_CL->cmd_table_phys = AtaReq->ahci.ahci_base64;
2087 } else
2088 if(AtaReq->ahci.ahci_cmd_ptr) {
2089 KdPrint2((PRINT_PREFIX " AHCI AtaReq->Chan CMD %#x (ph %#x) -> %#x (ph %#x)\n",
2090 AtaReq->ahci.ahci_cmd_ptr, (ULONG)(AtaReq->ahci.ahci_base64),
2091 &(chan->AhciCtlBlock->cmd), chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd) ));
2092 RtlCopyMemory(&(chan->AhciCtlBlock->cmd), AtaReq->ahci.ahci_cmd_ptr,
2093 FIELD_OFFSET(IDE_AHCI_CMD, prd_tab)+AHCI_CL->prd_length*sizeof(IDE_AHCI_PRD_ENTRY));
2094 AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2095 } else {
2096 KdPrint2((PRINT_PREFIX " no AHCI CMD\n"));
2097 //AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2098 return 0;
2099 }
2100 if(AHCI_CL->cmd_table_phys & AHCI_CMD_ALIGNEMENT_MASK) {
2101 KdPrint2((PRINT_PREFIX " AHCI CMD address is not aligned (mask %#x)\n", (ULONG)AHCI_CMD_ALIGNEMENT_MASK));
2102 return 0;
2103 }
2104
2105 #ifdef DBG
2106 KdPrint2((" prd_length %#x, flags %#x, base %I64x\n", AHCI_CL->prd_length, AHCI_CL->cmd_flags,
2107 AHCI_CL->cmd_table_phys));
2108 #endif // DBG
2109
2110 CMD0 = CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
2111 KdPrint2((" CMD %#x\n", CMD));
2112 // switch controller to ATAPI mode for ATA_PACKET commands only
2113 if(ATAPI_DEVICE(chan, DeviceNumber) &&
2114 AtaReq->ahci.ahci_cmd_ptr->cfis[2] == IDE_COMMAND_ATAPI_PACKET) {
2115 KdPrint2((" ATAPI\n"));
2116 CMD |= ATA_AHCI_P_CMD_ATAPI;
2117 KdDump(&(AtaReq->ahci.ahci_cmd_ptr->acmd), 16);
2118 } else {
2119 CMD &= ~ATA_AHCI_P_CMD_ATAPI;
2120 }
2121 if(CMD0 != CMD) {
2122 KdPrint2((" send CMD %#x, entries %#x\n", CMD, AHCI_CL->prd_length));
2123 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD);
2124 }
2125
2126 /* issue command to controller */
2127 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
2128 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, 0x01 << tag);
2129 chan->AhciPrevCI |= 0x01 << tag;
2130
2131 if(!ATAPI_DEVICE(chan, DeviceNumber)) {
2132 // TODO: check if we send ATA_RESET and wait for ready of so.
2133 if(AtaReq->ahci.ahci_cmd_ptr->cfis[2] == IDE_COMMAND_ATAPI_RESET) {
2134 ULONG TFD;
2135 ULONG i;
2136
2137 for(i=0; i<1000000; i++) {
2138 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
2139 if(!(TFD & IDE_STATUS_BUSY)) {
2140 break;
2141 }
2142 }
2143 if(TFD & IDE_STATUS_BUSY) {
2144 KdPrint2((" timeout\n"));
2145 }
2146 if(TFD & IDE_STATUS_ERROR) {
2147 KdPrint2((" ERROR %#x\n", (UCHAR)(TFD >> 8)));
2148 }
2149 AtaReq->ahci.in_status = TFD;
2150
2151 return IDE_STATUS_SUCCESS;
2152 }
2153 }
2154
2155 return IDE_STATUS_IDLE;
2156
2157 } // end UniataAhciBeginTransaction()
2158
2159 UCHAR
2160 NTAPI
2161 UniataAhciEndTransaction(
2162 IN PVOID HwDeviceExtension,
2163 IN ULONG lChannel,
2164 IN ULONG DeviceNumber,
2165 IN PSCSI_REQUEST_BLOCK Srb
2166 )
2167 {
2168 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2169 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
2170 //ULONG Channel = deviceExtension->Channel + lChannel;
2171 //ULONG hIS;
2172 ULONG CI, ACT;
2173 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
2174 ULONG TFD;
2175 PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
2176 ULONG tag=0;
2177 //ULONG i;
2178 PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
2179 //PHW_LU_EXTENSION LunExt;
2180
2181 KdPrint2(("UniataAhciEndTransaction: lChan %d\n", chan->lChannel));
2182
2183 //LunExt = chan->lun[DeviceNumber];
2184
2185 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
2186 KdPrint2((" TFD %#x\n", TFD));
2187
2188 if(TFD & IDE_STATUS_ERROR) {
2189 AtaReq->ahci.in_error = (UCHAR)(TFD >> 8);
2190 KdPrint2((" ERROR %#x\n", AtaReq->ahci.in_error));
2191 } else {
2192 AtaReq->ahci.in_error = 0;
2193 }
2194 AtaReq->ahci.in_status = TFD;
2195
2196 //if (request->flags & ATA_R_CONTROL) {
2197
2198 AtaReq->ahci.in_bcount = (ULONG)(RCV_FIS[12]) | ((ULONG)(RCV_FIS[13]) << 8);
2199 AtaReq->ahci.in_lba = (ULONG)(RCV_FIS[4]) | ((ULONGLONG)(RCV_FIS[5]) << 8) |
2200 ((ULONGLONG)(RCV_FIS[6]) << 16);
2201 if(chan->ChannelCtrlFlags & CTRFLAGS_LBA48) {
2202 AtaReq->ahci.in_lba |= ((ULONGLONG)(RCV_FIS[8]) << 24) |
2203 ((ULONGLONG)(RCV_FIS[9]) << 32) |
2204 ((ULONGLONG)(RCV_FIS[10]) << 40);
2205 } else {
2206 AtaReq->ahci.in_lba |= ((ULONGLONG)(RCV_FIS[8]) << 24) |
2207 ((ULONGLONG)(RCV_FIS[9]) << 32) |
2208 ((ULONGLONG)(RCV_FIS[7] & 0x0f) << 24);
2209 }
2210 AtaReq->WordsTransfered = AHCI_CL->bytecount/2;
2211 /*
2212 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
2213 KdPrint2(("RCV:\n"));
2214 KdDump(RCV_FIS, 24);
2215 KdPrint2(("PIO:\n"));
2216 KdDump(&(chan->AhciCtlBlock->rcv_fis.psfis[0]), 24);
2217
2218 KdPrint2(("len: %d vs %d\n", AHCI_CL->bytecount, (ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8) ));
2219 if(!AHCI_CL->bytecount) {
2220 AtaReq->WordsTransfered = ((ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8)) / 2;
2221 }
2222 }
2223 */
2224 ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT);
2225 CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI);
2226 if(CI & (1 << tag)) {
2227 // clear CI
2228 KdPrint2((" Incomplete command, CI %#x, ACT %#x\n", CI, ACT));
2229 KdPrint2((" FIS status %#x, error %#x\n", RCV_FIS[2], RCV_FIS[3]));
2230
2231 #if DBG
2232 UniataDumpAhciPortRegs(chan);
2233 #endif
2234 if(!UniataAhciAbortOperation(chan)) {
2235 KdPrint2((" Abort failed, need RESET\n"));
2236 }
2237 #if DBG
2238 UniataDumpAhciPortRegs(chan);
2239 #endif
2240 chan->AhciPrevCI = CI & ~((ULONG)1 << tag);
2241 if(chan->AhciPrevCI) {
2242 KdPrint2((" Need command list restart, CI %#x\n", chan->AhciPrevCI));
2243 }
2244 } else {
2245 chan->AhciPrevCI &= ~((ULONG)1 << tag);
2246 RtlZeroMemory(AHCI_CL, sizeof(IDE_AHCI_CMD_LIST));
2247 }
2248 //}
2249
2250 return 0;
2251
2252 } // end UniataAhciEndTransaction()
2253
2254 VOID
2255 NTAPI
2256 UniataAhciResume(
2257 IN PHW_CHANNEL chan
2258 )
2259 {
2260 ULONGLONG base;
2261
2262 KdPrint2(("UniataAhciResume: lChan %d\n", chan->lChannel));
2263
2264 #ifdef DBG
2265 //UniataDumpAhciPortRegs(chan);
2266 #endif // DBG
2267
2268 /* Disable port interrupts */
2269 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
2270
2271 /* setup work areas */
2272 base = chan->AHCI_CTL_PhAddr;
2273 if(!base) {
2274 KdPrint2((PRINT_PREFIX " AHCI buffer allocation failed\n"));
2275 return;
2276 }
2277 KdPrint2((PRINT_PREFIX " AHCI CLB setup\n"));
2278 if(base & AHCI_CLB_ALIGNEMENT_MASK) {
2279 KdPrint2((PRINT_PREFIX " AHCI CLB address is not aligned (mask %#x)\n", (ULONG)AHCI_FIS_ALIGNEMENT_MASK));
2280 }
2281 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CLB,
2282 (ULONG)(base & 0xffffffff));
2283 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CLB + 4,
2284 (ULONG)((base >> 32) & 0xffffffff));
2285
2286 KdPrint2((PRINT_PREFIX " AHCI RCV FIS setup\n"));
2287 base = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, rcv_fis);
2288 if(base & AHCI_FIS_ALIGNEMENT_MASK) {
2289 KdPrint2((PRINT_PREFIX " AHCI FIS address is not aligned (mask %#x)\n", (ULONG)AHCI_FIS_ALIGNEMENT_MASK));
2290 }
2291 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_FB,
2292 (ULONG)(base & 0xffffffff));
2293 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_FB + 4,
2294 (ULONG)((base >> 32) & 0xffffffff));
2295
2296 /* activate the channel and power/spin up device */
2297 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD,
2298 (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD |
2299 (((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM)) ? ATA_AHCI_P_CMD_ALPE : 0) |
2300 (((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM2)) ? ATA_AHCI_P_CMD_ASP : 0 ))
2301 );
2302
2303 #ifdef DBG
2304 //UniataDumpAhciPortRegs(chan);
2305 #endif // DBG
2306
2307 UniataAhciStartFR(chan);
2308 UniataAhciStart(chan);
2309
2310 #ifdef DBG
2311 UniataDumpAhciPortRegs(chan);
2312 #endif // DBG
2313
2314 return;
2315 } // end UniataAhciResume()
2316
2317 #if 0
2318 VOID
2319 NTAPI
2320 UniataAhciSuspend(
2321 IN PHW_CHANNEL chan
2322 )
2323 {
2324 ULONGLONG base;
2325 SATA_SCONTROL_REG SControl;
2326
2327 KdPrint2(("UniataAhciSuspend:\n"));
2328
2329 /* Disable port interrupts */
2330 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
2331
2332 /* Reset command register. */
2333 UniataAhciStop(chan);
2334 UniataAhciStopFR(chan);
2335 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, 0);
2336
2337 /* Allow everything including partial and slumber modes. */
2338 UniataSataWritePort4(chan, IDX_SATA_SControl, 0, 0);
2339
2340 /* Request slumber mode transition and give some time to get there. */
2341 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, ATA_AHCI_P_CMD_SLUMBER);
2342 AtapiStallExecution(100);
2343
2344 /* Disable PHY. */
2345 SControl.Reg = 0;
2346 SControl.DET = SStatus_DET_Offline;
2347 UniataSataWritePort4(chan, IDX_SATA_SControl, SControl.Reg, 0);
2348
2349 return;
2350 } // end UniataAhciSuspend()
2351 #endif
2352
2353 BOOLEAN
2354 NTAPI
2355 UniataAhciReadPM(
2356 IN PHW_CHANNEL chan,
2357 IN ULONG DeviceNumber,
2358 IN ULONG Reg,
2359 OUT PULONG result
2360 )
2361 {
2362 //ULONG Channel = deviceExtension->Channel + lChannel;
2363 //ULONG hIS;
2364 //ULONG CI;
2365 //AHCI_IS_REG IS;
2366 //ULONG tag=0;
2367 PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
2368 PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
2369
2370 KdPrint(("UniataAhciReadPM: lChan %d [%#x]\n", chan->lChannel, DeviceNumber));
2371
2372 if(DeviceNumber == DEVNUM_NOT_SPECIFIED) {
2373 (*result) = UniataSataReadPort4(chan, Reg, 0);
2374 return TRUE;
2375 }
2376 if(DeviceNumber < AHCI_DEV_SEL_PM) {
2377 switch(Reg) {
2378 case IDX_SATA_SStatus:
2379 Reg = 0; break;
2380 case IDX_SATA_SError:
2381 Reg = 1; break;
2382 case IDX_SATA_SControl:
2383 Reg = 2; break;
2384 default:
2385 return FALSE;
2386 }
2387 }
2388
2389 RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis));
2390 AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D;
2391 AHCI_CMD->cfis[1] = AHCI_FIS_COMM_PM;
2392 AHCI_CMD->cfis[2] = IDE_COMMAND_READ_PM;
2393 AHCI_CMD->cfis[3] = (UCHAR)Reg;
2394 AHCI_CMD->cfis[7] = (UCHAR)(IDE_USE_LBA | DeviceNumber);
2395 AHCI_CMD->cfis[15] = IDE_DC_A_4BIT;
2396
2397 if(UniataAhciSendCommand(chan->DeviceExtension, chan->lChannel, DeviceNumber, 0, 10) == IDE_STATUS_WRONG) {
2398 KdPrint2((" PM read failed\n"));
2399 return FALSE;
2400 }
2401
2402 KdDump(RCV_FIS, sizeof(chan->AhciCtlBlock->rcv_fis.rfis));
2403
2404 (*result) = UniataAhciUlongFromRFIS(RCV_FIS);
2405 return TRUE;
2406
2407 } // end UniataAhciReadPM()
2408
2409 UCHAR
2410 NTAPI
2411 UniataAhciWritePM(
2412 IN PHW_CHANNEL chan,
2413 IN ULONG DeviceNumber,
2414 IN ULONG Reg,
2415 IN ULONG value
2416 )
2417 {
2418 //ULONG Channel = deviceExtension->Channel + lChannel;
2419 //ULONG hIS;
2420 //ULONG CI;
2421 //AHCI_IS_REG IS;
2422 //ULONG tag=0;
2423 ULONG TFD;
2424 PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
2425 //PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
2426
2427 KdPrint(("UniataAhciWritePM: lChan %d [%#x] %#x\n", chan->lChannel, DeviceNumber, value));
2428
2429 if(DeviceNumber == DEVNUM_NOT_SPECIFIED) {
2430 UniataSataWritePort4(chan, Reg, value, 0);
2431 return 0;
2432 }
2433 if(DeviceNumber < AHCI_DEV_SEL_PM) {
2434 switch(Reg) {
2435 case IDX_SATA_SStatus:
2436 Reg = 0; break;
2437 case IDX_SATA_SError:
2438 Reg = 1; break;
2439 case IDX_SATA_SControl:
2440 Reg = 2; break;
2441 default:
2442 return IDE_STATUS_WRONG;
2443 }
2444 }
2445
2446 RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis));
2447 AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D;
2448 AHCI_CMD->cfis[1] = AHCI_FIS_COMM_PM;
2449 AHCI_CMD->cfis[2] = IDE_COMMAND_WRITE_PM;
2450 AHCI_CMD->cfis[3] = (UCHAR)Reg;
2451 AHCI_CMD->cfis[7] = (UCHAR)(IDE_USE_LBA | DeviceNumber);
2452
2453 AHCI_CMD->cfis[12] = (UCHAR)(value & 0xff);
2454 AHCI_CMD->cfis[4] = (UCHAR)((value >> 8) & 0xff);
2455 AHCI_CMD->cfis[5] = (UCHAR)((value >> 16) & 0xff);
2456 AHCI_CMD->cfis[6] = (UCHAR)((value >> 24) & 0xff);
2457
2458 AHCI_CMD->cfis[15] = IDE_DC_A_4BIT;
2459
2460 if(UniataAhciSendCommand(chan->DeviceExtension, chan->lChannel, DeviceNumber, 0, 100) == IDE_STATUS_WRONG) {
2461 KdPrint2((" PM write failed\n"));
2462 return IDE_STATUS_WRONG;
2463 }
2464
2465 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
2466
2467 if(TFD & IDE_STATUS_ERROR) {
2468 KdPrint2((" ERROR %#x\n", (UCHAR)(TFD >> 8)));
2469 }
2470 return (UCHAR)(TFD >> 8);
2471
2472 } // end UniataAhciWritePM()
2473
2474 VOID
2475 UniataAhciSetupCmdPtr(
2476 IN OUT PATA_REQ AtaReq
2477 )
2478 {
2479 union {
2480 PUCHAR prd_base;
2481 ULONGLONG prd_base64;
2482 };
2483 union {
2484 PUCHAR prd_base0;
2485 ULONGLONG prd_base64_0;
2486 };
2487 #ifdef DBG
2488 ULONG d;
2489 #endif // DBG
2490
2491 prd_base64_0 = prd_base64 = 0;
2492 prd_base = (PUCHAR)(&AtaReq->ahci_cmd0);
2493 prd_base0 = prd_base;
2494
2495 prd_base64 = (prd_base64 + max(FIELD_OFFSET(ATA_REQ, ahci_cmd0), AHCI_CMD_ALIGNEMENT_MASK+1)) & ~AHCI_CMD_ALIGNEMENT_MASK;
2496
2497 #ifdef DBG
2498 d = (ULONG)(prd_base64 - prd_base64_0);
2499 KdPrint2((PRINT_PREFIX " AtaReq %#x: cmd aligned %I64x, d=%x\n", AtaReq, prd_base64, d));
2500 #endif // DBG
2501
2502 AtaReq->ahci.ahci_cmd_ptr = (PIDE_AHCI_CMD)prd_base64;
2503 KdPrint2((PRINT_PREFIX " ahci_cmd_ptr %#x\n", AtaReq->ahci.ahci_cmd_ptr));
2504 } // end UniataAhciSetupCmdPtr()
2505
2506 PSCSI_REQUEST_BLOCK
2507 NTAPI
2508 BuildAhciInternalSrb (
2509 IN PVOID HwDeviceExtension,
2510 IN ULONG DeviceNumber,
2511 IN ULONG lChannel,
2512 IN PUCHAR Buffer,
2513 IN ULONG Length
2514 )
2515 {
2516 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2517 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
2518 PSCSI_REQUEST_BLOCK srb;
2519 // PCDB cdb;
2520 PATA_REQ AtaReq = chan->AhciInternalAtaReq;
2521
2522 KdPrint(("BuildAhciInternalSrb: lChan %d [%#x]\n", lChannel, DeviceNumber));
2523
2524 if(!AtaReq) {
2525 KdPrint2((PRINT_PREFIX " !chan->AhciInternalAtaReq\n"));
2526 return NULL;
2527 }
2528
2529 //RtlZeroMemory((PCHAR) AtaReq, sizeof(ATA_REQ));
2530 //RtlZeroMemory((PCHAR) AtaReq, FIELD_OFFSET(ATA_REQ, ahci));
2531 UniAtaClearAtaReq(AtaReq);
2532
2533 srb = chan->AhciInternalSrb;
2534
2535 RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK));
2536
2537 srb->PathId = (UCHAR)lChannel;
2538 srb->TargetId = (UCHAR)DeviceNumber;
2539 srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
2540 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
2541
2542 // Set flags to disable synchronous negociation.
2543 //srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2544
2545 // Set timeout to 4 seconds.
2546 srb->TimeOutValue = 4;
2547
2548 srb->CdbLength = 6;
2549 srb->DataBuffer = Buffer;
2550 srb->DataTransferLength = Length;
2551 srb->SrbExtension = AtaReq;
2552
2553 AtaReq->Srb = srb;
2554 AtaReq->DataBuffer = (PUSHORT)Buffer;
2555 AtaReq->TransferLength = Length;
2556
2557 //if(!AtaReq->ahci.ahci_cmd_ptr) {
2558 //UniataAhciSetupCmdPtr(AtaReq);
2559 //AtaReq->ahci.ahci_cmd_ptr = &(chan->AhciCtlBlock->cmd);
2560 //AtaReq->ahci.ahci_base64 = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2561 //}
2562 //AtaReq->ahci.ahci_cmd_ptr = &(AtaReq->ahci_cmd0);
2563 //AtaReq->ahci.ahci_base64 = NULL; // indicate that we should copy command to proper place
2564
2565 KdPrint2((PRINT_PREFIX " Srb %#x, AtaReq %#x, CMD %#x ph %I64x\n", srb, AtaReq,
2566 AtaReq->ahci.ahci_cmd_ptr, AtaReq->ahci.ahci_base64));
2567
2568 /* // Set CDB operation code.
2569 cdb = (PCDB)srb->Cdb;
2570 cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
2571 cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
2572 */
2573 return srb;
2574 } // end BuildAhciInternalSrb()
2575