Synchronize up to trunk's revision r57756.
[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 ULONG PI;
649 ULONG CAP;
650 ULONG GHC;
651 BOOLEAN MemIo = FALSE;
652
653 KdPrint2((PRINT_PREFIX " UniataAhciInit:\n"));
654
655 #ifdef DBG
656 UniataDumpAhciRegs(deviceExtension);
657 #endif //DBG
658
659 /* disable AHCI interrupts, for MSI compatibility issue
660 see http://www.intel.com/Assets/PDF/specupdate/307014.pdf
661 26. AHCI Reset and MSI Request
662 */
663
664 KdPrint2((PRINT_PREFIX " get GHC\n"));
665 /* enable AHCI mode */
666 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
667 if(!(GHC & AHCI_GHC_AE)) {
668 KdPrint2((PRINT_PREFIX " enable AHCI mode, disable intr, GHC %#x\n", GHC));
669 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC,
670 (GHC | AHCI_GHC_AE) & ~AHCI_GHC_IE);
671 } else {
672 KdPrint2((PRINT_PREFIX " disable intr, GHC %#x\n", GHC));
673 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC,
674 GHC & ~AHCI_GHC_IE);
675 }
676 AtapiStallExecution(100);
677
678 /* read GHC again and reset AHCI controller */
679 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
680 KdPrint2((PRINT_PREFIX " reset AHCI controller, GHC %#x\n", GHC));
681 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC,
682 GHC | AHCI_GHC_HR);
683
684 for(i=0; i<1000; i++) {
685 AtapiStallExecution(1000);
686 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
687 KdPrint2((PRINT_PREFIX " AHCI GHC %#x\n", GHC));
688 if(!(GHC & AHCI_GHC_HR)) {
689 break;
690 }
691 }
692 if(GHC & AHCI_GHC_HR) {
693 KdPrint2((PRINT_PREFIX " AHCI reset failed\n"));
694 return FALSE;
695 }
696
697 /* re-enable AHCI mode */
698 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
699 if(!(GHC & AHCI_GHC_AE)) {
700 KdPrint2((PRINT_PREFIX " re-enable AHCI mode, GHC %#x\n", GHC));
701 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC,
702 GHC | AHCI_GHC_AE);
703 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
704 }
705 KdPrint2((PRINT_PREFIX " AHCI GHC %#x\n", GHC));
706 if(!(GHC & AHCI_GHC_AE)) {
707 KdPrint2((PRINT_PREFIX " Can't enable AHCI mode\n"));
708 return FALSE;
709 }
710
711 deviceExtension->AHCI_CAP =
712 CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
713 KdPrint2((PRINT_PREFIX " AHCI CAP %#x\n", CAP));
714 if(CAP & AHCI_CAP_S64A) {
715 KdPrint2((PRINT_PREFIX " AHCI 64bit\n"));
716 deviceExtension->Host64 = TRUE;
717 }
718 KdPrint2((PRINT_PREFIX " AHCI %d CMD slots\n", (CAP & AHCI_CAP_NCS_MASK) >> 8 ));
719 if(CAP & AHCI_CAP_PMD) {
720 KdPrint2((PRINT_PREFIX " AHCI multi-block PIO\n"));
721 }
722 if(CAP & AHCI_CAP_SAM) {
723 KdPrint2((PRINT_PREFIX " AHCI legasy SATA\n"));
724 }
725 /* get the number of HW channels */
726 PI = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_PI);
727 KdPrint2((PRINT_PREFIX " AHCI PI %#x\n", PI));
728
729 /* clear interrupts */
730 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_IS,
731 UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS));
732
733 /* enable AHCI interrupts */
734 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC,
735 UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC) | AHCI_GHC_IE);
736
737 BaseMemAddress = deviceExtension->BaseIoAHCI_0.Addr;
738 MemIo = deviceExtension->BaseIoAHCI_0.MemIo;
739
740 deviceExtension->MaxTransferMode = ATA_SA150+(((CAP & AHCI_CAP_ISS_MASK) >> 20)-1);
741 KdPrint2((PRINT_PREFIX " SATA Gen %d\n", ((CAP & AHCI_CAP_ISS_MASK) >> 20) ));
742
743 for(c=0; c<deviceExtension->NumberChannels; c++) {
744 chan = &deviceExtension->chan[c];
745 offs = sizeof(IDE_AHCI_REGISTERS) + c*sizeof(IDE_AHCI_PORT_REGISTERS);
746
747 KdPrint2((PRINT_PREFIX " chan %d, offs %#x\n", c, offs));
748
749 chan->MaxTransferMode = deviceExtension->MaxTransferMode;
750
751 AtapiSetupLunPtrs(chan, deviceExtension, c);
752
753 chan->BaseIoAHCI_Port = deviceExtension->BaseIoAHCI_0;
754 chan->BaseIoAHCI_Port.Addr = BaseMemAddress + offs;
755
756 chan->RegTranslation[IDX_IO1_i_Status ].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, TFD.STS);
757 chan->RegTranslation[IDX_IO1_i_Status ].MemIo = MemIo;
758 chan->RegTranslation[IDX_IO2_AltStatus] = chan->RegTranslation[IDX_IO1_i_Status];
759 chan->RegTranslation[IDX_IO1_i_Error ].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, TFD.ERR);
760 chan->RegTranslation[IDX_IO1_i_Error ].MemIo = MemIo;
761 chan->RegTranslation[IDX_IO1_i_CylinderLow ].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SIG.LbaLow);
762 chan->RegTranslation[IDX_IO1_i_CylinderLow ].MemIo = MemIo;
763 chan->RegTranslation[IDX_IO1_i_CylinderHigh].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SIG.LbaHigh);
764 chan->RegTranslation[IDX_IO1_i_CylinderHigh].MemIo = MemIo;
765 chan->RegTranslation[IDX_IO1_i_BlockCount ].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SIG.SectorCount);
766 chan->RegTranslation[IDX_IO1_i_BlockCount ].MemIo = MemIo;
767
768 UniataInitSyncBaseIO(chan);
769
770 chan->RegTranslation[IDX_SATA_SStatus].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SSTS);
771 chan->RegTranslation[IDX_SATA_SStatus].MemIo = MemIo;
772 chan->RegTranslation[IDX_SATA_SError].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SERR);
773 chan->RegTranslation[IDX_SATA_SError].MemIo = MemIo;
774 chan->RegTranslation[IDX_SATA_SControl].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SCTL);
775 chan->RegTranslation[IDX_SATA_SControl].MemIo = MemIo;
776 chan->RegTranslation[IDX_SATA_SActive].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SACT);
777 chan->RegTranslation[IDX_SATA_SActive].MemIo = MemIo;
778
779 AtapiDmaAlloc(HwDeviceExtension, NULL, c);
780
781 if(!UniataAhciChanImplemented(deviceExtension, c)) {
782 KdPrint2((PRINT_PREFIX " chan %d not implemented\n", c));
783 continue;
784 }
785
786 UniataAhciResume(chan);
787
788 chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
789 }
790
791 return TRUE;
792 } // end UniataAhciInit()
793
794 BOOLEAN
795 NTAPI
796 UniAtaAhciValidateVersion(
797 IN PHW_DEVICE_EXTENSION deviceExtension,
798 IN ULONG version,
799 IN BOOLEAN Strict
800 )
801 {
802 switch(version) {
803 case 0x00000000:
804 case 0xffffffff:
805 KdPrint((" wrong AHCI revision %#x\n", version));
806 return FALSE;
807 case 0x00000905:
808 case 0x00010000:
809 case 0x00010100:
810 case 0x00010200:
811 case 0x00010300:
812 break;
813 default:
814 KdPrint2((PRINT_PREFIX " Unknown AHCI revision\n"));
815 if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"CheckAhciRevision", Strict)) {
816 KdPrint((" AHCI revision excluded\n"));
817 return FALSE;
818 }
819 }
820 return TRUE;
821 } // end UniAtaAhciValidateVersion()
822
823 BOOLEAN
824 NTAPI
825 UniataAhciDetect(
826 IN PVOID HwDeviceExtension,
827 IN PPCI_COMMON_CONFIG pciData, // optional
828 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
829 )
830 {
831 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
832 //ULONG slotNumber = deviceExtension->slotNumber;
833 ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
834 ULONG version;
835 ULONG i, n;
836 ULONG PI;
837 ULONG CAP;
838 ULONG CAP2;
839 ULONG GHC, GHC0;
840 ULONG BOHC;
841 ULONG NumberChannels;
842 ULONG v_Mn, v_Mj;
843 ULONG BaseMemAddress;
844 BOOLEAN MemIo = FALSE;
845 BOOLEAN found = FALSE;
846
847 KdPrint2((PRINT_PREFIX " UniataAhciDetect:\n"));
848
849 if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreAhci", 0)) {
850 KdPrint((" AHCI excluded\n"));
851 return FALSE;
852 }
853 BaseMemAddress = AtapiGetIoRange(HwDeviceExtension, ConfigInfo, pciData, SystemIoBusNumber,
854 5, 0, 0x10);
855 if(!BaseMemAddress) {
856 KdPrint2((PRINT_PREFIX " AHCI init failed - no IoRange\n"));
857 return FALSE;
858 }
859 if((*ConfigInfo->AccessRanges)[5].RangeInMemory) {
860 KdPrint2((PRINT_PREFIX "MemIo\n"));
861 MemIo = TRUE;
862 }
863 deviceExtension->BaseIoAHCI_0.Addr = BaseMemAddress;
864 deviceExtension->BaseIoAHCI_0.MemIo = MemIo;
865
866 #ifdef DBG
867 UniataDumpAhciRegs(deviceExtension);
868 #endif //DBG
869
870 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
871 if(GHC & AHCI_GHC_HR) {
872 KdPrint2((PRINT_PREFIX " AHCI in reset state\n"));
873 return FALSE;
874 }
875
876 /* check AHCI mode. Save state and try enable */
877 GHC0 =
878 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
879 KdPrint2((PRINT_PREFIX " check AHCI mode, GHC %#x\n", GHC));
880
881 version = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_VS);
882
883 if(!(GHC & AHCI_GHC_AE)) {
884 KdPrint2((PRINT_PREFIX " Non-AHCI GHC (!AE), check revision %#x\n", version));
885 if(!UniAtaAhciValidateVersion(deviceExtension, version, FALSE)) {
886 KdPrint2((PRINT_PREFIX " Non-AHCI\n"));
887 goto exit_detect;
888 }
889 KdPrint2((PRINT_PREFIX " try enable\n"));
890 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC,
891 (GHC | AHCI_GHC_AE) & ~AHCI_GHC_IE);
892 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
893
894 KdPrint2((PRINT_PREFIX " re-check AHCI mode, GHC %#x\n", GHC));
895 if(!(GHC & AHCI_GHC_AE)) {
896 KdPrint2((PRINT_PREFIX " Non-AHCI GHC (!AE)\n"));
897 goto exit_detect;
898 }
899 }
900
901 CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
902 CAP2 = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP2);
903 KdPrint2((PRINT_PREFIX " AHCI CAP %#x, CAP2 %#x\n", CAP, CAP2));
904 if(CAP & AHCI_CAP_S64A) {
905 KdPrint2((PRINT_PREFIX " 64bit"));
906 //deviceExtension->Host64 = TRUE; // this is just DETECT, do not update anything
907 }
908 if(CAP2 & AHCI_CAP2_BOH) {
909 BOHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_BOHC);
910 KdPrint2((PRINT_PREFIX " BOHC %#x", BOHC));
911 }
912 if(CAP & AHCI_CAP_NCQ) {
913 KdPrint2((PRINT_PREFIX " NCQ"));
914 }
915 if(CAP & AHCI_CAP_SNTF) {
916 KdPrint2((PRINT_PREFIX " SNTF"));
917 }
918 if(CAP & AHCI_CAP_CCC) {
919 KdPrint2((PRINT_PREFIX " CCC"));
920 }
921 KdPrint2((PRINT_PREFIX "\n"));
922
923 /* get the number of HW channels */
924 PI = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_PI);
925 deviceExtension->AHCI_PI = PI;
926 KdPrint2((PRINT_PREFIX " AHCI PI %#x\n", PI));
927 for(i=PI, n=0; i; n++, i=i>>1);
928 NumberChannels =
929 max((CAP & AHCI_CAP_NOP_MASK)+1, n);
930
931 KdPrint2((PRINT_PREFIX " CommandSlots %d\n", (CAP & AHCI_CAP_NCS_MASK)>>8 ));
932 KdPrint2((PRINT_PREFIX " Channels %d\n", n));
933
934 switch(deviceExtension->DevID) {
935 case ATA_M88SX6111:
936 NumberChannels = 1;
937 break;
938 case ATA_M88SX6121:
939 NumberChannels = 2;
940 break;
941 case ATA_M88SX6141:
942 case ATA_M88SX6145:
943 NumberChannels = 4;
944 break;
945 } // switch()
946
947 if(!NumberChannels) {
948 KdPrint2((PRINT_PREFIX " Non-AHCI - NumberChannels=0\n"));
949 found = FALSE;
950 goto exit_detect;
951 }
952
953 v_Mj = ((version >> 20) & 0xf0) + ((version >> 16) & 0x0f);
954 v_Mn = ((version >> 4) & 0xf0) + (version & 0x0f);
955
956 KdPrint2((PRINT_PREFIX " AHCI version %#x.%02x controller with %d ports (mask %#x) detected\n",
957 v_Mj, v_Mn,
958 NumberChannels, PI));
959 KdPrint((" AHCI SATA Gen %d\n", (((CAP & AHCI_CAP_ISS_MASK) >> 20)) ));
960
961 if(CAP & AHCI_CAP_SPM) {
962 KdPrint2((PRINT_PREFIX " PM supported\n"));
963 if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreAhciPM", 1 /* DEBUG */)) {
964 KdPrint2((PRINT_PREFIX "SATA/AHCI w/o PM, max luns 1\n"));
965 deviceExtension->NumberLuns = 1;
966 //chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE;
967 } else {
968 KdPrint2((PRINT_PREFIX "SATA/AHCI -> possible PM, max luns %d\n", SATA_MAX_PM_UNITS));
969 deviceExtension->NumberLuns = SATA_MAX_PM_UNITS;
970 //deviceExtension->NumberLuns = 1;
971 }
972 } else {
973 KdPrint2((PRINT_PREFIX " PM not supported -> 1 lun/chan\n"));
974 deviceExtension->NumberLuns = 1;
975 }
976
977 if(!UniAtaAhciValidateVersion(deviceExtension, version, TRUE)) {
978 goto exit_detect;
979 }
980
981 deviceExtension->HwFlags |= UNIATA_SATA | UNIATA_AHCI;
982 if(deviceExtension->NumberChannels < NumberChannels) {
983 deviceExtension->NumberChannels = NumberChannels;
984 }
985 deviceExtension->DmaSegmentLength = 0x3fffff+1; // 4MB
986 deviceExtension->DmaSegmentAlignmentMask = -1; // no restrictions
987
988 deviceExtension->BusMaster = DMA_MODE_AHCI;
989 deviceExtension->MaxTransferMode = max(deviceExtension->MaxTransferMode, ATA_SA150+(((CAP & AHCI_CAP_ISS_MASK) >> 20)-1) );
990
991 found = TRUE;
992
993 exit_detect:
994 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, GHC0);
995 KdPrint((" AHCI detect status %d\n", found));
996
997 return found;
998 } // end UniataAhciDetect()
999
1000 UCHAR
1001 NTAPI
1002 UniataAhciStatus(
1003 IN PVOID HwDeviceExtension,
1004 IN ULONG lChannel,
1005 IN ULONG DeviceNumber
1006 )
1007 {
1008 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1009 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1010 ULONG Channel = deviceExtension->Channel + lChannel;
1011 ULONG hIS;
1012 ULONG CI, ACT;
1013 AHCI_IS_REG IS;
1014 SATA_SSTATUS_REG SStatus;
1015 SATA_SERROR_REG SError;
1016 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1017 ULONG tag=0;
1018
1019 KdPrint(("UniataAhciStatus(%d-%d):\n", lChannel, Channel));
1020
1021 hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
1022 KdPrint((" hIS %#x\n", hIS));
1023 hIS &= (1 << Channel);
1024 if(!hIS) {
1025 return INTERRUPT_REASON_IGNORE;
1026 }
1027 IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS);
1028 CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI);
1029 ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT);
1030 SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus);
1031 SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError);
1032
1033 /* clear interrupt(s) */
1034 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_IS, hIS);
1035 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS.Reg);
1036 AtapiWritePort4(chan, IDX_SATA_SError, SError.Reg);
1037
1038 KdPrint((" AHCI: is=%08x ss=%08x serror=%08x CI=%08x, ACT=%08x\n",
1039 IS.Reg, SStatus.Reg, SError.Reg, CI, ACT));
1040
1041 /* do we have cold connect surprise */
1042 if(IS.CPDS) {
1043 }
1044
1045 /* check for and handle connect events */
1046 if(IS.PCS) {
1047 UniataSataEvent(HwDeviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH);
1048 }
1049 if(IS.PRCS) {
1050 UniataSataEvent(HwDeviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH);
1051 }
1052 chan->AhciCompleteCI = (chan->AhciPrevCI ^ CI) & chan->AhciPrevCI; // only 1->0 states
1053 chan->AhciPrevCI = CI;
1054 KdPrint((" AHCI: complete mask %#x\n", chan->AhciCompleteCI));
1055 chan->AhciLastIS = IS.Reg;
1056 if(CI & (1 << tag)) {
1057 #ifdef DBG
1058 UniataDumpAhciPortRegs(chan);
1059 #endif //DBG
1060 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
1061 if(IS.Reg &
1062 (ATA_AHCI_P_IX_OF | ATA_AHCI_P_IX_INF | ATA_AHCI_P_IX_IF |
1063 ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_HBF | ATA_AHCI_P_IX_TFE)) {
1064 KdPrint((" AHCI: unexpected, error\n"));
1065 } else {
1066 KdPrint((" AHCI: unexpected, incomplete command or error ?\n"));
1067 /*
1068 ULONG TFD;
1069
1070 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
1071 KdPrint2((" TFD %#x\n", TFD));
1072 if(TFD & IDE_STATUS_BUSY) {
1073 KdPrint2((" Seems to be interrupt on error\n"));
1074 return INTERRUPT_REASON_OUR;
1075 }
1076 */
1077 return INTERRUPT_REASON_UNEXPECTED;
1078 }
1079 }
1080 return INTERRUPT_REASON_OUR;
1081
1082 } // end UniataAhciStatus()
1083
1084 VOID
1085 NTAPI
1086 UniataAhciSnapAtaRegs(
1087 IN PHW_CHANNEL chan,
1088 IN ULONG DeviceNumber,
1089 IN OUT PIDEREGS_EX regs
1090 )
1091 {
1092 ULONG TFD, SIG;
1093
1094 regs->bDriveHeadReg = IDE_DRIVE_SELECT_1;
1095 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
1096 regs->bCommandReg = (UCHAR)(TFD & 0xff);
1097 regs->bFeaturesReg = (UCHAR)((TFD >> 8) & 0xff);
1098
1099 SIG = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_SIG);
1100 regs->bSectorCountReg = (UCHAR)(SIG & 0xff);
1101 regs->bSectorNumberReg = (UCHAR)((SIG >> 8) & 0xff);
1102 regs->bCylLowReg = (UCHAR)((SIG >> 16) & 0xff);
1103 regs->bCylHighReg = (UCHAR)((SIG >> 24) & 0xff);
1104 regs->bOpFlags = 0;
1105
1106 return;
1107 } // end UniataAhciSnapAtaRegs()
1108
1109 ULONG
1110 NTAPI
1111 UniataAhciSetupFIS_H2D(
1112 IN PHW_DEVICE_EXTENSION deviceExtension,
1113 IN ULONG DeviceNumber,
1114 IN ULONG lChannel,
1115 OUT PUCHAR fis,
1116 IN UCHAR command,
1117 IN ULONGLONG lba,
1118 IN USHORT count,
1119 IN USHORT feature
1120 )
1121 {
1122 //ULONG i;
1123 PUCHAR plba;
1124 BOOLEAN need48;
1125 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1126
1127 KdPrint2((PRINT_PREFIX " AHCI setup FIS %x, ch %d, dev %d\n", fis, lChannel, DeviceNumber));
1128 //i = 0;
1129 plba = (PUCHAR)&lba;
1130
1131 RtlZeroMemory(fis, 20);
1132
1133 fis[0] = AHCI_FIS_TYPE_ATA_H2D; /* host to device */
1134 fis[1] = 0x80 | ((UCHAR)DeviceNumber & 0x0f); /* command FIS (note PM goes here) */
1135 fis[IDX_AHCI_o_DriveSelect] = IDE_DRIVE_SELECT_1 |
1136 ((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_48)) ? IDE_USE_LBA : 0);
1137 fis[IDX_AHCI_o_Control] = IDE_DC_A_4BIT;
1138
1139 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1140 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1141 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1142 */
1143 command == IDE_COMMAND_ATAPI_PACKET) {
1144 fis[IDX_AHCI_o_Command] = IDE_COMMAND_ATAPI_PACKET;
1145 if(feature & ATA_F_DMA) {
1146 fis[IDX_AHCI_o_Feature] = (UCHAR)(feature & 0xff);
1147 } else {
1148 fis[IDX_AHCI_o_CylinderLow] = (UCHAR)(count & 0xff);
1149 fis[IDX_AHCI_o_CylinderHigh] = (UCHAR)(count>>8) & 0xff;
1150 }
1151 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1152 } else {
1153
1154 if(((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp|ATA_CMD_FLAG_FUA)) == ATA_CMD_FLAG_LBAIOsupp) &&
1155 CheckIfBadBlock(chan->lun[DeviceNumber], lba, count)) {
1156 KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count));
1157 //return IDE_STATUS_ERROR;
1158 //return SRB_STATUS_ERROR;
1159 return 0;
1160 }
1161
1162 need48 = UniAta_need_lba48(command, lba, count,
1163 chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48);
1164
1165 /* translate command into 48bit version */
1166 if(need48) {
1167 if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) {
1168 command = AtaCommands48[command];
1169 } else {
1170 KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n"));
1171 return 0;
1172 }
1173 }
1174
1175 fis[IDX_AHCI_o_Command] = command;
1176 fis[IDX_AHCI_o_Feature] = (UCHAR)feature;
1177
1178 fis[IDX_AHCI_o_BlockNumber] = plba[0];
1179 fis[IDX_AHCI_o_CylinderLow] = plba[1];
1180 fis[IDX_AHCI_o_CylinderHigh] = plba[2];
1181
1182 fis[IDX_AHCI_o_BlockCount] = (UCHAR)count & 0xff;
1183
1184 if(need48) {
1185 //i++;
1186 fis[IDX_AHCI_o_Control] |= IDE_DC_USE_HOB;
1187
1188 fis[IDX_AHCI_o_BlockNumberExp] = plba[3];
1189 fis[IDX_AHCI_o_CylinderLowExp] = plba[4];
1190 fis[IDX_AHCI_o_CylinderHighExp] = plba[5];
1191
1192 fis[IDX_AHCI_o_BlockCountExp] = (UCHAR)(count>>8) & 0xff;
1193
1194 fis[IDX_AHCI_o_FeatureExp] = (UCHAR)(feature>>8) & 0xff;
1195
1196 chan->ChannelCtrlFlags |= CTRFLAGS_LBA48;
1197 } else {
1198 //#ifdef _MSC_VER
1199 //#pragma warning(push)
1200 //#pragma warning(disable:4333) // right shift by too large amount, data loss
1201 //#endif
1202 fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f);
1203 chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48;
1204 //#ifdef _MSC_VER
1205 //#pragma warning(pop)
1206 //#endif
1207 }
1208
1209 //fis[14] = 0x00;
1210
1211 }
1212
1213 KdDump(fis, 20);
1214
1215 return 20;
1216 } // end UniataAhciSetupFIS_H2D()
1217
1218 ULONG
1219 NTAPI
1220 UniataAhciSetupFIS_H2D_Direct(
1221 IN PHW_DEVICE_EXTENSION deviceExtension,
1222 IN ULONG DeviceNumber,
1223 IN ULONG lChannel,
1224 OUT PUCHAR fis,
1225 IN PIDEREGS_EX regs
1226 )
1227 {
1228 //ULONG i;
1229 //PUCHAR plba;
1230 BOOLEAN need48;
1231 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1232 UCHAR command;
1233
1234 command = regs->bCommandReg;
1235
1236 KdPrint2((PRINT_PREFIX " AHCI setup FIS Direct %x, ch %d, dev %d\n", fis, lChannel, DeviceNumber));
1237 //i = 0;
1238 //plba = (PUCHAR)&lba;
1239
1240 RtlZeroMemory(fis, 20);
1241
1242 fis[0] = AHCI_FIS_TYPE_ATA_H2D; /* host to device */
1243 fis[1] = 0x80 | ((UCHAR)DeviceNumber & 0x0f); /* command FIS (note PM goes here) */
1244 fis[IDX_AHCI_o_DriveSelect] = IDE_DRIVE_SELECT_1 |
1245 ((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_48)) ? IDE_USE_LBA : 0);
1246 fis[IDX_AHCI_o_Control] = IDE_DC_A_4BIT;
1247
1248 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command,
1249 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET
1250 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
1251 */
1252 command == IDE_COMMAND_ATAPI_PACKET) {
1253 /* fis[IDX_AHCI_o_Command] = IDE_COMMAND_ATAPI_PACKET;
1254 if(feature & ATA_F_DMA) {
1255 fis[IDX_AHCI_o_Feature] = (UCHAR)(feature & 0xff);
1256 } else {
1257 fis[IDX_AHCI_o_CylinderLow] = (UCHAR)(count & 0xff);
1258 fis[IDX_AHCI_o_CylinderHigh] = (UCHAR)(count>>8) & 0xff;
1259 }*/
1260 return 0;
1261 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT;
1262 } else {
1263
1264 need48 = (regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) &&
1265 chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48;
1266
1267 /* translate command into 48bit version */
1268 if(need48) {
1269 if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) {
1270 command = AtaCommands48[command];
1271 } else {
1272 KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n"));
1273 return 0;
1274 }
1275 }
1276
1277 fis[IDX_AHCI_o_Command] = command;
1278 fis[IDX_AHCI_o_Feature] = regs->bFeaturesReg;
1279
1280 fis[IDX_AHCI_o_BlockNumber] = regs->bSectorNumberReg;
1281 fis[IDX_AHCI_o_CylinderLow] = regs->bCylLowReg;
1282 fis[IDX_AHCI_o_CylinderHigh] = regs->bCylHighReg;
1283
1284 fis[IDX_AHCI_o_BlockCount] = regs->bSectorCountReg;
1285
1286 if(need48) {
1287 //i++;
1288 fis[IDX_AHCI_o_Control] |= IDE_DC_USE_HOB;
1289
1290 fis[IDX_AHCI_o_BlockNumberExp] = regs->bSectorNumberRegH;
1291 fis[IDX_AHCI_o_CylinderLowExp] = regs->bCylLowRegH;
1292 fis[IDX_AHCI_o_CylinderHighExp] = regs->bCylHighRegH;
1293
1294 fis[IDX_AHCI_o_BlockCountExp] = regs->bSectorCountRegH;
1295
1296 fis[IDX_AHCI_o_FeatureExp] = regs->bFeaturesRegH;
1297
1298 chan->ChannelCtrlFlags |= CTRFLAGS_LBA48;
1299 } else {
1300 //fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f);
1301 chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48;
1302 }
1303 fis[IDX_AHCI_o_DriveSelect] |= regs->bDriveHeadReg & 0x0f;
1304 }
1305
1306 KdDump(fis, 20);
1307
1308 return 20;
1309 } // end UniataAhciSetupFIS_H2D_Direct()
1310
1311 UCHAR
1312 NTAPI
1313 UniataAhciWaitCommandReady(
1314 IN PHW_CHANNEL chan,
1315 IN ULONG timeout
1316 )
1317 {
1318 AHCI_IS_REG IS;
1319 //ULONG ACT;
1320 ULONG CI=0;
1321 ULONG i;
1322 ULONG SError;
1323 ULONG tag=0;
1324
1325 timeout *= 5;
1326
1327 for (i=0; i<timeout; i++) {
1328 CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI);
1329 //ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT);
1330 if (!(( CI >> tag) & 0x01)) {
1331 break;
1332 }
1333 IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS);
1334 //KdPrint((" IS %#x\n", IS.Reg));
1335 if(IS.Reg) {
1336 break;
1337 }
1338 SError = AtapiReadPort4(chan, IDX_SATA_SError);
1339 if(SError) {
1340 KdPrint((" AHCI: error %#x\n", SError));
1341 i = timeout;
1342 break;
1343 }
1344 AtapiStallExecution(200);
1345 }
1346 KdPrint((" CI %#x\n", CI));
1347
1348 //SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus);
1349 //SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError);
1350
1351 /* clear interrupt(s) */
1352 IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS);
1353 KdPrint((" IS %#x\n", IS.Reg));
1354 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS.Reg);
1355
1356 if (timeout && (i >= timeout)) {
1357 #ifdef DBG
1358 ULONG TFD;
1359
1360 SError = AtapiReadPort4(chan, IDX_SATA_SError);
1361 KdPrint((" AHCI: timeout, SError %#x\n", SError));
1362
1363 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
1364 KdPrint2((" TFD %#x\n", TFD));
1365 #endif //DBG
1366
1367 return IDE_STATUS_WRONG;
1368 }
1369
1370 return IDE_STATUS_IDLE;
1371 } // end UniataAhciWaitCommandReady()
1372
1373 UCHAR
1374 NTAPI
1375 UniataAhciSendCommand(
1376 IN PVOID HwDeviceExtension,
1377 IN ULONG lChannel,
1378 IN ULONG DeviceNumber,
1379 IN USHORT ahci_flags,
1380 IN ULONG timeout
1381 )
1382 {
1383 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1384 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1385 //ULONG Channel = deviceExtension->Channel + lChannel;
1386 //ULONG hIS;
1387 //ULONG SError;
1388 //SATA_SSTATUS_REG SStatus;
1389 //SATA_SERROR_REG SError;
1390 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1391 //ULONGIO_PTR base;
1392 ULONG tag=0;
1393
1394 PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1395
1396 KdPrint(("UniataAhciSendCommand: lChan %d\n", chan->lChannel));
1397
1398 AHCI_CL->prd_length = 0;
1399 //AHCI_CL->cmd_flags = (20 / sizeof(ULONG)) | ahci_flags | (DeviceNumber << 12);
1400 AHCI_CL->cmd_flags = UniAtaAhciAdjustIoFlags(0, ahci_flags, 20, DeviceNumber);
1401
1402 AHCI_CL->bytecount = 0;
1403 AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
1404 if(AHCI_CL->cmd_table_phys & AHCI_CMD_ALIGNEMENT_MASK) {
1405 KdPrint2((PRINT_PREFIX " AHCI CMD address is not aligned (mask %#x)\n", (ULONG)AHCI_CMD_ALIGNEMENT_MASK));
1406 }
1407
1408 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
1409 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, 1 << tag);
1410
1411 return UniataAhciWaitCommandReady(chan, timeout);
1412
1413 } // end UniataAhciSendCommand()
1414
1415 UCHAR
1416 NTAPI
1417 UniataAhciSendPIOCommand(
1418 IN PVOID HwDeviceExtension,
1419 IN ULONG lChannel,
1420 IN ULONG DeviceNumber,
1421 IN PSCSI_REQUEST_BLOCK Srb,
1422 IN PUCHAR data,
1423 IN ULONG length, /* bytes */
1424 IN UCHAR command,
1425 IN ULONGLONG lba,
1426 IN USHORT bcount, /* block count, just ATA register */
1427 IN USHORT feature,
1428 IN USHORT ahci_flags,
1429 IN ULONG wait_flags,
1430 IN ULONG timeout
1431 )
1432 {
1433 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1434 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1435 UCHAR statusByte;
1436 PATA_REQ AtaReq;
1437 ULONG fis_size;
1438 //ULONG tag=0;
1439 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1440 PIDE_AHCI_CMD AHCI_CMD = NULL;
1441
1442 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1443
1444 KdPrint2((PRINT_PREFIX "UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x bcount %#x feature %#x, buff %#x, len %#x, WF %#x \n",
1445 deviceExtension->DevIndex, lChannel, DeviceNumber, command, lba, bcount, feature, data, length, wait_flags ));
1446
1447 if(length/DEV_BSIZE != bcount) {
1448 KdPrint((" length/DEV_BSIZE != bcount\n"));
1449 }
1450
1451 #ifdef DBG
1452 //UniataDumpAhciPortRegs(chan);
1453 #endif // DBG
1454
1455 if(!Srb) {
1456 Srb = BuildAhciInternalSrb(HwDeviceExtension, DeviceNumber, lChannel, data, length);
1457 if(!Srb) {
1458 KdPrint((" !Srb\n"));
1459 return IDE_STATUS_WRONG;
1460 }
1461 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1462 //should be already called on init
1463 }
1464 AtaReq = (PATA_REQ)(Srb->SrbExtension);
1465 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1466
1467 AHCI_CMD = AtaReq->ahci.ahci_cmd_ptr;
1468
1469 fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
1470 &(AHCI_CMD->cfis[0]),
1471 command,
1472 lba,
1473 bcount,
1474 feature
1475 );
1476
1477 if(!fis_size) {
1478 KdPrint2(("!fis_size\n"));
1479 return IDE_STATUS_WRONG;
1480 }
1481
1482 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1483 ahci_flags = UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber);
1484 KdPrint2(("ahci_flags %#x\n", ahci_flags));
1485
1486 if(data) {
1487 if(ahci_flags & ATA_AHCI_CMD_WRITE) {
1488 AtaReq->Flags &= ~REQ_FLAG_READ;
1489 Srb->SrbFlags |= SRB_FLAGS_DATA_OUT;
1490 KdPrint((" assume OUT\n"));
1491 } else {
1492 AtaReq->Flags |= REQ_FLAG_READ;
1493 Srb->SrbFlags |= SRB_FLAGS_DATA_IN;
1494 KdPrint((" assume IN\n"));
1495 }
1496 if(!AtapiDmaSetup(HwDeviceExtension,
1497 DeviceNumber,
1498 lChannel, // logical channel,
1499 Srb,
1500 data,
1501 length)) {
1502 KdPrint2((" can't setup buffer\n"));
1503 return IDE_STATUS_WRONG;
1504 }
1505 }
1506
1507 AtaReq->ahci.io_cmd_flags = ahci_flags;
1508
1509 #ifdef DBG
1510 //UniataDumpAhciPortRegs(chan);
1511 #endif // DBG
1512
1513 UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
1514
1515 #ifdef DBG
1516 //UniataDumpAhciPortRegs(chan);
1517 #endif // DBG
1518
1519 if(wait_flags == ATA_IMMEDIATE) {
1520 statusByte = 0;
1521 KdPrint2((" return imemdiately\n"));
1522 } else {
1523 statusByte = UniataAhciWaitCommandReady(chan, timeout);
1524 UniataAhciStatus(HwDeviceExtension, lChannel, DeviceNumber);
1525 UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
1526 }
1527
1528 return statusByte;
1529
1530 } // end UniataAhciSendPIOCommand()
1531
1532 UCHAR
1533 NTAPI
1534 UniataAhciSendPIOCommandDirect(
1535 IN PVOID HwDeviceExtension,
1536 IN ULONG lChannel,
1537 IN ULONG DeviceNumber,
1538 IN PSCSI_REQUEST_BLOCK Srb,
1539 IN PIDEREGS_EX regs,
1540 IN ULONG wait_flags,
1541 IN ULONG timeout
1542 )
1543 {
1544 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1545 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1546 UCHAR statusByte;
1547 PATA_REQ AtaReq;
1548 ULONG fis_size;
1549 //ULONG tag=0;
1550 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1551 PIDE_AHCI_CMD AHCI_CMD = NULL;
1552 USHORT ahci_flags=0;
1553 // USHORT bcount=0;
1554
1555 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
1556
1557 KdPrint2((PRINT_PREFIX "UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, buff %#x, len %#x, WF %#x \n",
1558 deviceExtension->DevIndex, lChannel, DeviceNumber, Srb->DataBuffer, Srb->DataTransferLength, wait_flags ));
1559
1560 // if(Srb->DataTransferLength/DEV_BSIZE != bcount) {
1561 // KdPrint((" length/DEV_BSIZE != bcount\n"));
1562 // }
1563
1564 #ifdef DBG
1565 //UniataDumpAhciPortRegs(chan);
1566 #endif // DBG
1567
1568 if(!Srb) {
1569 KdPrint((" !Srb\n"));
1570 return IDE_STATUS_WRONG;
1571 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup
1572 //should be already called on init
1573 }
1574 AtaReq = (PATA_REQ)(Srb->SrbExtension);
1575 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq));
1576
1577 AHCI_CMD = AtaReq->ahci.ahci_cmd_ptr;
1578 if(!AHCI_CMD) {
1579 KdPrint((" !AHCI_CMD\n"));
1580 return IDE_STATUS_WRONG;
1581 }
1582
1583 if(Srb->DataTransferLength) {
1584 if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
1585 ahci_flags |= ATA_AHCI_CMD_WRITE;
1586 AtaReq->Flags &= ~REQ_FLAG_READ;
1587 } else {
1588 AtaReq->Flags |= REQ_FLAG_READ;
1589 }
1590 }
1591
1592 fis_size = UniataAhciSetupFIS_H2D_Direct(deviceExtension, DeviceNumber, lChannel,
1593 &(AHCI_CMD->cfis[0]),
1594 regs);
1595
1596 if(!fis_size) {
1597 KdPrint2(("!fis_size\n"));
1598 return IDE_STATUS_WRONG;
1599 }
1600
1601 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n"));
1602 ahci_flags = UniAtaAhciAdjustIoFlags(regs->bCommandReg, ahci_flags, fis_size, DeviceNumber);
1603 KdPrint2(("ahci_flags %#x\n", ahci_flags));
1604
1605 if(Srb->DataTransferLength) {
1606 if(!AtapiDmaSetup(HwDeviceExtension,
1607 DeviceNumber,
1608 lChannel, // logical channel,
1609 Srb,
1610 (PUCHAR)(Srb->DataBuffer),
1611 Srb->DataTransferLength)) {
1612 KdPrint2((" can't setup buffer\n"));
1613 return IDE_STATUS_WRONG;
1614 }
1615 }
1616
1617 AtaReq->ahci.io_cmd_flags = ahci_flags;
1618
1619 #ifdef DBG
1620 //UniataDumpAhciPortRegs(chan);
1621 #endif // DBG
1622
1623 UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
1624
1625 #ifdef DBG
1626 //UniataDumpAhciPortRegs(chan);
1627 #endif // DBG
1628
1629 if(wait_flags == ATA_IMMEDIATE) {
1630 statusByte = 0;
1631 KdPrint2((" return imemdiately\n"));
1632 } else {
1633 statusByte = UniataAhciWaitCommandReady(chan, timeout);
1634 UniataAhciStatus(HwDeviceExtension, lChannel, DeviceNumber);
1635 UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
1636 }
1637
1638 return statusByte;
1639
1640 } // end UniataAhciSendPIOCommandDirect()
1641
1642 BOOLEAN
1643 NTAPI
1644 UniataAhciAbortOperation(
1645 IN PHW_CHANNEL chan
1646 )
1647 {
1648 /* kick controller into sane state */
1649 if(!UniataAhciStop(chan)) {
1650 return FALSE;
1651 }
1652 if(!UniataAhciStopFR(chan)) {
1653 return FALSE;
1654 }
1655 if(!UniataAhciCLO(chan)) {
1656 return FALSE;
1657 }
1658 UniataAhciStartFR(chan);
1659 UniataAhciStart(chan);
1660
1661 return TRUE;
1662 } // end UniataAhciAbortOperation()
1663
1664 ULONG
1665 NTAPI
1666 UniataAhciSoftReset(
1667 IN PVOID HwDeviceExtension,
1668 IN ULONG lChannel,
1669 IN ULONG DeviceNumber
1670 )
1671 {
1672 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1673 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1674 //ULONG Channel = deviceExtension->Channel + lChannel;
1675 //ULONG hIS;
1676 //ULONG CI;
1677 //AHCI_IS_REG IS;
1678 //ULONG tag=0;
1679
1680 KdPrint(("UniataAhciSoftReset: lChan %d\n", chan->lChannel));
1681
1682 PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
1683 PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
1684
1685 /* kick controller into sane state */
1686 if(!UniataAhciAbortOperation(chan)) {
1687 KdPrint2((" abort failed\n"));
1688 return (ULONG)(-1);
1689 }
1690
1691 /* pull reset active */
1692 RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis));
1693 AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D;
1694 AHCI_CMD->cfis[1] = (UCHAR)DeviceNumber & 0x0f;
1695 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1696 AHCI_CMD->cfis[15] = (IDE_DC_A_4BIT | IDE_DC_RESET_CONTROLLER);
1697
1698 if(UniataAhciSendCommand(HwDeviceExtension, lChannel, DeviceNumber, ATA_AHCI_CMD_RESET | ATA_AHCI_CMD_CLR_BUSY, 100) == IDE_STATUS_WRONG) {
1699 KdPrint2((" timeout\n"));
1700 return (ULONG)(-1);
1701 }
1702 AtapiStallExecution(50);
1703
1704 /* pull reset inactive */
1705 RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis));
1706 AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D;
1707 AHCI_CMD->cfis[1] = (UCHAR)DeviceNumber & 0x0f;
1708 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT;
1709 AHCI_CMD->cfis[15] = (IDE_DC_A_4BIT);
1710 if(UniataAhciSendCommand(HwDeviceExtension, lChannel, DeviceNumber, 0, 3000) == IDE_STATUS_WRONG) {
1711 KdPrint2((" timeout (2)\n"));
1712 return (ULONG)(-1);
1713 }
1714
1715 UniataAhciWaitReady(chan, 1);
1716
1717 KdDump(RCV_FIS, sizeof(chan->AhciCtlBlock->rcv_fis.rfis));
1718
1719 return UniataAhciUlongFromRFIS(RCV_FIS);
1720
1721 } // end UniataAhciSoftReset()
1722
1723 ULONG
1724 NTAPI
1725 UniataAhciWaitReady(
1726 IN PHW_CHANNEL chan,
1727 IN ULONG timeout
1728 )
1729 {
1730 ULONG TFD;
1731 ULONG i;
1732
1733 KdPrint2(("UniataAhciWaitReady: lChan %d\n", chan->lChannel));
1734
1735 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1736
1737 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
1738 for(i=0; i<timeout && (TFD &
1739 (IDE_STATUS_DRQ | IDE_STATUS_BUSY)); i++) {
1740 AtapiStallExecution(1000);
1741 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
1742 }
1743
1744 KdPrint2((" TFD %#x\n", TFD));
1745
1746 return TFD;
1747
1748 } // end UniataAhciWaitReady()
1749
1750 ULONG
1751 NTAPI
1752 UniataAhciHardReset(
1753 IN PVOID HwDeviceExtension,
1754 IN ULONG lChannel,
1755 OUT PULONG signature
1756 )
1757 {
1758 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1759 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1760 //ULONG Channel = deviceExtension->Channel + lChannel;
1761 ULONG TFD;
1762
1763
1764 KdPrint(("UniataAhciHardReset: lChan %d\n", chan->lChannel));
1765
1766 (*signature) = 0xffffffff;
1767
1768 UniataAhciStop(chan);
1769 if(UniataSataPhyEnable(HwDeviceExtension, lChannel, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE) == IDE_STATUS_WRONG) {
1770 KdPrint((" no PHY\n"));
1771 return IDE_STATUS_WRONG;
1772 }
1773
1774 /* Wait for clearing busy status. */
1775 TFD = UniataAhciWaitReady(chan, 15000);
1776 if(TFD & (IDE_STATUS_DRQ | IDE_STATUS_BUSY)) {
1777 KdPrint((" busy: TFD %#x\n", TFD));
1778 return TFD;
1779 }
1780 KdPrint((" TFD %#x\n", TFD));
1781
1782 #ifdef DBG
1783 UniataDumpAhciPortRegs(chan);
1784 #endif // DBG
1785
1786 (*signature) = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_SIG);
1787 KdPrint((" sig: %#x\n", *signature));
1788
1789 UniataAhciStart(chan);
1790
1791 return 0;
1792
1793 } // end UniataAhciHardReset()
1794
1795 VOID
1796 NTAPI
1797 UniataAhciReset(
1798 IN PVOID HwDeviceExtension,
1799 IN ULONG lChannel
1800 )
1801 {
1802 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1803 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1804 //ULONG Channel = deviceExtension->Channel + lChannel;
1805 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
1806 ULONG CAP;
1807 //ULONGIO_PTR base;
1808 ULONG signature;
1809 ULONG i;
1810 ULONG VendorID = deviceExtension->DevID & 0xffff;
1811
1812 KdPrint(("UniataAhciReset: lChan %d\n", chan->lChannel));
1813
1814 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs);
1815
1816 /* Disable port interrupts */
1817 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
1818
1819 if(UniataAhciHardReset(HwDeviceExtension, lChannel, &signature)) {
1820
1821 KdPrint((" No devices in all LUNs\n"));
1822 for (i=0; i<deviceExtension->NumberLuns; i++) {
1823 // Zero device fields to ensure that if earlier devices were found,
1824 // but not claimed, the fields are cleared.
1825 UniataForgetDevice(chan->lun[i]);
1826 }
1827
1828 /* enable wanted port interrupts */
1829 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE,
1830 ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC);
1831 return;
1832 }
1833
1834 /* enable wanted port interrupts */
1835 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE,
1836 (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF |
1837 ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF |
1838 ((/*ch->pm_level == */0) ? (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC) : 0) |
1839 ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB |
1840 ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR) );
1841
1842 /*
1843 * Only probe for PortMultiplier if HW has support.
1844 * Ignore Marvell, which is not working,
1845 */
1846 CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
1847 if ((CAP & AHCI_CAP_SPM) &&
1848 (VendorID != ATA_MARVELL_ID)) {
1849 KdPrint((" check PM\n"));
1850 signature = UniataAhciSoftReset(HwDeviceExtension, lChannel, AHCI_DEV_SEL_PM);
1851 /* Workaround for some ATI chips, failing to soft-reset
1852 * when port multiplicator supported, but absent.
1853 * XXX: We can also check PxIS.IPMS==1 here to be sure. */
1854 if (signature == 0xffffffff) {
1855 KdPrint((" re-check PM\n"));
1856 signature = UniataAhciSoftReset(HwDeviceExtension, lChannel, 0);
1857 }
1858 } else {
1859 signature = UniataAhciSoftReset(HwDeviceExtension, lChannel, 0);
1860 }
1861
1862 KdPrint((" signature %#x\n", signature));
1863 chan->lun[0]->DeviceFlags &= ~(DFLAGS_ATAPI_DEVICE | DFLAGS_DEVICE_PRESENT | CTRFLAGS_AHCI_PM);
1864 switch (signature >> 16) {
1865 case 0x0000:
1866 KdPrint((" ATA dev\n"));
1867 chan->lun[0]->DeviceFlags |= DFLAGS_DEVICE_PRESENT;
1868 chan->PmLunMap = 0;
1869 break;
1870 case 0x9669:
1871 KdPrint((" PM\n"));
1872 if(deviceExtension->NumberLuns > 1) {
1873 chan->ChannelCtrlFlags |= CTRFLAGS_AHCI_PM;
1874 UniataSataIdentifyPM(chan);
1875 } else {
1876 KdPrint((" no PM supported (1 lun/chan)\n"));
1877 }
1878 break;
1879 case 0xeb14:
1880 KdPrint((" ATAPI dev\n"));
1881 chan->lun[0]->DeviceFlags |= (DFLAGS_ATAPI_DEVICE | DFLAGS_DEVICE_PRESENT);
1882 chan->PmLunMap = 0;
1883 break;
1884 default: /* SOS XXX */
1885 KdPrint((" default to ATA ???\n"));
1886 chan->lun[0]->DeviceFlags |= DFLAGS_DEVICE_PRESENT;
1887 chan->PmLunMap = 0;
1888 }
1889
1890 return;
1891
1892 } // end UniataAhciReset()
1893
1894 VOID
1895 NTAPI
1896 UniataAhciStartFR(
1897 IN PHW_CHANNEL chan
1898 )
1899 {
1900 ULONG CMD;
1901
1902 KdPrint2(("UniataAhciStartFR: lChan %d\n", chan->lChannel));
1903
1904 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
1905 KdPrint2((" CMD %#x\n", CMD));
1906 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD | ATA_AHCI_P_CMD_FRE);
1907
1908 return;
1909 } // end UniataAhciStartFR()
1910
1911 BOOLEAN
1912 NTAPI
1913 UniataAhciStopFR(
1914 IN PHW_CHANNEL chan
1915 )
1916 {
1917 ULONG CMD;
1918 ULONG i;
1919
1920 KdPrint2(("UniataAhciStopFR: lChan %d\n", chan->lChannel));
1921
1922 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
1923 KdPrint2((" CMD %#x\n", CMD));
1924 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD & ~ATA_AHCI_P_CMD_FRE);
1925
1926 for(i=0; i<1000; i++) {
1927 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
1928 if(!(CMD & ATA_AHCI_P_CMD_FR)) {
1929 KdPrint2((" final CMD %#x\n", CMD));
1930 return TRUE;
1931 }
1932 AtapiStallExecution(1000);
1933 }
1934 KdPrint2((" CMD %#x\n", CMD));
1935 KdPrint((" SError %#x\n", AtapiReadPort4(chan, IDX_SATA_SError)));
1936 KdPrint2(("UniataAhciStopFR: timeout\n"));
1937 return FALSE;
1938 } // end UniataAhciStopFR()
1939
1940 VOID
1941 NTAPI
1942 UniataAhciStart(
1943 IN PHW_CHANNEL chan
1944 )
1945 {
1946 ULONG IS, CMD;
1947 SATA_SERROR_REG SError;
1948
1949 KdPrint2(("UniataAhciStart: lChan %d\n", chan->lChannel));
1950
1951 /* clear SATA error register */
1952 SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError);
1953
1954 /* clear any interrupts pending on this channel */
1955 IS = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS);
1956 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS);
1957
1958 KdPrint2((" SError %#x, IS %#x\n", SError.Reg, IS));
1959
1960 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
1961 KdPrint2((" CMD %#x\n", CMD));
1962 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD,
1963 CMD |
1964 ATA_AHCI_P_CMD_ST |
1965 ((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) ? ATA_AHCI_P_CMD_PMA : 0));
1966
1967 return;
1968 } // end UniataAhciStart()
1969
1970 BOOLEAN
1971 NTAPI
1972 UniataAhciCLO(
1973 IN PHW_CHANNEL chan
1974 )
1975 {
1976 //PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1977 //PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
1978 ULONG CAP, CMD;
1979 //SATA_SERROR_REG SError;
1980 ULONG i;
1981
1982 KdPrint2(("UniataAhciCLO: lChan %d\n", chan->lChannel));
1983
1984 /* issue Command List Override if supported */
1985 //CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP);
1986 CAP = chan->DeviceExtension->AHCI_CAP;
1987 if(!(CAP & AHCI_CAP_SCLO)) {
1988 return TRUE;
1989 }
1990 KdPrint2((" send CLO\n"));
1991 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
1992 CMD |= ATA_AHCI_P_CMD_CLO;
1993 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD);
1994
1995 for(i=0; i<1000; i++) {
1996 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
1997 if(!(CMD & ATA_AHCI_P_CMD_CLO)) {
1998 KdPrint2((" final CMD %#x\n", CMD));
1999 return TRUE;
2000 }
2001 AtapiStallExecution(1000);
2002 }
2003 KdPrint2((" CMD %#x\n", CMD));
2004 KdPrint2(("UniataAhciCLO: timeout\n"));
2005 return FALSE;
2006 } // end UniataAhciCLO()
2007
2008 BOOLEAN
2009 NTAPI
2010 UniataAhciStop(
2011 IN PHW_CHANNEL chan
2012 )
2013 {
2014 ULONG CMD;
2015 //SATA_SERROR_REG SError;
2016 ULONG i;
2017
2018 KdPrint2(("UniataAhciStop: lChan %d\n", chan->lChannel));
2019
2020 /* issue Command List Override if supported */
2021 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
2022 CMD &= ~ATA_AHCI_P_CMD_ST;
2023 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD);
2024
2025 for(i=0; i<1000; i++) {
2026 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
2027 if(!(CMD & ATA_AHCI_P_CMD_CR)) {
2028 KdPrint2((" final CMD %#x\n", CMD));
2029 return TRUE;
2030 }
2031 AtapiStallExecution(1000);
2032 }
2033 KdPrint2((" CMD %#x\n", CMD));
2034 KdPrint((" SError %#x\n", AtapiReadPort4(chan, IDX_SATA_SError)));
2035 KdPrint2(("UniataAhciStop: timeout\n"));
2036 return FALSE;
2037 } // end UniataAhciStop()
2038
2039 UCHAR
2040 NTAPI
2041 UniataAhciBeginTransaction(
2042 IN PVOID HwDeviceExtension,
2043 IN ULONG lChannel,
2044 IN ULONG DeviceNumber,
2045 IN PSCSI_REQUEST_BLOCK Srb
2046 )
2047 {
2048 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2049 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
2050 //ULONG Channel = deviceExtension->Channel + lChannel;
2051 //ULONG hIS;
2052 ULONG CMD, CMD0;
2053 //AHCI_IS_REG IS;
2054 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
2055 //SATA_SSTATUS_REG SStatus;
2056 //SATA_SERROR_REG SError;
2057 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS);
2058 //ULONGIO_PTR base;
2059 ULONG tag=0;
2060 //ULONG i;
2061
2062 PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
2063
2064 KdPrint2(("UniataAhciBeginTransaction: lChan %d, AtaReq %#x\n", chan->lChannel, AtaReq));
2065
2066 if(Srb->DataTransferLength && (!AtaReq->dma_entries || AtaReq->dma_entries >= (USHORT)0xffff)) {
2067 KdPrint2(("UniataAhciBeginTransaction wrong DMA tab len %x\n", AtaReq->dma_entries));
2068 return 0;
2069 }
2070
2071 AHCI_CL->prd_length = (USHORT)(AtaReq->dma_entries);
2072 AHCI_CL->cmd_flags = AtaReq->ahci.io_cmd_flags;
2073 AHCI_CL->bytecount = 0;
2074 if(AtaReq->ahci.ahci_base64) {
2075 KdPrint2((PRINT_PREFIX " AHCI AtaReq CMD %#x (ph %#x)\n", AtaReq->ahci.ahci_cmd_ptr, (ULONG)(AtaReq->ahci.ahci_base64)));
2076 AHCI_CL->cmd_table_phys = AtaReq->ahci.ahci_base64;
2077 } else
2078 if(AtaReq->ahci.ahci_cmd_ptr) {
2079 KdPrint2((PRINT_PREFIX " AHCI AtaReq->Chan CMD %#x (ph %#x) -> %#x (ph %#x)\n",
2080 AtaReq->ahci.ahci_cmd_ptr, (ULONG)(AtaReq->ahci.ahci_base64),
2081 &(chan->AhciCtlBlock->cmd), chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd) ));
2082 RtlCopyMemory(&(chan->AhciCtlBlock->cmd), AtaReq->ahci.ahci_cmd_ptr,
2083 FIELD_OFFSET(IDE_AHCI_CMD, prd_tab)+AHCI_CL->prd_length*sizeof(IDE_AHCI_PRD_ENTRY));
2084 AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2085 } else {
2086 KdPrint2((PRINT_PREFIX " no AHCI CMD\n"));
2087 //AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2088 return 0;
2089 }
2090 if(AHCI_CL->cmd_table_phys & AHCI_CMD_ALIGNEMENT_MASK) {
2091 KdPrint2((PRINT_PREFIX " AHCI CMD address is not aligned (mask %#x)\n", (ULONG)AHCI_CMD_ALIGNEMENT_MASK));
2092 return 0;
2093 }
2094
2095 #ifdef DBG
2096 KdPrint2((" prd_length %#x, flags %#x, base %I64x\n", AHCI_CL->prd_length, AHCI_CL->cmd_flags,
2097 AHCI_CL->cmd_table_phys));
2098 #endif // DBG
2099
2100 CMD0 = CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
2101 KdPrint2((" CMD %#x\n", CMD));
2102 // switch controller to ATAPI mode for ATA_PACKET commands only
2103 if(ATAPI_DEVICE(chan, DeviceNumber) &&
2104 AtaReq->ahci.ahci_cmd_ptr->cfis[2] == IDE_COMMAND_ATAPI_PACKET) {
2105 KdPrint2((" ATAPI\n"));
2106 CMD |= ATA_AHCI_P_CMD_ATAPI;
2107 KdDump(&(AtaReq->ahci.ahci_cmd_ptr->acmd), 16);
2108 } else {
2109 CMD &= ~ATA_AHCI_P_CMD_ATAPI;
2110 }
2111 if(CMD0 != CMD) {
2112 KdPrint2((" send CMD %#x, entries %#x\n", CMD, AHCI_CL->prd_length));
2113 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD);
2114 }
2115
2116 /* issue command to controller */
2117 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
2118 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, 0x01 << tag);
2119 chan->AhciPrevCI |= 0x01 << tag;
2120
2121 if(!ATAPI_DEVICE(chan, DeviceNumber)) {
2122 // TODO: check if we send ATA_RESET and wait for ready of so.
2123 if(AtaReq->ahci.ahci_cmd_ptr->cfis[2] == IDE_COMMAND_ATAPI_RESET) {
2124 ULONG TFD;
2125 ULONG i;
2126
2127 for(i=0; i<1000000; i++) {
2128 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
2129 if(!(TFD & IDE_STATUS_BUSY)) {
2130 break;
2131 }
2132 }
2133 if(TFD & IDE_STATUS_BUSY) {
2134 KdPrint2((" timeout\n"));
2135 }
2136 if(TFD & IDE_STATUS_ERROR) {
2137 KdPrint2((" ERROR %#x\n", (UCHAR)(TFD >> 8)));
2138 }
2139 AtaReq->ahci.in_status = TFD;
2140
2141 return IDE_STATUS_SUCCESS;
2142 }
2143 }
2144
2145 return IDE_STATUS_IDLE;
2146
2147 } // end UniataAhciBeginTransaction()
2148
2149 UCHAR
2150 NTAPI
2151 UniataAhciEndTransaction(
2152 IN PVOID HwDeviceExtension,
2153 IN ULONG lChannel,
2154 IN ULONG DeviceNumber,
2155 IN PSCSI_REQUEST_BLOCK Srb
2156 )
2157 {
2158 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2159 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
2160 //ULONG Channel = deviceExtension->Channel + lChannel;
2161 //ULONG hIS;
2162 ULONG CI, ACT;
2163 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
2164 ULONG TFD;
2165 PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
2166 ULONG tag=0;
2167 //ULONG i;
2168 PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]);
2169 PHW_LU_EXTENSION LunExt;
2170
2171 KdPrint2(("UniataAhciEndTransaction: lChan %d\n", chan->lChannel));
2172
2173 LunExt = chan->lun[DeviceNumber];
2174
2175 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
2176 KdPrint2((" TFD %#x\n", TFD));
2177
2178 if(TFD & IDE_STATUS_ERROR) {
2179 AtaReq->ahci.in_error = (UCHAR)(TFD >> 8);
2180 KdPrint2((" ERROR %#x\n", AtaReq->ahci.in_error));
2181 } else {
2182 AtaReq->ahci.in_error = 0;
2183 }
2184 AtaReq->ahci.in_status = TFD;
2185
2186 //if (request->flags & ATA_R_CONTROL) {
2187
2188 AtaReq->ahci.in_bcount = (ULONG)(RCV_FIS[12]) | ((ULONG)(RCV_FIS[13]) << 8);
2189 AtaReq->ahci.in_lba = (ULONG)(RCV_FIS[4]) | ((ULONGLONG)(RCV_FIS[5]) << 8) |
2190 ((ULONGLONG)(RCV_FIS[6]) << 16);
2191 if(chan->ChannelCtrlFlags & CTRFLAGS_LBA48) {
2192 AtaReq->ahci.in_lba |= ((ULONGLONG)(RCV_FIS[8]) << 24) |
2193 ((ULONGLONG)(RCV_FIS[9]) << 32) |
2194 ((ULONGLONG)(RCV_FIS[10]) << 40);
2195 } else {
2196 AtaReq->ahci.in_lba |= ((ULONGLONG)(RCV_FIS[8]) << 24) |
2197 ((ULONGLONG)(RCV_FIS[9]) << 32) |
2198 ((ULONGLONG)(RCV_FIS[7] & 0x0f) << 24);
2199 }
2200 AtaReq->WordsTransfered = AHCI_CL->bytecount/2;
2201 /*
2202 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
2203 KdPrint2(("RCV:\n"));
2204 KdDump(RCV_FIS, 24);
2205 KdPrint2(("PIO:\n"));
2206 KdDump(&(chan->AhciCtlBlock->rcv_fis.psfis[0]), 24);
2207
2208 KdPrint2(("len: %d vs %d\n", AHCI_CL->bytecount, (ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8) ));
2209 if(!AHCI_CL->bytecount) {
2210 AtaReq->WordsTransfered = ((ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8)) / 2;
2211 }
2212 }
2213 */
2214 ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT);
2215 CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI);
2216 if(CI & (1 << tag)) {
2217 // clear CI
2218 KdPrint2((" Incomplete command, CI %#x, ACT %#x\n", CI, ACT));
2219 KdPrint2((" FIS status %#x, error %#x\n", RCV_FIS[2], RCV_FIS[3]));
2220
2221 #if DBG
2222 UniataDumpAhciPortRegs(chan);
2223 #endif
2224 if(!UniataAhciAbortOperation(chan)) {
2225 KdPrint2((" Abort failed, need RESET\n"));
2226 }
2227 #if DBG
2228 UniataDumpAhciPortRegs(chan);
2229 #endif
2230 chan->AhciPrevCI = CI & ~((ULONG)1 << tag);
2231 if(chan->AhciPrevCI) {
2232 KdPrint2((" Need command list restart, CI %#x\n", chan->AhciPrevCI));
2233 }
2234 } else {
2235 chan->AhciPrevCI &= ~((ULONG)1 << tag);
2236 RtlZeroMemory(AHCI_CL, sizeof(IDE_AHCI_CMD_LIST));
2237 }
2238 //}
2239
2240 return 0;
2241
2242 } // end UniataAhciEndTransaction()
2243
2244 VOID
2245 NTAPI
2246 UniataAhciResume(
2247 IN PHW_CHANNEL chan
2248 )
2249 {
2250 ULONGLONG base;
2251
2252 KdPrint2(("UniataAhciResume: lChan %d\n", chan->lChannel));
2253
2254 #ifdef DBG
2255 //UniataDumpAhciPortRegs(chan);
2256 #endif // DBG
2257
2258 /* Disable port interrupts */
2259 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
2260
2261 /* setup work areas */
2262 base = chan->AHCI_CTL_PhAddr;
2263 if(!base) {
2264 KdPrint2((PRINT_PREFIX " AHCI buffer allocation failed\n"));
2265 return;
2266 }
2267 KdPrint2((PRINT_PREFIX " AHCI CLB setup\n"));
2268 if(base & AHCI_CLB_ALIGNEMENT_MASK) {
2269 KdPrint2((PRINT_PREFIX " AHCI CLB address is not aligned (mask %#x)\n", (ULONG)AHCI_FIS_ALIGNEMENT_MASK));
2270 }
2271 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CLB,
2272 (ULONG)(base & 0xffffffff));
2273 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CLB + 4,
2274 (ULONG)((base >> 32) & 0xffffffff));
2275
2276 KdPrint2((PRINT_PREFIX " AHCI RCV FIS setup\n"));
2277 base = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, rcv_fis);
2278 if(base & AHCI_FIS_ALIGNEMENT_MASK) {
2279 KdPrint2((PRINT_PREFIX " AHCI FIS address is not aligned (mask %#x)\n", (ULONG)AHCI_FIS_ALIGNEMENT_MASK));
2280 }
2281 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_FB,
2282 (ULONG)(base & 0xffffffff));
2283 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_FB + 4,
2284 (ULONG)((base >> 32) & 0xffffffff));
2285
2286 /* activate the channel and power/spin up device */
2287 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD,
2288 (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD |
2289 (((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM)) ? ATA_AHCI_P_CMD_ALPE : 0) |
2290 (((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM2)) ? ATA_AHCI_P_CMD_ASP : 0 ))
2291 );
2292
2293 #ifdef DBG
2294 //UniataDumpAhciPortRegs(chan);
2295 #endif // DBG
2296
2297 UniataAhciStartFR(chan);
2298 UniataAhciStart(chan);
2299
2300 #ifdef DBG
2301 UniataDumpAhciPortRegs(chan);
2302 #endif // DBG
2303
2304 return;
2305 } // end UniataAhciResume()
2306
2307 #if 0
2308 VOID
2309 NTAPI
2310 UniataAhciSuspend(
2311 IN PHW_CHANNEL chan
2312 )
2313 {
2314 ULONGLONG base;
2315 SATA_SCONTROL_REG SControl;
2316
2317 KdPrint2(("UniataAhciSuspend:\n"));
2318
2319 /* Disable port interrupts */
2320 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
2321
2322 /* Reset command register. */
2323 UniataAhciStop(chan);
2324 UniataAhciStopFR(chan);
2325 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, 0);
2326
2327 /* Allow everything including partial and slumber modes. */
2328 UniataSataWritePort4(chan, IDX_SATA_SControl, 0, 0);
2329
2330 /* Request slumber mode transition and give some time to get there. */
2331 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, ATA_AHCI_P_CMD_SLUMBER);
2332 AtapiStallExecution(100);
2333
2334 /* Disable PHY. */
2335 SControl.Reg = 0;
2336 SControl.DET = SStatus_DET_Offline;
2337 UniataSataWritePort4(chan, IDX_SATA_SControl, SControl.Reg, 0);
2338
2339 return;
2340 } // end UniataAhciSuspend()
2341 #endif
2342
2343 BOOLEAN
2344 NTAPI
2345 UniataAhciReadPM(
2346 IN PHW_CHANNEL chan,
2347 IN ULONG DeviceNumber,
2348 IN ULONG Reg,
2349 OUT PULONG result
2350 )
2351 {
2352 //ULONG Channel = deviceExtension->Channel + lChannel;
2353 //ULONG hIS;
2354 //ULONG CI;
2355 //AHCI_IS_REG IS;
2356 //ULONG tag=0;
2357 PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
2358 PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
2359
2360 KdPrint(("UniataAhciReadPM: lChan %d [%#x]\n", chan->lChannel, DeviceNumber));
2361
2362 if(DeviceNumber == DEVNUM_NOT_SPECIFIED) {
2363 (*result) = UniataSataReadPort4(chan, Reg, 0);
2364 return TRUE;
2365 }
2366 if(DeviceNumber < AHCI_DEV_SEL_PM) {
2367 switch(Reg) {
2368 case IDX_SATA_SStatus:
2369 Reg = 0; break;
2370 case IDX_SATA_SError:
2371 Reg = 1; break;
2372 case IDX_SATA_SControl:
2373 Reg = 2; break;
2374 default:
2375 return FALSE;
2376 }
2377 }
2378
2379 RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis));
2380 AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D;
2381 AHCI_CMD->cfis[1] = AHCI_FIS_COMM_PM;
2382 AHCI_CMD->cfis[2] = IDE_COMMAND_READ_PM;
2383 AHCI_CMD->cfis[3] = (UCHAR)Reg;
2384 AHCI_CMD->cfis[7] = (UCHAR)(IDE_USE_LBA | DeviceNumber);
2385 AHCI_CMD->cfis[15] = IDE_DC_A_4BIT;
2386
2387 if(UniataAhciSendCommand(chan->DeviceExtension, chan->lChannel, DeviceNumber, 0, 10) == IDE_STATUS_WRONG) {
2388 KdPrint2((" PM read failed\n"));
2389 return FALSE;
2390 }
2391
2392 KdDump(RCV_FIS, sizeof(chan->AhciCtlBlock->rcv_fis.rfis));
2393
2394 (*result) = UniataAhciUlongFromRFIS(RCV_FIS);
2395 return TRUE;
2396
2397 } // end UniataAhciReadPM()
2398
2399 UCHAR
2400 NTAPI
2401 UniataAhciWritePM(
2402 IN PHW_CHANNEL chan,
2403 IN ULONG DeviceNumber,
2404 IN ULONG Reg,
2405 IN ULONG value
2406 )
2407 {
2408 //ULONG Channel = deviceExtension->Channel + lChannel;
2409 //ULONG hIS;
2410 //ULONG CI;
2411 //AHCI_IS_REG IS;
2412 //ULONG tag=0;
2413 ULONG TFD;
2414 PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
2415 //PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]);
2416
2417 KdPrint(("UniataAhciWritePM: lChan %d [%#x] %#x\n", chan->lChannel, DeviceNumber, value));
2418
2419 if(DeviceNumber == DEVNUM_NOT_SPECIFIED) {
2420 UniataSataWritePort4(chan, Reg, value, 0);
2421 return 0;
2422 }
2423 if(DeviceNumber < AHCI_DEV_SEL_PM) {
2424 switch(Reg) {
2425 case IDX_SATA_SStatus:
2426 Reg = 0; break;
2427 case IDX_SATA_SError:
2428 Reg = 1; break;
2429 case IDX_SATA_SControl:
2430 Reg = 2; break;
2431 default:
2432 return IDE_STATUS_WRONG;
2433 }
2434 }
2435
2436 RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis));
2437 AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D;
2438 AHCI_CMD->cfis[1] = AHCI_FIS_COMM_PM;
2439 AHCI_CMD->cfis[2] = IDE_COMMAND_WRITE_PM;
2440 AHCI_CMD->cfis[3] = (UCHAR)Reg;
2441 AHCI_CMD->cfis[7] = (UCHAR)(IDE_USE_LBA | DeviceNumber);
2442
2443 AHCI_CMD->cfis[12] = (UCHAR)(value & 0xff);
2444 AHCI_CMD->cfis[4] = (UCHAR)((value >> 8) & 0xff);
2445 AHCI_CMD->cfis[5] = (UCHAR)((value >> 16) & 0xff);
2446 AHCI_CMD->cfis[6] = (UCHAR)((value >> 24) & 0xff);
2447
2448 AHCI_CMD->cfis[15] = IDE_DC_A_4BIT;
2449
2450 if(UniataAhciSendCommand(chan->DeviceExtension, chan->lChannel, DeviceNumber, 0, 100) == IDE_STATUS_WRONG) {
2451 KdPrint2((" PM write failed\n"));
2452 return IDE_STATUS_WRONG;
2453 }
2454
2455 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD);
2456
2457 if(TFD & IDE_STATUS_ERROR) {
2458 KdPrint2((" ERROR %#x\n", (UCHAR)(TFD >> 8)));
2459 }
2460 return (UCHAR)(TFD >> 8);
2461
2462 } // end UniataAhciWritePM()
2463
2464 VOID
2465 UniataAhciSetupCmdPtr(
2466 IN OUT PATA_REQ AtaReq
2467 )
2468 {
2469 union {
2470 PUCHAR prd_base;
2471 ULONGLONG prd_base64;
2472 };
2473 union {
2474 PUCHAR prd_base0;
2475 ULONGLONG prd_base64_0;
2476 };
2477 ULONG d;
2478
2479 prd_base64_0 = prd_base64 = 0;
2480 prd_base = (PUCHAR)(&AtaReq->ahci_cmd0);
2481 prd_base0 = prd_base;
2482
2483 prd_base64 = (prd_base64 + max(FIELD_OFFSET(ATA_REQ, ahci_cmd0), AHCI_CMD_ALIGNEMENT_MASK+1)) & ~AHCI_CMD_ALIGNEMENT_MASK;
2484
2485 d = (ULONG)(prd_base64 - prd_base64_0);
2486 KdPrint2((PRINT_PREFIX " AtaReq %#x: cmd aligned %I64x, d=%x\n", AtaReq, prd_base64, d));
2487
2488 AtaReq->ahci.ahci_cmd_ptr = (PIDE_AHCI_CMD)prd_base64;
2489 KdPrint2((PRINT_PREFIX " ahci_cmd_ptr %#x\n", AtaReq->ahci.ahci_cmd_ptr));
2490 } // end UniataAhciSetupCmdPtr()
2491
2492 PSCSI_REQUEST_BLOCK
2493 NTAPI
2494 BuildAhciInternalSrb (
2495 IN PVOID HwDeviceExtension,
2496 IN ULONG DeviceNumber,
2497 IN ULONG lChannel,
2498 IN PUCHAR Buffer,
2499 IN ULONG Length
2500 )
2501 {
2502 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2503 PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
2504 PSCSI_REQUEST_BLOCK srb;
2505 // PCDB cdb;
2506 PATA_REQ AtaReq = chan->AhciInternalAtaReq;
2507
2508 KdPrint(("BuildAhciInternalSrb: lChan %d [%#x]\n", lChannel, DeviceNumber));
2509
2510 if(!AtaReq) {
2511 KdPrint2((PRINT_PREFIX " !chan->AhciInternalAtaReq\n"));
2512 return NULL;
2513 }
2514
2515 //RtlZeroMemory((PCHAR) AtaReq, sizeof(ATA_REQ));
2516 //RtlZeroMemory((PCHAR) AtaReq, FIELD_OFFSET(ATA_REQ, ahci));
2517 UniAtaClearAtaReq(AtaReq);
2518
2519 srb = chan->AhciInternalSrb;
2520
2521 RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK));
2522
2523 srb->PathId = (UCHAR)lChannel;
2524 srb->TargetId = (UCHAR)DeviceNumber;
2525 srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
2526 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
2527
2528 // Set flags to disable synchronous negociation.
2529 //srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2530
2531 // Set timeout to 4 seconds.
2532 srb->TimeOutValue = 4;
2533
2534 srb->CdbLength = 6;
2535 srb->DataBuffer = Buffer;
2536 srb->DataTransferLength = Length;
2537 srb->SrbExtension = AtaReq;
2538
2539 AtaReq->Srb = srb;
2540 AtaReq->DataBuffer = (PUSHORT)Buffer;
2541 AtaReq->TransferLength = Length;
2542
2543 //if(!AtaReq->ahci.ahci_cmd_ptr) {
2544 //UniataAhciSetupCmdPtr(AtaReq);
2545 //AtaReq->ahci.ahci_cmd_ptr = &(chan->AhciCtlBlock->cmd);
2546 //AtaReq->ahci.ahci_base64 = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd);
2547 //}
2548 //AtaReq->ahci.ahci_cmd_ptr = &(AtaReq->ahci_cmd0);
2549 //AtaReq->ahci.ahci_base64 = NULL; // indicate that we should copy command to proper place
2550
2551 KdPrint2((PRINT_PREFIX " Srb %#x, AtaReq %#x, CMD %#x ph %I64x\n", srb, AtaReq,
2552 AtaReq->ahci.ahci_cmd_ptr, AtaReq->ahci.ahci_base64));
2553
2554 /* // Set CDB operation code.
2555 cdb = (PCDB)srb->Cdb;
2556 cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
2557 cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
2558 */
2559 return srb;
2560 } // end BuildAhciInternalSrb()
2561