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