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