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