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