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