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