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