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