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