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