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