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